#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#include <wolfssl/internal.h>
#ifndef WC_NO_RNG
#include <wolfssl/wolfcrypt/random.h>
#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
#define BN_IS_NULL(bn) (((bn) == NULL) || ((bn)->internal == NULL))
#if defined(OPENSSL_EXTRA) && !defined(NO_ASN)
static int wolfssl_bn_set_neg(WOLFSSL_BIGNUM* bn, int neg)
{
int ret = 1;
if (BN_IS_NULL(bn)) {
WOLFSSL_MSG("bn NULL error");
ret = WOLFSSL_FATAL_ERROR;
}
#if !defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_SP_INT_NEGATIVE)
else if (neg) {
mp_setneg((mp_int*)bn->internal);
}
else {
((mp_int*)bn->internal)->sign = MP_ZPOS;
}
#endif
return ret;
}
#endif
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
int wolfssl_bn_get_value(WOLFSSL_BIGNUM* bn, mp_int* mpi)
{
int ret = 1;
WOLFSSL_MSG("Entering wolfssl_bn_get_value_mp");
if (BN_IS_NULL(bn)) {
WOLFSSL_MSG("bn NULL error");
ret = WOLFSSL_FATAL_ERROR;
}
else if (mpi == NULL) {
WOLFSSL_MSG("mpi NULL error");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == 1) && mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
WOLFSSL_MSG("mp_copy error");
ret = WOLFSSL_FATAL_ERROR;
}
return ret;
}
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
if ((bn == NULL) || (mpi == NULL)) {
WOLFSSL_MSG("mpi or bn NULL error");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == 1) && (*bn == NULL)) {
a = wolfSSL_BN_new();
if (a == NULL) {
WOLFSSL_MSG("wolfssl_bn_set_value alloc failed");
ret = WOLFSSL_FATAL_ERROR;
}
*bn = a;
}
if ((ret == 1) && (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY)) {
WOLFSSL_MSG("mp_copy error");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == -1) && (a != NULL)) {
wolfSSL_BN_free(a);
*bn = NULL;
}
return ret;
}
static void wolfssl_bn_init(WOLFSSL_BIGNUM* bn)
{
XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM));
(void)mp_init(&bn->mpi);
bn->internal = &bn->mpi;
}
WOLFSSL_BIGNUM* wolfSSL_BN_new(void)
{
WOLFSSL_BIGNUM* bn = NULL;
#ifdef WOLFSSL_DEBUG_OPENSSL
WOLFSSL_ENTER("wolfSSL_BN_new");
#endif
bn = (WOLFSSL_BIGNUM*)XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL,
DYNAMIC_TYPE_BIGINT);
if (bn == NULL) {
WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure");
}
else {
wolfssl_bn_init(bn);
}
return bn;
}
#if !defined(USE_INTEGER_HEAP_MATH) && !defined(HAVE_WOLF_BIGINT)
void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn)
{
#ifdef WOLFSSL_DEBUG_OPENSSL
WOLFSSL_ENTER("wolfSSL_BN_init");
#endif
if (bn != NULL) {
wolfssl_bn_init(bn);
}
}
#endif
void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn)
{
#ifdef WOLFSSL_DEBUG_OPENSSL
WOLFSSL_ENTER("wolfSSL_BN_free");
#endif
if (bn != NULL) {
if (bn->internal != NULL) {
mp_free(&bn->mpi);
}
XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT);
}
}
void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn)
{
#ifdef WOLFSSL_DEBUG_OPENSSL
WOLFSSL_ENTER("wolfSSL_BN_clear_free");
#endif
if (bn != NULL) {
if (bn->internal != NULL) {
mp_forcezero((mp_int*)bn->internal);
}
wolfSSL_BN_free(bn);
}
}
void wolfSSL_BN_clear(WOLFSSL_BIGNUM* bn)
{
#ifdef WOLFSSL_DEBUG_OPENSSL
WOLFSSL_ENTER("wolfSSL_BN_clear");
#endif
if (!BN_IS_NULL(bn)) {
mp_forcezero((mp_int*)bn->internal);
}
}
#endif
#ifdef OPENSSL_EXTRA
static WOLFSSL_BIGNUM* bn_one = NULL;
const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void)
{
WOLFSSL_BIGNUM* one;
WOLFSSL_ENTER("wolfSSL_BN_value_one");
one = bn_one;
if ((one == NULL) && ((one = wolfSSL_BN_new()) != NULL)) {
if (mp_set_int((mp_int*)one->internal, 1) != MP_OKAY) {
wolfSSL_BN_free(one);
one = NULL;
}
else
#ifndef SINGLE_THREADED
if (bn_one == NULL)
#endif
{
bn_one = one;
}
#ifndef SINGLE_THREADED
if (bn_one != one) {
wolfSSL_BN_free(one);
one = bn_one;
}
#endif
}
return one;
}
static void wolfSSL_BN_free_one(void) {
wolfSSL_BN_free(bn_one);
bn_one = NULL;
}
WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn)
{
int err = 0;
WOLFSSL_BIGNUM* ret = NULL;
WOLFSSL_ENTER("wolfSSL_BN_dup");
if (BN_IS_NULL(bn)) {
WOLFSSL_MSG("bn NULL error");
err = 1;
}
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) {
wolfSSL_BN_free(ret);
ret = NULL;
}
return ret;
}
WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn)
{
WOLFSSL_ENTER("wolfSSL_BN_copy");
if (BN_IS_NULL(r) || BN_IS_NULL(bn)) {
WOLFSSL_MSG("r or bn NULL error");
r = NULL;
}
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) {
r->neg = bn->neg;
}
return r;
}
int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_bn2bin");
if (BN_IS_NULL(bn)) {
WOLFSSL_MSG("NULL bn error");
ret = WOLFSSL_FATAL_ERROR;
}
else {
ret = mp_unsigned_bin_size((mp_int*)bn->internal);
if ((r != NULL) && (mp_to_unsigned_bin((mp_int*)bn->internal, r) !=
MP_OKAY)) {
WOLFSSL_MSG("mp_to_unsigned_bin error");
ret = WOLFSSL_FATAL_ERROR;
}
}
return ret;
}
WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* data, int len,
WOLFSSL_BIGNUM* ret)
{
WOLFSSL_BIGNUM* bn = NULL;
WOLFSSL_ENTER("wolfSSL_BN_bin2bn");
if (len < 0) {
ret = NULL;
}
else if (ret == NULL) {
ret = wolfSSL_BN_new();
bn = ret;
}
if (ret != NULL) {
if (ret->internal == NULL) {
ret = NULL;
}
else if (data != NULL) {
if (mp_read_unsigned_bin((mp_int*)ret->internal, data, (word32)len)
!= 0) {
WOLFSSL_MSG("mp_read_unsigned_bin failure");
ret = NULL;
}
else {
bn = NULL;
}
}
else if (data == NULL) {
wolfSSL_BN_zero(ret);
bn = NULL;
}
}
wolfSSL_BN_free(bn);
return ret;
}
static char* wolfssl_bn_bn2radix(const WOLFSSL_BIGNUM* bn, int radix)
{
int err = 0;
int len = 0;
char* str = NULL;
if (BN_IS_NULL(bn)) {
WOLFSSL_MSG("bn NULL error");
err = 1;
}
if ((!err) && (mp_radix_size((mp_int*)bn->internal, radix, &len) !=
MP_OKAY)) {
WOLFSSL_MSG("mp_radix_size failure");
err = 1;
}
if (!err) {
str = (char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_OPENSSL);
if (str == NULL) {
WOLFSSL_MSG("BN_bn2hex malloc string failure");
err = 1;
}
}
if ((!err) && (mp_toradix((mp_int*)bn->internal, str, radix) != MP_OKAY)) {
err = 1;
}
if (err) {
XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL);
str = NULL;
}
return str;
}
char* wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn)
{
WOLFSSL_ENTER("wolfSSL_BN_bn2hex");
return wolfssl_bn_bn2radix(bn, MP_RADIX_HEX);
}
static int wolfssl_bn_radix2bn(WOLFSSL_BIGNUM** bn, const char* str, int radix)
{
int ret = 1;
WOLFSSL_BIGNUM* a = NULL;
if ((bn == NULL) || (str == NULL) || (str[0] == '\0')) {
WOLFSSL_MSG("Bad function argument");
ret = 0;
}
if ((ret == 1) && (*bn == NULL)) {
a = wolfSSL_BN_new();
if (a == NULL) {
WOLFSSL_MSG("BN new failed");
ret = 0;
}
*bn = a;
}
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)) {
wolfSSL_BN_free(a);
*bn = NULL;
}
return ret;
}
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)
char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn)
{
WOLFSSL_ENTER("wolfSSL_BN_bn2hex");
return wolfssl_bn_bn2radix(bn, MP_RADIX_DEC);
}
#else
char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn)
{
(void)bn;
WOLFSSL_ENTER("wolfSSL_BN_bn2dec");
return NULL;
}
#endif
#ifndef NO_RSA
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
int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str)
{
(void)bn;
(void)str;
WOLFSSL_ENTER("wolfSSL_BN_bn2dec");
return 0;
}
#endif
int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_num_bytes");
if (BN_IS_NULL(bn)) {
ret = 0;
}
else {
ret = mp_unsigned_bin_size((mp_int*)bn->internal);
}
return ret;
}
int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_num_bits");
if (BN_IS_NULL(bn)) {
ret = 0;
}
else {
ret = mp_count_bits((mp_int*)bn->internal);
}
return ret;
}
int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM* bn)
{
int ret;
if (BN_IS_NULL(bn)) {
ret = 0;
}
else {
ret = mp_isneg((mp_int*)bn->internal);
}
return ret;
}
int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_is_odd");
if (BN_IS_NULL(bn)) {
ret = 0;
}
else {
ret = (mp_isodd((mp_int*)bn->internal) == MP_YES);
}
return ret;
}
#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 0;
}
#endif
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;
}
int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n)
{
int ret = 1;
WC_DECLARE_VAR(tmp, mp_int, 1, 0);
if (BN_IS_NULL(bn) || (n < 0)) {
WOLFSSL_MSG("bn NULL error");
ret = 0;
}
if ((ret == 1) && (mp_is_bit_set((mp_int*)bn->internal, n))) {
WC_ALLOC_VAR_EX(tmp, mp_int, 1, NULL, DYNAMIC_TYPE_BIGINT, ret=0);
if (ret == 1) {
XMEMSET(tmp, 0, sizeof(mp_int));
if (mp_init(tmp) != MP_OKAY) {
ret = 0;
}
}
if ((ret == 1) && (mp_set_bit(tmp, n) != MP_OKAY)) {
ret = 0;
}
if ((ret == 1) && (mp_sub((mp_int*)bn->internal, tmp,
(mp_int*)bn->internal) != MP_OKAY)) {
ret = 0;
}
mp_clear(tmp);
WC_FREE_VAR_EX(tmp, NULL, DYNAMIC_TYPE_BIGINT);
}
return ret;
}
int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n)
{
int ret;
if (BN_IS_NULL(bn) || (n < 0)) {
WOLFSSL_MSG("bn NULL error");
ret = 0;
}
else {
ret = mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n);
}
return ret;
}
void wolfSSL_BN_zero(WOLFSSL_BIGNUM* bn)
{
if (!BN_IS_NULL(bn)) {
mp_zero((mp_int*)bn->internal);
}
}
int wolfSSL_BN_one(WOLFSSL_BIGNUM* bn)
{
int ret;
if (BN_IS_NULL(bn)) {
ret = 0;
}
else {
ret = wolfSSL_BN_set_word(bn, 1);
}
return ret;
}
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
}
WOLFSSL_BN_ULONG wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn)
{
WOLFSSL_BN_ULONG ret;
WOLFSSL_ENTER("wolfSSL_BN_get_word");
if (BN_IS_NULL(bn)) {
WOLFSSL_MSG("Invalid argument");
ret = 0;
}
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 {
ret = wolfssl_bn_get_word_1((mp_int*)bn->internal);
}
return ret;
}
int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, unsigned long w)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_BN_set_word");
if (BN_IS_NULL(bn)) {
WOLFSSL_MSG("bn NULL error");
ret = 0;
}
if ((ret == 1) && (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY)) {
WOLFSSL_MSG("mp_init_set_int error");
ret = 0;
}
return ret;
}
int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b)
{
int ret;
int bIsNull;
WOLFSSL_ENTER("wolfSSL_BN_cmp");
bIsNull = BN_IS_NULL(b);
if (BN_IS_NULL(a)) {
if (bIsNull) {
ret = 0;
}
else {
ret = -1;
}
}
else if (bIsNull) {
ret = 1;
}
else {
PRAGMA_GCC_DIAG_PUSH
PRAGMA_GCC("GCC diagnostic ignored \"-Wduplicated-branches\"")
ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal);
if (ret == MP_EQ) {
ret = 0;
}
else if (ret == MP_GT) {
ret = 1;
}
else if (ret == MP_LT) {
ret = -1;
}
else {
ret = WOLFSSL_FATAL_ERROR;
}
PRAGMA_GCC_DIAG_POP
}
return ret;
}
int wolfSSL_BN_ucmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b)
{
int ret = 0;
int bIsNull;
WOLFSSL_ENTER("wolfSSL_BN_ucmp");
bIsNull = BN_IS_NULL(b);
if (BN_IS_NULL(a)) {
if (bIsNull) {
ret = 0;
}
else {
ret = -1;
}
}
else if (bIsNull) {
ret = 1;
}
else {
WOLFSSL_BIGNUM* abs_a = wolfSSL_BN_dup(a);
WOLFSSL_BIGNUM* abs_b = wolfSSL_BN_dup(b);
if (abs_a == NULL || abs_b == NULL) {
WOLFSSL_MSG("wolfSSL_BN_dup failed");
wolfSSL_BN_free(abs_a);
wolfSSL_BN_free(abs_b);
return WOLFSSL_FATAL_ERROR;
}
if (wolfSSL_BN_is_negative(abs_a)) {
wolfssl_bn_set_neg(abs_a, 1);
}
if (wolfSSL_BN_is_negative(abs_b)) {
wolfssl_bn_set_neg(abs_b, 1);
}
ret = wolfSSL_BN_cmp(abs_a, abs_b);
wolfSSL_BN_free(abs_a);
wolfSSL_BN_free(abs_b);
}
return ret;
}
int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_is_zero");
if (BN_IS_NULL(bn)) {
ret = 0;
}
else {
ret = (mp_iszero((mp_int*)bn->internal) == MP_YES);
}
return ret;
}
int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_is_one");
if (BN_IS_NULL(bn)) {
ret = 0;
}
else {
ret = (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ);
}
return ret;
}
int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_is_word");
if (BN_IS_NULL(bn)) {
WOLFSSL_MSG("bn NULL error");
ret = 0;
}
else
#if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT)
if (w > (WOLFSSL_BN_ULONG)MP_MASK) {
mp_int w_mp;
if (mp_init(&w_mp) != MP_OKAY) {
ret = 0;
}
else if (mp_set_int(&w_mp, w) != MP_OKAY) {
ret = 0;
}
else {
ret = (mp_cmp((mp_int *)bn->internal, &w_mp) == MP_EQ);
mp_free(&w_mp);
}
}
else
#endif
{
ret = (mp_isword((mp_int*)bn->internal, (mp_digit)w) == MP_YES);
}
return ret;
}
enum BN_WORD_OP {
BN_WORD_ADD = 0,
BN_WORD_SUB = 1,
BN_WORD_MUL = 2,
BN_WORD_DIV = 3,
BN_WORD_MOD = 4
};
static int bn_word_helper(const WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w,
enum BN_WORD_OP op, WOLFSSL_BN_ULONG* mod_res)
{
int ret = 1;
WOLFSSL_ENTER("bn_word_helper");
if (ret == 1 && BN_IS_NULL(bn)) {
WOLFSSL_MSG("bn NULL error");
ret = 0;
}
if (ret == 1) {
int rc = MP_OKAY;
#if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT)
if (w > (WOLFSSL_BN_ULONG)MP_MASK) {
DECL_MP_INT_SIZE_DYN(w_mp, sizeof(WOLFSSL_BN_ULONG) * CHAR_BIT,
sizeof(WOLFSSL_BN_ULONG) * CHAR_BIT);
NEW_MP_INT_SIZE(w_mp, sizeof(WOLFSSL_BN_ULONG) * CHAR_BIT, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
#ifdef MP_INT_SIZE_CHECK_NULL
if (w_mp == NULL) {
WOLFSSL_MSG("NEW_MP_INT_SIZE error");
ret = 0;
}
#endif
if (ret == 1 && mp_set_int(w_mp, w) != MP_OKAY) {
WOLFSSL_MSG("mp_set_int error");
ret = 0;
}
if (ret == 1) {
switch (op) {
case BN_WORD_ADD:
rc = mp_add((mp_int*)bn->internal, w_mp,
(mp_int*)bn->internal);
break;
case BN_WORD_SUB:
rc = mp_sub((mp_int*)bn->internal, w_mp,
(mp_int*)bn->internal);
break;
case BN_WORD_MUL:
rc = mp_mul((mp_int*)bn->internal, w_mp,
(mp_int*)bn->internal);
break;
case BN_WORD_DIV:
rc = mp_div((mp_int*)bn->internal, w_mp,
(mp_int*)bn->internal, NULL);
break;
case BN_WORD_MOD:
rc = mp_mod((mp_int*) bn->internal, w_mp,
w_mp);
if (rc == MP_OKAY && mod_res != NULL)
*mod_res = wolfssl_bn_get_word_1(w_mp);
break;
default:
rc = WOLFSSL_NOT_IMPLEMENTED;
break;
}
}
FREE_MP_INT_SIZE(w_mp, NULL, DYNAMIC_TYPE_RSA);
}
else
#endif
{
switch (op) {
case BN_WORD_ADD:
rc = mp_add_d((mp_int*)bn->internal, (mp_digit)w,
(mp_int*)bn->internal);
break;
case BN_WORD_SUB:
rc = mp_sub_d((mp_int*)bn->internal, (mp_digit)w,
(mp_int*)bn->internal);
break;
case BN_WORD_MUL:
rc = mp_mul_d((mp_int*)bn->internal, (mp_digit)w,
(mp_int*)bn->internal);
break;
case BN_WORD_DIV:
#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
defined(WC_MP_TO_RADIX)
rc = mp_div_d((mp_int*)bn->internal, (mp_digit)w,
(mp_int*)bn->internal, NULL);
#else
rc = WOLFSSL_NOT_IMPLEMENTED;
#endif
#else
rc = WOLFSSL_NOT_IMPLEMENTED;
#endif
break;
case BN_WORD_MOD:
{
mp_digit _mod_res;
rc = mp_mod_d((mp_int*) bn->internal, (mp_digit) w,
&_mod_res);
if (rc == MP_OKAY && mod_res != NULL)
*mod_res = (WOLFSSL_BN_ULONG)_mod_res;
}
break;
default:
rc = WOLFSSL_NOT_IMPLEMENTED;
break;
}
}
if (ret == 1 && rc != MP_OKAY) {
WOLFSSL_MSG("mp word operation error or not implemented");
ret = 0;
}
}
WOLFSSL_LEAVE("bn_word_helper", ret);
return ret;
}
int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_add_word");
ret = bn_word_helper(bn, w, BN_WORD_ADD, NULL);
WOLFSSL_LEAVE("wolfSSL_BN_add_word", ret);
return ret;
}
int wolfSSL_BN_sub_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_sub_word");
ret = bn_word_helper(bn, w, BN_WORD_SUB, NULL);
WOLFSSL_LEAVE("wolfSSL_BN_sub_word", ret);
return ret;
}
int wolfSSL_BN_mul_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_mul_word");
ret = bn_word_helper(bn, w, BN_WORD_MUL, NULL);
WOLFSSL_LEAVE("wolfSSL_BN_mul_word", ret);
return ret;
}
int wolfSSL_BN_div_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w)
{
int ret;
WOLFSSL_ENTER("wolfSSL_BN_div_word");
ret = bn_word_helper(bn, w, BN_WORD_DIV, NULL);
WOLFSSL_LEAVE("wolfSSL_BN_div_word", ret);
return ret;
}
#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || \
!defined(NO_DSA))
WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn,
WOLFSSL_BN_ULONG w)
{
int ret;
WOLFSSL_BN_ULONG res = 0;
WOLFSSL_ENTER("wolfSSL_BN_mod_word");
ret = bn_word_helper(bn, w, BN_WORD_MOD, &res);
WOLFSSL_LEAVE("wolfSSL_BN_mod_word", ret);
return ret == 1 ? res : (WOLFSSL_BN_ULONG)-1;
}
#endif
#ifndef WOLFSSL_SP_MATH
int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_BN_lshift");
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;
}
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;
}
int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_BN_rshift");
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;
}
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
int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_BN_add");
if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
WOLFSSL_MSG("bn NULL error");
ret = 0;
}
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;
}
int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
const WOLFSSL_BIGNUM* b)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_BN_sub");
if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
ret = 0;
}
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;
}
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");
if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
ret = 0;
}
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
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;
WOLFSSL_BIGNUM* res = dv;
(void)ctx;
WOLFSSL_ENTER("wolfSSL_BN_div");
if (BN_IS_NULL(res)) {
res = wolfSSL_BN_new();
}
if (BN_IS_NULL(res) || BN_IS_NULL(rem) || BN_IS_NULL(a) || BN_IS_NULL(d)) {
ret = 0;
}
if ((ret == 1) && (mp_div((mp_int*)a->internal, (mp_int*)d->internal,
(mp_int*)res->internal, (mp_int*)rem->internal) != MP_OKAY)) {
ret = 0;
}
if (res != dv)
wolfSSL_BN_free(res);
WOLFSSL_LEAVE("wolfSSL_BN_div", ret);
return ret;
}
#endif
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");
if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
ret = 0;
}
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;
}
#ifndef WOLFSSL_SP_MATH
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;
(void)ctx;
WOLFSSL_ENTER("wolfSSL_BN_add");
if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b) || BN_IS_NULL(m)) {
WOLFSSL_MSG("bn NULL error");
ret = 0;
}
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
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;
(void)ctx;
WOLFSSL_ENTER("wolfSSL_BN_mod_mul");
if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b) || BN_IS_NULL(m)) {
WOLFSSL_MSG("Bad Argument");
ret = 0;
}
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;
}
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;
(void)ctx;
WOLFSSL_ENTER("wolfSSL_BN_mod_exp");
if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(e) || BN_IS_NULL(m)) {
WOLFSSL_MSG("Bad Argument");
ret = 0;
}
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;
}
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;
(void)ctx;
WOLFSSL_ENTER("wolfSSL_BN_mod_inverse");
if (BN_IS_NULL(a) || BN_IS_NULL(m) || ((r != NULL) &&
(r->internal == NULL))) {
WOLFSSL_MSG("a or n NULL error");
err = 1;
}
if ((!err) && (r == NULL)) {
t = wolfSSL_BN_new();
if (t == NULL){
WOLFSSL_MSG("WolfSSL_BN_new() failed");
err = 1;
}
r = t;
}
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;
}
#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)
int wolfSSL_BN_gcd(WOLFSSL_BIGNUM* r, WOLFSSL_BIGNUM* a, WOLFSSL_BIGNUM* b,
WOLFSSL_BN_CTX* ctx)
{
int ret = 1;
(void)ctx;
WOLFSSL_ENTER("wolfSSL_BN_gcd");
if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
ret = 0;
}
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
int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
{
int ret = 1;
word32 len = (word32)((bits + 7) / 8);
WC_RNG* rng;
WOLFSSL_ENTER("wolfSSL_BN_rand");
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;
}
if ((ret == 1) && (bits == 0)) {
mp_zero((mp_int*)bn->internal);
}
else if (ret == 1) {
byte* buff = NULL;
if ((rng = wolfssl_make_global_rng()) == NULL) {
WOLFSSL_MSG("Failed to use global RNG.");
ret = 0;
}
if ((ret == 1) && ((buff = (byte*)XMALLOC(len, NULL,
DYNAMIC_TYPE_TMP_BUFFER)) == NULL)) {
WOLFSSL_MSG("Failed to allocate buffer.");
ret = 0;
}
if ((ret == 1) && wc_RNG_GenerateBlock(rng, buff, len) != 0) {
WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
ret = 0;
}
if ((ret == 1) && mp_read_unsigned_bin((mp_int*)bn->internal, buff, len)
!= MP_OKAY) {
WOLFSSL_MSG("mp_read_unsigned_bin failed");
ret = 0;
}
XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (ret == 1) {
mp_rshb((mp_int*)bn->internal, 8 - (bits % 8));
}
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;
}
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;
}
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;
}
int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
{
return wolfSSL_BN_rand(bn, bits, top, bottom);
}
#define RANGE_MAX_TRIALS 100
int wolfSSL_BN_rand_range(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *range)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_BN_rand_range");
if (BN_IS_NULL(r) || BN_IS_NULL(range)) {
WOLFSSL_MSG("Bad parameter");
ret = 0;
}
if (ret == 1) {
int n = wolfSSL_BN_num_bits(range);
if (n <= 1) {
wolfSSL_BN_zero(r);
}
else {
int i;
for (i = 0; (ret == 1) && (i < RANGE_MAX_TRIALS); i++) {
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;
}
else if (wolfSSL_BN_cmp(r, range) < 0) {
break;
}
}
if (i >= RANGE_MAX_TRIALS) {
WOLFSSL_MSG("wolfSSL_BN_rand_range too many iterations");
ret = 0;
}
}
}
return ret;
}
#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 = 1;
WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
WC_RNG* rng = NULL;
int localRng = 0;
(void)cb;
WOLFSSL_ENTER("wolfSSL_BN_generate_prime_ex");
if ((safe == 1) || (add != NULL) || (rem != NULL)) {
ret = 0;
}
else if (BN_IS_NULL(prime)) {
ret = 0;
}
if ((ret == 1) && ((rng = wolfssl_make_rng(tmpRng, &localRng)) == NULL)) {
ret = 0;
}
if ((ret == 1) && (mp_rand_prime((mp_int*)prime->internal, (bits + 7) / 8,
rng, NULL) != MP_OKAY)) {
ret = 0;
}
if (localRng) {
wc_FreeRng(rng);
WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
}
WOLFSSL_LEAVE("wolfSSL_BN_generate_prime_ex", ret);
return ret;
}
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;
WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
int localRng = 0;
int res = MP_NO;
(void)ctx;
(void)cb;
WOLFSSL_ENTER("wolfSSL_BN_is_prime_ex");
if (BN_IS_NULL(bn)) {
WOLFSSL_MSG("bn NULL error");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == 1) && ((rng = wolfssl_make_rng(tmpRng, &localRng)) == NULL)) {
ret = WOLFSSL_FATAL_ERROR;
}
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 = WOLFSSL_FATAL_ERROR;
}
if (localRng) {
wc_FreeRng(rng);
WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
}
if ((ret != -1) && (res != MP_YES)) {
WOLFSSL_MSG("mp_prime_is_prime_ex not prime");
ret = 0;
}
return ret;
}
#endif
#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) && \
defined(XFPRINTF)
int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn)
{
int ret = 1;
char* buf = NULL;
WOLFSSL_ENTER("wolfSSL_BN_print_fp");
if ((fp == XBADFILE) || BN_IS_NULL(bn)) {
WOLFSSL_MSG("bn NULL error");
ret = 0;
}
if ((ret == 1) && ((buf = wolfSSL_BN_bn2hex(bn)) == NULL)) {
WOLFSSL_MSG("wolfSSL_BN_bn2hex failure");
ret = 0;
}
if ((ret == 1) && (XFPRINTF(fp, "%s", buf) < 0)) {
ret = 0;
}
XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
return ret;
}
#endif
#ifndef NO_WOLFSSL_BN_CTX
WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void)
{
WOLFSSL_BN_CTX* ctx = NULL;
WOLFSSL_ENTER("wolfSSL_BN_CTX_new");
ctx = (WOLFSSL_BN_CTX*)XMALLOC(sizeof(WOLFSSL_BN_CTX), NULL,
DYNAMIC_TYPE_OPENSSL);
if (ctx != NULL) {
XMEMSET(ctx, 0, sizeof(WOLFSSL_BN_CTX));
}
return ctx;
}
#ifndef NO_WOLFSSL_STUB
void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx)
{
(void)ctx;
WOLFSSL_ENTER("wolfSSL_BN_CTX_init");
WOLFSSL_STUB("wolfSSL_BN_CTX_init");
WOLFSSL_MSG("wolfSSL_BN_CTX_init is deprecated");
}
#endif
void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx)
{
WOLFSSL_ENTER("wolfSSL_BN_CTX_free");
if (ctx != NULL) {
while (ctx->list != NULL) {
struct WOLFSSL_BN_CTX_LIST* tmp = ctx->list;
ctx->list = ctx->list->next;
wolfSSL_BN_free(tmp->bn);
XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
}
XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
}
}
WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx)
{
WOLFSSL_BIGNUM* bn = NULL;
WOLFSSL_ENTER("wolfSSL_BN_CTX_get");
if (ctx != NULL) {
struct WOLFSSL_BN_CTX_LIST* node = (struct WOLFSSL_BN_CTX_LIST*)XMALLOC(
sizeof(struct WOLFSSL_BN_CTX_LIST), NULL, DYNAMIC_TYPE_OPENSSL);
if (node != NULL) {
XMEMSET(node, 0, sizeof(struct WOLFSSL_BN_CTX_LIST));
bn = node->bn = wolfSSL_BN_new();
if (node->bn != NULL) {
node->next = ctx->list;
ctx->list = node;
}
else {
XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
node = NULL;
}
}
}
return bn;
}
#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
#endif
WOLFSSL_BN_MONT_CTX* wolfSSL_BN_MONT_CTX_new(void)
{
static int mont;
WOLFSSL_ENTER("wolfSSL_BN_MONT_CTX_new");
return (WOLFSSL_BN_MONT_CTX*)&mont;
}
void wolfSSL_BN_MONT_CTX_free(WOLFSSL_BN_MONT_CTX *mont)
{
(void)mont;
WOLFSSL_ENTER("wolfSSL_BN_MONT_CTX_free");
}
int wolfSSL_BN_MONT_CTX_set(WOLFSSL_BN_MONT_CTX *mont,
const WOLFSSL_BIGNUM *mod, WOLFSSL_BN_CTX *ctx)
{
(void) mont;
(void) mod;
(void) ctx;
WOLFSSL_ENTER("wolfSSL_BN_MONT_CTX_set");
return WOLFSSL_SUCCESS;
}
int wolfSSL_BN_mod_exp_mont_word(WOLFSSL_BIGNUM *r, WOLFSSL_BN_ULONG a,
const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx,
WOLFSSL_BN_MONT_CTX *mont)
{
WOLFSSL_BIGNUM* tmp = NULL;
int ret = WOLFSSL_SUCCESS;
(void)mont;
WOLFSSL_ENTER("wolfSSL_BN_mod_exp_mont_word");
if (ret == WOLFSSL_SUCCESS && (tmp = wolfSSL_BN_new()) == NULL) {
WOLFSSL_MSG("wolfSSL_BN_new failed");
ret = WOLFSSL_FAILURE;
}
if (ret == WOLFSSL_SUCCESS && (wolfSSL_BN_set_word(tmp, (unsigned long)a))
== WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
WOLFSSL_MSG("wolfSSL_BN_set_word failed");
ret = WOLFSSL_FAILURE;
}
if (ret == WOLFSSL_SUCCESS)
ret = wolfSSL_BN_mod_exp(r, tmp, p, m, ctx);
wolfSSL_BN_free(tmp);
return ret;
}
#endif
#endif