From e4c2386b61196b0ab297ef176944f1dbdfb4be70 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 6 Mar 2023 14:17:25 +1000 Subject: [PATCH] BN compatibility API: move implementation out to separate API BN APIs from ssl.c have been moved out to ssl_bn.c that is included in ssl.c. Added defines for BN_rand() and BN_pseudo_rand() to indicate which bits are to be set. 'internal' field now always maps to the ;mpi' field that is a MP integer. SetIndividualInternal/External renamed to wolfssl_bn_get/set_value. Fixed BN APIs to work as closely to OpenSSL as possible. Added tests. Moved wolfssl_make_rng out to ssl.c as BN APIs are using it now. SP int and TFM now check trials are in a valid range for mp_prime_is_prime_ex(). --- src/include.am | 3 +- src/internal.c | 3 +- src/pk.c | 159 +-- src/ssl.c | 1717 +---------------------------- src/ssl_bn.c | 2386 ++++++++++++++++++++++++++++++++++++++++ tests/api.c | 1197 ++++++++++++++++---- wolfcrypt/src/sp_int.c | 7 +- wolfcrypt/src/tfm.c | 2 + wolfssl/openssl/bn.h | 26 +- 9 files changed, 3504 insertions(+), 1996 deletions(-) create mode 100644 src/ssl_bn.c diff --git a/src/include.am b/src/include.am index dacd89f56..d43194aae 100644 --- a/src/include.am +++ b/src/include.am @@ -18,8 +18,9 @@ MAINTAINERCLEANFILES+= $(FIPS_FILES) EXTRA_DIST += src/bio.c EXTRA_DIST += src/conf.c -EXTRA_DIST += src/ssl_misc.c EXTRA_DIST += src/pk.c +EXTRA_DIST += src/ssl_bn.c +EXTRA_DIST += src/ssl_misc.c EXTRA_DIST += src/x509.c EXTRA_DIST += src/x509_str.c diff --git a/src/internal.c b/src/internal.c index fef559a0d..64102062b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -24512,7 +24512,8 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) if (XSTRCMP(substrCurrent, "ECDHE") == 0 || XSTRCMP(substrCurrent, "RSA") == 0 || XSTRCMP(substrCurrent, "DHE") == 0) { - XMEMCPY(name, substrCurrent, length); + if (name != substrCurrent) + XMEMMOVE(name, substrCurrent, length); name[length] = '\0'; break; } diff --git a/src/pk.c b/src/pk.c index 7608b732e..4c4aedc18 100644 --- a/src/pk.c +++ b/src/pk.c @@ -764,53 +764,6 @@ static int wolfssl_der_length(const unsigned char* seq, int len) #endif /* OPENSSL_EXTRA */ -#if !defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC) -/* Too many defines to check explicitly - prototype it and always include - * for RSA and DH. */ -WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local); - -/* Make a random number generator or get global if possible. - * - * Global may not be available and NULL will be returned. - * - * @param [in, out] rng Local random number generator. - * @param [out] local Local random number generator returned. - * @return NULL on failure. - * @return A random number generator object. - */ -WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local) -{ - WC_RNG* ret = NULL; - - /* Assume not local until one created. */ - *local = 0; - -#ifdef WOLFSSL_SMALL_STACK - /* Allocate RNG object . */ - rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); -#endif - /* Check we have a local RNG object and initialize. */ - if ((rng != NULL) && (wc_InitRng(rng) == 0)) { - ret = rng; - *local = 1; - } - if (ret == NULL) { - #ifdef HAVE_GLOBAL_RNG - WOLFSSL_MSG("Bad RNG Init, trying global"); - #endif - ret = wolfssl_make_global_rng(); - } - - if (ret != rng) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(rng, NULL, DYNAMIC_TYPE_RNG); -#endif - } - - return ret; -} -#endif - /******************************************************************************* * START OF RSA API ******************************************************************************/ @@ -2464,13 +2417,13 @@ int SetRsaExternal(WOLFSSL_RSA* rsa) RsaKey* key = (RsaKey*)rsa->internal; /* Copy modulus. */ - ret = SetIndividualExternal(&rsa->n, &key->n); + ret = wolfssl_bn_set_value(&rsa->n, &key->n); if (ret != 1) { WOLFSSL_ERROR_MSG("rsa n error"); } if (ret == 1) { /* Copy public exponent. */ - ret = SetIndividualExternal(&rsa->e, &key->e); + ret = wolfssl_bn_set_value(&rsa->e, &key->e); if (ret != 1) { WOLFSSL_ERROR_MSG("rsa e error"); } @@ -2479,21 +2432,21 @@ int SetRsaExternal(WOLFSSL_RSA* rsa) if (key->type == RSA_PRIVATE) { if (ret == 1) { /* Copy private exponent. */ - ret = SetIndividualExternal(&rsa->d, &key->d); + ret = wolfssl_bn_set_value(&rsa->d, &key->d); if (ret != 1) { WOLFSSL_ERROR_MSG("rsa d error"); } } if (ret == 1) { /* Copy first prime. */ - ret = SetIndividualExternal(&rsa->p, &key->p); + ret = wolfssl_bn_set_value(&rsa->p, &key->p); if (ret != 1) { WOLFSSL_ERROR_MSG("rsa p error"); } } if (ret == 1) { /* Copy second prime. */ - ret = SetIndividualExternal(&rsa->q, &key->q); + ret = wolfssl_bn_set_value(&rsa->q, &key->q); if (ret != 1) { WOLFSSL_ERROR_MSG("rsa q error"); } @@ -2501,21 +2454,21 @@ int SetRsaExternal(WOLFSSL_RSA* rsa) #ifndef RSA_LOW_MEM if (ret == 1) { /* Copy d mod p-1. */ - ret = SetIndividualExternal(&rsa->dmp1, &key->dP); + ret = wolfssl_bn_set_value(&rsa->dmp1, &key->dP); if (ret != 1) { WOLFSSL_ERROR_MSG("rsa dP error"); } } if (ret == 1) { /* Copy d mod q-1. */ - ret = SetIndividualExternal(&rsa->dmq1, &key->dQ); + ret = wolfssl_bn_set_value(&rsa->dmq1, &key->dQ); if (ret != 1) { WOLFSSL_ERROR_MSG("rsa dq error"); } } if (ret == 1) { /* Copy 1/q mod p. */ - ret = SetIndividualExternal(&rsa->iqmp, &key->u); + ret = wolfssl_bn_set_value(&rsa->iqmp, &key->u); if (ret != 1) { WOLFSSL_ERROR_MSG("rsa u error"); } @@ -2562,14 +2515,14 @@ int SetRsaInternal(WOLFSSL_RSA* rsa) RsaKey* key = (RsaKey*)rsa->internal; /* Copy down modulus if available. */ - if ((rsa->n != NULL) && (SetIndividualInternal(rsa->n, &key->n) != 1)) { + if ((rsa->n != NULL) && (wolfssl_bn_get_value(rsa->n, &key->n) != 1)) { WOLFSSL_ERROR_MSG("rsa n key error"); ret = -1; } /* Copy down public exponent if available. */ if ((ret == 1) && (rsa->e != NULL) && - (SetIndividualInternal(rsa->e, &key->e) != 1)) { + (wolfssl_bn_get_value(rsa->e, &key->e) != 1)) { WOLFSSL_ERROR_MSG("rsa e key error"); ret = -1; } @@ -2579,7 +2532,7 @@ int SetRsaInternal(WOLFSSL_RSA* rsa) /* Copy down private exponent if available. */ if ((ret == 1) && (rsa->d != NULL)) { - if (SetIndividualInternal(rsa->d, &key->d) != 1) { + if (wolfssl_bn_get_value(rsa->d, &key->d) != 1) { WOLFSSL_ERROR_MSG("rsa d key error"); ret = -1; } @@ -2591,14 +2544,14 @@ int SetRsaInternal(WOLFSSL_RSA* rsa) /* Copy down first prime if available. */ if ((ret == 1) && (rsa->p != NULL) && - (SetIndividualInternal(rsa->p, &key->p) != 1)) { + (wolfssl_bn_get_value(rsa->p, &key->p) != 1)) { WOLFSSL_ERROR_MSG("rsa p key error"); ret = -1; } /* Copy down second prime if available. */ if ((ret == 1) && (rsa->q != NULL) && - (SetIndividualInternal(rsa->q, &key->q) != 1)) { + (wolfssl_bn_get_value(rsa->q, &key->q) != 1)) { WOLFSSL_ERROR_MSG("rsa q key error"); ret = -1; } @@ -2606,21 +2559,21 @@ int SetRsaInternal(WOLFSSL_RSA* rsa) #ifndef RSA_LOW_MEM /* Copy down d mod p-1 if available. */ if ((ret == 1) && (rsa->dmp1 != NULL) && - (SetIndividualInternal(rsa->dmp1, &key->dP) != 1)) { + (wolfssl_bn_get_value(rsa->dmp1, &key->dP) != 1)) { WOLFSSL_ERROR_MSG("rsa dP key error"); ret = -1; } /* Copy down d mod q-1 if available. */ if ((ret == 1) && (rsa->dmp1 != NULL) && - (SetIndividualInternal(rsa->dmq1, &key->dQ) != 1)) { + (wolfssl_bn_get_value(rsa->dmq1, &key->dQ) != 1)) { WOLFSSL_ERROR_MSG("rsa dQ key error"); ret = -1; } /* Copy down 1/q mod p if available. */ if ((ret == 1) && (rsa->iqmp != NULL) && - (SetIndividualInternal(rsa->iqmp, &key->u) != 1)) { + (wolfssl_bn_get_value(rsa->iqmp, &key->u) != 1)) { WOLFSSL_ERROR_MSG("rsa u key error"); ret = -1; } @@ -4752,27 +4705,27 @@ int SetDsaExternal(WOLFSSL_DSA* dsa) key = (DsaKey*)dsa->internal; - if (SetIndividualExternal(&dsa->p, &key->p) != 1) { + if (wolfssl_bn_set_value(&dsa->p, &key->p) != 1) { WOLFSSL_MSG("dsa p key error"); return -1; } - if (SetIndividualExternal(&dsa->q, &key->q) != 1) { + if (wolfssl_bn_set_value(&dsa->q, &key->q) != 1) { WOLFSSL_MSG("dsa q key error"); return -1; } - if (SetIndividualExternal(&dsa->g, &key->g) != 1) { + if (wolfssl_bn_set_value(&dsa->g, &key->g) != 1) { WOLFSSL_MSG("dsa g key error"); return -1; } - if (SetIndividualExternal(&dsa->pub_key, &key->y) != 1) { + if (wolfssl_bn_set_value(&dsa->pub_key, &key->y) != 1) { WOLFSSL_MSG("dsa y key error"); return -1; } - if (SetIndividualExternal(&dsa->priv_key, &key->x) != 1) { + if (wolfssl_bn_set_value(&dsa->priv_key, &key->x) != 1) { WOLFSSL_MSG("dsa x key error"); return -1; } @@ -4798,25 +4751,25 @@ int SetDsaInternal(WOLFSSL_DSA* dsa) key = (DsaKey*)dsa->internal; if (dsa->p != NULL && - SetIndividualInternal(dsa->p, &key->p) != 1) { + wolfssl_bn_get_value(dsa->p, &key->p) != 1) { WOLFSSL_MSG("rsa p key error"); return -1; } if (dsa->q != NULL && - SetIndividualInternal(dsa->q, &key->q) != 1) { + wolfssl_bn_get_value(dsa->q, &key->q) != 1) { WOLFSSL_MSG("rsa q key error"); return -1; } if (dsa->g != NULL && - SetIndividualInternal(dsa->g, &key->g) != 1) { + wolfssl_bn_get_value(dsa->g, &key->g) != 1) { WOLFSSL_MSG("rsa g key error"); return -1; } if (dsa->pub_key != NULL) { - if (SetIndividualInternal(dsa->pub_key, &key->y) != 1) { + if (wolfssl_bn_get_value(dsa->pub_key, &key->y) != 1) { WOLFSSL_MSG("rsa pub_key error"); return -1; } @@ -4826,7 +4779,7 @@ int SetDsaInternal(WOLFSSL_DSA* dsa) } if (dsa->priv_key != NULL) { - if (SetIndividualInternal(dsa->priv_key, &key->x) != 1) { + if (wolfssl_bn_get_value(dsa->priv_key, &key->x) != 1) { WOLFSSL_MSG("rsa priv_key error"); return -1; } @@ -5573,15 +5526,15 @@ WOLFSSL_DSA* wolfSSL_d2i_DSAparams(WOLFSSL_DSA** dsa, const unsigned char** der, err = GetInt(&internalKey->g, *der, &idx, (word32)derLen) != 0; } if (err == 0) { - err = SetIndividualExternal(&ret->p, &internalKey->p) + err = wolfssl_bn_set_value(&ret->p, &internalKey->p) != 1; } if (err == 0) { - err = SetIndividualExternal(&ret->q, &internalKey->q) + err = wolfssl_bn_set_value(&ret->q, &internalKey->q) != 1; } if (err == 0) { - err = SetIndividualExternal(&ret->g, &internalKey->g) + err = wolfssl_bn_set_value(&ret->g, &internalKey->g) != 1; } if (err == 0 && dsa != NULL) { @@ -6097,21 +6050,21 @@ WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x, return NULL; } - if (SetIndividualExternal(&dsa->p, &key->p) != 1) { + if (wolfssl_bn_set_value(&dsa->p, &key->p) != 1) { WOLFSSL_MSG("dsa p key error"); FreeDer(&pDer); wolfSSL_DSA_free(dsa); return NULL; } - if (SetIndividualExternal(&dsa->q, &key->q) != 1) { + if (wolfssl_bn_set_value(&dsa->q, &key->q) != 1) { WOLFSSL_MSG("dsa q key error"); FreeDer(&pDer); wolfSSL_DSA_free(dsa); return NULL; } - if (SetIndividualExternal(&dsa->g, &key->g) != 1) { + if (wolfssl_bn_set_value(&dsa->g, &key->g) != 1) { WOLFSSL_MSG("dsa g key error"); FreeDer(&pDer); wolfSSL_DSA_free(dsa); @@ -6146,26 +6099,26 @@ WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa) key = (DhKey*)dh->internal; if (dsa->p != NULL && - SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) + wolfssl_bn_get_value(((WOLFSSL_DSA*)dsa)->p, &key->p) != 1) { WOLFSSL_MSG("rsa p key error"); wolfSSL_DH_free(dh); return NULL; } if (dsa->g != NULL && - SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) + wolfssl_bn_get_value(((WOLFSSL_DSA*)dsa)->g, &key->g) != 1) { WOLFSSL_MSG("rsa g key error"); wolfSSL_DH_free(dh); return NULL; } - if (SetIndividualExternal(&dh->p, &key->p) != 1) { + if (wolfssl_bn_set_value(&dh->p, &key->p) != 1) { WOLFSSL_MSG("dsa p key error"); wolfSSL_DH_free(dh); return NULL; } - if (SetIndividualExternal(&dh->g, &key->g) != 1) { + if (wolfssl_bn_set_value(&dh->g, &key->g) != 1) { WOLFSSL_MSG("dsa g key error"); wolfSSL_DH_free(dh); return NULL; @@ -7749,21 +7702,21 @@ int SetDhExternal_ex(WOLFSSL_DH *dh, int elm) if ((ret == 1) && (elm & ELEMENT_P)) { /* Set the prime. */ - if (SetIndividualExternal(&dh->p, &key->p) != 1) { + if (wolfssl_bn_set_value(&dh->p, &key->p) != 1) { WOLFSSL_ERROR_MSG("dh param p error"); ret = -1; } } if ((ret == 1) && (elm & ELEMENT_G)) { /* Set the generator. */ - if (SetIndividualExternal(&dh->g, &key->g) != 1) { + if (wolfssl_bn_set_value(&dh->g, &key->g) != 1) { WOLFSSL_ERROR_MSG("dh param g error"); ret = -1; } } if ((ret == 1) && (elm & ELEMENT_Q)) { /* Set the order. */ - if (SetIndividualExternal(&dh->q, &key->q) != 1) { + if (wolfssl_bn_set_value(&dh->q, &key->q) != 1) { WOLFSSL_ERROR_MSG("dh param q error"); ret = -1; } @@ -7771,14 +7724,14 @@ int SetDhExternal_ex(WOLFSSL_DH *dh, int elm) #ifdef WOLFSSL_DH_EXTRA if ((ret == 1) && (elm & ELEMENT_PRV)) { /* Set the private key. */ - if (SetIndividualExternal(&dh->priv_key, &key->priv) != 1) { + if (wolfssl_bn_set_value(&dh->priv_key, &key->priv) != 1) { WOLFSSL_ERROR_MSG("No DH Private Key"); ret = -1; } } if ((ret == 1) && (elm & ELEMENT_PUB)) { /* Set the public key. */ - if (SetIndividualExternal(&dh->pub_key, &key->pub) != 1) { + if (wolfssl_bn_set_value(&dh->pub_key, &key->pub) != 1) { WOLFSSL_ERROR_MSG("No DH Public Key"); ret = -1; } @@ -7839,20 +7792,20 @@ int SetDhInternal(WOLFSSL_DH* dh) } if (ret == 1) { /* Transfer prime. */ - if (SetIndividualInternal(dh->p, &key->p) != 1) { + if (wolfssl_bn_get_value(dh->p, &key->p) != 1) { ret = -1; } } if (ret == 1) { /* Transfer generator. */ - if (SetIndividualInternal(dh->g, &key->g) != 1) { + if (wolfssl_bn_get_value(dh->g, &key->g) != 1) { ret = -1; } } #ifdef HAVE_FFDHE_Q /* Transfer order if available. */ if ((ret == 1) && (dh->q != NULL)) { - if (SetIndividualInternal(dh->q, &key->q) != 1) { + if (wolfssl_bn_get_value(dh->q, &key->q) != 1) { ret = -1; } } @@ -7861,14 +7814,14 @@ int SetDhInternal(WOLFSSL_DH* dh) /* Transfer private key if available. */ if ((ret == 1) && (dh->priv_key != NULL) && (!wolfSSL_BN_is_zero(dh->priv_key))) { - if (SetIndividualInternal(dh->priv_key, &key->priv) != 1) { + if (wolfssl_bn_get_value(dh->priv_key, &key->priv) != 1) { ret = -1; } } /* Transfer public key if available. */ if ((ret == 1) && (dh->pub_key != NULL) && (!wolfSSL_BN_is_zero(dh->pub_key))) { - if (SetIndividualInternal(dh->pub_key, &key->pub) != 1) { + if (wolfssl_bn_get_value(dh->pub_key, &key->pub) != 1) { ret = -1; } } @@ -8100,7 +8053,7 @@ int wolfSSL_DH_set0_key(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *pub_key, wolfSSL_BN_free(dh->pub_key); dh->pub_key = pub_key; #ifdef WOLFSSL_DH_EXTRA - if (SetIndividualInternal(dh->pub_key, &key->pub) != 1) { + if (wolfssl_bn_get_value(dh->pub_key, &key->pub) != 1) { ret = 0; } #endif @@ -8111,7 +8064,7 @@ int wolfSSL_DH_set0_key(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *pub_key, wolfSSL_BN_clear_free(dh->priv_key); dh->priv_key = priv_key; #ifdef WOLFSSL_DH_EXTRA - if (SetIndividualInternal(dh->priv_key, &key->priv) != 1) { + if (wolfssl_bn_get_value(dh->priv_key, &key->priv) != 1) { ret = 0; } #endif @@ -9457,18 +9410,18 @@ static int ec_point_internal_set(WOLFSSL_EC_POINT *p) ecc_point* point = (ecc_point*)p->internal; /* Set X ordinate if available. */ - if ((p->X != NULL) && (SetIndividualInternal(p->X, point->x) != 1)) { + if ((p->X != NULL) && (wolfssl_bn_get_value(p->X, point->x) != 1)) { WOLFSSL_MSG("ecc point X error"); ret = -1; } /* Set Y ordinate if available. */ - if ((ret == 1) && (p->Y != NULL) && (SetIndividualInternal(p->Y, + if ((ret == 1) && (p->Y != NULL) && (wolfssl_bn_get_value(p->Y, point->y) != 1)) { WOLFSSL_MSG("ecc point Y error"); ret = -1; } /* Set Z ordinate if available. */ - if ((ret == 1) && (p->Z != NULL) && (SetIndividualInternal(p->Z, + if ((ret == 1) && (p->Z != NULL) && (wolfssl_bn_get_value(p->Z, point->z) != 1)) { WOLFSSL_MSG("ecc point Z error"); ret = -1; @@ -9504,17 +9457,17 @@ static int ec_point_external_set(WOLFSSL_EC_POINT *p) ecc_point* point = (ecc_point*)p->internal; /* Set X ordinate. */ - if (SetIndividualExternal(&p->X, point->x) != 1) { + if (wolfssl_bn_set_value(&p->X, point->x) != 1) { WOLFSSL_MSG("ecc point X error"); ret = -1; } /* Set Y ordinate. */ - if ((ret == 1) && (SetIndividualExternal(&p->Y, point->y) != 1)) { + if ((ret == 1) && (wolfssl_bn_set_value(&p->Y, point->y) != 1)) { WOLFSSL_MSG("ecc point Y error"); ret = -1; } /* Set Z ordinate. */ - if ((ret == 1) && (SetIndividualExternal(&p->Z, point->z) != 1)) { + if ((ret == 1) && (wolfssl_bn_set_value(&p->Z, point->z) != 1)) { WOLFSSL_MSG("ecc point Z error"); ret = -1; } @@ -12583,7 +12536,7 @@ int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) /* set the external privkey */ if ((ret == 1) && (key->type == ECC_PRIVATEKEY) && - (SetIndividualExternal(&eckey->priv_key, &key->k) != 1)) { + (wolfssl_bn_set_value(&eckey->priv_key, &key->k) != 1)) { WOLFSSL_MSG("ec priv key error"); ret = -1; } @@ -12654,7 +12607,7 @@ int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) /* set privkey */ if ((ret == 1) && (eckey->priv_key != NULL)) { - if (SetIndividualInternal(eckey->priv_key, &key->k) != 1) { + if (wolfssl_bn_get_value(eckey->priv_key, &key->k) != 1) { WOLFSSL_MSG("ec key priv error"); ret = -1; } diff --git a/src/ssl.c b/src/ssl.c index c66243fd8..575fe9979 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -147,8 +147,8 @@ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) #include - int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi); - int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi); + int wolfssl_bn_get_value(WOLFSSL_BIGNUM* bn, mp_int* mpi); + int wolfssl_bn_set_value(WOLFSSL_BIGNUM** bn, mp_int* mpi); #endif #if defined(WOLFSSL_QT) @@ -293,12 +293,8 @@ int wc_OBJ_sn2nid(const char *sn) #ifndef WOLFCRYPT_ONLY -#ifndef OPENSSL_EXTRA_NO_PK -#define WOLFSSL_PK_INCLUDED -#include "src/pk.c" -#endif - -#if !defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC) +#if !defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC) || \ + (defined(OPENSSL_EXTRA) && defined(WOLFSSL_KEY_GEN) && !defined(NO_DSA)) #define HAVE_GLOBAL_RNG /* consolidate flags for using globalRNG */ static WC_RNG globalRNG; @@ -350,6 +346,55 @@ WC_RNG* wolfssl_make_global_rng(void) return ret; } +/* Too many defines to check explicitly - prototype it and always include + * for RSA, DH, ECC and DSA for BN. */ +WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local); + +/* Make a random number generator or get global if possible. + * + * Global may not be available and NULL will be returned. + * + * @param [in, out] rng Local random number generator. + * @param [out] local Local random number generator returned. + * @return NULL on failure. + * @return A random number generator object. + */ +WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local) +{ + WC_RNG* ret = NULL; + + /* Assume not local until one created. */ + *local = 0; + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate RNG object . */ + rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); +#endif + /* Check we have a local RNG object and initialize. */ + if ((rng != NULL) && (wc_InitRng(rng) == 0)) { + ret = rng; + *local = 1; + } + if (ret == NULL) { + #ifdef HAVE_GLOBAL_RNG + WOLFSSL_MSG("Bad RNG Init, trying global"); + #endif + ret = wolfssl_make_global_rng(); + } + + if (ret != rng) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); +#endif + } + + return ret; +} +#endif + +#ifndef OPENSSL_EXTRA_NO_PK +#define WOLFSSL_PK_INCLUDED +#include "src/pk.c" #endif #ifdef OPENSSL_EXTRA @@ -36526,33 +36571,6 @@ int oid2nid(word32 oid, int grp) return -1; } -/* when calling SetIndividualInternal, mpi should be cleared by caller if no - * longer used. ie mp_free(mpi). This is to free data when fastmath is - * disabled since a copy of mpi is made by this function and placed into bn. - */ -int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi) -{ - WOLFSSL_MSG("Entering SetIndividualInternal"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FATAL_ERROR; - } - - if (mpi == NULL) { - WOLFSSL_MSG("mpi NULL error"); - return WOLFSSL_FATAL_ERROR; - } - - if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - return WOLFSSL_FATAL_ERROR; - } - - return WOLFSSL_SUCCESS; -} - - #ifndef NO_ASN WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, WOLFSSL_BIGNUM *bn) @@ -36614,7 +36632,7 @@ WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, /* mp_clear needs called because mpi is copied and causes memory leak with * --disable-fastmath */ - ret = SetIndividualExternal(&bn, mpi); + ret = wolfssl_bn_set_value(&bn, mpi); mp_clear(mpi); #ifdef WOLFSSL_SMALL_STACK @@ -36642,1480 +36660,13 @@ void wolfSSL_ERR_remove_state(unsigned long id) } } - -WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void) -{ - static int ctx; /* wolfcrypt doesn't now need ctx */ - - WOLFSSL_MSG("wolfSSL_BN_CTX_new"); - return (WOLFSSL_BN_CTX*)&ctx; - -} - -void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx) -{ - (void)ctx; - WOLFSSL_MSG("wolfSSL_BN_CTX_init"); -} - - -void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx) -{ - (void)ctx; - WOLFSSL_MSG("wolfSSL_BN_CTX_free"); - /* do free since static ctx that does nothing */ -} - -/* WOLFSSL_SUCCESS on ok */ -int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, - const WOLFSSL_BIGNUM* b) -{ - WOLFSSL_MSG("wolfSSL_BN_sub"); - - if (r == NULL || a == NULL || b == NULL) - return 0; - - if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal, - (mp_int*)r->internal) == MP_OKAY) - return WOLFSSL_SUCCESS; - - WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed"); - return 0; -} - -int wolfSSL_BN_mul(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b, - WOLFSSL_BN_CTX *ctx) -{ - int ret = WOLFSSL_SUCCESS; - - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_BN_mul"); - - if (r == NULL || a == NULL || b == NULL || r->internal == NULL || - a->internal == NULL || b->internal == NULL) { - ret = WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS) { - ret = mp_mul((mp_int*)a->internal, (mp_int*)b->internal, - (mp_int*)r->internal); - if (ret == MP_OKAY) { - ret = WOLFSSL_SUCCESS; - } - else { - ret = WOLFSSL_FAILURE; - } - } - - WOLFSSL_LEAVE("wolfSSL_BN_mul", ret); - - return ret; -} - -#ifndef WOLFSSL_SP_MATH -int wolfSSL_BN_div(WOLFSSL_BIGNUM* dv, WOLFSSL_BIGNUM* rem, - const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* d, - WOLFSSL_BN_CTX* ctx) -{ - int ret = WOLFSSL_SUCCESS; - - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_BN_div"); - - if (dv == NULL || rem == NULL || a == NULL || d == NULL || - dv->internal == NULL || rem->internal == NULL || a->internal == NULL || - d->internal == NULL) { - ret = WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS) { - ret = mp_div((mp_int*)a->internal, (mp_int*)d->internal, - (mp_int*)dv->internal, (mp_int*)rem->internal); - if (ret == MP_OKAY) { - ret = WOLFSSL_SUCCESS; - } - else { - ret = WOLFSSL_FAILURE; - } - } - - WOLFSSL_LEAVE("wolfSSL_BN_div", ret); - - return ret; -} -#endif - -#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) /* Needed to get mp_gcd. */ -int wolfSSL_BN_gcd(WOLFSSL_BIGNUM* r, WOLFSSL_BIGNUM* a, WOLFSSL_BIGNUM* b, - WOLFSSL_BN_CTX* ctx) -{ - int ret = WOLFSSL_SUCCESS; - - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_BN_gcd"); - - if (r == NULL || a == NULL || b == NULL || r->internal == NULL || - a->internal == NULL || b->internal == NULL) { - ret = WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS) { - ret = mp_gcd((mp_int*)a->internal, (mp_int*)b->internal, - (mp_int*)r->internal); - if (ret == MP_OKAY) { - ret = WOLFSSL_SUCCESS; - } - else { - ret = WOLFSSL_FAILURE; - } - } - - WOLFSSL_LEAVE("wolfSSL_BN_gcd", ret); - - return ret; -} -#endif /* !NO_RSA && WOLFSSL_KEY_GEN */ - -/* WOLFSSL_SUCCESS on ok */ -int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, - const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c) -{ - (void)c; - WOLFSSL_MSG("wolfSSL_BN_mod"); - - if (r == NULL || a == NULL || b == NULL) - return 0; - - if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal, - (mp_int*)r->internal) == MP_OKAY) - return WOLFSSL_SUCCESS; - - WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed"); - return 0; -} - - -/* r = (a^p) % m */ -int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, - const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) -{ - int ret; - - WOLFSSL_ENTER("wolfSSL_BN_mod_exp"); - - (void) ctx; - if (r == NULL || a == NULL || p == NULL || m == NULL) { - WOLFSSL_MSG("Bad Argument"); - return WOLFSSL_FAILURE; - } - - if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal, - (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) { - return WOLFSSL_SUCCESS; - } - - WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret); - (void)ret; - - return WOLFSSL_FAILURE; -} - -/* r = (a * p) % m */ -int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, - const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) -{ - int ret; - - WOLFSSL_ENTER("wolfSSL_BN_mod_mul"); - - (void) ctx; - if (r == NULL || a == NULL || p == NULL || m == NULL) { - WOLFSSL_MSG("Bad Argument"); - return WOLFSSL_FAILURE; - } - - if ((ret = mp_mulmod((mp_int*)a->internal,(mp_int*)p->internal, - (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) { - return WOLFSSL_SUCCESS; - } - - WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret); - (void)ret; - - return WOLFSSL_FAILURE; -} - -const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) -{ - WOLFSSL_MSG("wolfSSL_BN_value_one"); - - if (bn_one == NULL) { - bn_one = wolfSSL_BN_new(); - if (bn_one) { - if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) { - /* handle error by freeing BN and returning NULL */ - wolfSSL_BN_free(bn_one); - bn_one = NULL; - } - } - } - - return bn_one; -} - -/* return compliant with OpenSSL - * size of BIGNUM in bytes, 0 if error */ -int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_ENTER("wolfSSL_BN_num_bytes"); - - if (bn == NULL || bn->internal == NULL) - return WOLFSSL_FAILURE; - - return mp_unsigned_bin_size((mp_int*)bn->internal); -} - -/* return compliant with OpenSSL - * size of BIGNUM in bits, 0 if error */ -int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_ENTER("wolfSSL_BN_num_bits"); - - if (bn == NULL || bn->internal == NULL) - return WOLFSSL_FAILURE; - - return mp_count_bits((mp_int*)bn->internal); -} - -int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM* bn) -{ - if (bn == NULL) - return WOLFSSL_FAILURE; - - return mp_isneg((mp_int*)bn->internal); -} - -void wolfSSL_BN_zero(WOLFSSL_BIGNUM* bn) -{ - if (bn == NULL || bn->internal == NULL) { - return; - } - - mp_zero((mp_int*)bn->internal); -} - -int wolfSSL_BN_one(WOLFSSL_BIGNUM* bn) -{ - int ret = WOLFSSL_SUCCESS; - - if (bn == NULL || bn->internal == NULL) { - return WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS) { - ret = wolfSSL_BN_set_word(bn, 1); - } - - return ret; -} - -/* return compliant with OpenSSL - * 1 if BIGNUM is zero, 0 else */ -int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_is_zero"); - - if (bn == NULL || bn->internal == NULL) - return WOLFSSL_FAILURE; - - if (mp_iszero((mp_int*)bn->internal) == MP_YES) - return WOLFSSL_SUCCESS; - - return WOLFSSL_FAILURE; -} - -/* return compliant with OpenSSL - * 1 if BIGNUM is one, 0 else */ -int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_is_one"); - - if (bn == NULL || bn->internal == NULL) - return WOLFSSL_FAILURE; - - if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ) - return WOLFSSL_SUCCESS; - - return WOLFSSL_FAILURE; -} - -/* return compliant with OpenSSL - * 1 if BIGNUM is odd, 0 else */ -int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_is_odd"); - - if (bn == NULL || bn->internal == NULL) - return WOLFSSL_FAILURE; - - if (mp_isodd((mp_int*)bn->internal) == MP_YES) - return WOLFSSL_SUCCESS; - - return WOLFSSL_FAILURE; -} - -/* return compliant with OpenSSL - * 1 if BIGNUM is word, 0 else */ -int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) -{ - WOLFSSL_MSG("wolfSSL_BN_is_word"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FAILURE; - } - - if (w <= (WOLFSSL_BN_ULONG)MP_MASK) { - if (mp_isword((mp_int*)bn->internal, (mp_digit)w) == MP_YES) { - return WOLFSSL_SUCCESS; - } - } else { - int ret; - mp_int w_mp; - if (mp_init(&w_mp) != MP_OKAY) - return WOLFSSL_FAILURE; - if (mp_set_int(&w_mp, w) != MP_OKAY) - return WOLFSSL_FAILURE; - ret = mp_cmp((mp_int *)bn->internal, &w_mp); - mp_free(&w_mp); - if (ret == MP_EQ) - return WOLFSSL_SUCCESS; - } - - return WOLFSSL_FAILURE; -} - -/* return compliant with OpenSSL - * -1 if a < b, 0 if a == b and 1 if a > b - */ -int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) -{ - int ret; - - WOLFSSL_MSG("wolfSSL_BN_cmp"); - - if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL) - return WOLFSSL_FATAL_ERROR; - - ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal); - - return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1)); -} - -/* return compliant with OpenSSL - * length of BIGNUM in bytes, -1 if error */ -int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r) -{ - WOLFSSL_MSG("wolfSSL_BN_bn2bin"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("NULL bn error"); - return WOLFSSL_FATAL_ERROR; - } - - if (r == NULL) - return mp_unsigned_bin_size((mp_int*)bn->internal); - - if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) { - WOLFSSL_MSG("mp_to_unsigned_bin error"); - return WOLFSSL_FATAL_ERROR; - } - - return mp_unsigned_bin_size((mp_int*)bn->internal); -} - - -WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len, - WOLFSSL_BIGNUM* ret) -{ - int weOwn = 0; - - WOLFSSL_MSG("wolfSSL_BN_bin2bn"); - - /* if ret is null create a BN */ - if (ret == NULL) { - ret = wolfSSL_BN_new(); - weOwn = 1; - if (ret == NULL) - return NULL; - } - - /* check ret and ret->internal then read in value */ - if (ret && ret->internal) { - if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) { - WOLFSSL_MSG("mp_read_unsigned_bin failure"); - if (weOwn) - wolfSSL_BN_free(ret); - return NULL; - } - } else { - /* This may be overly defensive */ - if (weOwn) - wolfSSL_BN_free(ret); - return NULL; - } - - return ret; -} - -/* return compliant with OpenSSL - * 1 if success, 0 if error */ -#ifndef NO_WOLFSSL_STUB -int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) -{ - (void)bn; - (void)n; - WOLFSSL_ENTER("wolfSSL_BN_mask_bits"); - WOLFSSL_STUB("BN_mask_bits"); - return WOLFSSL_FAILURE; -} -#endif - -/* WOLFSSL_SUCCESS on ok */ -int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) -{ - int ret = WOLFSSL_SUCCESS; - int len = (bits + 7) / 8; - WC_RNG* rng = &globalRNG; - byte* buff = NULL; - - WOLFSSL_ENTER("wolfSSL_BN_rand"); - - if ((bn == NULL || bn->internal == NULL) || bits < 0 || - (bits == 0 && (bottom != 0 || top != -1)) || (bits == 1 && top > 0)) { - WOLFSSL_MSG("Bad argument"); - ret = WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS) { - if (len == 0) { - mp_zero((mp_int*)bn->internal); - } - else { - buff = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (buff == NULL) { - WOLFSSL_MSG("Failed to allocate buffer."); - XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - ret = WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS && initGlobalRNG == 0 && - wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Failed to use global RNG."); - ret = WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS && - wc_RNG_GenerateBlock(rng, buff, len) != 0) { - WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); - ret = WOLFSSL_FAILURE; - } - if (ret == WOLFSSL_SUCCESS && - mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) - != MP_OKAY) { - WOLFSSL_MSG("mp_read_unsigned_bin failed"); - ret = WOLFSSL_FAILURE; - } - if (ret == WOLFSSL_SUCCESS) { - /* Truncate to requested bit length. */ - mp_rshb((mp_int*)bn->internal, 8 - (bits % 8)); - - if (top == 0) { - if (mp_set_bit((mp_int*)bn->internal, bits - 1) - != MP_OKAY) { - WOLFSSL_MSG("Failed to set top bit"); - ret = WOLFSSL_FAILURE; - } - } - else if (top > 0) { - if (mp_set_bit((mp_int*)bn->internal, bits - 1) - != MP_OKAY || - mp_set_bit((mp_int*)bn->internal, bits - 2) - != MP_OKAY) { - WOLFSSL_MSG("Failed to set top 2 bits"); - ret = WOLFSSL_FAILURE; - } - } - } - if (ret == WOLFSSL_SUCCESS && bottom && - mp_set_bit((mp_int*)bn->internal, 0) != MP_OKAY) { - WOLFSSL_MSG("Failed to set 0th bit"); - ret = WOLFSSL_FAILURE; - } - - if (buff != NULL) { - XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } - } - } - - WOLFSSL_LEAVE("wolfSSL_BN_rand", ret); - - return ret; -} - -/** - * N = length of range input var - * Generate N-bit length numbers until generated number is less than range - * @param r Output number - * @param range The upper limit of generated output - * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure - */ -int wolfSSL_BN_rand_range(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *range) -{ - int n; - int iter = 0; - WOLFSSL_MSG("wolfSSL_BN_rand_range"); - - if (r == NULL || range == NULL) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } - - n = wolfSSL_BN_num_bits(range); - - if (n <= 1) { - wolfSSL_BN_zero(r); - } - else { - do { - if (iter >= 100) { - WOLFSSL_MSG("wolfSSL_BN_rand_range too many iterations"); - return WOLFSSL_FAILURE; - } - iter++; - if (wolfSSL_BN_pseudo_rand(r, n, -1, 0) == WOLFSSL_FAILURE) { - WOLFSSL_MSG("wolfSSL_BN_rand error"); - return WOLFSSL_FAILURE; - } - } while(wolfSSL_BN_cmp(r, range) >= 0); - } - return WOLFSSL_SUCCESS; -} - -/* WOLFSSL_SUCCESS on ok - * code is same as wolfSSL_BN_rand except for how top and bottom is handled. - * top -1 then leave most sig bit alone - * top 0 then most sig is set to 1 - * top is 1 then first two most sig bits are 1 - * - * bottom is hot then odd number */ -int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) -{ - int ret = 0; - int len; - int initTmpRng = 0; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRNG = NULL; - byte* buff = NULL; -#else - WC_RNG tmpRNG[1]; - byte buff[1024]; -#endif - - WOLFSSL_ENTER("wolfSSL_BN_pseudo_rand"); - - if (bits <= 0) { - return WOLFSSL_FAILURE; - } - - len = bits / 8; - if (bits % 8) - len++; - - /* has to be a length of at least 1 since we set buf[0] and buf[len-1] */ - if (top == 1 || top == 0 || bottom == 1) { - if (len < 1) { - return WOLFSSL_FAILURE; - } - } - -#ifdef WOLFSSL_SMALL_STACK - buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); - tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (buff == NULL || tmpRNG == NULL) { - XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } -#endif - - if (bn == NULL || bn->internal == NULL) - WOLFSSL_MSG("Bad function arguments"); - else if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else if (initGlobalRNG) - rng = &globalRNG; - - if (rng) { - if (wc_RNG_GenerateBlock(rng, buff, len) != 0) - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); - else { - switch (top) { - case -1: - break; - - case 0: - buff[0] |= 0x80; - break; - - case 1: - buff[0] |= 0x80 | 0x40; - break; - } - - if (bottom == 1) { - buff[len-1] |= 0x01; - } - - if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY) - WOLFSSL_MSG("mp read bin failed"); - else - ret = WOLFSSL_SUCCESS; - } - } - - if (initTmpRng) - wc_FreeRng(tmpRNG); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -/* return code compliant with OpenSSL : - * 1 if bit set, 0 else - */ -int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n) -{ - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FAILURE; - } - - return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n); -} - -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n) -{ - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FAILURE; - } - - if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) { - WOLFSSL_MSG("mp_set_bit error"); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; -} - - -int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n) -{ - int ret = WOLFSSL_FAILURE; -#ifndef WOLFSSL_SMALL_STACK - mp_int tmp[1]; -#else - mp_int* tmp = NULL; -#endif - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - goto end; - } - if (mp_is_bit_set((mp_int*)bn->internal, n)) { -#ifdef WOLFSSL_SMALL_STACK - tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (tmp == NULL) { - goto end; - } -#endif - if (mp_init(tmp) != MP_OKAY) { - goto end; - } - if (mp_set_bit(tmp, n) != MP_OKAY) { - goto cleanup; - } - if (mp_sub((mp_int*)bn->internal, tmp, (mp_int*)bn->internal) != MP_OKAY) { - goto cleanup; - } - } else { - goto end; - } - - ret = WOLFSSL_SUCCESS; -cleanup: - mp_clear(tmp); - -end: -#ifdef WOLFSSL_SMALL_STACK - if (tmp) - XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); -#endif - return ret; -} - - -/* WOLFSSL_SUCCESS on ok */ -/* Note on use: this function expects str to be an even length. It is - * converting pairs of bytes into 8-bit values. As an example, the RSA - * public exponent is commonly 0x010001. To get it to convert, you need - * to pass in the string "010001", it will fail if you use "10001". This - * is an affect of how Base16_Decode() works. - */ -int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) -{ - int ret = 0; - word32 decSz = 1024; -#ifdef WOLFSSL_SMALL_STACK - byte* decoded; -#else - byte decoded[1024]; -#endif - int weOwn = 0; - int strLen; - - WOLFSSL_MSG("wolfSSL_BN_hex2bn"); - -#ifdef WOLFSSL_SMALL_STACK - decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_DER); - if (decoded == NULL) - return ret; -#endif - - if (str == NULL || str[0] == '\0') { - WOLFSSL_MSG("Bad function argument"); - ret = WOLFSSL_FAILURE; - } else { - strLen = (int)XSTRLEN(str); - /* ignore trailing new lines */ - while (str[strLen-1] == '\n' && strLen > 0) strLen--; - - if (Base16_Decode((byte*)str, strLen, decoded, &decSz) < 0) - WOLFSSL_MSG("Bad Base16_Decode error"); - else if (bn == NULL) - ret = decSz; - else { - if (*bn == NULL) { - *bn = wolfSSL_BN_new(); - if (*bn != NULL) { - weOwn = 1; - } - } - - if (*bn == NULL) - WOLFSSL_MSG("BN new failed"); - else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) { - WOLFSSL_MSG("Bad bin2bn error"); - if (weOwn == 1) { - wolfSSL_BN_free(*bn); /* Free new BN */ - } - } - else - ret = WOLFSSL_SUCCESS; - } - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, NULL, DYNAMIC_TYPE_DER); -#endif - - return ret; -} - - -WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_BIGNUM* ret; - - WOLFSSL_MSG("wolfSSL_BN_dup"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return NULL; - } - - ret = wolfSSL_BN_new(); - if (ret == NULL) { - WOLFSSL_MSG("bn new error"); - return NULL; - } - - if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - wolfSSL_BN_free(ret); - return NULL; - } - - ret->neg = bn->neg; - - return ret; -} - - -WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_copy"); - - if (r == NULL || bn == NULL) { - WOLFSSL_MSG("r or bn NULL error"); - return NULL; - } - - if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - return NULL; - } - - r->neg = bn->neg; - - return r; -} - -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, unsigned long w) -{ - WOLFSSL_MSG("wolfSSL_BN_set_word"); - - if (bn == NULL) { - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FAILURE; - } - - if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) { - WOLFSSL_MSG("mp_init_set_int error"); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; -} - -static WOLFSSL_BN_ULONG wolfSSL_BN_get_word_1(mp_int *mp) { -#if DIGIT_BIT >= (SIZEOF_LONG * CHAR_BIT) - return (WOLFSSL_BN_ULONG)mp->dp[0]; -#else - WOLFSSL_BN_ULONG ret = 0UL; - unsigned int digit_i; - - for (digit_i = 0; digit_i < (unsigned int)mp->used; ++digit_i) - ret |= ((WOLFSSL_BN_ULONG)mp->dp[digit_i]) << (DIGIT_BIT * digit_i); - - return ret; -#endif -} - -/* Returns the big number as an unsigned long if possible. - * - * bn big number structure to get value from - * - * Returns value or 0xFFFFFFFFL if bigger than unsigned long. - */ -WOLFSSL_BN_ULONG wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_get_word"); - - if (bn == NULL) { - WOLFSSL_MSG("Invalid argument"); - return 0; - } - - if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) { - WOLFSSL_MSG("bignum is larger than unsigned long"); - return 0xFFFFFFFFL; - } - - return wolfSSL_BN_get_word_1((mp_int*)bn->internal); -} - -/* return code compliant with OpenSSL : - * number length in decimal if success, 0 if error - */ -#ifndef NO_WOLFSSL_STUB -int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) -{ - (void)bn; - (void)str; - - WOLFSSL_MSG("wolfSSL_BN_dec2bn"); - WOLFSSL_STUB("BN_dec2bn"); - return WOLFSSL_FAILURE; -} -#endif - -#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) -char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn) -{ - int len = 0; - char *buf; - - WOLFSSL_MSG("wolfSSL_BN_bn2dec"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return NULL; - } - - if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_DEC, &len) != MP_OKAY) { - WOLFSSL_MSG("mp_radix_size failure"); - return NULL; - } - - buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); - if (buf == NULL) { - WOLFSSL_MSG("BN_bn2dec malloc buffer failure"); - return NULL; - } - - if (mp_todecimal((mp_int*)bn->internal, buf) != MP_OKAY) { - XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); - return NULL; - } - - return buf; -} -#else -char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn) -{ - (void)bn; - - WOLFSSL_MSG("wolfSSL_BN_bn2dec"); - - return NULL; -} -#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ - -/* Internal function for adding/subtracting an unsigned long from a - * WOLFSSL_BIGNUM. To add, pass "sub" as 0. To subtract, pass it as 1. - * Returns 1 (WOLFSSL_SUCCESS) on success and 0 (WOLFSSL_FAILURE) on failure. - */ -static int wolfSSL_BN_add_word_int(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w, - int sub) -{ - int ret = WOLFSSL_SUCCESS; - int rc = 0; -#ifdef WOLFSSL_SMALL_STACK - mp_int *w_mp = (mp_int *)XMALLOC(sizeof(*w_mp), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (w_mp == NULL) - return WOLFSSL_FAILURE; -#else - mp_int w_mp[1]; -#endif - - XMEMSET(w_mp, 0, sizeof(*w_mp)); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - ret = WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS) { - if (w <= (WOLFSSL_BN_ULONG)MP_MASK) { - if (sub == 1) { - rc = mp_sub_d((mp_int*)bn->internal, (mp_digit)w, - (mp_int*)bn->internal); - } - else { - rc = mp_add_d((mp_int*)bn->internal, (mp_digit)w, - (mp_int*)bn->internal); - } - if (rc != MP_OKAY) { - WOLFSSL_MSG("mp_add/sub_d error"); - ret = WOLFSSL_FAILURE; - } - } - else { - if (mp_init(w_mp) != MP_OKAY) { - ret = WOLFSSL_FAILURE; - } - if (ret == WOLFSSL_SUCCESS) { - if (mp_set_int(w_mp, w) != MP_OKAY) { - ret = WOLFSSL_FAILURE; - } - } - if (ret == WOLFSSL_SUCCESS) { - if (sub == 1) { - rc = mp_sub((mp_int *)bn->internal, w_mp, - (mp_int *)bn->internal); - } - else { - rc = mp_add((mp_int *)bn->internal, w_mp, - (mp_int *)bn->internal); - } - if (rc != MP_OKAY) { - WOLFSSL_MSG("mp_add/sub error"); - ret = WOLFSSL_FAILURE; - } - } - } - } - - mp_free(w_mp); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(w_mp, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w) -{ - int ret; - - WOLFSSL_ENTER("wolfSSL_BN_add_word"); - - ret = wolfSSL_BN_add_word_int(bn, w, 0); - - WOLFSSL_LEAVE("wolfSSL_BN_add_word", ret); - - return ret; -} - -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_sub_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) -{ - int ret; - - WOLFSSL_ENTER("wolfSSL_BN_sub_word"); - - ret = wolfSSL_BN_add_word_int(bn, w, 1); - - WOLFSSL_LEAVE("wolfSSL_BN_sub_word", ret); - - return ret; -} - -#ifndef WOLFSSL_SP_MATH -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) -{ - WOLFSSL_MSG("wolfSSL_BN_lshift"); - - if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FAILURE; - } - - if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_mul_2d error"); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; -} - -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) -{ - WOLFSSL_MSG("wolfSSL_BN_rshift"); - - if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FAILURE; - } - - if (mp_div_2d((mp_int*)bn->internal, n, - (mp_int*)r->internal, NULL) != MP_OKAY) { - WOLFSSL_MSG("mp_mul_2d error"); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; -} -#endif - -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b) -{ - WOLFSSL_MSG("wolfSSL_BN_add"); - - if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL || - b == NULL || b->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FAILURE; - } - - if (mp_add((mp_int*)a->internal, (mp_int*)b->internal, - (mp_int*)r->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_add_d error"); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; -} - -#ifndef WOLFSSL_SP_MATH -/* r = a + b (mod m) */ -int wolfSSL_BN_mod_add(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, - const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m, - WOLFSSL_BN_CTX *ctx) -{ - (void)ctx; - WOLFSSL_MSG("wolfSSL_BN_add"); - - if (r == NULL || r->internal == NULL || - a == NULL || a->internal == NULL || - b == NULL || b->internal == NULL || - m == NULL || m->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FAILURE; - } - - if (mp_addmod((mp_int*)a->internal, (mp_int*)b->internal, - (mp_int*)m->internal, (mp_int*)r->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_add_d error"); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; -} -#endif - -#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || !defined(NO_DSA)) - -int wolfSSL_BN_generate_prime_ex(WOLFSSL_BIGNUM* prime, int bits, - int safe, const WOLFSSL_BIGNUM* add, const WOLFSSL_BIGNUM* rem, - WOLFSSL_BN_GENCB* cb) -{ - int ret = WOLFSSL_SUCCESS; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* rng = NULL; -#else - WC_RNG rng[1]; -#endif - - (void)cb; - - WOLFSSL_ENTER("wolfSSL_BN_generate_prime_ex"); - - if (safe == 1 || add != NULL || rem != NULL) { - /* These parameters aren't supported, yet. */ - ret = WOLFSSL_FAILURE; - } - - if (prime == NULL || prime->internal == NULL) { - ret = WOLFSSL_FAILURE; - } - -#ifdef WOLFSSL_SMALL_STACK - if (ret == WOLFSSL_SUCCESS) { - rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (rng == NULL) { - ret = WOLFSSL_FAILURE; - } - } -#endif - if (ret == WOLFSSL_SUCCESS) { - XMEMSET(rng, 0, sizeof(WC_RNG)); - if (wc_InitRng(rng) != 0) { - ret = WOLFSSL_FAILURE; - } - } - - if (ret == WOLFSSL_SUCCESS) { - if (mp_rand_prime((mp_int*)prime->internal, (bits + 7) / 8, rng, NULL) - != MP_OKAY) { - ret = WOLFSSL_FAILURE; - } - } - - wc_FreeRng(rng); -#ifdef WOLFSSL_SMALL_STACK - if (rng != NULL) - XFREE(rng, NULL, DYNAMIC_TYPE_RNG); -#endif - - WOLFSSL_LEAVE("wolfSSL_BN_generate_prime_ex", ret); - - return ret; -} - -/* return code compliant with OpenSSL : - * 1 if prime, 0 if not, -1 if error - */ -int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, - WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb) -{ - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRNG = NULL; -#else - WC_RNG tmpRNG[1]; -#endif - int initTmpRng = 0; - int res = MP_NO; - - (void)ctx; - (void)cb; - - WOLFSSL_MSG("wolfSSL_BN_is_prime_ex"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FATAL_ERROR; - } - -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRNG == NULL) - return WOLFSSL_FAILURE; -#endif - if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); - if (initGlobalRNG == 0) { - WOLFSSL_MSG("Global RNG no Init"); - } - else - rng = &globalRNG; - } - - if (rng) { - if (mp_prime_is_prime_ex((mp_int*)bn->internal, - nbchecks, &res, rng) != MP_OKAY) { - WOLFSSL_MSG("mp_prime_is_prime_ex error"); - res = MP_NO; - } - } - - if (initTmpRng) - wc_FreeRng(tmpRNG); -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); -#endif - - if (res != MP_YES) { - WOLFSSL_MSG("mp_prime_is_prime_ex not prime"); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; -} - -/* return code compliant with OpenSSL : - * (bn mod w) if success, -1 if error - */ -WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn, - WOLFSSL_BN_ULONG w) -{ - WOLFSSL_BN_ULONG ret = 0; - - WOLFSSL_MSG("wolfSSL_BN_mod_word"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR; - } - - if (w <= (WOLFSSL_BN_ULONG)MP_MASK) { - mp_digit bn_ret; - if (mp_mod_d((mp_int*)bn->internal, (mp_digit)w, &bn_ret) != MP_OKAY) { - WOLFSSL_MSG("mp_add_d error"); - return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR; - } - ret = (WOLFSSL_BN_ULONG)bn_ret; - } else { - int mp_ret; - mp_int w_mp, r_mp; - if (mp_init(&w_mp) != MP_OKAY) - return (unsigned long)WOLFSSL_FAILURE; - if (mp_init(&r_mp) != MP_OKAY) - return (unsigned long)WOLFSSL_FAILURE; - if (mp_set_int(&w_mp, w) != MP_OKAY) - return (unsigned long)WOLFSSL_FAILURE; - mp_ret = mp_mod((mp_int *)bn->internal, &w_mp, &r_mp); - ret = wolfSSL_BN_get_word_1(&r_mp); - mp_free(&r_mp); - mp_free(&w_mp); - if (mp_ret != MP_OKAY) { - WOLFSSL_MSG("mp_mod error"); - return (WOLFSSL_BN_ULONG)WOLFSSL_FAILURE; - } - } - - return ret; -} -#endif /* WOLFSSL_KEY_GEN && (!NO_RSA || !NO_DH || !NO_DSA) */ - -char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) -{ - int len = 0; - char *buf; - - WOLFSSL_ENTER("wolfSSL_BN_bn2hex"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return NULL; - } - - if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_HEX, &len) != MP_OKAY) { - WOLFSSL_MSG("mp_radix_size failure"); - return NULL; - } - - buf = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); - if (buf == NULL) { - WOLFSSL_MSG("BN_bn2hex malloc buffer failure"); - return NULL; - } - - if (mp_tohex((mp_int*)bn->internal, buf) != MP_OKAY) { - XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); - return NULL; - } - - return buf; -} - -#if !defined(NO_FILESYSTEM) && defined(XFPRINTF) -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn) -{ - char *buf; - int ret; - - WOLFSSL_ENTER("wolfSSL_BN_print_fp"); - - if (fp == XBADFILE || bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return WOLFSSL_FAILURE; - } - - buf = wolfSSL_BN_bn2hex(bn); - if (buf == NULL) { - WOLFSSL_MSG("wolfSSL_BN_bn2hex failure"); - return WOLFSSL_FAILURE; - } - - if (XFPRINTF(fp, "%s", buf) < 0) - ret = WOLFSSL_FAILURE; - else - ret = WOLFSSL_SUCCESS; - - XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); - - return ret; -} -#endif /* !NO_FILESYSTEM && XFPRINTF */ - - -WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx) -{ - /* ctx is not used, return new Bignum */ - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_BN_CTX_get"); - - return wolfSSL_BN_new(); -} - -#ifndef NO_WOLFSSL_STUB -void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx) -{ - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_BN_CTX_start"); - WOLFSSL_STUB("BN_CTX_start"); - WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD"); -} -#endif - - -WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r, - WOLFSSL_BIGNUM *a, - const WOLFSSL_BIGNUM *n, - WOLFSSL_BN_CTX *ctx) -{ - int dynamic = 0; - - /* ctx is not used */ - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_BN_mod_inverse"); - - /* check parameter */ - if (r == NULL) { - r = wolfSSL_BN_new(); - if (r == NULL){ - WOLFSSL_MSG("WolfSSL_BN_new() failed"); - return NULL; - } - dynamic = 1; - } - - if (a == NULL) { - WOLFSSL_MSG("a NULL error"); - if (dynamic == 1) { - wolfSSL_BN_free(r); - } - return NULL; - } - - if (n == NULL) { - WOLFSSL_MSG("n NULL error"); - if (dynamic == 1) { - wolfSSL_BN_free(r); - } - return NULL; - } - - /* Compute inverse of a modulo n and return r */ - if (mp_invmod((mp_int *)a->internal,(mp_int *)n->internal, - (mp_int*)r->internal) == MP_VAL){ - WOLFSSL_MSG("mp_invmod() error"); - if (dynamic == 1) { - wolfSSL_BN_free(r); - } - return NULL; - } - - return r; -} #endif /* OPENSSL_EXTRA */ + +#ifndef OPENSSL_EXTRA_NO_BN +#define WOLFSSL_SSL_BN_INCLUDED +#include "src/ssl_bn.c" +#endif /* OPENSSL_EXTRA_NO_BN */ + #if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && \ !defined(NO_ASN) #ifndef NO_BIO @@ -38514,154 +37065,6 @@ int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp) #endif /* !NO_ASN */ #endif /* OPENSSL_EXTRA */ -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) -/* when calling SetIndividualExternal, mpi should be cleared by caller if no - * longer used. ie mp_free(mpi). This is to free data when fastmath is - * disabled since a copy of mpi is made by this function and placed into bn. - */ -int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) -{ - byte dynamic = 0; - -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_MSG("Entering SetIndividualExternal"); -#endif - - if (mpi == NULL || bn == NULL) { - WOLFSSL_MSG("mpi NULL error"); - return WOLFSSL_FATAL_ERROR; - } - - if (*bn == NULL) { - *bn = wolfSSL_BN_new(); - if (*bn == NULL) { - WOLFSSL_MSG("SetIndividualExternal alloc failed"); - return WOLFSSL_FATAL_ERROR; - } - dynamic = 1; - } - - if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - if (dynamic == 1) { - wolfSSL_BN_free(*bn); - } - return WOLFSSL_FATAL_ERROR; - } - - return WOLFSSL_SUCCESS; -} - - -static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn) -{ - if (bn) - XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM)); -} - - -WOLFSSL_BIGNUM* wolfSSL_BN_new(void) -{ - WOLFSSL_BIGNUM* external; - mp_int* mpi; - -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_MSG("wolfSSL_BN_new"); -#endif - -#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT) - mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (mpi == NULL) { - WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure"); - return NULL; - } -#endif - - external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL, - DYNAMIC_TYPE_BIGINT); - if (external == NULL) { - WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure"); -#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT) - XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); -#endif - return NULL; - } - -#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) - mpi = &external->fp; -#endif - - InitwolfSSL_BigNum(external); - if (mp_init(mpi) != MP_OKAY) { - wolfSSL_BN_free(external); - return NULL; - } - external->internal = mpi; - - return external; -} - - -#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) -/* This function works without BN_free only with TFM */ -void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn) -{ - if(bn == NULL)return; -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_MSG("wolfSSL_BN_init"); -#endif - InitwolfSSL_BigNum(bn); - if (mp_init(&bn->fp) != MP_OKAY) - return; - bn->internal = (void *)&bn->fp; -} -#endif - -void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) -{ -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_MSG("wolfSSL_BN_free"); -#endif - if (bn) { - if (bn->internal) { - mp_int* bni = (mp_int*)bn->internal; - mp_free(bni); -#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT) - XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT); -#endif - bn->internal = NULL; - } - XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT); - /* bn = NULL, don't try to access or double free it */ - } - -} - -void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) -{ -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_MSG("wolfSSL_BN_clear_free"); -#endif - if (bn) { - if (bn->internal) { - mp_int* bni = (mp_int*)bn->internal; - mp_forcezero(bni); - } - wolfSSL_BN_free(bn); - } -} - -void wolfSSL_BN_clear(WOLFSSL_BIGNUM* bn) -{ -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_MSG("wolfSSL_BN_clear"); -#endif - if (bn && bn->internal) { - mp_forcezero((mp_int*)bn->internal); - } -} -#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - #ifdef OPENSSL_ALL #if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) diff --git a/src/ssl_bn.c b/src/ssl_bn.c new file mode 100644 index 000000000..caea92027 --- /dev/null +++ b/src/ssl_bn.c @@ -0,0 +1,2386 @@ +/* ssl_bn.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + + #include +#ifndef WC_NO_RNG + #include +#endif + +#if !defined(WOLFSSL_SSL_BN_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning ssl_bn.c does not need to be compiled separately from ssl.c + #endif +#else + +/* Check on validity of big number. + * + * Used for parameter validation. + * + * @param [in] bn Big number. + * @return 1 when bn is not NULL and internal representation is not NULL. + * @return 0 otherwise. + */ +#define BN_IS_NULL(bn) (((bn) == NULL) || ((bn)->internal == NULL)) + +/******************************************************************************* + * Constructor/Destructor/Initializer APIs + ******************************************************************************/ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Get the internal representation value into an MP integer. + * + * When calling wolfssl_bn_get_value, mpi should be cleared by caller if no + * longer used. ie mp_free(mpi). This is to free data when fastmath is + * disabled since a copy of mpi is made by this function and placed into bn. + * + * @param [in] bn Big number to copy value from. + * @param [in, out] mpi MP integer to copy into. + * @return 1 on success. + * @return -1 when bn or internal representation of bn is NULL. + * @return -1 when mpi is NULL. + * @return -1 when copy fails. + */ +int wolfssl_bn_get_value(WOLFSSL_BIGNUM* bn, mp_int* mpi) +{ + int ret = 1; + + WOLFSSL_MSG("Entering wolfssl_bn_get_value_mp"); + + /* Validate parameters. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = -1; + } + else if (mpi == NULL) { + WOLFSSL_MSG("mpi NULL error"); + ret = -1; + } + + /* Copy the internal representation into MP integer. */ + if ((ret == 1) && mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + ret = -1; + } + + return ret; +} + +/* Set big number internal representation to value in mpi. + * + * Will create a new big number if bn points to NULL. + * + * When calling wolfssl_bn_set_value, mpi should be cleared by caller if no + * longer used. ie mp_free(mpi). This is to free data when fastmath is + * disabled since a copy of mpi is made by this function and placed into bn. + * + * @param [in, out] bn Pointer to big number to have value. + * @param [in] mpi MP integer with value to set. + * @return 1 on success. + * @return -1 when mpi or bn is NULL. + * @return -1 when creating a new big number fails. + * @return -1 when copying MP integer fails. + */ +int wolfssl_bn_set_value(WOLFSSL_BIGNUM** bn, mp_int* mpi) +{ + int ret = 1; + WOLFSSL_BIGNUM* a = NULL; + +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfssl_bn_set_value"); +#endif + + /* Validate parameters. */ + if ((bn == NULL) || (mpi == NULL)) { + WOLFSSL_MSG("mpi or bn NULL error"); + ret = -1; + } + + /* Allocate a new big number if one not passed in. */ + if ((ret == 1) && (*bn == NULL)) { + a = wolfSSL_BN_new(); + if (a == NULL) { + WOLFSSL_MSG("wolfssl_bn_set_value alloc failed"); + ret = -1; + } + *bn = a; + } + + /* Copy MP integer value into internal representation of big number. */ + if ((ret == 1) && (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY)) { + WOLFSSL_MSG("mp_copy error"); + ret = -1; + } + + /* Dispose of any allocated big number on error. */ + if ((ret == -1) && (a != NULL)) { + BN_free(a); + *bn = NULL; + } + return ret; +} + +/* Initialize a big number. + * + * Assumes bn is not NULL. + * + * @param [in, out] bn Big number to initialize. + */ +static void wolfssl_bn_init(WOLFSSL_BIGNUM* bn) +{ + /* Clear fields of big number. */ + XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM)); + /* Initialization only fails when passed NULL. */ + (void)mp_init(&bn->mpi); + /* Set an internal representation. */ + bn->internal = &bn->mpi; +} + +/* Create a new big number. + * + * @return An allocated and initialized big number on success. + * @return NULL on failure. + */ +WOLFSSL_BIGNUM* wolfSSL_BN_new(void) +{ + WOLFSSL_BIGNUM* bn = NULL; + +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_BN_new"); +#endif + + /* Allocate memory for big number. */ + bn = (WOLFSSL_BIGNUM*)XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL, + DYNAMIC_TYPE_BIGINT); + if (bn == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure"); + } + else { + /* Initialize newly allocated object. */ + wolfssl_bn_init(bn); + } + + return bn; +} + +#if !defined(USE_INTEGER_HEAP_MATH) && !defined(HAVE_WOLF_BIGINT) +/* Initialize a big number. + * + * Call this instead of wolfSSL_BN_new() and wolfSSL_BN_free(). + * + * Do not call this API after wolfSSL_BN_new() or wolfSSL_BN_init(). + * + * @param [in, out] bn Big number to initialize. + */ +void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn) +{ +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_BN_init"); +#endif + + /* Validate parameter. */ + if (bn != NULL) { + /* Initialize big number object. */ + wolfssl_bn_init(bn); + } +} +#endif + +/* Dispose of big number. + * + * bn is unusable after this call. + * + * @param [in, out] bn Big number to free. + */ +void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) +{ +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_BN_free"); +#endif + + /* Validate parameter. */ + if (bn != NULL) { + /* Cleanup any internal representation. */ + if (bn->internal != NULL) { + /* Free MP integer. */ + mp_free(&bn->mpi); + } + /* Dispose of big number object. */ + XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT); + /* bn = NULL, don't try to access or double free it */ + } +} + +/* Zeroize and dispose of big number. + * + * bn is unusable after this call. + * + * @param [in, out] bn Big number to clear and free. + */ +void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) +{ +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_BN_clear_free"); +#endif + + /* Validate parameter. */ + if (bn != NULL) { + /* Check for internal representation. */ + if (bn->internal != NULL) { + /* Zeroize MP integer. */ + mp_forcezero((mp_int*)bn->internal); + } + /* Dispose of big number. */ + wolfSSL_BN_free(bn); + } +} + +/* Zeroize big number. + * + * @param [in, out] bn Big number to clear. + */ +void wolfSSL_BN_clear(WOLFSSL_BIGNUM* bn) +{ +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_BN_clear"); +#endif + + /* Validate parameter. */ + if (!BN_IS_NULL(bn)) { + /* Zeroize MP integer. */ + mp_forcezero((mp_int*)bn->internal); + } +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#ifdef OPENSSL_EXTRA +/* Return a big number with the value of one. + * + * @return A big number with the value one on success. + * @return NULL on failure. + */ +const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) +{ + WOLFSSL_BIGNUM* one; + + WOLFSSL_ENTER("wolfSSL_BN_value_one"); + + /* Get the global object. */ + one = bn_one; + /* Create a new big number if global not set. */ + if ((one == NULL) && ((one = wolfSSL_BN_new()) != NULL)) { + /* Set internal representation to have a value of 1. */ + if (mp_set_int((mp_int*)one->internal, 1) != MP_OKAY) { + /* Dispose of big number on error. */ + wolfSSL_BN_free(one); + one = NULL; + } + else + #ifndef SINGLE_THREADED + /* Ensure global has not been set by another thread. */ + if (bn_one == NULL) + #endif + { + /* Set this big number as the global. */ + bn_one = one; + } + #ifndef SINGLE_THREADED + /* Check if another thread has set the global. */ + if (bn_one != one) { + /* Dispose of this big number and return the global. */ + wolfSSL_BN_free(one); + one = bn_one; + } + #endif + } + + return one; +} + + +/* Create a new big number with the same value as the one passed in. + * + * @param [in] bn Big number to duplicate. + * @return Big number on success. + * @return NULL when bn or internal representation of bn is NULL. + * @return NULL when creating a new big number fails. + * @return NULL when copying the internal representation fails. + */ +WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn) +{ + int err = 0; + WOLFSSL_BIGNUM* ret = NULL; + + WOLFSSL_ENTER("wolfSSL_BN_dup"); + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + err = 1; + } + + /* Create a new big number to return. */ + if ((!err) && ((ret = wolfSSL_BN_new()) == NULL)) { + WOLFSSL_MSG("bn new error"); + err = 1; + } + + if (!err) { + err = (wolfSSL_BN_copy(ret, bn) == NULL); + } + + if (err) { + /* Dispose of dynamically allocated data. */ + wolfSSL_BN_free(ret); + ret = NULL; + } + return ret; +} + +/* Copy value from bn into another r. + * + * @param [in, out] r Big number to copy into. + * @param [in] bn Big number to copy from. + * @return Big number copied into on success. + * @return NULL when r or bn is NULL. + * @return NULL when copying fails. + */ +WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_ENTER("wolfSSL_BN_copy"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(bn)) { + WOLFSSL_MSG("r or bn NULL error"); + r = NULL; + } + + /* Copy the value in. */ + if ((r != NULL) && mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != + MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + r = NULL; + } + + if (r != NULL) { + /* Copy other fields in a big number. */ + r->neg = bn->neg; + } + + return r; +} + + +/******************************************************************************* + * Encode/Decode APIs. + ******************************************************************************/ + +/* Encode the number is a big-endian byte array. + * + * Assumes byte array is large enough to hold encoding when not NULL. + * Use NULL for byte array to get length. + * + * Return compliant with OpenSSL. + * + * @param [in] bn Big number to reduced + * @param [out] r Byte array to encode into. May be NULL. + * @return Length of big number in bytes on success. + * @return -1 when bn is NULL or encoding fails. + */ +int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_bn2bin"); + + /* Validate parameters. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("NULL bn error"); + ret = -1; + } + else { + /* Get the length of the encoding. */ + ret = mp_unsigned_bin_size((mp_int*)bn->internal); + /* Encode if byte array supplied. */ + if ((r != NULL) && (mp_to_unsigned_bin((mp_int*)bn->internal, r) != + MP_OKAY)) { + WOLFSSL_MSG("mp_to_unsigned_bin error"); + ret = -1; + } + } + + return ret; +} + + +/* Return a big number with value of the decoding of the big-endian byte array. + * + * Returns ret when not NULL. + * Allocates a big number when ret is NULL. + * Assumes str is not NULL. + * + * @param [in] data Byte array to decode. + * @param [in] len Number of bytes in byte array. + * @param [in, out] ret Big number to reduced. May be NULL. + * @return A big number on success. + * @return NULL on failure. + */ +WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* data, int len, + WOLFSSL_BIGNUM* ret) +{ + WOLFSSL_BIGNUM* bn = NULL; + + WOLFSSL_ENTER("wolfSSL_BN_bin2bn"); + + /* Validate parameters. */ + if ((data == NULL) || (len < 0)) { + ret = NULL; + } + /* Allocate a new big number when ret is NULL. */ + else if (ret == NULL) { + ret = wolfSSL_BN_new(); + bn = ret; + } + + /* Check ret is usable. */ + if (ret != NULL) { + /* Check internal representation is usable. */ + if (ret->internal == NULL) { + ret = NULL; + } + else { + /* Decode into big number. */ + if (mp_read_unsigned_bin((mp_int*)ret->internal, data, len) != 0) { + WOLFSSL_MSG("mp_read_unsigned_bin failure"); + /* Don't return anything on failure. bn will be freed if set. */ + ret = NULL; + } + else { + /* Don't free bn as we may be returning it. */ + bn = NULL; + } + } + } + + /* Dispose of allocated BN not being returned. */ + wolfSSL_BN_free(bn); + + return ret; +} + +/* Encode the big number value into a string, of the radix, that is allocated. + * + * @param [in] bn Big number to encode. + * @param [in] radix Radix to encode to. + * @return String with encoding on success. + * @return NULL when bn or internal representation of bn is NULL. + * @return NULL on failure. + */ +static char* wolfssl_bn_bn2radix(const WOLFSSL_BIGNUM* bn, int radix) +{ + int err = 0; + int len = 0; + char* str = NULL; + + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + err = 1; + } + + /* Determine length of encoding. */ + if ((!err) && (mp_radix_size((mp_int*)bn->internal, radix, &len) != + MP_OKAY)) { + WOLFSSL_MSG("mp_radix_size failure"); + err = 1; + } + + if (!err) { + /* Allocate string. */ + str = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (str == NULL) { + WOLFSSL_MSG("BN_bn2hex malloc string failure"); + err = 1; + } + } + + /* Encode into string using wolfCrypt. */ + if ((!err) && (mp_toradix((mp_int*)bn->internal, str, radix) != MP_OKAY)) { + err = 1; + } + + if (err) { + /* Dispose of dynamically allocated data. */ + XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL); + /* Don't return freed string. */ + str = NULL; + } + return str; +} + +/* Encode the big number value into hex string that is allocated. + * + * @param [in] bn Big number to encode. + * @return String with encoding on success. + * @return NULL when bn or internal representation of bn is NULL. + * @return NULL on failure. + */ +char* wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) +{ + WOLFSSL_ENTER("wolfSSL_BN_bn2hex"); + return wolfssl_bn_bn2radix(bn, MP_RADIX_HEX); +} + +/* Decode string of a radix into a big number. + * + * If bn is a pointer to NULL, then a new big number is allocated and assigned. + * + * Note on use: this function expects str to be an even length. It is + * converting pairs of bytes into 8-bit values. As an example, the RSA + * public exponent is commonly 0x010001. To get it to convert, you need + * to pass in the string "010001", it will fail if you use "10001". This + * is an affect of how Base16_Decode() works. + * + * @param [in, out] bn Pointer to a big number. May point to NULL. + * @param [in] str Hex string to decode. + * @param [in] radix Radix to decode from. + * @return 1 on success. + * @return 0 when bn or str is NULL or str is zero length. + * @return 0 when creating a new big number fails. + * @return 0 when decoding fails. + */ +static int wolfssl_bn_radix2bn(WOLFSSL_BIGNUM** bn, const char* str, int radix) +{ + int ret = 1; + WOLFSSL_BIGNUM* a = NULL; + + /* Validate parameters. */ + if ((bn == NULL) || (str == NULL) || (str[0] == '\0')) { + WOLFSSL_MSG("Bad function argument"); + ret = 0; + } + /* Check if we have a big number to decode into. */ + if ((ret == 1) && (*bn == NULL)) { + /* Allocate a new big number. */ + a = wolfSSL_BN_new(); + if (a == NULL) { + WOLFSSL_MSG("BN new failed"); + ret = 0; + } + /* Return allocated big number. */ + *bn = a; + } + /* Decode hex string into internal representation. */ + if ((ret == 1) && (mp_read_radix((mp_int*)(*bn)->internal, str, radix) != + MP_OKAY)) { + WOLFSSL_MSG("Bad read_radix error"); + ret = 0; + } + + if ((ret == 0) && (a != NULL)) { + /* Dispose of big number. */ + wolfSSL_BN_free(a); + /* Don't return freed big number. */ + *bn = NULL; + } + return ret; +} + +/* Decode hex string into a big number. + * + * If bn is a pointer to NULL, then a new big number is allocated and assigned. + * + * Note on use: this function expects str to be an even length. It is + * converting pairs of bytes into 8-bit values. As an example, the RSA + * public exponent is commonly 0x010001. To get it to convert, you need + * to pass in the string "010001", it will fail if you use "10001". This + * is an affect of how Base16_Decode() works. + * + * @param [in, out] bn Pointer to a big number. May point to NULL. + * @param [in] str Hex string to decode. + * @return 1 on success. + * @return 0 when bn or str is NULL or str is zero length. + * @return 0 when creating a new big number fails. + * @return 0 when decoding fails. + */ +int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) +{ + WOLFSSL_ENTER("wolfSSL_BN_hex2bn"); + return wolfssl_bn_radix2bn(bn, str, MP_RADIX_HEX); +} + +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) +/* Encode big number into decimal string. + * + * @param [in] bn Big number to encode. + * @return String with encoding on success. + * @return NULL when bn or internal representation of bn is NULL. + * @return NULL on failure. + */ +char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn) +{ + WOLFSSL_ENTER("wolfSSL_BN_bn2hex"); + return wolfssl_bn_bn2radix(bn, MP_RADIX_DEC); +} +#else +/* Encode big number into decimal string. + * + * @param [in] bn Big number to encode. + * @return NULL as implementation not available. + */ +char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn) +{ + (void)bn; + WOLFSSL_ENTER("wolfSSL_BN_bn2dec"); + return NULL; +} +#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ + + +#ifndef NO_RSA +/* Decode hex string into a big number. + * + * If bn is a pointer to NULL, then a new big number is allocated and assigned. + * + * Note on use: this function expects str to be an even length. It is + * converting pairs of bytes into 8-bit values. As an example, the RSA + * public exponent is commonly 0x010001. To get it to convert, you need + * to pass in the string "010001", it will fail if you use "10001". This + * is an affect of how Base16_Decode() works. + * + * @param [in, out] bn Pointer to a big number. May point to NULL. + * @param [in] str Hex string to decode. + * @return 1 on success. + * @return 0 when bn or str is NULL or str is zero length. + * @return 0 when creating a new big number fails. + * @return 0 when decoding fails. + */ +int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) +{ + WOLFSSL_ENTER("wolfSSL_BN_bn2dec"); + return wolfssl_bn_radix2bn(bn, str, MP_RADIX_DEC); +} +#else +/* Decode hex string into a big number. + * + * @param [in, out] bn Pointer to a big number. May point to NULL. + * @param [in] str Hex string to decode. + * @return 0 as implementation not available.. + */ +int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) +{ + (void)bn; + (void)str; + WOLFSSL_ENTER("wolfSSL_BN_bn2dec"); + return 0; +} +#endif + +/******************************************************************************* + * Get/Set APIs + ******************************************************************************/ + +/* Calculate the number of bytes need to represent big number. + * + * Return compliant with OpenSSL. + * + * @param [in] bn Big number to use. + * @return Size of BIGNUM in bytes on success. + * @return 0 when bn or internal representation of bn is NULL. + */ +int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_num_bytes"); + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + ret = 0; + } + else { + /* Get size from wolfCrypt. */ + ret = mp_unsigned_bin_size((mp_int*)bn->internal); + } + + return ret; +} + +/* Calculate the number of bits need to represent big number. + * + * Return compliant with OpenSSL. + * + * @param [in] bn Big number to use. + * @return Size of BIGNUM in bits on success. + * @return 0 when bn or internal representation of bn is NULL. + */ +int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_num_bits"); + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + ret = 0; + } + else { + /* Get size from wolfCrypt. */ + ret = mp_count_bits((mp_int*)bn->internal); + } + + return ret; +} + +/* Indicates whether a big number is negative. + * + * @param [in] bn Big number to use. + * @return 1 when number is negative. + * @return 0 when number is positive. + * @return 0 when bn is NULL. + */ +int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM* bn) +{ + int ret; + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + ret = 0; + } + else { + /* Check sign with wolfCrypt. */ + ret = mp_isneg((mp_int*)bn->internal); + } + + return ret; +} + +/* Indicates whether a big number is odd. + * + * Return compliant with OpenSSL. + * + * @param [in] bn Big number to use. + * @return 1 when number is odd. + * @return 0 when number is even. + * @return 0 when bn or internal representation of bn is NULL. + */ +int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_is_odd"); + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + ret = 0; + } + else { + /* wolfCrypt checks whether value is odd. */ + ret = (mp_isodd((mp_int*)bn->internal) == MP_YES); + } + + return ret; +} + +#ifndef NO_WOLFSSL_STUB +/* Mask the lowest n bits. + * + * TODO: mp_mod_2d() + * + * Return compliant with OpenSSL. + * + * @param [in, out] bn Big number to operation on. + * @param [in] n Number of bits. + * @return 0 on failure. + */ +int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) +{ + (void)bn; + (void)n; + WOLFSSL_ENTER("wolfSSL_BN_mask_bits"); + WOLFSSL_STUB("BN_mask_bits"); + return 0; +} +#endif + +/* Set a bit of the value in a big number. + * + * Return code compliant with OpenSSL. + * + * @param [in, out] bn Big number to modify. + * @return 1 on success. + * @return 0 when bn or internal representation of bn is NULL. + * @return 0 when failed to set bit. + */ +int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n) +{ + int ret = 1; + + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + else if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) { + WOLFSSL_MSG("mp_set_bit error"); + ret = 0; + } + + return ret; +} + +/* Clear a bit of the value in a big number. + * + * Return code compliant with OpenSSL. + * + * @param [in] bn Big number to check. + * @param [in] n Inidex of bit to check. + * @return 1 on success. + * @return 0 when bn or internal representation of bn is NULL. + * @return 0 when failed to clear bit. + */ +int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n) +{ + int ret = 1; +#ifndef WOLFSSL_SMALL_STACK + mp_int tmp[1]; +#else + mp_int* tmp = NULL; +#endif + + /* Validate parameters. */ + if (BN_IS_NULL(bn) || (n < 0)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + /* Check if bit is set to clear. */ + if ((ret == 1) && (mp_is_bit_set((mp_int*)bn->internal, n))) { + #ifdef WOLFSSL_SMALL_STACK + /* Allocate a new MP integer to hold bit to clear. */ + tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (tmp == NULL) { + ret = 0; + } + #endif + if (ret == 1) { + /* Reset new MP integer. */ + XMEMSET(tmp, 0, sizeof(mp_int)); + if (mp_init(tmp) != MP_OKAY) { + ret = 0; + } + } + /* Set the bit to clear into temporary MP integer. */ + if ((ret == 1) && (mp_set_bit(tmp, n) != MP_OKAY)) { + ret = 0; + } + /* Clear bit by sutraction. */ + if ((ret == 1) && (mp_sub((mp_int*)bn->internal, tmp, + (mp_int*)bn->internal) != MP_OKAY)) { + ret = 0; + } + + /* Free any dynamic memory in MP integer. */ + mp_clear(tmp); + #ifdef WOLFSSL_SMALL_STACK + /* Dispose of temporary MP integer. */ + XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); + #endif + } + + return ret; +} + +/* Returns whether the bit is set in the value of the big number. + * + * When bn is NULL, returns 0. + * + * Return code compliant with OpenSSL. + * + * @param [in] bn Big number to check. + * @param [in] n Inidex of bit to check. + * @return 1 if bit set. + * @return 0 otherwise. + */ +int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n) +{ + int ret; + + /* Check for big number value. */ + if (BN_IS_NULL(bn) || (n < 0)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + else { + /* Set bit with wolfCrypt. */ + ret = mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n); + } + + return ret; +} + +/* Set the big number to the value 0. + * + * @param [in, out] bn Big number to use. + */ +void wolfSSL_BN_zero(WOLFSSL_BIGNUM* bn) +{ + /* Validate parameter. */ + if (!BN_IS_NULL(bn)) { + /* Set wolfCrypt representation to 0. */ + mp_zero((mp_int*)bn->internal); + } +} + +/* Set the big number to the value 0. + * + * @param [in, out] bn Big number to use. + * @return 1 on success. + * @return 0 when bn or internal representation of bn is NULL. + */ +int wolfSSL_BN_one(WOLFSSL_BIGNUM* bn) +{ + int ret; + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + ret = 0; + } + else { + /* Set to value one. */ + ret = wolfSSL_BN_set_word(bn, 1); + } + + return ret; +} + +/* Get the value of the MP integer as a word. + * + * Assumes the MP integer value will fit in a word. + * + * @param [in] mp MP integer. + * @return Value of MP integer as an unsigned long. + */ +static WOLFSSL_BN_ULONG wolfssl_bn_get_word_1(mp_int *mp) { +#if DIGIT_BIT >= (SIZEOF_LONG * CHAR_BIT) + return (WOLFSSL_BN_ULONG)mp->dp[0]; +#else + WOLFSSL_BN_ULONG ret = 0UL; + unsigned int i; + + for (i = 0; i < (unsigned int)mp->used; ++i) { + ret |= ((WOLFSSL_BN_ULONG)mp->dp[i]) << (DIGIT_BIT * i); + } + + return ret; +#endif +} + +/* Return the value of big number as an unsigned long if possible. + * + * @param [in] bn Big number to get value from. + * @return Value or 0xFFFFFFFFL if bigger than unsigned long. + */ +WOLFSSL_BN_ULONG wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_BN_ULONG ret; + + WOLFSSL_ENTER("wolfSSL_BN_get_word"); + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("Invalid argument"); + ret = 0; + } + /* Check whether big number is to fit in an unsigned long. */ + else if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) { + WOLFSSL_MSG("bignum is larger than unsigned long"); + ret = WOLFSSL_BN_MAX_VAL; + } + else { + /* Get the word from the internal representation. */ + ret = wolfssl_bn_get_word_1((mp_int*)bn->internal); + } + + return ret; +} + +/* Set the big number to the value in the word. + * + * Return code compliant with OpenSSL. + * + * @param [in, out] bn Big number to set. + * @param [in w Word to set. + * @return 1 on success. + * @return 0 when bn is NULL or setting value failed. + */ +int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, unsigned long w) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_BN_set_word"); + + /* Validate parameters. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + + /* Set the word into the internal representation. */ + if ((ret == 1) && (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY)) { + WOLFSSL_MSG("mp_init_set_int error"); + ret = 0; + } + + return ret; +} + +/******************************************************************************* + * Comparison APIs + ******************************************************************************/ + +/* Compares two big numbers. a <=> b + * + * NULL equals NULL + * NULL less than not NULL + * not NULL greater than NULL. + * + * Return compliant with OpenSSL. + * + * @param [in] bn First big number to compare. + * @param [in] bn Second big number to compare. + * @return -1 when a is less than b (a < b). + * @return 0 when a is equal to b (a == b). + * @return 1 when a is greater than b (a > b). + * @return 0 when bn or internal representation of bn is NULL. + */ +int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) +{ + int ret; + int bIsNull; + + WOLFSSL_ENTER("wolfSSL_BN_cmp"); + + /* Must know whether b is NULL. */ + bIsNull = BN_IS_NULL(b); + /* Check whether a is NULL. */ + if (BN_IS_NULL(a)) { + if (bIsNull) { + /* NULL equals NULL. */ + ret = 0; + } + else { + /* NULL less than not NULL. */ + ret = -1; + } + } + else if (bIsNull) { + /* not NULL greater than NULL. */ + ret = 1; + } + else { + /* Compare big numbers with wolfCrypt. */ + ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal); + /* Convert wolfCrypt return value. */ + if (ret == MP_EQ) { + ret = 0; + } + else if (ret == MP_GT) { + ret = 1; + } + else { + ret = -1; + } + } + + return ret; +} + +/* Indicates whether a big number is the value 0. + * + * Return compliant with OpenSSL. + * + * @param [in] bn Big number to use. + * @return 1 when number is zero. + * @return 0 when number is not zero. + * @return 0 when bn or internal representation of bn is NULL. + */ +int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_is_zero"); + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + ret = 0; + } + else { + /* wolfCrypt checks whether value is 0. */ + ret = (mp_iszero((mp_int*)bn->internal) == MP_YES); + } + + return ret; +} + +/* Indicates whether a big number is the value 1. + * + * Return compliant with OpenSSL. + * + * @param [in] bn Big number to use. + * @return 1 when number is one. + * @return 0 when number is not one. + * @return 0 when bn or internal representation of bn is NULL. + */ +int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_is_one"); + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + ret = 0; + } + else { + /* wolfCrypt checks whether value is 1. */ + ret = (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ); + } + + return ret; +} + +/* Indicates whether a big number is the value passed in. + * + * Return compliant with OpenSSL. + * + * @param [in] bn Big number to use. + * @return 1 when big number is the value. + * @return 0 when big number is not the value. + * @return 0 when bn or internal representation of bn is NULL. + */ +int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_is_word"); + + /* Validate parameter. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + else +#if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT) + /* When value is greater than what can be stored in one digit - special + * case. */ + if (w > (WOLFSSL_BN_ULONG)MP_MASK) { + /* TODO: small stack */ + mp_int w_mp; + + /* Create a MP to hold the number. */ + if (mp_init(&w_mp) != MP_OKAY) { + ret = 0; + } + /* Set the value - held in more than one digit. */ + else if (mp_set_int(&w_mp, w) != MP_OKAY) { + ret = 0; + } + else { + /* Compare MP representations. */ + ret = (mp_cmp((mp_int *)bn->internal, &w_mp) == MP_EQ); + mp_free(&w_mp); + } + } + else +#endif + { + /* wolfCrypt checks whether it is the value. */ + ret = (mp_isword((mp_int*)bn->internal, (mp_digit)w) == MP_YES); + } + + return ret; +} + + +/******************************************************************************* + * Word operation APIs. + ******************************************************************************/ + +/* Add/subtract a word to/from a big number. + * + * Internal function for adding/subtracting an unsigned long from a + * WOLFSSL_BIGNUM. To add, pass "sub" as 0. To subtract, pass it as 1. + * + * @param [in, out] bn Big number to operate on. + * @param [in] w Word to operate with. + * @param [in] sub Indicates whether operation to perform is a subtract. + * @return 1 on success. + * @return 0 in failure. + */ +static int wolfssl_bn_add_word_int(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w, + int sub) +{ + int ret = 1; + int rc = 0; +#if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT) +#ifdef WOLFSSL_SMALL_STACK + mp_int* w_mp = NULL; +#else + mp_int w_mp[1]; +#endif /* WOLFSSL_SMALL_STACK */ +#endif + +#if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT) +#ifdef WOLFSSL_SMALL_STACK + /* Allocate temporary MP integer. */ + w_mp = (mp_int*)XMALLOC(sizeof(*w_mp), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (w_mp == NULL) { + ret = 0; + } + else +#endif /* WOLFSSL_SMALL_STACK */ + { + /* Clear out MP integer so it can be freed. */ + XMEMSET(w_mp, 0, sizeof(*w_mp)); + } +#endif + + /* Validate parameters. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + + if (ret == 1) { +#if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT) + if (w > (WOLFSSL_BN_ULONG)MP_MASK) { + /* Initialize temporary MP integer. */ + if (mp_init(w_mp) != MP_OKAY) { + ret = 0; + } + /* Set value into temporary MP integer. */ + if ((ret == 1) && (mp_set_int(w_mp, w) != MP_OKAY)) { + ret = 0; + } + if (ret == 1) { + if (sub) { + /* Subtract as MP integer. */ + rc = mp_sub((mp_int *)bn->internal, w_mp, + (mp_int *)bn->internal); + } + else { + /* Add as MP integer. */ + rc = mp_add((mp_int *)bn->internal, w_mp, + (mp_int *)bn->internal); + } + if (rc != MP_OKAY) { + WOLFSSL_MSG("mp_add/sub error"); + ret = 0; + } + } + } + else +#endif + { + if (sub) { + /* Subtract word from MP integer. */ + rc = mp_sub_d((mp_int*)bn->internal, (mp_digit)w, + (mp_int*)bn->internal); + } + else { + /* Add word from MP integer. */ + rc = mp_add_d((mp_int*)bn->internal, (mp_digit)w, + (mp_int*)bn->internal); + } + if (rc != MP_OKAY) { + WOLFSSL_MSG("mp_add/sub_d error"); + ret = 0; + } + } + } + +#if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT) + mp_free(w_mp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(w_mp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* WOLFSSL_SMALL_STACK */ +#endif + return ret; +} + +/* Add a word to a big number. + * + * Return code compliant with OpenSSL. + * + * @param [in, out] bn Big number to operate on. + * @param [in] w Word to operate with. + * @return 1 on success. + * @return 0 in failure. + */ +int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_add_word"); + + ret = wolfssl_bn_add_word_int(bn, w, 0); + + WOLFSSL_LEAVE("wolfSSL_BN_add_word", ret); + + return ret; +} + +/* Subtract a word from a big number. + * + * Return code compliant with OpenSSL. + * + * @param [in, out] bn Big number to operate on. + * @param [in] w Word to operate with. + * @return 1 on success. + * @return 0 in failure. + */ +int wolfSSL_BN_sub_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_sub_word"); + + ret = wolfssl_bn_add_word_int(bn, w, 1); + + WOLFSSL_LEAVE("wolfSSL_BN_sub_word", ret); + + return ret; +} + +#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || \ + !defined(NO_DSA)) +/* Calculate bn modulo word w. bn % w + * + * Return code compliant with OpenSSL. + * + * @return Word result on success + * @return -1 on error + */ +WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn, + WOLFSSL_BN_ULONG w) +{ + WOLFSSL_BN_ULONG ret = 0; + + WOLFSSL_ENTER("wolfSSL_BN_mod_word"); + + /* Validate parameters. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = (WOLFSSL_BN_ULONG)-1; + } + +#if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT) + if ((ret == 0) && (w > (WOLFSSL_BN_ULONG)MP_MASK)) { + /* TODO: small stack */ + mp_int w_mp; + mp_int r_mp; + + /* Memset MP integers to be safe to free. */ + XMEMSET(&w_mp, 0, sizeof(w_mp)); + XMEMSET(&r_mp, 0, sizeof(r_mp)); + + /* Initialize MP integer to hold word. */ + if (mp_init(&w_mp) != MP_OKAY) { + ret = (WOLFSSL_BN_ULONG)-1; + } + /* Initialize MP integer to hold result word. */ + if ((ret == 0) && (mp_init(&r_mp) != MP_OKAY)) { + ret = (WOLFSSL_BN_ULONG)-1; + } + /* Set modulus word into MP integer. */ + if ((ret == 0) && (mp_set_int(&w_mp, w) != MP_OKAY)) { + ret = (WOLFSSL_BN_ULONG)-1; + } + /* Calculate modulus result. */ + if ((ret == 0) && (mp_mod((mp_int *)bn->internal, &w_mp, &r_mp) != + MP_OKAY)) { + WOLFSSL_MSG("mp_mod error"); + ret = (WOLFSSL_BN_ULONG)-1; + } + if (ret == 0) { + /* Get modulus result into an unsigned long. */ + ret = wolfssl_bn_get_word_1(&r_mp); + } + + /* Dispose of dynamically allocated data. */ + mp_free(&r_mp); + mp_free(&w_mp); + } + else +#endif + if (ret == 0) { + mp_digit mp_ret; + + /* Calculate modulus result using wolfCrypt. */ + if (mp_mod_d((mp_int*)bn->internal, (mp_digit)w, &mp_ret) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + ret = (WOLFSSL_BN_ULONG)-1; + } + else { + /* Return result. */ + ret = (WOLFSSL_BN_ULONG)mp_ret; + } + } + + return ret; +} +#endif /* WOLFSSL_KEY_GEN && (!NO_RSA || !NO_DH || !NO_DSA) */ + +/******************************************************************************* + * Shift APIs + ******************************************************************************/ + +#ifndef WOLFSSL_SP_MATH +/* Shift the value in bn left by n bits into r. r = bn << n + * + * Return code compliant with OpenSSL. + * + * @return 1 on success. + * @return 0 when r or bn or internal representation is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_BN_lshift"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + else if (n < 0) { + WOLFSSL_MSG("n value error"); + ret = 0; + } + + /* Use wolfCrypt perform operation. */ + if ((ret == 1) && (mp_mul_2d((mp_int*)bn->internal, n, + (mp_int*)r->internal) != MP_OKAY)) { + WOLFSSL_MSG("mp_mul_2d error"); + ret = 0; + } + + return ret; +} + +/* Shift the value in bn right by n bits into r. r = bn >> n + * + * Return code compliant with OpenSSL. + * + * @return 1 on success. + * @return 0 when r or bn or internal representation is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_BN_rshift"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + else if (n < 0) { + WOLFSSL_MSG("n value error"); + ret = 0; + } + + /* Use wolfCrypt perform operation. */ + if ((ret == 1) && (mp_div_2d((mp_int*)bn->internal, n, (mp_int*)r->internal, + NULL) != MP_OKAY)) { + WOLFSSL_MSG("mp_mul_2d error"); + ret = 0; + } + + return ret; +} +#endif + +/******************************************************************************* + * Simple Math APIs + ******************************************************************************/ + +/* Add a to b into r. r = a + b + * + * Return code compliant with OpenSSL. + * + * @param [out] r Big number to put result into. + * @param [in] a Big number to be added to. + * @param [in] b Big number to add with. + * + * @return 1 on success. + * @return 0 when r, a or b or internal representation is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_BN_add"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + + /* Add the internal representations into internal representation. */ + if ((ret == 1) && (mp_add((mp_int*)a->internal, (mp_int*)b->internal, + (mp_int*)r->internal) != MP_OKAY)) { + WOLFSSL_MSG("mp_add_d error"); + ret = 0; + } + + return ret; +} + +/* Subtract a from b into r. r = a - b + * + * @param [out] r Big number to put result into. + * @param [in] a Big number to be subtracted from. + * @param [in] b Big number to subtract with. + * + * @return 1 on success. + * @return 0 when r, a or b is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, + const WOLFSSL_BIGNUM* b) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_BN_sub"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) { + ret = 0; + } + + /* Have wolfCrypt perform operation with internal representations. */ + if ((ret == 1) && (mp_sub((mp_int*)a->internal,(mp_int*)b->internal, + (mp_int*)r->internal) != MP_OKAY)) { + ret = 0; + } + + WOLFSSL_LEAVE("wolfSSL_BN_sub mp_sub", ret); + return ret; +} + +/* Multiply a with b into r. r = a * b + * + * @param [out] r Big number to put result into. + * @param [in] a Big number to be multiplied. + * @param [in] b Big number to multiply with. + * @param [in] ctx BN context object. Unused. + * + * @return 1 on success. + * @return 0 when r, a or b is NULL. + * @return 0 when internal representation of r, a or b is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_mul(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b, + WOLFSSL_BN_CTX *ctx) +{ + int ret = 1; + + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_mul"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) { + ret = 0; + } + + /* Have wolfCrypt perform operation with internal representations. */ + if ((ret == 1) && (mp_mul((mp_int*)a->internal, (mp_int*)b->internal, + (mp_int*)r->internal) != MP_OKAY)) { + ret = 0; + } + + WOLFSSL_LEAVE("wolfSSL_BN_mul", ret); + return ret; +} + +#ifndef WOLFSSL_SP_MATH +/* Divide a by b into dv and put remainder into rem. dv = a / b, rem = a % b + * + * @param [out] dv Big number to put division result into. + * @param [out] rem Big number to put remainder into. + * @param [in] a Big number to be divided. + * @param [in] b Big number to divide with. + * @param [in] ctx BN context object. Unused. + * + * @return 1 on success. + * @return 0 when dv, rem, a or b is NULL. + * @return 0 when internal representation of dv, rem, a or b is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_div(WOLFSSL_BIGNUM* dv, WOLFSSL_BIGNUM* rem, + const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* d, WOLFSSL_BN_CTX* ctx) +{ + int ret = 1; + + /* BN context not needed. */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_div"); + + /* Validate parameters. */ + if (BN_IS_NULL(dv) || BN_IS_NULL(rem) || BN_IS_NULL(a) || BN_IS_NULL(d)) { + ret = 0; + } + + /* Have wolfCrypt perform operation with internal representations. */ + if ((ret == 1) && (mp_div((mp_int*)a->internal, (mp_int*)d->internal, + (mp_int*)dv->internal, (mp_int*)rem->internal) != MP_OKAY)) { + ret = 0; + } + + WOLFSSL_LEAVE("wolfSSL_BN_div", ret); + return ret; +} +#endif + +/* Calculate a mod b into r. r = a % b + * + * @param [out] r Big number to put result into. + * @param [in] a Big number to reduced + * @param [in] b Big number to reduce with. + * @param [in] ctx BN context object. Unused. + * + * @return 1 on success. + * @return 0 when r, a or b is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, + const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c) +{ + int ret = 1; + + (void)c; + + WOLFSSL_ENTER("wolfSSL_BN_mod"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) { + ret = 0; + } + + /* Have wolfCrypt perform operation with internal representations. */ + if ((ret == 1) && (mp_mod((mp_int*)a->internal,(mp_int*)b->internal, + (mp_int*)r->internal) != MP_OKAY)) { + ret = 0; + } + + WOLFSSL_LEAVE("wolfSSL_BN_mod mp_mod", ret); + return ret; +} + +/******************************************************************************* + * Math and Mod APIs + ******************************************************************************/ + +#ifndef WOLFSSL_SP_MATH +/* Add a to b modulo m into r. r = a + b (mod m) + * + * @param [in, out] r Big number to hold result. + * @param [in] a Big number to add to. + * @param [in] b Big number to add with. + * @param [in] m Big number that is the modulus. + * @param [in] ctx BN context. Not used. + * @return 1 on success. + * @return 0 when r, a or b or internal representation is NULL. + * @return 0 on calculation failure. + */ +int wolfSSL_BN_mod_add(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + int ret = 1; + + /* BN context not needed. */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_add"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b) || BN_IS_NULL(m)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + + /* Perfom operation with wolfCrypt. */ + if ((ret == 1) && (mp_addmod((mp_int*)a->internal, (mp_int*)b->internal, + (mp_int*)m->internal, (mp_int*)r->internal) != MP_OKAY)) { + WOLFSSL_MSG("mp_add_d error"); + ret = 0; + } + + return ret; +} +#endif + +/* Calculate a multiplied by b, mod m into r. r = (a * b) % m + * + * @param [out] r Big number to put result into. + * @param [in] a Base as a big number. + * @param [in] b Multiplier as a big number. + * @param [in] m Modulus as a big number. + * @param [in] ctx BN context object. Unused. + * + * @return 1 on success. + * @return 0 when r, a, b or m is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + int ret = 1; + + /* BN context not needed. */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_mod_mul"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b) || BN_IS_NULL(m)) { + WOLFSSL_MSG("Bad Argument"); + ret = 0; + } + + /* Have wolfCrypt perform operation with internal representations. */ + if ((ret == 1) && (mp_mulmod((mp_int*)a->internal, (mp_int*)b->internal, + (mp_int*)m->internal, (mp_int*)r->internal)) != MP_OKAY) { + ret = 0; + } + + WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret); + return ret; +} + + +/* Calculate a to the power of e, mod m into r. r = (a ^ e) % m + * + * @param [out] r Big number to put result into. + * @param [in] a Base as a big number. + * @param [in] e Exponent as a big number. + * @param [in] m Modulus as a big number. + * @param [in] ctx BN context object. Unused. + * + * @return 1 on success. + * @return 0 when r, a, p or m is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *e, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + int ret = 1; + + /* BN context not needed. */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_mod_exp"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(e) || BN_IS_NULL(m)) { + WOLFSSL_MSG("Bad Argument"); + ret = 0; + } + + /* Have wolfCrypt perform operation with internal representations. */ + if ((ret == 1) && (mp_exptmod((mp_int*)a->internal, (mp_int*)e->internal, + (mp_int*)m->internal, (mp_int*)r->internal)) != MP_OKAY) { + ret = 0; + } + + WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret); + return ret; +} + +/* Calculate the modular inverse of a mod m into r. r = a^-1 mod m + * + * A new big number is allocated when r is NULL. + * + * @param [in, out] r Big number to hold result. May be NULL. + * @param [in] a Big number to invert. + * @param [in] m Big number that is the modulus. + * @param [in] ctx BN context. Not used. + * @return Big number holding result on success. + * @return NULL on failure. + */ +WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + int err = 0; + WOLFSSL_BIGNUM* t = NULL; + + /* BN context not needed. */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_mod_inverse"); + + /* Validate parameters. */ + if (BN_IS_NULL(a) || BN_IS_NULL(m) || ((r != NULL) && + (r->internal == NULL))) { + WOLFSSL_MSG("a or n NULL error"); + err = 1; + } + /* Check whether we have a result big number. */ + if ((!err) && (r == NULL)) { + /* Allocate a new big number to hold result and be returned. */ + t = wolfSSL_BN_new(); + if (t == NULL){ + WOLFSSL_MSG("WolfSSL_BN_new() failed"); + err = 1; + } + r = t; + } + + /* Compute inverse of a modulo n and return in r */ + if ((!err) && (mp_invmod((mp_int *)a->internal, (mp_int *)m->internal, + (mp_int*)r->internal) != MP_OKAY)) { + WOLFSSL_MSG("mp_invmod() error"); + err = 1; + } + + if (err) { + wolfSSL_BN_free(t); + r = NULL; + } + return r; +} + +/******************************************************************************* + * Other Math APIs + ******************************************************************************/ + +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) +/* Needed to get mp_gcd. */ +/* Greatest Common Divisor (GCM) of a and b into r. r = GCD(a, b) + * + * @param [out] r Big number to put result into. + * @param [in] a First big number. + * @param [in] b Second big number. + * @param [in] ctx BN context object. Unused. + * + * @return 1 on success. + * @return 0 when r, a or b is NULL. + * @return 0 when internal representation of r, a or b is NULL. + * @return 0 on failure. + */ +int wolfSSL_BN_gcd(WOLFSSL_BIGNUM* r, WOLFSSL_BIGNUM* a, WOLFSSL_BIGNUM* b, + WOLFSSL_BN_CTX* ctx) +{ + int ret = 1; + + /* BN context not needed. */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_gcd"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) { + ret = 0; + } + + /* Have wolfCrypt perform operation with internal representations. */ + if ((ret == 1) && (mp_gcd((mp_int*)a->internal, (mp_int*)b->internal, + (mp_int*)r->internal) != MP_OKAY)) { + ret = 0; + } + + WOLFSSL_LEAVE("wolfSSL_BN_gcd", ret); + return ret; +} +#endif /* !NO_RSA && WOLFSSL_KEY_GEN */ + +/******************************************************************************* + * Random APIs + ******************************************************************************/ + +/* Generates a random number up to bits long. + * + * @param [in, out] bn Big number to generate into. + * @param [in] bits Number of bits in word. + * @param [in] top Whether top bits must be set. + * Valid values: WOLFSSL_BN_RAND_TOP_ANY, + * WOLFSSL_BN_RAND_TOP_ONE, WOLFSSL_BN_RAND_TOP_TWO. + * @param [in] botttom Whether bottom bit must be set. + * Valid values: WOLFSSL_BN_RAND_BOTTOM_ANY, + WOLFSSL_BN_RAND_BOTTOM_ODD. + * @return 1 on success. + * @return 0 when bn is NULL. + * @return 0 when bits is invalid. + * @return 0 when bits and top/bottom are invalid. + * @return 0 when generation fails. + */ +int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) +{ + int ret = 1; + int len = (bits + 7) / 8; + WC_RNG* rng; + + WOLFSSL_ENTER("wolfSSL_BN_rand"); + + /* Validate parameters. */ + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("Bad argument - bn"); + ret = 0; + } + else if (bits < 0) { + WOLFSSL_MSG("Bad argument - bits < 0"); + ret = 0; + } + else if ((bits == 0) && ((bottom != WOLFSSL_BN_RAND_BOTTOM_ANY) || + (top != WOLFSSL_BN_RAND_TOP_ANY))) { + WOLFSSL_MSG("Bad top/bottom - bits == 0"); + ret = 0; + } + else if ((bits == 1) && (top > WOLFSSL_BN_RAND_TOP_ONE)) { + WOLFSSL_MSG("Bad top - bits == 1"); + ret = 0; + } + + /* Handle simple case of zero bits. */ + if ((ret == 1) && (bits == 0)) { + mp_zero((mp_int*)bn->internal); + } + else if (ret == 1) { + byte* buff = NULL; + + /* Get random to global random to generate bits. */ + if ((rng = wolfssl_make_global_rng()) == NULL) { + WOLFSSL_MSG("Failed to use global RNG."); + ret = 0; + } + + /* Allocate buffer to hold generated bits. */ + if ((ret == 1) && ((buff = (byte*)XMALLOC(len, NULL, + DYNAMIC_TYPE_TMP_BUFFER)) == NULL)) { + WOLFSSL_MSG("Failed to allocate buffer."); + ret = 0; + } + /* Generate bytes to cover bits. */ + if ((ret == 1) && wc_RNG_GenerateBlock(rng, buff, len) != 0) { + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + ret = 0; + } + /* Read bytes in to big number. */ + if ((ret == 1) && mp_read_unsigned_bin((mp_int*)bn->internal, buff, len) + != MP_OKAY) { + WOLFSSL_MSG("mp_read_unsigned_bin failed"); + ret = 0; + } + /* Dispose of buffer - no longer needed. */ + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret == 1) { + /* Truncate to requested bit length. */ + mp_rshb((mp_int*)bn->internal, 8 - (bits % 8)); + } + + /* Set top bit when required. */ + if ((ret == 1) && (top >= WOLFSSL_BN_RAND_TOP_ONE) && + (mp_set_bit((mp_int*)bn->internal, bits - 1) != MP_OKAY)) { + WOLFSSL_MSG("Failed to set top bit"); + ret = 0; + } + /* Set second top bit when required. */ + if ((ret == 1) && (top > WOLFSSL_BN_RAND_TOP_ONE) && + (mp_set_bit((mp_int*)bn->internal, bits - 2) != MP_OKAY)) { + WOLFSSL_MSG("Failed to set second top bit"); + ret = 0; + } + /* Set bottom bit when required. */ + if ((ret == 1) && (bottom == WOLFSSL_BN_RAND_BOTTOM_ODD) && + (mp_set_bit((mp_int*)bn->internal, 0) != MP_OKAY)) { + WOLFSSL_MSG("Failed to set 0th bit"); + ret = 0; + } + } + + WOLFSSL_LEAVE("wolfSSL_BN_rand", ret); + + return ret; +} + +/* Generates a pseudo-random number up to bits long. + * + * Implemented using wolfSSL_BN_rand(). + * + * @param [in, out] bn Big number to generate into. + * @param [in] bits Number of bits in word. + * @param [in] top Whether top bits must be set. + * Valid values: WOLFSSL_BN_RAND_TOP_ANY, + * WOLFSSL_BN_RAND_TOP_ONE, WOLFSSL_BN_RAND_TOP_TWO. + * @param [in] botttom Whether bottom bit must be set. + * Valid values: WOLFSSL_BN_RAND_BOTTOM_ANY, + WOLFSSL_BN_RAND_BOTTOM_ODD. + * @return 1 on success. + * @return 0 when bn is NULL. + * @return 0 when bits is invalid. + * @return 0 when bits and top/bottom are invalid. + * @return 0 when generation fails. + */ +int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) +{ + return wolfSSL_BN_rand(bn, bits, top, bottom); +} + +/* Maximum number of trials to attempt at generating a number in range. */ +#define RANGE_MAX_TRIALS 100 + +/* Generate big number to be a value between 0 and range-1. + * + * N = length of range input var + * + * Generate N-bit length numbers until generated number is less than range + * @param [in] r Big number to generate into. + * @param [in] range The upper limit of generated number. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_BN_rand_range(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *range) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_BN_rand_range"); + + /* Validate parameters. */ + if (BN_IS_NULL(r) || BN_IS_NULL(range)) { + WOLFSSL_MSG("Bad parameter"); + ret = 0; + } + + if (ret == 1) { + /* Calculate number of bits in modulus. */ + int n = wolfSSL_BN_num_bits(range); + + if (n <= 1) { + /* Modulus is 0 or 1. */ + wolfSSL_BN_zero(r); + } + else { + int i; + /* Try generating a number in range for a limited number of trials. + */ + for (i = 0; (ret == 1) && (i < RANGE_MAX_TRIALS); i++) { + /* Generate a random number in range. */ + if (wolfSSL_BN_pseudo_rand(r, n, WOLFSSL_BN_RAND_TOP_ANY, + WOLFSSL_BN_RAND_BOTTOM_ANY) == 0) { + WOLFSSL_MSG("wolfSSL_BN_rand error"); + ret = 0; + } + /* Check if in range. */ + else if (wolfSSL_BN_cmp(r, range) < 0) { + break; + } + } + /* Fail if max trial attempts made. */ + if (i >= RANGE_MAX_TRIALS) { + WOLFSSL_MSG("wolfSSL_BN_rand_range too many iterations"); + ret = 0; + } + } + } + + return ret; +} + +/******************************************************************************* + * Prime APIs + ******************************************************************************/ + +#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || \ + !defined(NO_DSA)) + +/* Generate a prime number. + * + * @param [in, out] prime Big number to generate into. + * @param [in] bits Number of bits in generated number. + * @param [in] safe Whether number must be a safe prime. + * @param [in] add Value to add when generating. Not used. + * @param [in] rem Remainder of number modulo add. Not used. + * @param [in] cb Generation callback. Not used. + * @return 1 on success. + * @return 0 when prime is NULL. + * @return 0 when safe required or add or rem is not NULL. + * @return 0 on generation failure. + */ +int wolfSSL_BN_generate_prime_ex(WOLFSSL_BIGNUM* prime, int bits, + int safe, const WOLFSSL_BIGNUM* add, const WOLFSSL_BIGNUM* rem, + WOLFSSL_BN_GENCB* cb) +{ + int ret = 1; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRng = NULL; +#else + WC_RNG tmpRng[1]; +#endif + WC_RNG* rng = NULL; + int localRng = 0; + + /* Callback not used. */ + (void)cb; + + WOLFSSL_ENTER("wolfSSL_BN_generate_prime_ex"); + + /* Check unsupported parameters. */ + if ((safe == 1) || (add != NULL) || (rem != NULL)) { + ret = 0; + } + /* Validate parameters. */ + else if (BN_IS_NULL(prime)) { + ret = 0; + } + + /* Create a new RNG or use global. */ + if ((ret == 1) && ((rng = wolfssl_make_rng(tmpRng, &localRng)) == NULL)) { + ret = 0; + } + + /* Use wolfCrypt to generate a prime. */ + if ((ret == 1) && (mp_rand_prime((mp_int*)prime->internal, (bits + 7) / 8, + rng, NULL) != MP_OKAY)) { + ret = 0; + } + + if (localRng) { + /* Dispose of local RNG that was created. */ + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + #endif + } + + WOLFSSL_LEAVE("wolfSSL_BN_generate_prime_ex", ret); + + return ret; +} + +/* Check whether a big number is prime. + * + * Return code compliant with OpenSSL. + * + * @param [in] bn Big number to check. + * @param [in] checks Number of Miller-Rabin tests to perform. + * @param [in] ctx BN context. Not used. + * @param [in] cb Generation callback. Not used. + * @return 1 when number is prime. + * @return 0 when number is not prime. + * @return -1 when bn is NULL or failure when checking. + */ +int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int checks, + WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb) +{ + int ret = 1; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRng = NULL; +#else + WC_RNG tmpRng[1]; +#endif + int localRng = 0; + int res = MP_NO; + + /* BN context not needed. */ + (void)ctx; + (void)cb; + + WOLFSSL_ENTER("wolfSSL_BN_is_prime_ex"); + + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = -1; + } + + /* Create a new RNG or use global. */ + if ((ret == 1) && ((rng = wolfssl_make_rng(tmpRng, &localRng)) == NULL)) { + ret = -1; + } + + if ((ret == 1) && (mp_prime_is_prime_ex((mp_int*)bn->internal, checks, &res, + rng) != MP_OKAY)) { + WOLFSSL_MSG("mp_prime_is_prime_ex error"); + ret = -1; + } + + if (localRng) { + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + #endif + } + + if ((ret != -1) && (res != MP_YES)) { + WOLFSSL_MSG("mp_prime_is_prime_ex not prime"); + ret = 0; + } + + return ret; +} + +#endif /* WOLFSSL_KEY_GEN && (!NO_RSA || !NO_DH || !NO_DSA) */ + +/******************************************************************************* + * Print APIs + ******************************************************************************/ + +#if !defined(NO_FILESYSTEM) && defined(XFPRINTF) +/* Print big number to file pointer. + * + * Return code compliant with OpenSSL. + * + * @param [in] fp File pointer. + * @param [in] bn Big number to print. + * @return 1 on success. + * @return 0 when fp is a bad file pointer. + * @return 0 when bn is NULL. + * @return 0 when creating hex string fails. + * @return 0 when printing fails. + */ +int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn) +{ + int ret = 1; + char* buf = NULL; + + WOLFSSL_ENTER("wolfSSL_BN_print_fp"); + + /* Validate parameters. */ + if ((fp == XBADFILE) || BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = 0; + } + + /* Create a hex string of big number. */ + if ((ret == 1) && ((buf = wolfSSL_BN_bn2hex(bn)) == NULL)) { + WOLFSSL_MSG("wolfSSL_BN_bn2hex failure"); + ret = 0; + } + + /* Print hex string to file pointer. */ + if ((ret == 1) && (XFPRINTF(fp, "%s", buf) < 0)) { + ret = 0; + } + + /* Dispose of any allocated data. */ + XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); + + return ret; +} +#endif /* !NO_FILESYSTEM && XFPRINTF */ + +/******************************************************************************* + * BN_CTX APIs + ******************************************************************************/ + +/* Allocate and return a new BN context object. + * + * BN context not needed for operations. + * + * @return Pointer to dummy object. + */ +WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void) +{ + /* wolfcrypt doesn't need BN context. */ + static int ctx; + WOLFSSL_ENTER("wolfSSL_BN_CTX_new"); + return (WOLFSSL_BN_CTX*)&ctx; +} + +/* Initialize a BN context object. + * + * BN context not needed for operations. + * + * @param [in] ctx Dummy BN context. + */ +void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx) +{ + (void)ctx; + WOLFSSL_ENTER("wolfSSL_BN_CTX_init"); +} + + +/* Free a BN context object. + * + * BN context not needed for operations. + * + * @param [in] ctx Dummy BN context. + */ +void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx) +{ + (void)ctx; + WOLFSSL_ENTER("wolfSSL_BN_CTX_free"); + /* Don't do anything since using dummy, static BN context. */ +} + +/* Get a big number based on the BN context. + * + * @param [in] ctx BN context. Not used. + * @return Big number on success. + * @return NULL on failure. + */ +WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx) +{ + /* ctx is not used - returning a new big number. */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_CTX_get"); + + /* Return a new big number. */ + return wolfSSL_BN_new(); +} + +#ifndef NO_WOLFSSL_STUB +/* Start stack of temporary big numbers. + * + * Newly allocated big numbers are returned instead of having a stack. + * + * @param [in] ctx BN context. Not used. + */ +void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_CTX_start"); + WOLFSSL_STUB("BN_CTX_start"); + WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD"); +} +#endif + +#endif /* OPENSSL_EXTRA */ + +#endif /* !WOLFSSL_SSL_BN_INCLUDED */ + diff --git a/tests/api.c b/tests/api.c index 4af2e85c2..9d2dcceb6 100644 --- a/tests/api.c +++ b/tests/api.c @@ -36285,6 +36285,37 @@ static int test_X509_STORE_get0_objects(void) return res; } +static int test_wolfSSL_BN_CTX(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) + WOLFSSL_BN_CTX* bn_ctx; + WOLFSSL_BIGNUM* t; + + AssertNotNull(bn_ctx = wolfSSL_BN_CTX_new()); + + /* No implementation. */ + BN_CTX_init(NULL); + + AssertNotNull(t = BN_CTX_get(NULL)); + BN_free(t); + AssertNotNull(t = BN_CTX_get(bn_ctx)); + BN_free(t); + +#ifndef NO_WOLFSSL_STUB + /* No implementation. */ + BN_CTX_start(NULL); + BN_CTX_start(bn_ctx); +#endif + + BN_CTX_free(NULL); + BN_CTX_free(bn_ctx); + + res = TEST_RES_CHECK(1); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ + return res; +} + static int test_wolfSSL_BN(void) { int res = TEST_SKIPPED; @@ -36294,9 +36325,14 @@ static int test_wolfSSL_BN(void) BIGNUM* c; BIGNUM* d; ASN1_INTEGER* ai; + BIGNUM emptyBN; + + /* Setup */ + XMEMSET(&emptyBN, 0, sizeof(emptyBN)); + /* internal not set emptyBN. */ AssertNotNull(b = BN_new()); - AssertNotNull(c = BN_new()); + AssertNotNull(c = BN_dup(b)); AssertNotNull(d = BN_new()); ai = ASN1_INTEGER_new(); @@ -36309,88 +36345,37 @@ static int test_wolfSSL_BN(void) AssertNotNull(a = ASN1_INTEGER_to_BN(ai, NULL)); ASN1_INTEGER_free(ai); + + /* Invalid parameter testing. */ + BN_free(NULL); + AssertNull(BN_dup(NULL)); + AssertNull(BN_dup(&emptyBN)); + + AssertNull(BN_copy(NULL, NULL)); + AssertNull(BN_copy(b, NULL)); + AssertNull(BN_copy(NULL, c)); + AssertNull(BN_copy(b, &emptyBN)); + AssertNull(BN_copy(&emptyBN, c)); + + BN_clear(NULL); + BN_clear(&emptyBN); + + AssertIntEQ(BN_num_bytes(NULL), 0); + AssertIntEQ(BN_num_bytes(&emptyBN), 0); + + AssertIntEQ(BN_num_bits(NULL), 0); + AssertIntEQ(BN_num_bits(&emptyBN), 0); + + AssertIntEQ(BN_is_negative(NULL), 0); + AssertIntEQ(BN_is_negative(&emptyBN), 0); + /* END Invalid Parameters */ + + AssertIntEQ(BN_set_word(a, 3), SSL_SUCCESS); AssertIntEQ(BN_set_word(b, 2), SSL_SUCCESS); AssertIntEQ(BN_set_word(c, 5), SSL_SUCCESS); - /* a + 3 = */ - AssertIntEQ(BN_add_word(NULL, 3), WOLFSSL_FAILURE); - AssertIntEQ(BN_add_word(a, 3), WOLFSSL_SUCCESS); - - /* check result 3 + 3*/ - AssertIntEQ(BN_get_word(a), 6); - /* set a back to 3 */ - AssertIntEQ(BN_set_word(a, 3), SSL_SUCCESS); - - /* a - 3 = */ - AssertIntEQ(BN_sub_word(NULL, 3), WOLFSSL_FAILURE); - AssertIntEQ(BN_sub_word(a, 3), WOLFSSL_SUCCESS); - - /* check result 3 - 3*/ - AssertIntEQ(BN_get_word(a), 0); - /* set a back to 3 */ - AssertIntEQ(BN_set_word(a, 3), SSL_SUCCESS); - - /* a^b mod c = */ - AssertIntEQ(BN_mod_exp(d, NULL, b, c, NULL), WOLFSSL_FAILURE); - AssertIntEQ(BN_mod_exp(d, a, b, c, NULL), WOLFSSL_SUCCESS); - - /* check result 3^2 mod 5 */ - AssertIntEQ(BN_get_word(d), 4); - - /* a*b = */ - AssertIntEQ(BN_mul(d, NULL, b, NULL), WOLFSSL_FAILURE); - AssertIntEQ(BN_mul(d, a, b, NULL), WOLFSSL_SUCCESS); - - /* check result 3*2 */ - AssertIntEQ(BN_get_word(d), 6); - - /* c/b => db + a */ - AssertIntEQ(BN_div(d, NULL, c, b, NULL), WOLFSSL_FAILURE); - AssertIntEQ(BN_div(d, a, c, b, NULL), WOLFSSL_SUCCESS); - - /* check result 5/2 */ - AssertIntEQ(BN_get_word(d), 2); /* check quotient */ - AssertIntEQ(BN_get_word(a), 1); /* check remainder */ - /* set a back to 3 */ - AssertIntEQ(BN_set_word(a, 3), SSL_SUCCESS); - - /* a*b mod c = */ - AssertIntEQ(BN_mod_mul(d, NULL, b, c, NULL), SSL_FAILURE); - AssertIntEQ(BN_mod_mul(d, a, b, c, NULL), SSL_SUCCESS); - - /* check result 3*2 mod 5 */ - AssertIntEQ(BN_get_word(d), 1); - - AssertIntEQ(BN_set_word(a, 16), SSL_SUCCESS); - AssertIntEQ(BN_set_word(b, 24), SSL_SUCCESS); - -#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) - /* gcd of a and b */ - AssertIntEQ(BN_gcd(d, NULL, b, NULL), SSL_FAILURE); - AssertIntEQ(BN_gcd(d, a, b, NULL), SSL_SUCCESS); - - /* check result gcd(16, 24) */ - AssertIntEQ(BN_get_word(d), 8); -#endif /* !NO_RSA && WOLFSSL_KEY_GEN */ - - AssertIntEQ(BN_set_word(a, 1 << 6), SSL_SUCCESS); - AssertIntEQ(BN_rshift(b, a, 6), SSL_SUCCESS); - AssertIntEQ(BN_is_zero(b), 0); - AssertIntEQ(BN_rshift(b, a, 7), SSL_SUCCESS); - AssertIntEQ(BN_is_zero(b), 1); - AssertIntEQ(BN_rshift1(b, a), SSL_SUCCESS); - AssertIntEQ(BN_is_zero(b), 0); - - /* set b back to 2 */ - AssertIntEQ(BN_set_word(b, 2), SSL_SUCCESS); - - { - /* BN_mod_inverse test */ - BIGNUM *r = BN_new(); - BIGNUM *val = BN_mod_inverse(r,b,c,NULL); - AssertIntEQ((int)(BN_get_word(r) & 0x03), 3); - BN_free(val); - } + AssertIntEQ(BN_num_bits(a), 2); + AssertIntEQ(BN_num_bytes(a), 1); #if !defined(WOLFSSL_SP_MATH) && (!defined(WOLFSSL_SP_MATH_ALL) || \ defined(WOLFSSL_SP_INT_NEGATIVE)) @@ -36428,27 +36413,294 @@ static int test_wolfSSL_BN(void) AssertIntEQ(BN_get_word(c), 4); #endif + AssertIntEQ(BN_set_word(a, 3), 1); + AssertIntEQ(BN_set_word(b, 3), 1); + AssertIntEQ(BN_set_word(c, 4), 1); + + /* NULL == NULL, NULL < num, num > NULL */ + AssertIntEQ(BN_cmp(NULL, NULL), 0); + AssertIntEQ(BN_cmp(&emptyBN, &emptyBN), 0); + AssertIntLT(BN_cmp(NULL, b), 0); + AssertIntLT(BN_cmp(&emptyBN, b), 0); + AssertIntGT(BN_cmp(a, NULL), 0); + AssertIntGT(BN_cmp(a, &emptyBN), 0); + + AssertIntEQ(BN_cmp(a, b), 0); + AssertIntLT(BN_cmp(a, c), 0); + AssertIntGT(BN_cmp(c, b), 0); + + AssertIntEQ(BN_print_fp(XBADFILE, NULL), 0); + AssertIntEQ(BN_print_fp(XBADFILE, &emptyBN), 0); + AssertIntEQ(BN_print_fp(stderr, NULL), 0); + AssertIntEQ(BN_print_fp(stderr, &emptyBN), 0); + AssertIntEQ(BN_print_fp(XBADFILE, a), 0); + + AssertIntEQ(BN_print_fp(stderr, a), 1); + + BN_clear(a); + BN_free(a); BN_free(b); BN_free(c); BN_clear_free(d); - /* check that converting NULL and the null string returns an error */ - a = NULL; - AssertIntLE(BN_hex2bn(&a, NULL), 0); - AssertIntLE(BN_hex2bn(&a, ""), 0); - AssertNull(a); + res = TEST_RES_CHECK(1); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ + return res; +} - /* check that getting a string and a bin of the same number are equal, - * and that the comparison works EQ, LT and GT */ - AssertIntGT(BN_hex2bn(&a, "03"), 0); +static int test_wolfSSL_BN_init(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if !defined(USE_INTEGER_HEAP_MATH) && !defined(HAVE_WOLF_BIGINT) + BIGNUM* ap; + BIGNUM bv; + BIGNUM cv; + BIGNUM dv; + + AssertNotNull(ap = BN_new()); + + BN_init(NULL); + XMEMSET(&bv, 0, sizeof(bv)); + AssertNull(BN_dup(&bv)); + + BN_init(&bv); + BN_init(&cv); + BN_init(&dv); + + AssertIntEQ(BN_set_word(ap, 3), SSL_SUCCESS); + AssertIntEQ(BN_set_word(&bv, 2), SSL_SUCCESS); + AssertIntEQ(BN_set_word(&cv, 5), SSL_SUCCESS); + + /* a^b mod c = */ + AssertIntEQ(BN_mod_exp(&dv, NULL, &bv, &cv, NULL), WOLFSSL_FAILURE); + AssertIntEQ(BN_mod_exp(&dv, ap, &bv, &cv, NULL), WOLFSSL_SUCCESS); + + /* check result 3^2 mod 5 */ + AssertIntEQ(BN_get_word(&dv), 4); + + /* a*b mod c = */ + AssertIntEQ(BN_mod_mul(&dv, NULL, &bv, &cv, NULL), SSL_FAILURE); + AssertIntEQ(BN_mod_mul(&dv, ap, &bv, &cv, NULL), SSL_SUCCESS); + + /* check result 3*2 mod 5 */ + AssertIntEQ(BN_get_word(&dv), 1); + + BN_free(ap); + + res = TEST_RES_CHECK(1); +#endif +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ + return res; +} + +static int test_wolfSSL_BN_enc_dec(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) + BIGNUM* a; + BIGNUM* b; + BIGNUM* c = NULL; + BIGNUM emptyBN; + char* str; + const char* emptyStr = ""; + const char* numberStr = "12345"; + const char* badStr = "g12345"; +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) + const char* twoStr = "2"; +#endif + unsigned char binNum[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; + unsigned char outNum[5]; + + /* Setup */ + XMEMSET(&emptyBN, 0, sizeof(emptyBN)); + AssertNotNull(a = BN_new()); AssertNotNull(b = BN_new()); - AssertIntEQ(BN_set_word(b, 3), SSL_SUCCESS); - AssertNotNull(c = BN_new()); - AssertIntEQ(BN_set_word(c, 4), SSL_SUCCESS); + AssertIntEQ(BN_set_word(a, 2), 1); + + /* Invalid parameters */ + AssertIntEQ(BN_bn2bin(NULL, NULL), -1); + AssertIntEQ(BN_bn2bin(&emptyBN, NULL), -1); + AssertIntEQ(BN_bn2bin(NULL, outNum), -1); + AssertIntEQ(BN_bn2bin(&emptyBN, outNum), -1); + AssertNull(BN_bn2hex(NULL)); + AssertNull(BN_bn2hex(&emptyBN)); + AssertNull(BN_bn2dec(NULL)); + AssertNull(BN_bn2dec(&emptyBN)); + + AssertNull(BN_bin2bn(NULL, sizeof(binNum), NULL)); + AssertNull(BN_bin2bn(NULL, sizeof(binNum), a)); + AssertNull(BN_bin2bn(binNum, -1, a)); + AssertNull(BN_bin2bn(binNum, -1, NULL)); + AssertNull(BN_bin2bn(binNum, sizeof(binNum), &emptyBN)); + + AssertIntEQ(BN_hex2bn(NULL, NULL), 0); + AssertIntEQ(BN_hex2bn(NULL, numberStr), 0); + AssertIntEQ(BN_hex2bn(&a, NULL), 0); + AssertIntEQ(BN_hex2bn(&a, emptyStr), 0); + AssertIntEQ(BN_hex2bn(&a, badStr), 0); + AssertIntEQ(BN_hex2bn(&c, badStr), 0); + + AssertIntEQ(BN_dec2bn(NULL, NULL), 0); + AssertIntEQ(BN_dec2bn(NULL, numberStr), 0); + AssertIntEQ(BN_dec2bn(&a, NULL), 0); + AssertIntEQ(BN_dec2bn(&a, emptyStr), 0); + AssertIntEQ(BN_dec2bn(&a, badStr), 0); + AssertIntEQ(BN_dec2bn(&c, badStr), 0); + + AssertIntEQ(BN_set_word(a, 2), 1); + + AssertIntEQ(BN_bn2bin(a, NULL), 1); + AssertIntEQ(BN_bn2bin(a, outNum), 1); + AssertNotNull(BN_bin2bn(outNum, 1, b)); AssertIntEQ(BN_cmp(a, b), 0); - AssertIntLT(BN_cmp(a, c), 0); - AssertIntGT(BN_cmp(c, b), 0); + AssertNotNull(BN_bin2bn(binNum, sizeof(binNum), b)); + AssertIntEQ(BN_cmp(a, b), -1); + + AssertNotNull(str = BN_bn2hex(a)); + AssertNotNull(BN_hex2bn(&b, str)); + AssertIntEQ(BN_cmp(a, b), 0); + AssertNotNull(BN_hex2bn(&b, numberStr)); + AssertIntEQ(BN_cmp(a, b), -1); + XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL); + +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) + AssertNotNull(str = BN_bn2dec(a)); + AssertStrEQ(str, twoStr); + XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL); + +#ifndef NO_RSA + AssertNotNull(str = BN_bn2dec(a)); + AssertNotNull(BN_dec2bn(&b, str)); + AssertIntEQ(BN_cmp(a, b), 0); + AssertNotNull(BN_dec2bn(&b, numberStr)); + AssertIntEQ(BN_cmp(a, b), -1); + XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL); +#else + /* No implementation - fail with good parameters. */ + AssertIntEQ(BN_dec2bn(&a, numberStr), 0); +#endif +#endif + + BN_free(b); + BN_free(a); + + res = TEST_RES_CHECK(1); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ + return res; +} + +static int test_wolfSSL_BN_word(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) + BIGNUM* a; + BIGNUM* b; + BIGNUM* c; + BIGNUM av; + + AssertNotNull(a = BN_new()); + AssertNotNull(b = BN_new()); + AssertNotNull(c = BN_new()); + XMEMSET(&av, 0, sizeof(av)); + + /* Invalid parameter. */ + AssertIntEQ(BN_add_word(NULL, 3), 0); + AssertIntEQ(BN_add_word(&av, 3), 0); + AssertIntEQ(BN_sub_word(NULL, 3), 0); + AssertIntEQ(BN_sub_word(&av, 3), 0); + AssertIntEQ(BN_set_word(NULL, 3), 0); + AssertIntEQ(BN_set_word(&av, 3), 0); + AssertIntEQ(BN_get_word(NULL), 0); + AssertIntEQ(BN_get_word(&av), 0); + AssertIntEQ(BN_is_word(NULL, 3), 0); + AssertIntEQ(BN_is_word(&av, 3), 0); +#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || \ + !defined(NO_DSA)) + AssertIntEQ(BN_mod_word(NULL, 3), -1); + AssertIntEQ(BN_mod_word(&av, 3), -1); +#endif + AssertIntEQ(BN_one(NULL), 0); + AssertIntEQ(BN_one(&av), 0); + BN_zero(NULL); + BN_zero(&av); + AssertIntEQ(BN_is_one(NULL), 0); + AssertIntEQ(BN_is_one(&av), 0); + AssertIntEQ(BN_is_zero(NULL), 0); + AssertIntEQ(BN_is_zero(&av), 0); + + AssertIntEQ(BN_set_word(a, 3), 1); + AssertIntEQ(BN_set_word(b, 2), 1); + AssertIntEQ(BN_set_word(c, 5), 1); + + /* a + 3 = */ + AssertIntEQ(BN_add_word(a, 3), 1); + + /* check result 3 + 3*/ + AssertIntEQ(BN_get_word(a), 6); + AssertIntEQ(BN_is_word(a, 6), 1); + AssertIntEQ(BN_is_word(a, 5), 0); + + /* set a back to 3 */ + AssertIntEQ(BN_set_word(a, 3), 1); + + /* a - 3 = */ + AssertIntEQ(BN_sub_word(a, 3), 1); + + /* check result 3 - 3*/ + AssertIntEQ(BN_get_word(a), 0); + + AssertIntEQ(BN_one(a), 1); + AssertIntEQ(BN_is_word(a, 1), 1); + AssertIntEQ(BN_is_word(a, 0), 0); + AssertIntEQ(BN_is_one(a), 1); + AssertIntEQ(BN_is_zero(a), 0); + BN_zero(a); + AssertIntEQ(BN_is_word(a, 0), 1); + AssertIntEQ(BN_is_word(a, 1), 0); + AssertIntEQ(BN_is_zero(a), 1); + AssertIntEQ(BN_is_one(a), 0); + +#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || \ + !defined(NO_DSA)) + AssertIntEQ(BN_set_word(a, 5), 1); + AssertIntEQ(BN_mod_word(a, 3), 2); + AssertIntEQ(BN_mod_word(a, 0), -1); +#endif + + BN_free(c); + BN_free(b); + BN_free(a); + + res = TEST_RES_CHECK(1); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ + return res; +} + +static int test_wolfSSL_BN_bits(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) + BIGNUM* a; + BIGNUM emptyBN; + + /* Setup */ + XMEMSET(&emptyBN, 0, sizeof(emptyBN)); + AssertNotNull(a = BN_new()); + + /* Invalid parameters. */ + AssertIntEQ(BN_set_bit(NULL, 1), 0); + AssertIntEQ(BN_set_bit(&emptyBN, 1), 0); + AssertIntEQ(BN_set_bit(a, -1), 0); + AssertIntEQ(BN_clear_bit(NULL, 1), 0); + AssertIntEQ(BN_clear_bit(&emptyBN, 1), 0); + AssertIntEQ(BN_clear_bit(a, -1), 0); + AssertIntEQ(BN_is_bit_set(NULL, 1), 0); + AssertIntEQ(BN_is_bit_set(&emptyBN, 1), 0); + AssertIntEQ(BN_is_bit_set(a, -1), 0); + AssertIntEQ(BN_is_odd(NULL), 0); + AssertIntEQ(BN_is_odd(&emptyBN), 0); AssertIntEQ(BN_set_word(a, 0), 1); AssertIntEQ(BN_is_zero(a), 1); @@ -36459,54 +36711,616 @@ static int test_wolfSSL_BN(void) AssertIntEQ(BN_is_bit_set(a, 0x45), 0); AssertIntEQ(BN_is_zero(a), 1); - BN_free(a); - BN_free(b); - BN_free(c); + AssertIntEQ(BN_set_bit(a, 0), 1); + AssertIntEQ(BN_is_odd(a), 1); + AssertIntEQ(BN_clear_bit(a, 0), 1); + AssertIntEQ(BN_is_odd(a), 0); + AssertIntEQ(BN_set_bit(a, 1), 1); + AssertIntEQ(BN_is_odd(a), 0); - #if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) - { - BIGNUM *ap; - BIGNUM bv; - BIGNUM cv; - BIGNUM dv; + AssertIntEQ(BN_set_bit(a, 129), 1); + AssertIntEQ(BN_get_word(a), WOLFSSL_BN_MAX_VAL); - AssertNotNull(ap = BN_new()); - BN_init(&bv); - BN_init(&cv); - BN_init(&dv); - - AssertIntEQ(BN_set_word(ap, 3), SSL_SUCCESS); - AssertIntEQ(BN_set_word(&bv, 2), SSL_SUCCESS); - AssertIntEQ(BN_set_word(&cv, 5), SSL_SUCCESS); - - /* a^b mod c = */ - AssertIntEQ(BN_mod_exp(&dv, NULL, &bv, &cv, NULL), WOLFSSL_FAILURE); - AssertIntEQ(BN_mod_exp(&dv, ap, &bv, &cv, NULL), WOLFSSL_SUCCESS); - - /* check result 3^2 mod 5 */ - AssertIntEQ(BN_get_word(&dv), 4); - - /* a*b mod c = */ - AssertIntEQ(BN_mod_mul(&dv, NULL, &bv, &cv, NULL), SSL_FAILURE); - AssertIntEQ(BN_mod_mul(&dv, ap, &bv, &cv, NULL), SSL_SUCCESS); - - /* check result 3*2 mod 5 */ - AssertIntEQ(BN_get_word(&dv), 1); - - BN_free(ap); - } - #endif - -#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || !defined(NO_DSA)) - AssertNotNull(a = BN_new()); - AssertIntEQ(BN_generate_prime_ex(a, 512, 0, NULL, NULL, NULL), - SSL_SUCCESS); - AssertIntEQ(BN_is_prime_ex(a, 8, NULL, NULL), SSL_SUCCESS); - BN_free(a); +#ifndef NO_WOLFSSL_STUB + AssertIntEQ(BN_mask_bits(a, 1), 0); #endif + BN_free(a); + res = TEST_RES_CHECK(1); - #endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ +#endif + return res; +} + +static int test_wolfSSL_BN_shift(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) + BIGNUM* a; + BIGNUM* b; + BIGNUM emptyBN; + + /* Setup */ + XMEMSET(&emptyBN, 0, sizeof(emptyBN)); + AssertNotNull(a = BN_new()); + AssertNotNull(b = BN_new()); + + /* Invalid parameters. */ + AssertIntEQ(BN_lshift(NULL, NULL, 1), 0); + AssertIntEQ(BN_lshift(&emptyBN, NULL, 1), 0); + AssertIntEQ(BN_lshift(NULL, &emptyBN, 1), 0); + AssertIntEQ(BN_lshift(b, NULL, 1), 0); + AssertIntEQ(BN_lshift(b, &emptyBN, 1), 0); + AssertIntEQ(BN_lshift(NULL, a, 1), 0); + AssertIntEQ(BN_lshift(&emptyBN, a, 1), 0); + AssertIntEQ(BN_lshift(b, a, -1), 0); + + AssertIntEQ(BN_rshift(NULL, NULL, 1), 0); + AssertIntEQ(BN_rshift(&emptyBN, NULL, 1), 0); + AssertIntEQ(BN_rshift(NULL, &emptyBN, 1), 0); + AssertIntEQ(BN_rshift(b, NULL, 1), 0); + AssertIntEQ(BN_rshift(b, &emptyBN, 1), 0); + AssertIntEQ(BN_rshift(NULL, a, 1), 0); + AssertIntEQ(BN_rshift(&emptyBN, a, 1), 0); + AssertIntEQ(BN_rshift(b, a, -1), 0); + + AssertIntEQ(BN_set_word(a, 1), 1); + AssertIntEQ(BN_lshift(b, a, 1), 1); + AssertIntEQ(BN_is_word(b, 2), 1); + AssertIntEQ(BN_lshift(a, a, 1), 1); + AssertIntEQ(BN_is_word(a, 2), 1); + AssertIntEQ(BN_rshift(b, a, 1), 1); + AssertIntEQ(BN_is_word(b, 1), 1); + AssertIntEQ(BN_rshift(a, a, 1), 1); + AssertIntEQ(BN_is_word(a, 1), 1); + + BN_free(b); + BN_free(a); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_BN_math(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) + BIGNUM* a; + BIGNUM* b; + BIGNUM* r; + BIGNUM* rem; + BIGNUM emptyBN; + BN_ULONG val1; + BN_ULONG val2; + + /* Setup */ + XMEMSET(&emptyBN, 0, sizeof(emptyBN)); + AssertNotNull(a = BN_new()); + AssertNotNull(b = BN_new()); + AssertNotNull(r = BN_new()); + AssertNotNull(rem = BN_new()); + + /* Invalid parameters. */ + AssertIntEQ(BN_add(NULL, NULL, NULL), 0); + AssertIntEQ(BN_add(r, NULL, NULL), 0); + AssertIntEQ(BN_add(NULL, a, NULL), 0); + AssertIntEQ(BN_add(NULL, NULL, b), 0); + AssertIntEQ(BN_add(r, a, NULL), 0); + AssertIntEQ(BN_add(r, NULL, b), 0); + AssertIntEQ(BN_add(NULL, a, b), 0); + + AssertIntEQ(BN_add(&emptyBN, &emptyBN, &emptyBN), 0); + AssertIntEQ(BN_add(r, &emptyBN, &emptyBN), 0); + AssertIntEQ(BN_add(&emptyBN, a, &emptyBN), 0); + AssertIntEQ(BN_add(&emptyBN, &emptyBN, b), 0); + AssertIntEQ(BN_add(r, a, &emptyBN), 0); + AssertIntEQ(BN_add(r, &emptyBN, b), 0); + AssertIntEQ(BN_add(&emptyBN, a, b), 0); + + AssertIntEQ(BN_sub(NULL, NULL, NULL), 0); + AssertIntEQ(BN_sub(r, NULL, NULL), 0); + AssertIntEQ(BN_sub(NULL, a, NULL), 0); + AssertIntEQ(BN_sub(NULL, NULL, b), 0); + AssertIntEQ(BN_sub(r, a, NULL), 0); + AssertIntEQ(BN_sub(r, NULL, b), 0); + AssertIntEQ(BN_sub(NULL, a, b), 0); + + AssertIntEQ(BN_sub(&emptyBN, &emptyBN, &emptyBN), 0); + AssertIntEQ(BN_sub(r, &emptyBN, &emptyBN), 0); + AssertIntEQ(BN_sub(&emptyBN, a, &emptyBN), 0); + AssertIntEQ(BN_sub(&emptyBN, &emptyBN, b), 0); + AssertIntEQ(BN_sub(r, a, &emptyBN), 0); + AssertIntEQ(BN_sub(r, &emptyBN, b), 0); + AssertIntEQ(BN_sub(&emptyBN, a, b), 0); + + AssertIntEQ(BN_mul(NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mul(r, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mul(NULL, a, NULL, NULL), 0); + AssertIntEQ(BN_mul(NULL, NULL, b, NULL), 0); + AssertIntEQ(BN_mul(r, a, NULL, NULL), 0); + AssertIntEQ(BN_mul(r, NULL, b, NULL), 0); + AssertIntEQ(BN_mul(NULL, a, b, NULL), 0); + + AssertIntEQ(BN_mul(&emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mul(r, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mul(&emptyBN, a, &emptyBN, NULL), 0); + AssertIntEQ(BN_mul(&emptyBN, &emptyBN, b, NULL), 0); + AssertIntEQ(BN_mul(r, a, &emptyBN, NULL), 0); + AssertIntEQ(BN_mul(r, &emptyBN, b, NULL), 0); + AssertIntEQ(BN_mul(&emptyBN, a, b, NULL), 0); + + AssertIntEQ(BN_div(NULL, NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_div(r, NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_div(NULL, rem, NULL, NULL, NULL), 0); + AssertIntEQ(BN_div(NULL, NULL, a, NULL, NULL), 0); + AssertIntEQ(BN_div(NULL, NULL, NULL, b, NULL), 0); + AssertIntEQ(BN_div(NULL, rem, a, b, NULL), 0); + AssertIntEQ(BN_div(r, NULL, a, b, NULL), 0); + AssertIntEQ(BN_div(r, rem, NULL, b, NULL), 0); + AssertIntEQ(BN_div(r, rem, a, NULL, NULL), 0); + + AssertIntEQ(BN_div(&emptyBN, &emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_div(r, &emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_div(&emptyBN, rem, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_div(&emptyBN, &emptyBN, a, &emptyBN, NULL), 0); + AssertIntEQ(BN_div(&emptyBN, &emptyBN, &emptyBN, b, NULL), 0); + AssertIntEQ(BN_div(&emptyBN, rem, a, b, NULL), 0); + AssertIntEQ(BN_div(r, &emptyBN, a, b, NULL), 0); + AssertIntEQ(BN_div(r, rem, &emptyBN, b, NULL), 0); + AssertIntEQ(BN_div(r, rem, a, &emptyBN, NULL), 0); + + AssertIntEQ(BN_mod(NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod(r, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod(NULL, a, NULL, NULL), 0); + AssertIntEQ(BN_mod(NULL, NULL, b, NULL), 0); + AssertIntEQ(BN_mod(r, a, NULL, NULL), 0); + AssertIntEQ(BN_mod(r, NULL, b, NULL), 0); + AssertIntEQ(BN_mod(NULL, a, b, NULL), 0); + + AssertIntEQ(BN_mod(&emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod(r, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod(&emptyBN, a, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod(&emptyBN, &emptyBN, b, NULL), 0); + AssertIntEQ(BN_mod(r, a, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod(r, &emptyBN, b, NULL), 0); + AssertIntEQ(BN_mod(&emptyBN, a, b, NULL), 0); + /* END Invalid parameters. */ + + val1 = 8; + val2 = 3; + AssertIntEQ(BN_set_word(a, val1), 1); + AssertIntEQ(BN_set_word(b, val2), 1); + AssertIntEQ(BN_add(r, a, b), 1); + AssertIntEQ(BN_is_word(r, val1 + val2), 1); + AssertIntEQ(BN_sub(r, a, b), 1); + AssertIntEQ(BN_is_word(r, val1 - val2), 1); + AssertIntEQ(BN_mul(r, a, b, NULL), 1); + AssertIntEQ(BN_is_word(r, val1 * val2), 1); + AssertIntEQ(BN_div(r, rem, a, b, NULL), 1); + AssertIntEQ(BN_is_word(r, val1 / val2), 1); + AssertIntEQ(BN_is_word(rem, val1 % val2), 1); + AssertIntEQ(BN_mod(r, a, b, NULL), 1); + AssertIntEQ(BN_is_word(r, val1 % val2), 1); + + BN_free(rem); + BN_free(r); + BN_free(b); + BN_free(a); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_BN_math_mod(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) + BIGNUM* a; + BIGNUM* b; + BIGNUM* m; + BIGNUM* r; + BIGNUM* t; + BIGNUM emptyBN; + BN_ULONG val1; + BN_ULONG val2; + BN_ULONG val3; + + /* Setup */ + XMEMSET(&emptyBN, 0, sizeof(emptyBN)); + AssertNotNull(a = BN_new()); + AssertNotNull(b = BN_new()); + AssertNotNull(m = BN_new()); + AssertNotNull(r = BN_new()); + + /* Invalid parameters. */ + AssertIntEQ(BN_mod_add(NULL, NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod_add(r, NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod_add(NULL, a, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod_add(NULL, NULL, b, NULL, NULL), 0); + AssertIntEQ(BN_mod_add(NULL, NULL, NULL, m, NULL), 0); + AssertIntEQ(BN_mod_add(NULL, a, b, m, NULL), 0); + AssertIntEQ(BN_mod_add(r, NULL, b, m, NULL), 0); + AssertIntEQ(BN_mod_add(r, a, NULL, m, NULL), 0); + AssertIntEQ(BN_mod_add(r, a, m, NULL, NULL), 0); + + AssertIntEQ(BN_mod_add(&emptyBN, &emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_add(r, &emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_add(&emptyBN, a, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_add(&emptyBN, &emptyBN, b, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_add(&emptyBN, &emptyBN, &emptyBN, m, NULL), 0); + AssertIntEQ(BN_mod_add(&emptyBN, a, b, m, NULL), 0); + AssertIntEQ(BN_mod_add(r, &emptyBN, b, m, NULL), 0); + AssertIntEQ(BN_mod_add(r, a, &emptyBN, m, NULL), 0); + AssertIntEQ(BN_mod_add(r, a, m, &emptyBN, NULL), 0); + + AssertIntEQ(BN_mod_mul(NULL, NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod_mul(r, NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod_mul(NULL, a, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod_mul(NULL, NULL, b, NULL, NULL), 0); + AssertIntEQ(BN_mod_mul(NULL, NULL, NULL, m, NULL), 0); + AssertIntEQ(BN_mod_mul(NULL, a, b, m, NULL), 0); + AssertIntEQ(BN_mod_mul(r, NULL, b, m, NULL), 0); + AssertIntEQ(BN_mod_mul(r, a, NULL, m, NULL), 0); + AssertIntEQ(BN_mod_mul(r, a, m, NULL, NULL), 0); + + AssertIntEQ(BN_mod_mul(&emptyBN, &emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_mul(r, &emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_mul(&emptyBN, a, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_mul(&emptyBN, &emptyBN, b, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_mul(&emptyBN, &emptyBN, &emptyBN, m, NULL), 0); + AssertIntEQ(BN_mod_mul(&emptyBN, a, b, m, NULL), 0); + AssertIntEQ(BN_mod_mul(r, &emptyBN, b, m, NULL), 0); + AssertIntEQ(BN_mod_mul(r, a, &emptyBN, m, NULL), 0); + AssertIntEQ(BN_mod_mul(r, a, m, &emptyBN, NULL), 0); + + AssertIntEQ(BN_mod_exp(NULL, NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod_exp(r, NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod_exp(NULL, a, NULL, NULL, NULL), 0); + AssertIntEQ(BN_mod_exp(NULL, NULL, b, NULL, NULL), 0); + AssertIntEQ(BN_mod_exp(NULL, NULL, NULL, m, NULL), 0); + AssertIntEQ(BN_mod_exp(NULL, a, b, m, NULL), 0); + AssertIntEQ(BN_mod_exp(r, NULL, b, m, NULL), 0); + AssertIntEQ(BN_mod_exp(r, a, NULL, m, NULL), 0); + AssertIntEQ(BN_mod_exp(r, a, m, NULL, NULL), 0); + + AssertIntEQ(BN_mod_exp(&emptyBN, &emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_exp(r, &emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_exp(&emptyBN, a, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_exp(&emptyBN, &emptyBN, b, &emptyBN, NULL), 0); + AssertIntEQ(BN_mod_exp(&emptyBN, &emptyBN, &emptyBN, m, NULL), 0); + AssertIntEQ(BN_mod_exp(&emptyBN, a, b, m, NULL), 0); + AssertIntEQ(BN_mod_exp(r, &emptyBN, b, m, NULL), 0); + AssertIntEQ(BN_mod_exp(r, a, &emptyBN, m, NULL), 0); + AssertIntEQ(BN_mod_exp(r, a, m, &emptyBN, NULL), 0); + + AssertNull(BN_mod_inverse(r, NULL, NULL, NULL)); + AssertNull(BN_mod_inverse(r, a, NULL, NULL)); + AssertNull(BN_mod_inverse(r, NULL, m, NULL)); + AssertNull(BN_mod_inverse(r, NULL, m, NULL)); + AssertNull(BN_mod_inverse(r, a, NULL, NULL)); + + AssertNull(BN_mod_inverse(&emptyBN, &emptyBN, &emptyBN, NULL)); + AssertNull(BN_mod_inverse(r, &emptyBN, &emptyBN, NULL)); + AssertNull(BN_mod_inverse(&emptyBN, a, &emptyBN, NULL)); + AssertNull(BN_mod_inverse(&emptyBN, &emptyBN, m, NULL)); + AssertNull(BN_mod_inverse(&emptyBN, a, m, NULL)); + AssertNull(BN_mod_inverse(r, &emptyBN, m, NULL)); + AssertNull(BN_mod_inverse(r, a, &emptyBN, NULL)); + /* END Invalid parameters. */ + + val1 = 9; + val2 = 13; + val3 = 5; + AssertIntEQ(BN_set_word(a, val1), 1); + AssertIntEQ(BN_set_word(b, val2), 1); + AssertIntEQ(BN_set_word(m, val3), 1); + AssertIntEQ(BN_mod_add(r, a, b, m, NULL), 1); + AssertIntEQ(BN_is_word(r, (val1 + val2) % val3), 1); + AssertIntEQ(BN_mod_mul(r, a, b, m, NULL), 1); + AssertIntEQ(BN_is_word(r, (val1 * val2) % val3), 1); + + AssertIntEQ(BN_set_word(a, 2), 1); + AssertIntEQ(BN_set_word(b, 3), 1); + AssertIntEQ(BN_set_word(m, 5), 1); + /* (2 ^ 3) % 5 = 8 % 5 = 3 */ + AssertIntEQ(BN_mod_exp(r, a, b, m, NULL), 1); + AssertIntEQ(BN_is_word(r, 3), 1); + + /* (2 * 3) % 5 = 6 % 5 = 1 => inv = 3 */ + AssertNotNull(BN_mod_inverse(r, a, m, NULL)); + AssertIntEQ(BN_is_word(r, 3), 1); + AssertNotNull(t = BN_mod_inverse(NULL, a, m, NULL)); + AssertIntEQ(BN_is_word(t, 3), 1); + BN_free(t); + /* No inverse case. No inverse when a divides b. */ + AssertIntEQ(BN_set_word(a, 3), 1); + AssertIntEQ(BN_set_word(m, 9), 1); + AssertNull(BN_mod_inverse(r, a, m, NULL)); + + BN_free(r); + BN_free(m); + BN_free(b); + BN_free(a); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_BN_math_other(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) + BIGNUM* a; + BIGNUM* b; + BIGNUM* r; + BIGNUM emptyBN; + + /* Setup */ + XMEMSET(&emptyBN, 0, sizeof(emptyBN)); + AssertNotNull(a = BN_new()); + AssertNotNull(b = BN_new()); + AssertNotNull(r = BN_new()); + + /* Invalid parameters. */ + AssertIntEQ(BN_gcd(NULL, NULL, NULL, NULL), 0); + AssertIntEQ(BN_gcd(r, NULL, NULL, NULL), 0); + AssertIntEQ(BN_gcd(NULL, a, NULL, NULL), 0); + AssertIntEQ(BN_gcd(NULL, NULL, b, NULL), 0); + AssertIntEQ(BN_gcd(NULL, a, b, NULL), 0); + AssertIntEQ(BN_gcd(r, NULL, b, NULL), 0); + AssertIntEQ(BN_gcd(r, a, NULL, NULL), 0); + + AssertIntEQ(BN_gcd(&emptyBN, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_gcd(r, &emptyBN, &emptyBN, NULL), 0); + AssertIntEQ(BN_gcd(&emptyBN, a, &emptyBN, NULL), 0); + AssertIntEQ(BN_gcd(&emptyBN, &emptyBN, b, NULL), 0); + AssertIntEQ(BN_gcd(&emptyBN, a, b, NULL), 0); + AssertIntEQ(BN_gcd(r, &emptyBN, b, NULL), 0); + AssertIntEQ(BN_gcd(r, a, &emptyBN, NULL), 0); + /* END Invalid parameters. */ + + /* No comman factors between 2 and 3. */ + AssertIntEQ(BN_set_word(a, 2), 1); + AssertIntEQ(BN_set_word(b, 3), 1); + AssertIntEQ(BN_gcd(r, a, b, NULL), 1); + AssertIntEQ(BN_is_word(r, 1), 1); + /* 3 is largest value that divides both 6 and 9. */ + AssertIntEQ(BN_set_word(a, 6), 1); + AssertIntEQ(BN_set_word(b, 9), 1); + AssertIntEQ(BN_gcd(r, a, b, NULL), 1); + AssertIntEQ(BN_is_word(r, 3), 1); + /* GCD of 0 and 0 is undefined. */ + AssertIntEQ(BN_set_word(a, 0), 1); + AssertIntEQ(BN_set_word(b, 0), 1); + AssertIntEQ(BN_gcd(r, a, b, NULL), 0); + + /* Teardown */ + BN_free(r); + BN_free(b); + BN_free(a); + + res = TEST_RES_CHECK(1); +#endif +#endif + return res; +} + +static int test_wolfSSL_BN_rand(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) + BIGNUM* bn; + BIGNUM* range; + BIGNUM emptyBN; + + XMEMSET(&emptyBN, 0, sizeof(emptyBN)); + AssertNotNull(bn = BN_new()); + AssertNotNull(range = BN_new()); + + /* Invalid parameters. */ + AssertIntEQ(BN_rand(NULL, -1, 0, 0), 0); + AssertIntEQ(BN_rand(bn, -1, 0, 0), 0); + AssertIntEQ(BN_rand(NULL, 1, 0, 0), 0); + AssertIntEQ(BN_rand(&emptyBN, -1, 0, 0), 0); + AssertIntEQ(BN_rand(bn, -1, 0, 0), 0); + AssertIntEQ(BN_rand(&emptyBN, 1, 0, 0), 0); + + AssertIntEQ(BN_pseudo_rand(NULL, -1, 0, 0), 0); + AssertIntEQ(BN_pseudo_rand(bn, -1, 0, 0), 0); + AssertIntEQ(BN_pseudo_rand(NULL, 1, 0, 0), 0); + AssertIntEQ(BN_pseudo_rand(&emptyBN, -1, 0, 0), 0); + AssertIntEQ(BN_pseudo_rand(bn, -1, 0, 0), 0); + AssertIntEQ(BN_pseudo_rand(&emptyBN, 1, 0, 0), 0); + + AssertIntEQ(BN_rand_range(NULL, NULL), 0); + AssertIntEQ(BN_rand_range(bn, NULL), 0); + AssertIntEQ(BN_rand_range(NULL, range), 0); + AssertIntEQ(BN_rand_range(&emptyBN, &emptyBN), 0); + AssertIntEQ(BN_rand_range(bn, &emptyBN), 0); + AssertIntEQ(BN_rand_range(&emptyBN, range), 0); + + /* 0 bit random value must be 0 and so cannot set bit in any position. */ + AssertIntEQ(BN_rand(bn, 0, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ODD), 0); + AssertIntEQ(BN_rand(bn, 0, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ODD), 0); + AssertIntEQ(BN_rand(bn, 0, WOLFSSL_BN_RAND_TOP_ANY, + WOLFSSL_BN_RAND_BOTTOM_ODD), 0); + AssertIntEQ(BN_rand(bn, 0, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ANY), 0); + AssertIntEQ(BN_rand(bn, 0, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ANY), 0); + AssertIntEQ(BN_pseudo_rand(bn, 0, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ODD), 0); + AssertIntEQ(BN_pseudo_rand(bn, 0, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ODD), 0); + AssertIntEQ(BN_pseudo_rand(bn, 0, WOLFSSL_BN_RAND_TOP_ANY, + WOLFSSL_BN_RAND_BOTTOM_ODD), 0); + AssertIntEQ(BN_pseudo_rand(bn, 0, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ANY), 0); + AssertIntEQ(BN_pseudo_rand(bn, 0, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ANY), 0); + + /* 1 bit random value must have no more than one top bit set. */ + AssertIntEQ(BN_rand(bn, 1, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ANY), 0); + AssertIntEQ(BN_rand(bn, 1, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ODD), 0); + AssertIntEQ(BN_pseudo_rand(bn, 1, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ANY), 0); + AssertIntEQ(BN_pseudo_rand(bn, 1, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ODD), 0); + /* END Invalid parameters. */ + + /* 0 bit random: 0. */ + AssertIntEQ(BN_rand(bn, 0, WOLFSSL_BN_RAND_TOP_ANY, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_is_zero(bn), 1); + + AssertIntEQ(BN_set_word(bn, 2), 1); /* Make sure not zero. */ + AssertIntEQ(BN_pseudo_rand(bn, 0, WOLFSSL_BN_RAND_TOP_ANY, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_is_zero(bn), 1); + + /* 1 bit random: 0 or 1. */ + AssertIntEQ(BN_rand(bn, 1, WOLFSSL_BN_RAND_TOP_ANY, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntLT(BN_get_word(bn), 2); /* Make sure valid range. */ + AssertIntEQ(BN_rand(bn, 1, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_get_word(bn), 1); + AssertIntEQ(BN_rand(bn, 1, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ODD), 1); + AssertIntEQ(BN_get_word(bn), 1); + + AssertIntEQ(BN_pseudo_rand(bn, 1, WOLFSSL_BN_RAND_TOP_ANY, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntLT(BN_get_word(bn), 2); /* Make sure valid range. */ + AssertIntEQ(BN_pseudo_rand(bn, 1, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_get_word(bn), 1); + AssertIntEQ(BN_pseudo_rand(bn, 1, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ODD), 1); + AssertIntEQ(BN_get_word(bn), 1); + + AssertIntEQ(BN_rand(bn, 8, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_num_bits(bn), 8); + AssertIntEQ(BN_is_bit_set(bn, 7), 1); + AssertIntEQ(BN_pseudo_rand(bn, 8, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_num_bits(bn), 8); + AssertIntEQ(BN_is_bit_set(bn, 7), 1); + + AssertIntEQ(BN_rand(bn, 8, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_is_bit_set(bn, 7), 1); + AssertIntEQ(BN_is_bit_set(bn, 6), 1); + AssertIntEQ(BN_pseudo_rand(bn, 8, WOLFSSL_BN_RAND_TOP_TWO, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_is_bit_set(bn, 7), 1); + AssertIntEQ(BN_is_bit_set(bn, 6), 1); + + AssertIntEQ(BN_rand(bn, 8, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ODD), 1); + AssertIntEQ(BN_is_bit_set(bn, 0), 1); + AssertIntEQ(BN_pseudo_rand(bn, 8, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ODD), 1); + AssertIntEQ(BN_is_bit_set(bn, 0), 1); + + /* Regression test: Older versions of wolfSSL_BN_rand would round the + * requested number of bits up to the nearest multiple of 8. E.g. in this + * case, requesting a 13-bit random number would actually return a 16-bit + * random number. */ + AssertIntEQ(BN_rand(bn, 13, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_num_bits(bn), 13); + + AssertIntEQ(BN_rand(range, 64, WOLFSSL_BN_RAND_TOP_ONE, + WOLFSSL_BN_RAND_BOTTOM_ANY), 1); + AssertIntEQ(BN_rand_range(bn, range), 1); + + AssertIntEQ(BN_set_word(range, 0), 1); + AssertIntEQ(BN_rand_range(bn, range), 1); + AssertIntEQ(BN_set_word(range, 1), 1); + AssertIntEQ(BN_rand_range(bn, range), 1); + + BN_free(bn); + BN_free(range); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_BN_prime(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || !defined(NO_DSA)) + BIGNUM* a; + BIGNUM* add; + BIGNUM* rem; + BIGNUM emptyBN; + + XMEMSET(&emptyBN, 0, sizeof(emptyBN)); + AssertNotNull(a = BN_new()); + AssertNotNull(add = BN_new()); + AssertNotNull(rem = BN_new()); + + /* Invalid parameters. */ + /* BN_generate_prime_ex() + * prime - must have valid BIGNUM + * bits - Greater then 0 + * safe - not supported, must be 0 + * add - not supported, must be NULL + * rem - not supported, must be NULL + * cb - anything + */ + AssertIntEQ(BN_generate_prime_ex(NULL, -1, 1, add, rem, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(&emptyBN, -1, 1, add, rem, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(a, -1, 1, add, rem, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(NULL, 2, 1, add, rem, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(&emptyBN, 2, 1, add, rem, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(NULL, -1, 0, add, rem, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(&emptyBN, -1, 0, add, rem, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(NULL, -1, 1, NULL, rem, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(&emptyBN, -1, 1, NULL, rem, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(NULL, -1, 1, add, NULL, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(&emptyBN, -1, 1, add, NULL, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(NULL, 2, 0, NULL, NULL, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(&emptyBN, 2, 0, NULL, NULL, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(a, -1, 0, NULL, NULL, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(a, 0, 0, NULL, NULL, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(a, 2, 1, NULL, NULL, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(a, 2, 0, add, NULL, NULL), 0); + AssertIntEQ(BN_generate_prime_ex(a, 2, 0, NULL, rem, NULL), 0); + + AssertIntEQ(BN_is_prime_ex(NULL, -1, NULL, NULL), -1); + AssertIntEQ(BN_is_prime_ex(&emptyBN, -1, NULL, NULL), -1); + AssertIntEQ(BN_is_prime_ex(a, -1, NULL, NULL), -1); + AssertIntEQ(BN_is_prime_ex(a, 2048, NULL, NULL), -1); + AssertIntEQ(BN_is_prime_ex(NULL, 1, NULL, NULL), -1); + AssertIntEQ(BN_is_prime_ex(&emptyBN, 1, NULL, NULL), -1); + /* END Invalid parameters. */ + + AssertIntEQ(BN_generate_prime_ex(a, 512, 0, NULL, NULL, NULL), 1); + AssertIntEQ(BN_is_prime_ex(a, 8, NULL, NULL), 1); + + AssertIntEQ(BN_clear_bit(a, 0), 1); + AssertIntEQ(BN_is_prime_ex(a, 8, NULL, NULL), 0); + + BN_free(rem); + BN_free(add); + BN_free(a); + + res = TEST_RES_CHECK(1); +#endif +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ return res; } @@ -38983,92 +39797,6 @@ static int test_wolfSSL_RAND_bytes(void) return res; } -static int test_wolfSSL_BN_rand(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) - BIGNUM* bn; - BIGNUM* range; - - /* Error conditions. */ - /* NULL BN. */ - AssertIntEQ(BN_rand(NULL, 0, 0, 0), SSL_FAILURE); - AssertNotNull(bn = BN_new()); - /* Negative bits. */ - AssertIntEQ(BN_rand(bn, -2, 0, 0), SSL_FAILURE); - /* 0 bits and top is not -1. */ - AssertIntEQ(BN_rand(bn, 0, 1, 0), SSL_FAILURE); - /* 0 bits and bottom is not 0. */ - AssertIntEQ(BN_rand(bn, 0, 0, 1), SSL_FAILURE); - /* 1 bit and top is 1. */ - AssertIntEQ(BN_rand(bn, 1, 1, 0), SSL_FAILURE); - - AssertIntEQ(BN_rand(bn, 0, -1, 0), SSL_SUCCESS); - AssertIntEQ(BN_num_bits(bn), 0); - - AssertIntEQ(BN_rand(bn, 8, 0, 0), SSL_SUCCESS); - AssertIntEQ(BN_num_bits(bn), 8); - /* When top is 0, top bit should be 1. */ - AssertIntEQ(BN_is_bit_set(bn, 7), SSL_SUCCESS); - - AssertIntEQ(BN_rand(bn, 8, 1, 0), SSL_SUCCESS); - /* When top is 1, top 2 bits should be 1. */ - AssertIntEQ(BN_is_bit_set(bn, 7), SSL_SUCCESS); - AssertIntEQ(BN_is_bit_set(bn, 6), SSL_SUCCESS); - - AssertIntEQ(BN_rand(bn, 8, 0, 1), SSL_SUCCESS); - /* When bottom is 1, bottom bit should be 1. */ - AssertIntEQ(BN_is_bit_set(bn, 0), SSL_SUCCESS); - - /* Regression test: Older versions of wolfSSL_BN_rand would round the - * requested number of bits up to the nearest multiple of 8. E.g. in this - * case, requesting a 13-bit random number would actually return a 16-bit - * random number. */ - AssertIntEQ(BN_rand(bn, 13, 0, 0), SSL_SUCCESS); - AssertIntEQ(BN_num_bits(bn), 13); - - AssertNotNull(range = BN_new()); - AssertIntEQ(BN_rand(range, 64, 0, 0), SSL_SUCCESS); - AssertIntEQ(BN_rand_range(bn, range), SSL_SUCCESS); - BN_free(bn); - BN_free(range); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - -static int test_wolfSSL_pseudo_rand(void) -{ - int res = TEST_SKIPPED; - #if defined(OPENSSL_EXTRA) - BIGNUM* bn; - unsigned char bin[8]; - int i; - - /* BN_pseudo_rand returns 1 on success 0 on failure - * int BN_pseudo_rand(BIGNUM* bn, int bits, int top, int bottom) */ - for (i = 0; i < 10; i++) { - AssertNotNull(bn = BN_new()); - AssertIntEQ(BN_pseudo_rand(bn, 8, 0, 0), SSL_SUCCESS); - AssertIntGT(BN_bn2bin(bn, bin),0); - AssertIntEQ((bin[0] & 0x80), 0x80); /* top bit should be set */ - BN_free(bn); - } - - for (i = 0; i < 10; i++) { - AssertNotNull(bn = BN_new()); - AssertIntEQ(BN_pseudo_rand(bn, 8, 1, 1), SSL_SUCCESS); - AssertIntGT(BN_bn2bin(bn, bin),0); - AssertIntEQ((bin[0] & 0xc1), 0xc1); /* top bit should be set */ - BN_free(bn); - } - - res = TEST_RES_CHECK(1); - #endif - return res; -} - static int test_wolfSSL_PKCS8_Compat(void) { int res = TEST_SKIPPED; @@ -61590,7 +62318,8 @@ static int test_ticket_nonce_malloc(void) #if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_TLS12) && \ !defined(WOLFSSL_TICKET_DECRYPT_NO_CREATE) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ - !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) + !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && !defined(NO_RSA) && \ + defined(HAVE_ECC) static int test_ticket_ret_create(void) { @@ -62172,7 +62901,25 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_X509_STORE_load_locations), TEST_DECL(test_X509_STORE_get0_objects), TEST_DECL(test_wolfSSL_X509_load_crl_file), + + /* RAND compatability API */ + TEST_DECL(test_wolfSSL_RAND_set_rand_method), + TEST_DECL(test_wolfSSL_RAND_bytes), + + /* BN compatability API */ + TEST_DECL(test_wolfSSL_BN_CTX), TEST_DECL(test_wolfSSL_BN), + TEST_DECL(test_wolfSSL_BN_init), + TEST_DECL(test_wolfSSL_BN_enc_dec), + TEST_DECL(test_wolfSSL_BN_word), + TEST_DECL(test_wolfSSL_BN_bits), + TEST_DECL(test_wolfSSL_BN_shift), + TEST_DECL(test_wolfSSL_BN_math), + TEST_DECL(test_wolfSSL_BN_math_mod), + TEST_DECL(test_wolfSSL_BN_math_other), + TEST_DECL(test_wolfSSL_BN_rand), + TEST_DECL(test_wolfSSL_BN_prime), + TEST_DECL(test_wolfSSL_CTX_get0_set1_param), #ifndef NO_BIO TEST_DECL(test_wolfSSL_PEM_read_bio), @@ -62215,10 +62962,6 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_set_minmax_proto_version), TEST_DECL(test_wolfSSL_CTX_set_max_proto_version), TEST_DECL(test_wolfSSL_THREADID_hash), - TEST_DECL(test_wolfSSL_RAND_set_rand_method), - TEST_DECL(test_wolfSSL_RAND_bytes), - TEST_DECL(test_wolfSSL_BN_rand), - TEST_DECL(test_wolfSSL_pseudo_rand), TEST_DECL(test_wolfSSL_PKCS8_Compat), TEST_DECL(test_wolfSSL_PKCS8_d2i), TEST_DECL(test_error_queue_per_thread), diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 6f5b455ff..2f8aca658 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -18153,13 +18153,18 @@ int sp_prime_is_prime_ex(const sp_int* a, int trials, int* result, WC_RNG* rng) if ((a == NULL) || (result == NULL) || (rng == NULL)) { err = MP_VAL; } - #ifdef WOLFSSL_SP_INT_NEGATIVE if ((err == MP_OKAY) && (a->sign == MP_NEG)) { err = MP_VAL; } #endif + /* Ensure trials is valid. Maximum based on number of small primes + * available. */ + if ((err == MP_OKAY) && ((trials <= 0) || (trials > SP_PRIME_SIZE))) { + err = MP_VAL; + } + if ((err == MP_OKAY) && sp_isone(a)) { ret = MP_NO; haveRes = 1; diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 9efcd822e..c714cc7d1 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -5090,6 +5090,8 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) return FP_VAL; if (a->sign == FP_NEG) return FP_VAL; + if (t <= 0 || t > FP_PRIME_SIZE) + return FP_VAL; if (fp_isone(a)) { *result = FP_NO; diff --git a/wolfssl/openssl/bn.h b/wolfssl/openssl/bn.h index 5c94ac481..91a844413 100644 --- a/wolfssl/openssl/bn.h +++ b/wolfssl/openssl/bn.h @@ -40,11 +40,7 @@ typedef struct WOLFSSL_BIGNUM { int neg; /* openssh deference */ void *internal; /* our big num */ -#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) - sp_int fp; -#elif defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) - fp_int fp; -#endif + mp_int mpi; } WOLFSSL_BIGNUM; #define WOLFSSL_BN_ULONG unsigned long @@ -70,6 +66,15 @@ typedef struct WOLFSSL_BIGNUM { #endif #endif +#define WOLFSSL_BN_RAND_TOP_ANY -1 +#define WOLFSSL_BN_RAND_TOP_ONE 0 +#define WOLFSSL_BN_RAND_TOP_TWO 1 + +#define WOLFSSL_BN_RAND_BOTTOM_ANY 0 +#define WOLFSSL_BN_RAND_BOTTOM_ODD 1 + +#define WOLFSSL_BN_MAX_VAL ((BN_ULONG)-1) + typedef struct WOLFSSL_BN_CTX WOLFSSL_BN_CTX; typedef struct WOLFSSL_BN_GENCB WOLFSSL_BN_GENCB; @@ -78,7 +83,7 @@ WOLFSSL_API void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx); WOLFSSL_API void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx); WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_new(void); -#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) +#if !defined(USE_INTEGER_HEAP_MATH) && !defined(HAVE_WOLF_BIGINT) WOLFSSL_API void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn); #endif WOLFSSL_API void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn); @@ -179,6 +184,13 @@ WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse( #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +#define BN_RAND_TOP_ANY WOLFSSL_BN_RAND_TOP_ANY +#define BN_RAND_TOP_ONE WOLFSSL_BN_RAND_TOP_ONE +#define BN_RAND_TOP_TWO WOLFSSL_BN_RAND_TOP_TWO + +#define BN_RAND_BOTTOM_ANY WOLFSSL_BN_RAND_BOTTOM_ANY +#define BN_RAND_BOTTOM_ODD WOLFSSL_BN_RAND_BOTTOM_ODD + typedef WOLFSSL_BIGNUM BIGNUM; typedef WOLFSSL_BN_CTX BN_CTX; typedef WOLFSSL_BN_GENCB BN_GENCB; @@ -188,7 +200,9 @@ typedef WOLFSSL_BN_GENCB BN_GENCB; #define BN_CTX_free wolfSSL_BN_CTX_free #define BN_new wolfSSL_BN_new +#if !defined(USE_INTEGER_HEAP_MATH) && !defined(HAVE_WOLF_BIGINT) #define BN_init wolfSSL_BN_init +#endif #define BN_free wolfSSL_BN_free #define BN_clear_free wolfSSL_BN_clear_free #define BN_clear wolfSSL_BN_clear