BN_ADD(3ossl)
π BN_ADD(3ossl) β arithmetic operations on BIGNUMs π
okay bestie, pull up a chair πͺ because this is the page where OpenSSL does math. big math. like, numbers-so-big-they-don't-fit-in-a-normal-int math. this is BN_ADD(3ossl) from the OpenSSL manual, and yes it covers 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 and BN_gcd. that's fifteen functions. fifteen. she's booked and busy π
β¨ 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);
πΈ DESCRIPTION πΈ
the no-ctx girlies (aka the easy ones) π§
BN_add()β addsaandb, drops the answer inr(r=a+b). plot twist:ris allowed to be the sameBIGNUMasaorb. slay, in-place πBN_sub()β takesbaway froma, puts the result inr(r=a-b). and yeah,rcan be the sameBIGNUMasaorbagain.BN_mul()β multipliesaandb, result goes inr(r=a*b).rmay be the sameBIGNUMasaorb. oh and if you're multiplying by powers of 2 specifically? useBN_lshift(3)instead, that's the move π«ΆBN_sqr()β squaresa, result inr(r=a^2).randacan be the sameBIGNUM. this one is faster thanBN_mul(r,a,a)β no cap, it's literally built different β¨BN_div()β dividesabyd, puts the quotient indvand the remainder inrem(dv=a/d, rem=a%d). either ofdvandremmay beNULL, and if it is, that value justβ¦ doesn't come back. it's giving "no thoughts, no return value". the result rounds towards zero, which means ifais negative, the remainder will be zero or negative. and if you're dividing by powers of 2?BN_rshift(3), bestie.BN_mod()β it's justBN_div()withdvset toNULL. that's it. that's the whole vibe.BN_nnmod()β reducesamodulomand puts the nonnegative remainder inr. nn = nonnegative, iykyk πBN_mod_add()β addsatobmodulom, nonnegative result lands inr.BN_mod_sub()β subtractsbfromamodulom, nonnegative result lands inr.BN_mod_mul()β multipliesabyband finds the nonnegative remainder with respect to modulusm(r=(a*b) mod m).rmay be the sameBIGNUMasaorb. and if you're doing repeated computations with the same modulus, there are more efficient algorithms β go peek atBN_mod_mul_montgomery(3)andBN_mod_mul_reciprocal(3)πBN_mod_sqr()β squaresamodulom, result inr.BN_mod_sqrt()β returns the modular square root ofasuch thatin^2 = a (mod p). π¨ important π¨: the moduluspmust be a prime, otherwise you get an error or an incorrect "result". like, it will hand you something and act normal about it. the result is stored intoin, which can beNULLβ in that case the result gets newly allocated.BN_exp()β raisesato thep-th power, result inr(r=a^p). faster than callingBN_mul()over and over, thank god πBN_mod_exp()β computesato thep-th power modulom(r=a^p % m). uses less time and space thanBN_exp(). > but do NOT call this function whenmis even and any of the parameters have theBN_FLG_CONSTTIMEflag set. that one's a real warning, not a vibe check.BN_gcd()β computes the greatest common divisor ofaandb, result inr.rmay be the sameBIGNUMasaorb. the iconic GCD, we love her π
the ctx rules π
for all functions that take a ctx parameter, it must be a previously allocated BN_CTX used for temporary variables β see BN_CTX_new(3). unless the documentation for a specific function says otherwise, ctx must not be NULL. periodt.
and unless noted otherwise, the result BIGNUM must be different from the arguments. no sharing, bestie, we don't do that here π
π 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. like genuinely an error. don't. π
β RETURN VALUES β
BN_mod_sqrt() returns the result β which, reminder, may be incorrect if p is not a prime β or NULL. yes she can lie to you. be careful π«Ά
for all the remaining functions: 1 means success, 0 means error. and you should always check the return value, like:
if (!BN_add(r,a,b)) goto err;
the error codes can be obtained with ERR_get_error(3). always check, never guess, that's the rule β¨
π¦ SEE ALSO π¦
π COPYRIGHT π
Copyright 2000-2026 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 BN_ADD(3ossl) from OpenSSL 3.5.9, dated 2026-09-29 β go do huge math responsibly, check your return values, and don't pass an even m with BN_FLG_CONSTTIME. mwah πβ¨
π¦ where this page comes from
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms