BN_ADD(3ossl)

πŸ“¦ version 3.5.0, in opensuse-leap 16.0

πŸ’… BN_ADD(3ossl) β€” the BIGNUM arithmetic glow-up

okay so bestie, this is the BN_ADD(3ossl) page from OpenSSL, and it's literally the whole math department in one file. big-number arithmetic, but make it fashion. no cap, this is the page you keep open in a second terminal while you're doing crypto stuff and pretending you remember how long division works.


✨ NAME ✨

BN_add, BN_sub, BN_mul, BN_sqr, BN_div, BN_mod, BN_nnmod, BN_mod_add, BN_mod_sub, BN_mod_mul, BN_mod_sqr, BN_mod_sqrt, BN_exp, BN_mod_exp, BN_gcd β€” all of them are arithmetic operations on BIGNUMs. the whole squad. 🫢


🌸 SYNOPSIS 🌸

#include <openssl/bn.h>

int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);

int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);

int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);

int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);

int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d,
           BN_CTX *ctx);

int BN_mod(BIGNUM *rem, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);

int BN_nnmod(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);

int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
               BN_CTX *ctx);

int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
               BN_CTX *ctx);

int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
               BN_CTX *ctx);

int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);

BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);

int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);

int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
               const BIGNUM *m, BN_CTX *ctx);

int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);

like, look at all those ctx parameters. every single one of these is asking for a BN_CTX. we'll get to that. πŸŽ€


πŸ‘‘ DESCRIPTION πŸ‘‘

so here's the tea on every single one of these functions, one by one, no skips:

  • BN_add() β€” adds a and b, drops the result in r (r=a+b). and the icon behavior: r can be the same BIGNUM as a or b. aliasing rights! πŸ’…
  • BN_sub() β€” subtracts b from a, result goes in r (r=a-b). same deal, r may be the same BIGNUM as a or b.
  • BN_mul() β€” multiplies a and b into r (r=a*b). r may be the same BIGNUM as a or b. but bestie, if you're multiplying by powers of 2, don't do it here β€” use BN_lshift(3) instead. it's giving "use the right tool."
  • BN_sqr() β€” squares a into r (r=a^2). r and a may be the same BIGNUM. and listen: this is faster than BN_mul(r,a,a). so if you were about to do that... don't. πŸ™ˆ
  • BN_div() β€” divides a by d, quotient goes in dv, remainder goes in rem (dv=a/d, rem=a%d). either of dv and rem may be NULL, and then that value just isn't returned, no drama. the result is rounded towards zero, which means if a is negative, the remainder will be zero or negative. ⚠️ and for division by powers of 2, use BN_rshift(3), not this.
  • BN_mod() β€” it's literally BN_div() but with dv set to NULL. that's the whole thing. she's lowkey just div with extra steps.
  • BN_nnmod() β€” reduces a modulo m and puts the nonnegative remainder in r. the "nn" is doing the work, and we love an honest name.
  • BN_mod_add() β€” adds a to b modulo m, nonnegative result in r.
  • BN_mod_sub() β€” subtracts b from a modulo m, nonnegative result in r.
  • BN_mod_mul() β€” multiplies a by b and finds the nonnegative remainder against modulus m (r=(a*b) mod m). r may be the same BIGNUM as a or b. πŸ¦‹ and if you're doing repeated computations with the same modulus, go look at BN_mod_mul_montgomery(3) and BN_mod_mul_reciprocal(3) β€” those are the more efficient algorithms for that specific vibe.
  • BN_mod_sqr() β€” squares a modulo m, result in r.
  • BN_mod_sqrt() β€” returns the modular square root of a such that in^2 = a (mod p). 🚨 the modulus p must be a prime, otherwise you get an error or an incorrect "result" β€” yes, with the scare quotes, the manpage is being shady and correct. the result is stored into in, which can be NULL, and in that case it'll be newly allocated.
  • BN_exp() β€” raises a to the p-th power, result in r (r=a^p). faster than calling BN_mul() over and over like a person with no plan. πŸ”₯
  • BN_mod_exp() β€” computes a to the p-th power modulo m (r=a^p % m). uses less time and space than BN_exp(), so she's the efficient one. ⚠️ but do not call this function when m is even and any of the parameters have the BN_FLG_CONSTTIME flag set. that's a hard no, not a suggestion.
  • BN_gcd() β€” computes the greatest common divisor of a and b, result in r. r may be the same BIGNUM as a or b. iconic, unmatched, the moment.

and for all of these functions, ctx is a previously allocated BN_CTX used for temporary variables β€” see BN_CTX_new(3). ✨

πŸ’€ unless the page says otherwise, the result BIGNUM must be different from the arguments. yes, even though like four of these explicitly allow aliasing. read each one. the details are the details.

🧚 NOTES 🧚

for modular operations like BN_nnmod() or BN_mod_exp(), it is an error to use the same BIGNUM object for the modulus as for the output. so don't try to be cute and reuse the modulus buffer as your result buffer. it will not slay, it will just break. 😭


🌈 RETURN VALUES 🌈

BN_mod_sqrt() returns the result β€” possibly incorrect if p isn't a prime, which, yeah, you were warned β€” or NULL. 🫠

for all the remaining functions, 1 means success, 0 means error. and bestie, always check the return value, fr fr:

if (!BN_add(r,a,b)) goto err;

the error codes can be obtained by ERR_get_error(3). πŸ’–


⭐ SEE ALSO ⭐

ERR_get_error(3), BN_CTX_new(3), BN_add_word(3), BN_set_bit(3)


Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


and that's the whole page, bestie πŸŽ€ this was OpenSSL 3.5.0, dated 2026-09-25 β€” go forth and do big-number math responsibly, and pls pls pls check your return values πŸ’œ

πŸ“¦ where this page comes from