Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: wolfcrypt/src/sp_int.c
- Revision:
- 17:ff9d1e86ad5f
- Parent:
- 16:048e5e270a58
--- a/wolfcrypt/src/sp_int.c Tue Nov 19 14:32:16 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,665 +0,0 @@ -/* sp_int.c - * - * Copyright (C) 2006-2017 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 - */ - -/* Implementation by Sean Parkinson. */ - -#ifdef HAVE_CONFIG_H - #include <config.h> -#endif - -#include <wolfssl/wolfcrypt/settings.h> -#include <wolfssl/wolfcrypt/error-crypt.h> -#ifdef NO_INLINE - #include <wolfssl/wolfcrypt/misc.h> -#else - #define WOLFSSL_MISC_INCLUDED - #include <wolfcrypt/src/misc.c> -#endif - - -#ifdef WOLFSSL_SP_MATH - -#include <wolfssl/wolfcrypt/sp_int.h> - -/* Initialize the big number to be zero. - * - * a SP integer. - * returns MP_OKAY always. - */ -int sp_init(sp_int* a) -{ - a->used = 0; - a->size = SP_INT_DIGITS; - - return MP_OKAY; -} - -/* Initialize up to six big numbers to be zero. - * - * a SP integer. - * b SP integer. - * c SP integer. - * d SP integer. - * e SP integer. - * f SP integer. - * returns MP_OKAY always. - */ -int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d, sp_int* e, - sp_int* f) -{ - if (a != NULL) { - a->used = 0; - a->size = SP_INT_DIGITS; - } - if (b != NULL) { - b->used = 0; - b->size = SP_INT_DIGITS; - } - if (c != NULL) { - c->used = 0; - c->size = SP_INT_DIGITS; - } - if (d != NULL) { - d->used = 0; - d->size = SP_INT_DIGITS; - } - if (e != NULL) { - e->used = 0; - e->size = SP_INT_DIGITS; - } - if (f != NULL) { - f->used = 0; - f->size = SP_INT_DIGITS; - } - - return MP_OKAY; -} - -/* Clear the data from the big number and set to zero. - * - * a SP integer. - */ -void sp_clear(sp_int* a) -{ - int i; - - for (i=0; i<a->used; i++) - a->dp[i] = 0; - a->used = 0; -} - -/* Calculate the number of 8-bit values required to represent the big number. - * - * a SP integer. - * returns the count. - */ -int sp_unsigned_bin_size(sp_int* a) -{ - int size = sp_count_bits(a); - return (size + 7) / 8; -} - -/* Convert a number as an array of bytes in big-endian format to a big number. - * - * a SP integer. - * in Array of bytes. - * inSz Number of data bytes in array. - * returns MP_OKAY always. - */ -int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz) -{ - int i, j = 0, s = 0; - - a->dp[0] = 0; - for (i = inSz-1; i >= 0; i--) { - a->dp[j] |= ((sp_int_digit)in[i]) << s; - if (s == DIGIT_BIT - 8) { - a->dp[++j] = 0; - s = 0; - } - else if (s > DIGIT_BIT - 8) { - s = DIGIT_BIT - s; - if (j + 1 >= a->size) - break; - a->dp[++j] = in[i] >> s; - s = 8 - s; - } - else - s += 8; - } - - a->used = j + 1; - if (a->dp[j] == 0) - a->used--; - - for (j++; j < a->size; j++) - a->dp[j] = 0; - - return MP_OKAY; -} - -/* Convert a number as string in big-endian format to a big number. - * Only supports base-16 (hexadecimal). - * Negative values not supported. - * - * a SP integer. - * in NUL terminated string. - * radix Number of values in a digit. - * returns BAD_FUNC_ARG when radix not supported or value is negative, MP_VAL - * when a character is not valid and MP_OKAY otherwise. - */ -int sp_read_radix(sp_int* a, const char* in, int radix) -{ - int i, j, k; - char ch; - - if (radix != 16) - return BAD_FUNC_ARG; - - if (*in == '-') { - return BAD_FUNC_ARG; - } - - j = 0; - k = 0; - a->dp[0] = 0; - for (i = (int)(XSTRLEN(in) - 1); i >= 0; i--) { - ch = in[i]; - if (ch >= '0' && ch <= '9') - ch -= '0'; - else if (ch >= 'A' && ch <= 'F') - ch -= 'A' - 10; - else if (ch >= 'a' && ch <= 'f') - ch -= 'a' - 10; - else - return MP_VAL; - - a->dp[k] |= ((sp_int_digit)ch) << j; - j += 4; - if (j == DIGIT_BIT && k < SP_INT_DIGITS) - a->dp[++k] = 0; - j &= DIGIT_BIT - 1; - } - - a->used = k + 1; - if (a->dp[k] == 0) - a->used--; - - for (k++; k < a->size; k++) - a->dp[k] = 0; - - return MP_OKAY; -} - -/* Compare two big numbers. - * - * a SP integer. - * b SP integer. - * returns MP_GT if a is greater than b, MP_LT if a is less than b and MP_EQ - * when a equals b. - */ -int sp_cmp(sp_int* a, sp_int* b) -{ - int i; - - if (a->used > b->used) - return MP_GT; - else if (a->used < b->used) - return MP_LT; - - for (i = a->used - 1; i >= 0; i--) { - if (a->dp[i] > b->dp[i]) - return MP_GT; - else if (a->dp[i] < b->dp[i]) - return MP_LT; - } - return MP_EQ; -} - -/* Count the number of bits in the big number. - * - * a SP integer. - * returns the number of bits. - */ -int sp_count_bits(sp_int* a) -{ - int r = 0; - sp_int_digit d; - - r = a->used - 1; - while (r >= 0 && a->dp[r] == 0) - r--; - if (r < 0) - r = 0; - else { - d = a->dp[r]; - r *= DIGIT_BIT; - while (d != 0) { - r++; - d >>= 1; - } - } - - return r; -} - -/* Determine if the most significant byte of the encoded big number as the top - * bit set. - * - * a SP integer. - * returns 1 when the top bit is set and 0 otherwise. - */ -int sp_leading_bit(sp_int* a) -{ - int bit = 0; - sp_int_digit d; - - if (a->used > 0) { - d = a->dp[a->used - 1]; - while (d > (sp_int_digit)0xff) - d >>= 8; - bit = (int)(d >> 7); - } - - return bit; -} - -/* Convert the big number to an array of bytes in big-endian format. - * The array must be large enough for encoded number - use mp_unsigned_bin_size - * to calculate the number of bytes required. - * - * a SP integer. - * returns MP_OKAY always. - */ -int sp_to_unsigned_bin(sp_int* a, byte* out) -{ - int i, j, b; - - j = sp_unsigned_bin_size(a) - 1; - for (i=0; j>=0; i++) { - for (b = 0; b < SP_WORD_SIZE; b += 8) { - out[j--] = a->dp[i] >> b; - if (j < 0) - break; - } - } - - return MP_OKAY; -} - -/* Ensure the data in the big number is zeroed. - * - * a SP integer. - */ -void sp_forcezero(sp_int* a) -{ - ForceZero(a->dp, a->used * sizeof(sp_int_digit)); - a->used = 0; -} - -/* Copy value of big number a into b. - * - * a SP integer. - * b SP integer. - * returns MP_OKAY always. - */ -int sp_copy(sp_int* a, sp_int* b) -{ - if (a != b) { - XMEMCPY(b->dp, a->dp, a->used * sizeof(sp_int_digit)); - b->used = a->used; - } - return MP_OKAY; -} - -/* Set the big number to be the value of the digit. - * - * a SP integer. - * d Digit to be set. - * returns MP_OKAY always. - */ -int sp_set(sp_int* a, sp_int_digit d) -{ - a->dp[0] = d; - a->used = 1; - return MP_OKAY; -} - -/* Checks whether the value of the big number is zero. - * - * a SP integer. - * returns 1 when value is zero and 0 otherwise. - */ -int sp_iszero(sp_int* a) -{ - return a->used == 0; -} - -/* Recalculate the number of digits used. - * - * a SP integer. - */ -void sp_clamp(sp_int* a) -{ - int i; - - for (i = a->used - 1; i >= 0 && a->dp[i] == 0; i--) { - } - a->used = i + 1; -} - -/* Grow big number to be able to hold l digits. - * This function does nothing as the number of digits is fixed. - * - * a SP integer. - * l Number of digits. - * retuns MP_MEM if the number of digits requested is more than available and - * MP_OKAY otherwise. - */ -int sp_grow(sp_int* a, int l) -{ - if (l > a->size) - return MP_MEM; - (void)a; - (void)l; - return MP_OKAY; -} - -/* Sub a one digit number from the big number. - * - * a SP integer. - * d Digit to subtract. - * r SP integer - result. - * returns MP_OKAY always. - */ -int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r) -{ - int i = 0; - - r->used = a->used; - r->dp[0] = a->dp[0] - d; - if (r->dp[i] > a->dp[i]) { - for (; i < a->used; i++) { - r->dp[i] = a->dp[i] - 1; - if (r->dp[i] != (sp_int_digit)-1) - break; - } - } - for (; i < a->used; i++) - r->dp[i] = a->dp[i]; - - return MP_OKAY; -} - -/* Compare a one digit number with a big number. - * - * a SP integer. - * d Digit to compare with. - * returns MP_GT if a is greater than d, MP_LT if a is less than d and MP_EQ - * when a equals d. - */ -int sp_cmp_d(sp_int *a, sp_int_digit d) -{ - /* special case for zero*/ - if (a->used == 0) { - if (d == 0) - return MP_EQ; - else - return MP_LT; - } - else if (a->used > 1) - return MP_GT; - - /* compare the only digit of a to d */ - if (a->dp[0] > d) - return MP_GT; - else if (a->dp[0] < d) - return MP_LT; - return MP_EQ; -} - -/* Left shift the number by number of bits. - * Bits may be larger than the word size. - * - * a SP integer. - * n Number of bits to shift. - * returns MP_OKAY always. - */ -static int sp_lshb(sp_int* a, int n) -{ - int i; - - if (n >= SP_WORD_SIZE) { - sp_lshd(a, n / SP_WORD_SIZE); - n %= SP_WORD_SIZE; - } - - if (n == 0) - return MP_OKAY; - - a->dp[a->used] = 0; - for (i = a->used - 1; i >= 0; i--) { - a->dp[i+1] |= a->dp[i] >> (SP_WORD_SIZE - n); - a->dp[i] = a->dp[i] << n; - } - if (a->dp[a->used] != 0) - a->used++; - - return MP_OKAY; -} - -/* Subtract two large numbers into result: r = a - b - * a must be greater than b. - * - * a SP integer. - * b SP integer. - * r SP integer. - * returns MP_OKAY always. - */ -static int sp_sub(sp_int* a, sp_int* b, sp_int* r) -{ - int i; - sp_int_digit c = 0; - sp_int_digit t; - - for (i = 0; i < a->used && i < b->used; i++) { - t = a->dp[i] - b->dp[i] - c; - if (c == 0) - c = t > a->dp[i]; - else - c = t >= a->dp[i]; - r->dp[i] = t; - } - for (; i < a->used; i++) { - r->dp[i] = a->dp[i] - c; - c = r->dp[i] == (sp_int_digit)-1; - } - r->used = i; - sp_clamp(r); - - return MP_OKAY; -} - -/* Calculate the r = a mod m. - * - * a SP integer. - * m SP integer. - * r SP integer. - * returns MP_OKAY always. - */ -int sp_mod(sp_int* a, sp_int* m, sp_int* r) -{ - sp_int t; - int mBits = sp_count_bits(m); - int rBits; - - if (a != r) - sp_copy(a, r); - sp_init(&t); - - rBits = sp_count_bits(r); - while (rBits > mBits) { - sp_copy(m, &t); - sp_lshb(&t, rBits - mBits); - - if (sp_cmp(&t, r) == MP_GT) { - sp_copy(m, &t); - sp_lshb(&t, rBits - mBits - 1); - } - sp_sub(r, &t, r); - - rBits = sp_count_bits(r); - } - if (sp_cmp(r, m) != MP_LT) - sp_sub(r, m, r); - - return MP_OKAY; -} - -#if defined(USE_FAST_MATH) || !defined(NO_BIG_INT) -/* Clear all data in the big number and sets value to zero. - * - * a SP integer. - */ -void sp_zero(sp_int* a) -{ - XMEMSET(a->dp, 0, a->size); - a->used = 0; -} - -/* Add a one digit number to the big number. - * - * a SP integer. - * d Digit to add. - * r SP integer - result. - * returns MP_OKAY always. - */ -int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r) -{ - int i = 0; - - r->used = a->used; - r->dp[0] = a->dp[0] + d; - if (r->dp[i] < a->dp[i]) { - for (; i < a->used; i++) { - r->dp[i] = a->dp[i] + 1; - if (r->dp[i] != 0) - break; - } - - if (i == a->used) { - r->used++; - r->dp[i] = 1; - } - } - for (; i < a->used; i++) - r->dp[i] = a->dp[i]; - - return MP_OKAY; -} - -/* Left shift the big number by a number of digits. - * WIll chop off digits overflowing maximum size. - * - * a SP integer. - * s Number of digits to shift. - * returns MP_OKAY always. - */ -int sp_lshd(sp_int* a, int s) -{ - if (a->used + s > a->size) - a->used = a->size - s; - - XMEMMOVE(a->dp + s, a->dp, a->used * SP_INT_DIGITS); - a->used += s; - XMEMSET(a->dp, 0, s * sizeof(sp_int_digit)); - - return MP_OKAY; -} -#endif - -#ifndef NO_PWDBASED -/* Add two large numbers into result: r = a + b - * - * a SP integer. - * b SP integer. - * r SP integer. - * returns MP_OKAY always. - */ -int sp_add(sp_int* a, sp_int* b, sp_int* r) -{ - int i; - sp_digit c = 0; - sp_digit t; - - for (i = 0; i < a->used && i < b->used; i++) { - t = a->dp[i] + b->dp[i] + c; - if (c == 0) - c = t < a->dp[i]; - else - c = t <= a->dp[i]; - r->dp[i] = t; - } - for (; i < a->used; i++) { - r->dp[i] = a->dp[i] + c; - c = r->dp[i] == 0; - } - for (; i < b->used; i++) { - r->dp[i] = b->dp[i] + c; - c = r->dp[i] == 0; - } - r->dp[i] = c; - r->used = (int)(i + c); - - return MP_OKAY; -} -#endif - -#ifndef NO_RSA -/* Set a number into the big number. - * - * a SP integer. - * b Value to set. - * returns MP_OKAY always. - */ -int sp_set_int(sp_int* a, unsigned long b) -{ - a->used = 1; - a->dp[0] = b; - - return MP_OKAY; -} -#endif - -#if !defined(USE_FAST_MATH) -/* Returns the run time settings. - * - * returns the settings value. - */ -word32 CheckRunTimeSettings(void) -{ - return CTC_SETTINGS; -} -#endif - -#endif - -