wolfSSL SSL/TLS library, support up to TLS1.3

Dependents:   CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more

Committer:
wolfSSL
Date:
Fri Jun 05 00:11:07 2020 +0000
Revision:
17:a5f916481144
Parent:
16:8e0d178b1d1e
wolfSSL 4.4.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wolfSSL 15:117db924cf7c 1 /* tfm.c
wolfSSL 15:117db924cf7c 2 *
wolfSSL 16:8e0d178b1d1e 3 * Copyright (C) 2006-2020 wolfSSL Inc.
wolfSSL 15:117db924cf7c 4 *
wolfSSL 15:117db924cf7c 5 * This file is part of wolfSSL.
wolfSSL 15:117db924cf7c 6 *
wolfSSL 15:117db924cf7c 7 * wolfSSL is free software; you can redistribute it and/or modify
wolfSSL 15:117db924cf7c 8 * it under the terms of the GNU General Public License as published by
wolfSSL 15:117db924cf7c 9 * the Free Software Foundation; either version 2 of the License, or
wolfSSL 15:117db924cf7c 10 * (at your option) any later version.
wolfSSL 15:117db924cf7c 11 *
wolfSSL 15:117db924cf7c 12 * wolfSSL is distributed in the hope that it will be useful,
wolfSSL 15:117db924cf7c 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
wolfSSL 15:117db924cf7c 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wolfSSL 15:117db924cf7c 15 * GNU General Public License for more details.
wolfSSL 15:117db924cf7c 16 *
wolfSSL 15:117db924cf7c 17 * You should have received a copy of the GNU General Public License
wolfSSL 15:117db924cf7c 18 * along with this program; if not, write to the Free Software
wolfSSL 15:117db924cf7c 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
wolfSSL 15:117db924cf7c 20 */
wolfSSL 15:117db924cf7c 21
wolfSSL 15:117db924cf7c 22
wolfSSL 15:117db924cf7c 23
wolfSSL 15:117db924cf7c 24 /*
wolfSSL 15:117db924cf7c 25 * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca,
wolfSSL 15:117db924cf7c 26 * http://math.libtomcrypt.com
wolfSSL 15:117db924cf7c 27 */
wolfSSL 15:117db924cf7c 28
wolfSSL 15:117db924cf7c 29 /**
wolfSSL 15:117db924cf7c 30 * Edited by Moises Guimaraes (moises@wolfssl.com)
wolfSSL 15:117db924cf7c 31 * to fit wolfSSL's needs.
wolfSSL 15:117db924cf7c 32 */
wolfSSL 15:117db924cf7c 33
wolfSSL 15:117db924cf7c 34 #ifdef HAVE_CONFIG_H
wolfSSL 15:117db924cf7c 35 #include <config.h>
wolfSSL 15:117db924cf7c 36 #endif
wolfSSL 15:117db924cf7c 37
wolfSSL 15:117db924cf7c 38 /* in case user set USE_FAST_MATH there */
wolfSSL 15:117db924cf7c 39 #include <wolfssl/wolfcrypt/settings.h>
wolfSSL 15:117db924cf7c 40 #ifdef NO_INLINE
wolfSSL 15:117db924cf7c 41 #include <wolfssl/wolfcrypt/misc.h>
wolfSSL 15:117db924cf7c 42 #else
wolfSSL 15:117db924cf7c 43 #define WOLFSSL_MISC_INCLUDED
wolfSSL 15:117db924cf7c 44 #include <wolfcrypt/src/misc.c>
wolfSSL 15:117db924cf7c 45 #endif
wolfSSL 15:117db924cf7c 46
wolfSSL 15:117db924cf7c 47 #ifdef USE_FAST_MATH
wolfSSL 15:117db924cf7c 48
wolfSSL 15:117db924cf7c 49 #include <wolfssl/wolfcrypt/random.h>
wolfSSL 15:117db924cf7c 50 #include <wolfssl/wolfcrypt/tfm.h>
wolfSSL 15:117db924cf7c 51 #include <wolfcrypt/src/asm.c> /* will define asm MACROS or C ones */
wolfSSL 15:117db924cf7c 52 #include <wolfssl/wolfcrypt/wolfmath.h> /* common functions */
wolfSSL 15:117db924cf7c 53
wolfSSL 15:117db924cf7c 54 #if defined(FREESCALE_LTC_TFM)
wolfSSL 15:117db924cf7c 55 #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
wolfSSL 15:117db924cf7c 56 #endif
wolfSSL 15:117db924cf7c 57 #ifdef WOLFSSL_DEBUG_MATH
wolfSSL 15:117db924cf7c 58 #include <stdio.h>
wolfSSL 15:117db924cf7c 59 #endif
wolfSSL 15:117db924cf7c 60
wolfSSL 16:8e0d178b1d1e 61 #ifdef USE_WINDOWS_API
wolfSSL 16:8e0d178b1d1e 62 #pragma warning(disable:4127)
wolfSSL 16:8e0d178b1d1e 63 /* Disables the warning:
wolfSSL 16:8e0d178b1d1e 64 * 4127: conditional expression is constant
wolfSSL 16:8e0d178b1d1e 65 * in this file.
wolfSSL 16:8e0d178b1d1e 66 */
wolfSSL 16:8e0d178b1d1e 67 #endif
wolfSSL 16:8e0d178b1d1e 68
wolfSSL 16:8e0d178b1d1e 69 #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
wolfSSL 16:8e0d178b1d1e 70 #ifdef __cplusplus
wolfSSL 16:8e0d178b1d1e 71 extern "C" {
wolfSSL 16:8e0d178b1d1e 72 #endif
wolfSSL 16:8e0d178b1d1e 73 WOLFSSL_LOCAL int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod,
wolfSSL 16:8e0d178b1d1e 74 mp_int* res);
wolfSSL 16:8e0d178b1d1e 75 WOLFSSL_LOCAL int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod,
wolfSSL 16:8e0d178b1d1e 76 mp_int* res);
wolfSSL 16:8e0d178b1d1e 77 WOLFSSL_LOCAL int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod,
wolfSSL 16:8e0d178b1d1e 78 mp_int* res);
wolfSSL 16:8e0d178b1d1e 79 WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod,
wolfSSL 16:8e0d178b1d1e 80 mp_int* res);
wolfSSL 16:8e0d178b1d1e 81 WOLFSSL_LOCAL int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod,
wolfSSL 16:8e0d178b1d1e 82 mp_int* res);
wolfSSL 16:8e0d178b1d1e 83 #ifdef __cplusplus
wolfSSL 16:8e0d178b1d1e 84 } /* extern "C" */
wolfSSL 16:8e0d178b1d1e 85 #endif
wolfSSL 16:8e0d178b1d1e 86 #endif
wolfSSL 16:8e0d178b1d1e 87
wolfSSL 16:8e0d178b1d1e 88
wolfSSL 16:8e0d178b1d1e 89 #ifndef WOLFSSL_SP_MATH
wolfSSL 15:117db924cf7c 90 /* math settings check */
wolfSSL 15:117db924cf7c 91 word32 CheckRunTimeSettings(void)
wolfSSL 15:117db924cf7c 92 {
wolfSSL 15:117db924cf7c 93 return CTC_SETTINGS;
wolfSSL 15:117db924cf7c 94 }
wolfSSL 16:8e0d178b1d1e 95 #endif
wolfSSL 15:117db924cf7c 96
wolfSSL 15:117db924cf7c 97 /* math settings size check */
wolfSSL 15:117db924cf7c 98 word32 CheckRunTimeFastMath(void)
wolfSSL 15:117db924cf7c 99 {
wolfSSL 15:117db924cf7c 100 return FP_SIZE;
wolfSSL 15:117db924cf7c 101 }
wolfSSL 15:117db924cf7c 102
wolfSSL 15:117db924cf7c 103
wolfSSL 15:117db924cf7c 104 /* Functions */
wolfSSL 15:117db924cf7c 105
wolfSSL 15:117db924cf7c 106 void fp_add(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 15:117db924cf7c 107 {
wolfSSL 15:117db924cf7c 108 int sa, sb;
wolfSSL 15:117db924cf7c 109
wolfSSL 15:117db924cf7c 110 /* get sign of both inputs */
wolfSSL 15:117db924cf7c 111 sa = a->sign;
wolfSSL 15:117db924cf7c 112 sb = b->sign;
wolfSSL 15:117db924cf7c 113
wolfSSL 15:117db924cf7c 114 /* handle two cases, not four */
wolfSSL 15:117db924cf7c 115 if (sa == sb) {
wolfSSL 15:117db924cf7c 116 /* both positive or both negative */
wolfSSL 15:117db924cf7c 117 /* add their magnitudes, copy the sign */
wolfSSL 15:117db924cf7c 118 c->sign = sa;
wolfSSL 15:117db924cf7c 119 s_fp_add (a, b, c);
wolfSSL 15:117db924cf7c 120 } else {
wolfSSL 15:117db924cf7c 121 /* one positive, the other negative */
wolfSSL 15:117db924cf7c 122 /* subtract the one with the greater magnitude from */
wolfSSL 15:117db924cf7c 123 /* the one of the lesser magnitude. The result gets */
wolfSSL 15:117db924cf7c 124 /* the sign of the one with the greater magnitude. */
wolfSSL 15:117db924cf7c 125 if (fp_cmp_mag (a, b) == FP_LT) {
wolfSSL 15:117db924cf7c 126 c->sign = sb;
wolfSSL 15:117db924cf7c 127 s_fp_sub (b, a, c);
wolfSSL 15:117db924cf7c 128 } else {
wolfSSL 15:117db924cf7c 129 c->sign = sa;
wolfSSL 15:117db924cf7c 130 s_fp_sub (a, b, c);
wolfSSL 15:117db924cf7c 131 }
wolfSSL 15:117db924cf7c 132 }
wolfSSL 15:117db924cf7c 133 }
wolfSSL 15:117db924cf7c 134
wolfSSL 15:117db924cf7c 135 /* unsigned addition */
wolfSSL 15:117db924cf7c 136 void s_fp_add(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 15:117db924cf7c 137 {
wolfSSL 15:117db924cf7c 138 int x, y, oldused;
wolfSSL 15:117db924cf7c 139 fp_word t;
wolfSSL 15:117db924cf7c 140
wolfSSL 15:117db924cf7c 141 y = MAX(a->used, b->used);
wolfSSL 15:117db924cf7c 142 oldused = MIN(c->used, FP_SIZE); /* help static analysis w/ largest size */
wolfSSL 15:117db924cf7c 143 c->used = y;
wolfSSL 15:117db924cf7c 144
wolfSSL 15:117db924cf7c 145 t = 0;
wolfSSL 15:117db924cf7c 146 for (x = 0; x < y; x++) {
wolfSSL 15:117db924cf7c 147 t += ((fp_word)a->dp[x]) + ((fp_word)b->dp[x]);
wolfSSL 15:117db924cf7c 148 c->dp[x] = (fp_digit)t;
wolfSSL 15:117db924cf7c 149 t >>= DIGIT_BIT;
wolfSSL 15:117db924cf7c 150 }
wolfSSL 15:117db924cf7c 151 if (t != 0 && x < FP_SIZE) {
wolfSSL 15:117db924cf7c 152 c->dp[c->used++] = (fp_digit)t;
wolfSSL 15:117db924cf7c 153 ++x;
wolfSSL 15:117db924cf7c 154 }
wolfSSL 15:117db924cf7c 155
wolfSSL 15:117db924cf7c 156 c->used = x;
wolfSSL 15:117db924cf7c 157
wolfSSL 15:117db924cf7c 158 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 15:117db924cf7c 159 for (; x < oldused; x++) {
wolfSSL 15:117db924cf7c 160 c->dp[x] = 0;
wolfSSL 15:117db924cf7c 161 }
wolfSSL 15:117db924cf7c 162 fp_clamp(c);
wolfSSL 15:117db924cf7c 163 }
wolfSSL 15:117db924cf7c 164
wolfSSL 15:117db924cf7c 165 /* c = a - b */
wolfSSL 15:117db924cf7c 166 void fp_sub(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 15:117db924cf7c 167 {
wolfSSL 15:117db924cf7c 168 int sa, sb;
wolfSSL 15:117db924cf7c 169
wolfSSL 15:117db924cf7c 170 sa = a->sign;
wolfSSL 15:117db924cf7c 171 sb = b->sign;
wolfSSL 15:117db924cf7c 172
wolfSSL 15:117db924cf7c 173 if (sa != sb) {
wolfSSL 15:117db924cf7c 174 /* subtract a negative from a positive, OR */
wolfSSL 15:117db924cf7c 175 /* subtract a positive from a negative. */
wolfSSL 15:117db924cf7c 176 /* In either case, ADD their magnitudes, */
wolfSSL 15:117db924cf7c 177 /* and use the sign of the first number. */
wolfSSL 15:117db924cf7c 178 c->sign = sa;
wolfSSL 15:117db924cf7c 179 s_fp_add (a, b, c);
wolfSSL 15:117db924cf7c 180 } else {
wolfSSL 15:117db924cf7c 181 /* subtract a positive from a positive, OR */
wolfSSL 15:117db924cf7c 182 /* subtract a negative from a negative. */
wolfSSL 15:117db924cf7c 183 /* First, take the difference between their */
wolfSSL 15:117db924cf7c 184 /* magnitudes, then... */
wolfSSL 15:117db924cf7c 185 if (fp_cmp_mag (a, b) != FP_LT) {
wolfSSL 15:117db924cf7c 186 /* Copy the sign from the first */
wolfSSL 15:117db924cf7c 187 c->sign = sa;
wolfSSL 15:117db924cf7c 188 /* The first has a larger or equal magnitude */
wolfSSL 15:117db924cf7c 189 s_fp_sub (a, b, c);
wolfSSL 15:117db924cf7c 190 } else {
wolfSSL 15:117db924cf7c 191 /* The result has the *opposite* sign from */
wolfSSL 15:117db924cf7c 192 /* the first number. */
wolfSSL 15:117db924cf7c 193 c->sign = (sa == FP_ZPOS) ? FP_NEG : FP_ZPOS;
wolfSSL 15:117db924cf7c 194 /* The second has a larger magnitude */
wolfSSL 15:117db924cf7c 195 s_fp_sub (b, a, c);
wolfSSL 15:117db924cf7c 196 }
wolfSSL 15:117db924cf7c 197 }
wolfSSL 15:117db924cf7c 198 }
wolfSSL 15:117db924cf7c 199
wolfSSL 15:117db924cf7c 200 /* unsigned subtraction ||a|| >= ||b|| ALWAYS! */
wolfSSL 15:117db924cf7c 201 void s_fp_sub(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 15:117db924cf7c 202 {
wolfSSL 15:117db924cf7c 203 int x, oldbused, oldused;
wolfSSL 15:117db924cf7c 204 fp_word t;
wolfSSL 15:117db924cf7c 205
wolfSSL 15:117db924cf7c 206 oldused = c->used;
wolfSSL 15:117db924cf7c 207 oldbused = b->used;
wolfSSL 15:117db924cf7c 208 c->used = a->used;
wolfSSL 15:117db924cf7c 209 t = 0;
wolfSSL 15:117db924cf7c 210 for (x = 0; x < oldbused; x++) {
wolfSSL 15:117db924cf7c 211 t = ((fp_word)a->dp[x]) - (((fp_word)b->dp[x]) + t);
wolfSSL 15:117db924cf7c 212 c->dp[x] = (fp_digit)t;
wolfSSL 15:117db924cf7c 213 t = (t >> DIGIT_BIT)&1;
wolfSSL 15:117db924cf7c 214 }
wolfSSL 15:117db924cf7c 215 for (; x < a->used; x++) {
wolfSSL 15:117db924cf7c 216 t = ((fp_word)a->dp[x]) - t;
wolfSSL 15:117db924cf7c 217 c->dp[x] = (fp_digit)t;
wolfSSL 15:117db924cf7c 218 t = (t >> DIGIT_BIT)&1;
wolfSSL 15:117db924cf7c 219 }
wolfSSL 15:117db924cf7c 220
wolfSSL 15:117db924cf7c 221 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 15:117db924cf7c 222 for (; x < oldused; x++) {
wolfSSL 15:117db924cf7c 223 c->dp[x] = 0;
wolfSSL 15:117db924cf7c 224 }
wolfSSL 15:117db924cf7c 225 fp_clamp(c);
wolfSSL 15:117db924cf7c 226 }
wolfSSL 15:117db924cf7c 227
wolfSSL 15:117db924cf7c 228 /* c = a * b */
wolfSSL 16:8e0d178b1d1e 229 int fp_mul(fp_int *A, fp_int *B, fp_int *C)
wolfSSL 15:117db924cf7c 230 {
wolfSSL 16:8e0d178b1d1e 231 int ret = 0;
wolfSSL 15:117db924cf7c 232 int y, yy, oldused;
wolfSSL 15:117db924cf7c 233
wolfSSL 16:8e0d178b1d1e 234 #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
wolfSSL 16:8e0d178b1d1e 235 !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
wolfSSL 16:8e0d178b1d1e 236 ret = esp_mp_mul(A, B, C);
wolfSSL 16:8e0d178b1d1e 237 if(ret != -2) return ret;
wolfSSL 16:8e0d178b1d1e 238 #endif
wolfSSL 16:8e0d178b1d1e 239
wolfSSL 15:117db924cf7c 240 oldused = C->used;
wolfSSL 15:117db924cf7c 241
wolfSSL 15:117db924cf7c 242 y = MAX(A->used, B->used);
wolfSSL 15:117db924cf7c 243 yy = MIN(A->used, B->used);
wolfSSL 15:117db924cf7c 244
wolfSSL 15:117db924cf7c 245 /* call generic if we're out of range */
wolfSSL 15:117db924cf7c 246 if (y + yy > FP_SIZE) {
wolfSSL 16:8e0d178b1d1e 247 ret = fp_mul_comba(A, B, C);
wolfSSL 15:117db924cf7c 248 goto clean;
wolfSSL 15:117db924cf7c 249 }
wolfSSL 15:117db924cf7c 250
wolfSSL 15:117db924cf7c 251 /* pick a comba (unrolled 4/8/16/32 x or rolled) based on the size
wolfSSL 15:117db924cf7c 252 of the largest input. We also want to avoid doing excess mults if the
wolfSSL 15:117db924cf7c 253 inputs are not close to the next power of two. That is, for example,
wolfSSL 15:117db924cf7c 254 if say y=17 then we would do (32-17)^2 = 225 unneeded multiplications
wolfSSL 15:117db924cf7c 255 */
wolfSSL 15:117db924cf7c 256
wolfSSL 15:117db924cf7c 257 #if defined(TFM_MUL3) && FP_SIZE >= 6
wolfSSL 15:117db924cf7c 258 if (y <= 3) {
wolfSSL 16:8e0d178b1d1e 259 ret = fp_mul_comba3(A,B,C);
wolfSSL 15:117db924cf7c 260 goto clean;
wolfSSL 15:117db924cf7c 261 }
wolfSSL 15:117db924cf7c 262 #endif
wolfSSL 15:117db924cf7c 263 #if defined(TFM_MUL4) && FP_SIZE >= 8
wolfSSL 15:117db924cf7c 264 if (y == 4) {
wolfSSL 16:8e0d178b1d1e 265 ret = fp_mul_comba4(A,B,C);
wolfSSL 15:117db924cf7c 266 goto clean;
wolfSSL 15:117db924cf7c 267 }
wolfSSL 15:117db924cf7c 268 #endif
wolfSSL 15:117db924cf7c 269 #if defined(TFM_MUL6) && FP_SIZE >= 12
wolfSSL 15:117db924cf7c 270 if (y <= 6) {
wolfSSL 16:8e0d178b1d1e 271 ret = fp_mul_comba6(A,B,C);
wolfSSL 15:117db924cf7c 272 goto clean;
wolfSSL 15:117db924cf7c 273 }
wolfSSL 15:117db924cf7c 274 #endif
wolfSSL 15:117db924cf7c 275 #if defined(TFM_MUL7) && FP_SIZE >= 14
wolfSSL 15:117db924cf7c 276 if (y == 7) {
wolfSSL 16:8e0d178b1d1e 277 ret = fp_mul_comba7(A,B,C);
wolfSSL 15:117db924cf7c 278 goto clean;
wolfSSL 15:117db924cf7c 279 }
wolfSSL 15:117db924cf7c 280 #endif
wolfSSL 15:117db924cf7c 281 #if defined(TFM_MUL8) && FP_SIZE >= 16
wolfSSL 15:117db924cf7c 282 if (y == 8) {
wolfSSL 16:8e0d178b1d1e 283 ret = fp_mul_comba8(A,B,C);
wolfSSL 15:117db924cf7c 284 goto clean;
wolfSSL 15:117db924cf7c 285 }
wolfSSL 15:117db924cf7c 286 #endif
wolfSSL 15:117db924cf7c 287 #if defined(TFM_MUL9) && FP_SIZE >= 18
wolfSSL 15:117db924cf7c 288 if (y == 9) {
wolfSSL 16:8e0d178b1d1e 289 ret = fp_mul_comba9(A,B,C);
wolfSSL 15:117db924cf7c 290 goto clean;
wolfSSL 15:117db924cf7c 291 }
wolfSSL 15:117db924cf7c 292 #endif
wolfSSL 15:117db924cf7c 293 #if defined(TFM_MUL12) && FP_SIZE >= 24
wolfSSL 15:117db924cf7c 294 if (y <= 12) {
wolfSSL 16:8e0d178b1d1e 295 ret = fp_mul_comba12(A,B,C);
wolfSSL 15:117db924cf7c 296 goto clean;
wolfSSL 15:117db924cf7c 297 }
wolfSSL 15:117db924cf7c 298 #endif
wolfSSL 15:117db924cf7c 299 #if defined(TFM_MUL17) && FP_SIZE >= 34
wolfSSL 15:117db924cf7c 300 if (y <= 17) {
wolfSSL 16:8e0d178b1d1e 301 ret = fp_mul_comba17(A,B,C);
wolfSSL 15:117db924cf7c 302 goto clean;
wolfSSL 15:117db924cf7c 303 }
wolfSSL 15:117db924cf7c 304 #endif
wolfSSL 15:117db924cf7c 305
wolfSSL 15:117db924cf7c 306 #if defined(TFM_SMALL_SET) && FP_SIZE >= 32
wolfSSL 15:117db924cf7c 307 if (y <= 16) {
wolfSSL 16:8e0d178b1d1e 308 ret = fp_mul_comba_small(A,B,C);
wolfSSL 15:117db924cf7c 309 goto clean;
wolfSSL 15:117db924cf7c 310 }
wolfSSL 15:117db924cf7c 311 #endif
wolfSSL 15:117db924cf7c 312 #if defined(TFM_MUL20) && FP_SIZE >= 40
wolfSSL 15:117db924cf7c 313 if (y <= 20) {
wolfSSL 16:8e0d178b1d1e 314 ret = fp_mul_comba20(A,B,C);
wolfSSL 15:117db924cf7c 315 goto clean;
wolfSSL 15:117db924cf7c 316 }
wolfSSL 15:117db924cf7c 317 #endif
wolfSSL 15:117db924cf7c 318 #if defined(TFM_MUL24) && FP_SIZE >= 48
wolfSSL 15:117db924cf7c 319 if (yy >= 16 && y <= 24) {
wolfSSL 16:8e0d178b1d1e 320 ret = fp_mul_comba24(A,B,C);
wolfSSL 15:117db924cf7c 321 goto clean;
wolfSSL 15:117db924cf7c 322 }
wolfSSL 15:117db924cf7c 323 #endif
wolfSSL 15:117db924cf7c 324 #if defined(TFM_MUL28) && FP_SIZE >= 56
wolfSSL 15:117db924cf7c 325 if (yy >= 20 && y <= 28) {
wolfSSL 16:8e0d178b1d1e 326 ret = fp_mul_comba28(A,B,C);
wolfSSL 15:117db924cf7c 327 goto clean;
wolfSSL 15:117db924cf7c 328 }
wolfSSL 15:117db924cf7c 329 #endif
wolfSSL 15:117db924cf7c 330 #if defined(TFM_MUL32) && FP_SIZE >= 64
wolfSSL 15:117db924cf7c 331 if (yy >= 24 && y <= 32) {
wolfSSL 16:8e0d178b1d1e 332 ret = fp_mul_comba32(A,B,C);
wolfSSL 15:117db924cf7c 333 goto clean;
wolfSSL 15:117db924cf7c 334 }
wolfSSL 15:117db924cf7c 335 #endif
wolfSSL 15:117db924cf7c 336 #if defined(TFM_MUL48) && FP_SIZE >= 96
wolfSSL 15:117db924cf7c 337 if (yy >= 40 && y <= 48) {
wolfSSL 16:8e0d178b1d1e 338 ret = fp_mul_comba48(A,B,C);
wolfSSL 15:117db924cf7c 339 goto clean;
wolfSSL 15:117db924cf7c 340 }
wolfSSL 15:117db924cf7c 341 #endif
wolfSSL 15:117db924cf7c 342 #if defined(TFM_MUL64) && FP_SIZE >= 128
wolfSSL 15:117db924cf7c 343 if (yy >= 56 && y <= 64) {
wolfSSL 16:8e0d178b1d1e 344 ret = fp_mul_comba64(A,B,C);
wolfSSL 15:117db924cf7c 345 goto clean;
wolfSSL 15:117db924cf7c 346 }
wolfSSL 15:117db924cf7c 347 #endif
wolfSSL 16:8e0d178b1d1e 348 ret = fp_mul_comba(A,B,C);
wolfSSL 15:117db924cf7c 349
wolfSSL 15:117db924cf7c 350 clean:
wolfSSL 15:117db924cf7c 351 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 15:117db924cf7c 352 for (y = C->used; y >= 0 && y < oldused; y++) {
wolfSSL 15:117db924cf7c 353 C->dp[y] = 0;
wolfSSL 15:117db924cf7c 354 }
wolfSSL 16:8e0d178b1d1e 355
wolfSSL 16:8e0d178b1d1e 356 return ret;
wolfSSL 15:117db924cf7c 357 }
wolfSSL 15:117db924cf7c 358
wolfSSL 15:117db924cf7c 359 void fp_mul_2(fp_int * a, fp_int * b)
wolfSSL 15:117db924cf7c 360 {
wolfSSL 15:117db924cf7c 361 int x, oldused;
wolfSSL 15:117db924cf7c 362
wolfSSL 15:117db924cf7c 363 oldused = b->used;
wolfSSL 15:117db924cf7c 364 b->used = a->used;
wolfSSL 15:117db924cf7c 365
wolfSSL 15:117db924cf7c 366 {
wolfSSL 15:117db924cf7c 367 fp_digit r, rr, *tmpa, *tmpb;
wolfSSL 15:117db924cf7c 368
wolfSSL 15:117db924cf7c 369 /* alias for source */
wolfSSL 15:117db924cf7c 370 tmpa = a->dp;
wolfSSL 15:117db924cf7c 371
wolfSSL 15:117db924cf7c 372 /* alias for dest */
wolfSSL 15:117db924cf7c 373 tmpb = b->dp;
wolfSSL 15:117db924cf7c 374
wolfSSL 15:117db924cf7c 375 /* carry */
wolfSSL 15:117db924cf7c 376 r = 0;
wolfSSL 15:117db924cf7c 377 for (x = 0; x < a->used; x++) {
wolfSSL 15:117db924cf7c 378
wolfSSL 15:117db924cf7c 379 /* get what will be the *next* carry bit from the
wolfSSL 15:117db924cf7c 380 * MSB of the current digit
wolfSSL 15:117db924cf7c 381 */
wolfSSL 15:117db924cf7c 382 rr = *tmpa >> ((fp_digit)(DIGIT_BIT - 1));
wolfSSL 15:117db924cf7c 383
wolfSSL 15:117db924cf7c 384 /* now shift up this digit, add in the carry [from the previous] */
wolfSSL 15:117db924cf7c 385 *tmpb++ = ((*tmpa++ << ((fp_digit)1)) | r);
wolfSSL 15:117db924cf7c 386
wolfSSL 15:117db924cf7c 387 /* copy the carry that would be from the source
wolfSSL 15:117db924cf7c 388 * digit into the next iteration
wolfSSL 15:117db924cf7c 389 */
wolfSSL 15:117db924cf7c 390 r = rr;
wolfSSL 15:117db924cf7c 391 }
wolfSSL 15:117db924cf7c 392
wolfSSL 15:117db924cf7c 393 /* new leading digit? */
wolfSSL 15:117db924cf7c 394 if (r != 0 && b->used != (FP_SIZE-1)) {
wolfSSL 15:117db924cf7c 395 /* add a MSB which is always 1 at this point */
wolfSSL 15:117db924cf7c 396 *tmpb = 1;
wolfSSL 15:117db924cf7c 397 ++(b->used);
wolfSSL 15:117db924cf7c 398 }
wolfSSL 15:117db924cf7c 399
wolfSSL 15:117db924cf7c 400 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 15:117db924cf7c 401 tmpb = b->dp + b->used;
wolfSSL 15:117db924cf7c 402 for (x = b->used; x < oldused; x++) {
wolfSSL 15:117db924cf7c 403 *tmpb++ = 0;
wolfSSL 15:117db924cf7c 404 }
wolfSSL 15:117db924cf7c 405 }
wolfSSL 15:117db924cf7c 406 b->sign = a->sign;
wolfSSL 15:117db924cf7c 407 }
wolfSSL 15:117db924cf7c 408
wolfSSL 15:117db924cf7c 409 /* c = a * b */
wolfSSL 15:117db924cf7c 410 void fp_mul_d(fp_int *a, fp_digit b, fp_int *c)
wolfSSL 15:117db924cf7c 411 {
wolfSSL 15:117db924cf7c 412 fp_word w;
wolfSSL 15:117db924cf7c 413 int x, oldused;
wolfSSL 15:117db924cf7c 414
wolfSSL 15:117db924cf7c 415 oldused = c->used;
wolfSSL 15:117db924cf7c 416 c->used = a->used;
wolfSSL 15:117db924cf7c 417 c->sign = a->sign;
wolfSSL 15:117db924cf7c 418 w = 0;
wolfSSL 15:117db924cf7c 419 for (x = 0; x < a->used; x++) {
wolfSSL 15:117db924cf7c 420 w = ((fp_word)a->dp[x]) * ((fp_word)b) + w;
wolfSSL 15:117db924cf7c 421 c->dp[x] = (fp_digit)w;
wolfSSL 15:117db924cf7c 422 w = w >> DIGIT_BIT;
wolfSSL 15:117db924cf7c 423 }
wolfSSL 15:117db924cf7c 424 if (w != 0 && (a->used != FP_SIZE)) {
wolfSSL 15:117db924cf7c 425 c->dp[c->used++] = (fp_digit) w;
wolfSSL 15:117db924cf7c 426 ++x;
wolfSSL 15:117db924cf7c 427 }
wolfSSL 15:117db924cf7c 428
wolfSSL 15:117db924cf7c 429 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 16:8e0d178b1d1e 430 /* also checking FP_SIZE here for static analysis */
wolfSSL 16:8e0d178b1d1e 431 for (; x < oldused && x < FP_SIZE; x++) {
wolfSSL 15:117db924cf7c 432 c->dp[x] = 0;
wolfSSL 15:117db924cf7c 433 }
wolfSSL 15:117db924cf7c 434 fp_clamp(c);
wolfSSL 15:117db924cf7c 435 }
wolfSSL 15:117db924cf7c 436
wolfSSL 15:117db924cf7c 437 /* c = a * 2**d */
wolfSSL 15:117db924cf7c 438 void fp_mul_2d(fp_int *a, int b, fp_int *c)
wolfSSL 15:117db924cf7c 439 {
wolfSSL 15:117db924cf7c 440 fp_digit carry, carrytmp, shift;
wolfSSL 15:117db924cf7c 441 int x;
wolfSSL 15:117db924cf7c 442
wolfSSL 15:117db924cf7c 443 /* copy it */
wolfSSL 15:117db924cf7c 444 fp_copy(a, c);
wolfSSL 15:117db924cf7c 445
wolfSSL 15:117db924cf7c 446 /* handle whole digits */
wolfSSL 15:117db924cf7c 447 if (b >= DIGIT_BIT) {
wolfSSL 15:117db924cf7c 448 fp_lshd(c, b/DIGIT_BIT);
wolfSSL 15:117db924cf7c 449 }
wolfSSL 15:117db924cf7c 450 b %= DIGIT_BIT;
wolfSSL 15:117db924cf7c 451
wolfSSL 15:117db924cf7c 452 /* shift the digits */
wolfSSL 15:117db924cf7c 453 if (b != 0) {
wolfSSL 15:117db924cf7c 454 carry = 0;
wolfSSL 15:117db924cf7c 455 shift = DIGIT_BIT - b;
wolfSSL 15:117db924cf7c 456 for (x = 0; x < c->used; x++) {
wolfSSL 15:117db924cf7c 457 carrytmp = c->dp[x] >> shift;
wolfSSL 15:117db924cf7c 458 c->dp[x] = (c->dp[x] << b) + carry;
wolfSSL 15:117db924cf7c 459 carry = carrytmp;
wolfSSL 15:117db924cf7c 460 }
wolfSSL 15:117db924cf7c 461 /* store last carry if room */
wolfSSL 15:117db924cf7c 462 if (carry && x < FP_SIZE) {
wolfSSL 15:117db924cf7c 463 c->dp[c->used++] = carry;
wolfSSL 15:117db924cf7c 464 }
wolfSSL 15:117db924cf7c 465 }
wolfSSL 15:117db924cf7c 466 fp_clamp(c);
wolfSSL 15:117db924cf7c 467 }
wolfSSL 15:117db924cf7c 468
wolfSSL 15:117db924cf7c 469 /* generic PxQ multiplier */
wolfSSL 15:117db924cf7c 470 #if defined(HAVE_INTEL_MULX)
wolfSSL 15:117db924cf7c 471
wolfSSL 16:8e0d178b1d1e 472 WC_INLINE static int fp_mul_comba_mulx(fp_int *A, fp_int *B, fp_int *C)
wolfSSL 15:117db924cf7c 473
wolfSSL 15:117db924cf7c 474 {
wolfSSL 15:117db924cf7c 475 int ix, iy, iz, pa;
wolfSSL 16:8e0d178b1d1e 476 fp_int *dst;
wolfSSL 16:8e0d178b1d1e 477 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 478 fp_int tmp[1];
wolfSSL 16:8e0d178b1d1e 479 #else
wolfSSL 16:8e0d178b1d1e 480 fp_int *tmp;
wolfSSL 16:8e0d178b1d1e 481 #endif
wolfSSL 16:8e0d178b1d1e 482
wolfSSL 16:8e0d178b1d1e 483 /* Variables used but not seen by cppcheck. */
wolfSSL 16:8e0d178b1d1e 484 (void)ix; (void)iy; (void)iz;
wolfSSL 16:8e0d178b1d1e 485
wolfSSL 16:8e0d178b1d1e 486 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 487 tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 488 if (tmp == NULL)
wolfSSL 16:8e0d178b1d1e 489 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 490 #endif
wolfSSL 15:117db924cf7c 491
wolfSSL 15:117db924cf7c 492 /* get size of output and trim */
wolfSSL 15:117db924cf7c 493 pa = A->used + B->used;
wolfSSL 15:117db924cf7c 494 if (pa >= FP_SIZE) {
wolfSSL 15:117db924cf7c 495 pa = FP_SIZE-1;
wolfSSL 15:117db924cf7c 496 }
wolfSSL 15:117db924cf7c 497
wolfSSL 15:117db924cf7c 498 /* Always take branch to use tmp variable. This avoids a cache attack for
wolfSSL 15:117db924cf7c 499 * determining if C equals A */
wolfSSL 15:117db924cf7c 500 if (1) {
wolfSSL 16:8e0d178b1d1e 501 fp_init(tmp);
wolfSSL 16:8e0d178b1d1e 502 dst = tmp;
wolfSSL 15:117db924cf7c 503 }
wolfSSL 15:117db924cf7c 504
wolfSSL 15:117db924cf7c 505 TFM_INTEL_MUL_COMBA(A, B, dst) ;
wolfSSL 15:117db924cf7c 506
wolfSSL 15:117db924cf7c 507 dst->used = pa;
wolfSSL 15:117db924cf7c 508 dst->sign = A->sign ^ B->sign;
wolfSSL 15:117db924cf7c 509 fp_clamp(dst);
wolfSSL 15:117db924cf7c 510 fp_copy(dst, C);
wolfSSL 16:8e0d178b1d1e 511
wolfSSL 16:8e0d178b1d1e 512 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 513 XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 514 #endif
wolfSSL 16:8e0d178b1d1e 515
wolfSSL 16:8e0d178b1d1e 516 return FP_OKAY;
wolfSSL 15:117db924cf7c 517 }
wolfSSL 15:117db924cf7c 518 #endif
wolfSSL 15:117db924cf7c 519
wolfSSL 16:8e0d178b1d1e 520 int fp_mul_comba(fp_int *A, fp_int *B, fp_int *C)
wolfSSL 15:117db924cf7c 521 {
wolfSSL 16:8e0d178b1d1e 522 int ret = 0;
wolfSSL 15:117db924cf7c 523 int ix, iy, iz, tx, ty, pa;
wolfSSL 15:117db924cf7c 524 fp_digit c0, c1, c2, *tmpx, *tmpy;
wolfSSL 16:8e0d178b1d1e 525 fp_int *dst;
wolfSSL 16:8e0d178b1d1e 526 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 527 fp_int tmp[1];
wolfSSL 16:8e0d178b1d1e 528 #else
wolfSSL 16:8e0d178b1d1e 529 fp_int *tmp;
wolfSSL 16:8e0d178b1d1e 530 #endif
wolfSSL 16:8e0d178b1d1e 531
wolfSSL 16:8e0d178b1d1e 532 IF_HAVE_INTEL_MULX(ret = fp_mul_comba_mulx(A, B, C), return ret) ;
wolfSSL 16:8e0d178b1d1e 533
wolfSSL 16:8e0d178b1d1e 534 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 535 tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 536 if (tmp == NULL)
wolfSSL 16:8e0d178b1d1e 537 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 538 #endif
wolfSSL 15:117db924cf7c 539
wolfSSL 15:117db924cf7c 540 COMBA_START;
wolfSSL 15:117db924cf7c 541 COMBA_CLEAR;
wolfSSL 15:117db924cf7c 542
wolfSSL 15:117db924cf7c 543 /* get size of output and trim */
wolfSSL 15:117db924cf7c 544 pa = A->used + B->used;
wolfSSL 15:117db924cf7c 545 if (pa >= FP_SIZE) {
wolfSSL 15:117db924cf7c 546 pa = FP_SIZE-1;
wolfSSL 15:117db924cf7c 547 }
wolfSSL 15:117db924cf7c 548
wolfSSL 15:117db924cf7c 549 /* Always take branch to use tmp variable. This avoids a cache attack for
wolfSSL 15:117db924cf7c 550 * determining if C equals A */
wolfSSL 15:117db924cf7c 551 if (1) {
wolfSSL 16:8e0d178b1d1e 552 fp_init(tmp);
wolfSSL 16:8e0d178b1d1e 553 dst = tmp;
wolfSSL 15:117db924cf7c 554 }
wolfSSL 15:117db924cf7c 555
wolfSSL 15:117db924cf7c 556 for (ix = 0; ix < pa; ix++) {
wolfSSL 15:117db924cf7c 557 /* get offsets into the two bignums */
wolfSSL 15:117db924cf7c 558 ty = MIN(ix, (B->used > 0 ? B->used - 1 : 0));
wolfSSL 15:117db924cf7c 559 tx = ix - ty;
wolfSSL 15:117db924cf7c 560
wolfSSL 15:117db924cf7c 561 /* setup temp aliases */
wolfSSL 15:117db924cf7c 562 tmpx = A->dp + tx;
wolfSSL 15:117db924cf7c 563 tmpy = B->dp + ty;
wolfSSL 15:117db924cf7c 564
wolfSSL 15:117db924cf7c 565 /* this is the number of times the loop will iterate, essentially its
wolfSSL 15:117db924cf7c 566 while (tx++ < a->used && ty-- >= 0) { ... }
wolfSSL 15:117db924cf7c 567 */
wolfSSL 15:117db924cf7c 568 iy = MIN(A->used-tx, ty+1);
wolfSSL 15:117db924cf7c 569
wolfSSL 15:117db924cf7c 570 /* execute loop */
wolfSSL 15:117db924cf7c 571 COMBA_FORWARD;
wolfSSL 15:117db924cf7c 572 for (iz = 0; iz < iy; ++iz) {
wolfSSL 15:117db924cf7c 573 fp_digit _tmpx = *tmpx++;
wolfSSL 15:117db924cf7c 574 fp_digit _tmpy = *tmpy--;
wolfSSL 15:117db924cf7c 575 MULADD(_tmpx, _tmpy);
wolfSSL 15:117db924cf7c 576 }
wolfSSL 15:117db924cf7c 577
wolfSSL 15:117db924cf7c 578 /* store term */
wolfSSL 15:117db924cf7c 579 COMBA_STORE(dst->dp[ix]);
wolfSSL 15:117db924cf7c 580 }
wolfSSL 15:117db924cf7c 581 COMBA_FINI;
wolfSSL 15:117db924cf7c 582
wolfSSL 15:117db924cf7c 583 dst->used = pa;
wolfSSL 15:117db924cf7c 584 dst->sign = A->sign ^ B->sign;
wolfSSL 15:117db924cf7c 585 fp_clamp(dst);
wolfSSL 15:117db924cf7c 586 fp_copy(dst, C);
wolfSSL 16:8e0d178b1d1e 587
wolfSSL 16:8e0d178b1d1e 588 /* Variables used but not seen by cppcheck. */
wolfSSL 16:8e0d178b1d1e 589 (void)c0; (void)c1; (void)c2;
wolfSSL 16:8e0d178b1d1e 590
wolfSSL 16:8e0d178b1d1e 591 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 592 XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 593 #endif
wolfSSL 16:8e0d178b1d1e 594 return ret;
wolfSSL 15:117db924cf7c 595 }
wolfSSL 15:117db924cf7c 596
wolfSSL 15:117db924cf7c 597 /* a/b => cb + d == a */
wolfSSL 15:117db924cf7c 598 int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
wolfSSL 15:117db924cf7c 599 {
wolfSSL 15:117db924cf7c 600 int n, t, i, norm, neg;
wolfSSL 16:8e0d178b1d1e 601 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 602 fp_int q[1], x[1], y[1], t1[1], t2[1];
wolfSSL 16:8e0d178b1d1e 603 #else
wolfSSL 16:8e0d178b1d1e 604 fp_int *q, *x, *y, *t1, *t2;
wolfSSL 16:8e0d178b1d1e 605 #endif
wolfSSL 15:117db924cf7c 606
wolfSSL 15:117db924cf7c 607 /* is divisor zero ? */
wolfSSL 15:117db924cf7c 608 if (fp_iszero (b) == FP_YES) {
wolfSSL 15:117db924cf7c 609 return FP_VAL;
wolfSSL 15:117db924cf7c 610 }
wolfSSL 15:117db924cf7c 611
wolfSSL 15:117db924cf7c 612 /* if a < b then q=0, r = a */
wolfSSL 15:117db924cf7c 613 if (fp_cmp_mag (a, b) == FP_LT) {
wolfSSL 15:117db924cf7c 614 if (d != NULL) {
wolfSSL 15:117db924cf7c 615 fp_copy (a, d);
wolfSSL 15:117db924cf7c 616 }
wolfSSL 15:117db924cf7c 617 if (c != NULL) {
wolfSSL 15:117db924cf7c 618 fp_zero (c);
wolfSSL 15:117db924cf7c 619 }
wolfSSL 15:117db924cf7c 620 return FP_OKAY;
wolfSSL 15:117db924cf7c 621 }
wolfSSL 15:117db924cf7c 622
wolfSSL 16:8e0d178b1d1e 623 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 624 q = (fp_int*)XMALLOC(sizeof(fp_int) * 5, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 625 if (q == NULL) {
wolfSSL 16:8e0d178b1d1e 626 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 627 }
wolfSSL 16:8e0d178b1d1e 628 x = &q[1]; y = &q[2]; t1 = &q[3]; t2 = &q[4];
wolfSSL 16:8e0d178b1d1e 629 #endif
wolfSSL 16:8e0d178b1d1e 630
wolfSSL 16:8e0d178b1d1e 631 fp_init(q);
wolfSSL 16:8e0d178b1d1e 632 q->used = a->used + 2;
wolfSSL 16:8e0d178b1d1e 633
wolfSSL 16:8e0d178b1d1e 634 fp_init(t1);
wolfSSL 16:8e0d178b1d1e 635 fp_init(t2);
wolfSSL 16:8e0d178b1d1e 636 fp_init_copy(x, a);
wolfSSL 16:8e0d178b1d1e 637 fp_init_copy(y, b);
wolfSSL 15:117db924cf7c 638
wolfSSL 15:117db924cf7c 639 /* fix the sign */
wolfSSL 15:117db924cf7c 640 neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG;
wolfSSL 16:8e0d178b1d1e 641 x->sign = y->sign = FP_ZPOS;
wolfSSL 15:117db924cf7c 642
wolfSSL 15:117db924cf7c 643 /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
wolfSSL 16:8e0d178b1d1e 644 norm = fp_count_bits(y) % DIGIT_BIT;
wolfSSL 15:117db924cf7c 645 if (norm < (int)(DIGIT_BIT-1)) {
wolfSSL 15:117db924cf7c 646 norm = (DIGIT_BIT-1) - norm;
wolfSSL 16:8e0d178b1d1e 647 fp_mul_2d (x, norm, x);
wolfSSL 16:8e0d178b1d1e 648 fp_mul_2d (y, norm, y);
wolfSSL 15:117db924cf7c 649 } else {
wolfSSL 15:117db924cf7c 650 norm = 0;
wolfSSL 15:117db924cf7c 651 }
wolfSSL 15:117db924cf7c 652
wolfSSL 15:117db924cf7c 653 /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
wolfSSL 16:8e0d178b1d1e 654 n = x->used - 1;
wolfSSL 16:8e0d178b1d1e 655 t = y->used - 1;
wolfSSL 15:117db924cf7c 656
wolfSSL 15:117db924cf7c 657 /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
wolfSSL 16:8e0d178b1d1e 658 fp_lshd (y, n - t); /* y = y*b**{n-t} */
wolfSSL 16:8e0d178b1d1e 659
wolfSSL 16:8e0d178b1d1e 660 while (fp_cmp (x, y) != FP_LT) {
wolfSSL 16:8e0d178b1d1e 661 ++(q->dp[n - t]);
wolfSSL 16:8e0d178b1d1e 662 fp_sub (x, y, x);
wolfSSL 15:117db924cf7c 663 }
wolfSSL 15:117db924cf7c 664
wolfSSL 15:117db924cf7c 665 /* reset y by shifting it back down */
wolfSSL 16:8e0d178b1d1e 666 fp_rshd (y, n - t);
wolfSSL 15:117db924cf7c 667
wolfSSL 15:117db924cf7c 668 /* step 3. for i from n down to (t + 1) */
wolfSSL 15:117db924cf7c 669 for (i = n; i >= (t + 1); i--) {
wolfSSL 16:8e0d178b1d1e 670 if (i > x->used) {
wolfSSL 15:117db924cf7c 671 continue;
wolfSSL 15:117db924cf7c 672 }
wolfSSL 15:117db924cf7c 673
wolfSSL 15:117db924cf7c 674 /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
wolfSSL 15:117db924cf7c 675 * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
wolfSSL 16:8e0d178b1d1e 676 if (x->dp[i] == y->dp[t]) {
wolfSSL 16:8e0d178b1d1e 677 q->dp[i - t - 1] = (fp_digit) ((((fp_word)1) << DIGIT_BIT) - 1);
wolfSSL 15:117db924cf7c 678 } else {
wolfSSL 15:117db924cf7c 679 fp_word tmp;
wolfSSL 16:8e0d178b1d1e 680 tmp = ((fp_word) x->dp[i]) << ((fp_word) DIGIT_BIT);
wolfSSL 16:8e0d178b1d1e 681 tmp |= ((fp_word) x->dp[i - 1]);
wolfSSL 16:8e0d178b1d1e 682 tmp /= ((fp_word)y->dp[t]);
wolfSSL 16:8e0d178b1d1e 683 q->dp[i - t - 1] = (fp_digit) (tmp);
wolfSSL 15:117db924cf7c 684 }
wolfSSL 15:117db924cf7c 685
wolfSSL 15:117db924cf7c 686 /* while (q{i-t-1} * (yt * b + y{t-1})) >
wolfSSL 15:117db924cf7c 687 xi * b**2 + xi-1 * b + xi-2
wolfSSL 15:117db924cf7c 688
wolfSSL 15:117db924cf7c 689 do q{i-t-1} -= 1;
wolfSSL 15:117db924cf7c 690 */
wolfSSL 16:8e0d178b1d1e 691 q->dp[i - t - 1] = (q->dp[i - t - 1] + 1);
wolfSSL 15:117db924cf7c 692 do {
wolfSSL 16:8e0d178b1d1e 693 q->dp[i - t - 1] = (q->dp[i - t - 1] - 1);
wolfSSL 15:117db924cf7c 694
wolfSSL 15:117db924cf7c 695 /* find left hand */
wolfSSL 16:8e0d178b1d1e 696 fp_zero (t1);
wolfSSL 16:8e0d178b1d1e 697 t1->dp[0] = (t - 1 < 0) ? 0 : y->dp[t - 1];
wolfSSL 16:8e0d178b1d1e 698 t1->dp[1] = y->dp[t];
wolfSSL 16:8e0d178b1d1e 699 t1->used = 2;
wolfSSL 16:8e0d178b1d1e 700 fp_mul_d (t1, q->dp[i - t - 1], t1);
wolfSSL 15:117db924cf7c 701
wolfSSL 15:117db924cf7c 702 /* find right hand */
wolfSSL 16:8e0d178b1d1e 703 t2->dp[0] = (i - 2 < 0) ? 0 : x->dp[i - 2];
wolfSSL 16:8e0d178b1d1e 704 t2->dp[1] = (i - 1 < 0) ? 0 : x->dp[i - 1];
wolfSSL 16:8e0d178b1d1e 705 t2->dp[2] = x->dp[i];
wolfSSL 16:8e0d178b1d1e 706 t2->used = 3;
wolfSSL 16:8e0d178b1d1e 707 } while (fp_cmp_mag(t1, t2) == FP_GT);
wolfSSL 15:117db924cf7c 708
wolfSSL 15:117db924cf7c 709 /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
wolfSSL 16:8e0d178b1d1e 710 fp_mul_d (y, q->dp[i - t - 1], t1);
wolfSSL 16:8e0d178b1d1e 711 fp_lshd (t1, i - t - 1);
wolfSSL 16:8e0d178b1d1e 712 fp_sub (x, t1, x);
wolfSSL 15:117db924cf7c 713
wolfSSL 15:117db924cf7c 714 /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
wolfSSL 16:8e0d178b1d1e 715 if (x->sign == FP_NEG) {
wolfSSL 16:8e0d178b1d1e 716 fp_copy (y, t1);
wolfSSL 16:8e0d178b1d1e 717 fp_lshd (t1, i - t - 1);
wolfSSL 16:8e0d178b1d1e 718 fp_add (x, t1, x);
wolfSSL 16:8e0d178b1d1e 719 q->dp[i - t - 1] = q->dp[i - t - 1] - 1;
wolfSSL 15:117db924cf7c 720 }
wolfSSL 15:117db924cf7c 721 }
wolfSSL 15:117db924cf7c 722
wolfSSL 15:117db924cf7c 723 /* now q is the quotient and x is the remainder
wolfSSL 15:117db924cf7c 724 * [which we have to normalize]
wolfSSL 15:117db924cf7c 725 */
wolfSSL 15:117db924cf7c 726
wolfSSL 15:117db924cf7c 727 /* get sign before writing to c */
wolfSSL 16:8e0d178b1d1e 728 x->sign = x->used == 0 ? FP_ZPOS : a->sign;
wolfSSL 15:117db924cf7c 729
wolfSSL 15:117db924cf7c 730 if (c != NULL) {
wolfSSL 16:8e0d178b1d1e 731 fp_clamp (q);
wolfSSL 16:8e0d178b1d1e 732 fp_copy (q, c);
wolfSSL 15:117db924cf7c 733 c->sign = neg;
wolfSSL 15:117db924cf7c 734 }
wolfSSL 15:117db924cf7c 735
wolfSSL 15:117db924cf7c 736 if (d != NULL) {
wolfSSL 16:8e0d178b1d1e 737 fp_div_2d (x, norm, x, NULL);
wolfSSL 15:117db924cf7c 738
wolfSSL 15:117db924cf7c 739 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 16:8e0d178b1d1e 740 for (i = b->used; i < x->used; i++) {
wolfSSL 16:8e0d178b1d1e 741 x->dp[i] = 0;
wolfSSL 15:117db924cf7c 742 }
wolfSSL 16:8e0d178b1d1e 743 fp_clamp(x);
wolfSSL 16:8e0d178b1d1e 744 fp_copy (x, d);
wolfSSL 15:117db924cf7c 745 }
wolfSSL 15:117db924cf7c 746
wolfSSL 16:8e0d178b1d1e 747 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 748 XFREE(q, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 749 #endif
wolfSSL 15:117db924cf7c 750 return FP_OKAY;
wolfSSL 15:117db924cf7c 751 }
wolfSSL 15:117db924cf7c 752
wolfSSL 15:117db924cf7c 753 /* b = a/2 */
wolfSSL 15:117db924cf7c 754 void fp_div_2(fp_int * a, fp_int * b)
wolfSSL 15:117db924cf7c 755 {
wolfSSL 15:117db924cf7c 756 int x, oldused;
wolfSSL 15:117db924cf7c 757
wolfSSL 15:117db924cf7c 758 oldused = b->used;
wolfSSL 15:117db924cf7c 759 b->used = a->used;
wolfSSL 15:117db924cf7c 760 {
wolfSSL 15:117db924cf7c 761 fp_digit r, rr, *tmpa, *tmpb;
wolfSSL 15:117db924cf7c 762
wolfSSL 15:117db924cf7c 763 /* source alias */
wolfSSL 15:117db924cf7c 764 tmpa = a->dp + b->used - 1;
wolfSSL 15:117db924cf7c 765
wolfSSL 15:117db924cf7c 766 /* dest alias */
wolfSSL 15:117db924cf7c 767 tmpb = b->dp + b->used - 1;
wolfSSL 15:117db924cf7c 768
wolfSSL 15:117db924cf7c 769 /* carry */
wolfSSL 15:117db924cf7c 770 r = 0;
wolfSSL 15:117db924cf7c 771 for (x = b->used - 1; x >= 0; x--) {
wolfSSL 15:117db924cf7c 772 /* get the carry for the next iteration */
wolfSSL 15:117db924cf7c 773 rr = *tmpa & 1;
wolfSSL 15:117db924cf7c 774
wolfSSL 15:117db924cf7c 775 /* shift the current digit, add in carry and store */
wolfSSL 15:117db924cf7c 776 *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
wolfSSL 15:117db924cf7c 777
wolfSSL 15:117db924cf7c 778 /* forward carry to next iteration */
wolfSSL 15:117db924cf7c 779 r = rr;
wolfSSL 15:117db924cf7c 780 }
wolfSSL 15:117db924cf7c 781
wolfSSL 15:117db924cf7c 782 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 15:117db924cf7c 783 tmpb = b->dp + b->used;
wolfSSL 15:117db924cf7c 784 for (x = b->used; x < oldused; x++) {
wolfSSL 15:117db924cf7c 785 *tmpb++ = 0;
wolfSSL 15:117db924cf7c 786 }
wolfSSL 15:117db924cf7c 787 }
wolfSSL 15:117db924cf7c 788 b->sign = a->sign;
wolfSSL 15:117db924cf7c 789 fp_clamp (b);
wolfSSL 15:117db924cf7c 790 }
wolfSSL 15:117db924cf7c 791
wolfSSL 15:117db924cf7c 792 /* c = a / 2**b */
wolfSSL 15:117db924cf7c 793 void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d)
wolfSSL 15:117db924cf7c 794 {
wolfSSL 15:117db924cf7c 795 int D;
wolfSSL 15:117db924cf7c 796
wolfSSL 15:117db924cf7c 797 /* if the shift count is <= 0 then we do no work */
wolfSSL 15:117db924cf7c 798 if (b <= 0) {
wolfSSL 15:117db924cf7c 799 fp_copy (a, c);
wolfSSL 15:117db924cf7c 800 if (d != NULL) {
wolfSSL 15:117db924cf7c 801 fp_zero (d);
wolfSSL 15:117db924cf7c 802 }
wolfSSL 15:117db924cf7c 803 return;
wolfSSL 15:117db924cf7c 804 }
wolfSSL 15:117db924cf7c 805
wolfSSL 16:8e0d178b1d1e 806 /* get the remainder before a is changed in calculating c */
wolfSSL 16:8e0d178b1d1e 807 if (a == c && d != NULL) {
wolfSSL 16:8e0d178b1d1e 808 fp_mod_2d (a, b, d);
wolfSSL 15:117db924cf7c 809 }
wolfSSL 15:117db924cf7c 810
wolfSSL 15:117db924cf7c 811 /* copy */
wolfSSL 15:117db924cf7c 812 fp_copy(a, c);
wolfSSL 15:117db924cf7c 813
wolfSSL 15:117db924cf7c 814 /* shift by as many digits in the bit count */
wolfSSL 15:117db924cf7c 815 if (b >= (int)DIGIT_BIT) {
wolfSSL 15:117db924cf7c 816 fp_rshd (c, b / DIGIT_BIT);
wolfSSL 15:117db924cf7c 817 }
wolfSSL 15:117db924cf7c 818
wolfSSL 15:117db924cf7c 819 /* shift any bit count < DIGIT_BIT */
wolfSSL 15:117db924cf7c 820 D = (b % DIGIT_BIT);
wolfSSL 15:117db924cf7c 821 if (D != 0) {
wolfSSL 15:117db924cf7c 822 fp_rshb(c, D);
wolfSSL 15:117db924cf7c 823 }
wolfSSL 16:8e0d178b1d1e 824
wolfSSL 16:8e0d178b1d1e 825 /* get the remainder if a is not changed in calculating c */
wolfSSL 16:8e0d178b1d1e 826 if (a != c && d != NULL) {
wolfSSL 16:8e0d178b1d1e 827 fp_mod_2d (a, b, d);
wolfSSL 16:8e0d178b1d1e 828 }
wolfSSL 16:8e0d178b1d1e 829
wolfSSL 15:117db924cf7c 830 fp_clamp (c);
wolfSSL 15:117db924cf7c 831 }
wolfSSL 15:117db924cf7c 832
wolfSSL 15:117db924cf7c 833 /* c = a mod b, 0 <= c < b */
wolfSSL 15:117db924cf7c 834 int fp_mod(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 15:117db924cf7c 835 {
wolfSSL 16:8e0d178b1d1e 836 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 837 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 838 #else
wolfSSL 16:8e0d178b1d1e 839 fp_int *t;
wolfSSL 16:8e0d178b1d1e 840 #endif
wolfSSL 15:117db924cf7c 841 int err;
wolfSSL 15:117db924cf7c 842
wolfSSL 16:8e0d178b1d1e 843 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 844 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 845 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 846 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 847 #endif
wolfSSL 16:8e0d178b1d1e 848
wolfSSL 16:8e0d178b1d1e 849 fp_init(t);
wolfSSL 16:8e0d178b1d1e 850 err = fp_div(a, b, NULL, t);
wolfSSL 16:8e0d178b1d1e 851 if (err == FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 852 if (t->sign != b->sign) {
wolfSSL 16:8e0d178b1d1e 853 fp_add(t, b, c);
wolfSSL 16:8e0d178b1d1e 854 } else {
wolfSSL 16:8e0d178b1d1e 855 fp_copy(t, c);
wolfSSL 16:8e0d178b1d1e 856 }
wolfSSL 15:117db924cf7c 857 }
wolfSSL 16:8e0d178b1d1e 858
wolfSSL 16:8e0d178b1d1e 859 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 860 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 861 #endif
wolfSSL 16:8e0d178b1d1e 862 return err;
wolfSSL 15:117db924cf7c 863 }
wolfSSL 15:117db924cf7c 864
wolfSSL 15:117db924cf7c 865 /* c = a mod 2**d */
wolfSSL 15:117db924cf7c 866 void fp_mod_2d(fp_int *a, int b, fp_int *c)
wolfSSL 15:117db924cf7c 867 {
wolfSSL 15:117db924cf7c 868 int x;
wolfSSL 15:117db924cf7c 869
wolfSSL 15:117db924cf7c 870 /* zero if count less than or equal to zero */
wolfSSL 15:117db924cf7c 871 if (b <= 0) {
wolfSSL 15:117db924cf7c 872 fp_zero(c);
wolfSSL 15:117db924cf7c 873 return;
wolfSSL 15:117db924cf7c 874 }
wolfSSL 15:117db924cf7c 875
wolfSSL 15:117db924cf7c 876 /* get copy of input */
wolfSSL 15:117db924cf7c 877 fp_copy(a, c);
wolfSSL 15:117db924cf7c 878
wolfSSL 15:117db924cf7c 879 /* if 2**d is larger than we just return */
wolfSSL 15:117db924cf7c 880 if (b >= (DIGIT_BIT * a->used)) {
wolfSSL 15:117db924cf7c 881 return;
wolfSSL 15:117db924cf7c 882 }
wolfSSL 15:117db924cf7c 883
wolfSSL 15:117db924cf7c 884 /* zero digits above the last digit of the modulus */
wolfSSL 15:117db924cf7c 885 for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
wolfSSL 15:117db924cf7c 886 c->dp[x] = 0;
wolfSSL 15:117db924cf7c 887 }
wolfSSL 15:117db924cf7c 888 /* clear the digit that is not completely outside/inside the modulus */
wolfSSL 15:117db924cf7c 889 c->dp[b / DIGIT_BIT] &= ~((fp_digit)0) >> (DIGIT_BIT - b);
wolfSSL 15:117db924cf7c 890 fp_clamp (c);
wolfSSL 15:117db924cf7c 891 }
wolfSSL 15:117db924cf7c 892
wolfSSL 15:117db924cf7c 893 static int fp_invmod_slow (fp_int * a, fp_int * b, fp_int * c)
wolfSSL 15:117db924cf7c 894 {
wolfSSL 16:8e0d178b1d1e 895 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 896 fp_int x[1], y[1], u[1], v[1], A[1], B[1], C[1], D[1];
wolfSSL 16:8e0d178b1d1e 897 #else
wolfSSL 16:8e0d178b1d1e 898 fp_int *x, *y, *u, *v, *A, *B, *C, *D;
wolfSSL 16:8e0d178b1d1e 899 #endif
wolfSSL 16:8e0d178b1d1e 900 int err;
wolfSSL 15:117db924cf7c 901
wolfSSL 15:117db924cf7c 902 /* b cannot be negative */
wolfSSL 15:117db924cf7c 903 if (b->sign == FP_NEG || fp_iszero(b) == FP_YES) {
wolfSSL 15:117db924cf7c 904 return FP_VAL;
wolfSSL 15:117db924cf7c 905 }
wolfSSL 16:8e0d178b1d1e 906 if (fp_iszero(a) == FP_YES) {
wolfSSL 16:8e0d178b1d1e 907 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 908 }
wolfSSL 16:8e0d178b1d1e 909
wolfSSL 16:8e0d178b1d1e 910 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 911 x = (fp_int*)XMALLOC(sizeof(fp_int) * 8, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 912 if (x == NULL) {
wolfSSL 16:8e0d178b1d1e 913 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 914 }
wolfSSL 16:8e0d178b1d1e 915 y = &x[1]; u = &x[2]; v = &x[3]; A = &x[4]; B = &x[5]; C = &x[6]; D = &x[7];
wolfSSL 16:8e0d178b1d1e 916 #endif
wolfSSL 15:117db924cf7c 917
wolfSSL 15:117db924cf7c 918 /* init temps */
wolfSSL 16:8e0d178b1d1e 919 fp_init(x); fp_init(y);
wolfSSL 16:8e0d178b1d1e 920 fp_init(u); fp_init(v);
wolfSSL 16:8e0d178b1d1e 921 fp_init(A); fp_init(B);
wolfSSL 16:8e0d178b1d1e 922 fp_init(C); fp_init(D);
wolfSSL 15:117db924cf7c 923
wolfSSL 15:117db924cf7c 924 /* x = a, y = b */
wolfSSL 16:8e0d178b1d1e 925 if ((err = fp_mod(a, b, x)) != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 926 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 927 XFREE(x, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 928 #endif
wolfSSL 16:8e0d178b1d1e 929 return err;
wolfSSL 15:117db924cf7c 930 }
wolfSSL 16:8e0d178b1d1e 931 fp_copy(b, y);
wolfSSL 15:117db924cf7c 932
wolfSSL 15:117db924cf7c 933 /* 2. [modified] if x,y are both even then return an error! */
wolfSSL 16:8e0d178b1d1e 934 if (fp_iseven(x) == FP_YES && fp_iseven(y) == FP_YES) {
wolfSSL 16:8e0d178b1d1e 935 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 936 XFREE(x, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 937 #endif
wolfSSL 15:117db924cf7c 938 return FP_VAL;
wolfSSL 15:117db924cf7c 939 }
wolfSSL 15:117db924cf7c 940
wolfSSL 15:117db924cf7c 941 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
wolfSSL 16:8e0d178b1d1e 942 fp_copy (x, u);
wolfSSL 16:8e0d178b1d1e 943 fp_copy (y, v);
wolfSSL 16:8e0d178b1d1e 944 fp_set (A, 1);
wolfSSL 16:8e0d178b1d1e 945 fp_set (D, 1);
wolfSSL 15:117db924cf7c 946
wolfSSL 15:117db924cf7c 947 top:
wolfSSL 15:117db924cf7c 948 /* 4. while u is even do */
wolfSSL 16:8e0d178b1d1e 949 while (fp_iseven (u) == FP_YES) {
wolfSSL 15:117db924cf7c 950 /* 4.1 u = u/2 */
wolfSSL 16:8e0d178b1d1e 951 fp_div_2 (u, u);
wolfSSL 15:117db924cf7c 952
wolfSSL 15:117db924cf7c 953 /* 4.2 if A or B is odd then */
wolfSSL 16:8e0d178b1d1e 954 if (fp_isodd (A) == FP_YES || fp_isodd (B) == FP_YES) {
wolfSSL 15:117db924cf7c 955 /* A = (A+y)/2, B = (B-x)/2 */
wolfSSL 16:8e0d178b1d1e 956 fp_add (A, y, A);
wolfSSL 16:8e0d178b1d1e 957 fp_sub (B, x, B);
wolfSSL 15:117db924cf7c 958 }
wolfSSL 15:117db924cf7c 959 /* A = A/2, B = B/2 */
wolfSSL 16:8e0d178b1d1e 960 fp_div_2 (A, A);
wolfSSL 16:8e0d178b1d1e 961 fp_div_2 (B, B);
wolfSSL 15:117db924cf7c 962 }
wolfSSL 15:117db924cf7c 963
wolfSSL 15:117db924cf7c 964 /* 5. while v is even do */
wolfSSL 16:8e0d178b1d1e 965 while (fp_iseven (v) == FP_YES) {
wolfSSL 15:117db924cf7c 966 /* 5.1 v = v/2 */
wolfSSL 16:8e0d178b1d1e 967 fp_div_2 (v, v);
wolfSSL 15:117db924cf7c 968
wolfSSL 15:117db924cf7c 969 /* 5.2 if C or D is odd then */
wolfSSL 16:8e0d178b1d1e 970 if (fp_isodd (C) == FP_YES || fp_isodd (D) == FP_YES) {
wolfSSL 15:117db924cf7c 971 /* C = (C+y)/2, D = (D-x)/2 */
wolfSSL 16:8e0d178b1d1e 972 fp_add (C, y, C);
wolfSSL 16:8e0d178b1d1e 973 fp_sub (D, x, D);
wolfSSL 15:117db924cf7c 974 }
wolfSSL 15:117db924cf7c 975 /* C = C/2, D = D/2 */
wolfSSL 16:8e0d178b1d1e 976 fp_div_2 (C, C);
wolfSSL 16:8e0d178b1d1e 977 fp_div_2 (D, D);
wolfSSL 15:117db924cf7c 978 }
wolfSSL 15:117db924cf7c 979
wolfSSL 15:117db924cf7c 980 /* 6. if u >= v then */
wolfSSL 16:8e0d178b1d1e 981 if (fp_cmp (u, v) != FP_LT) {
wolfSSL 15:117db924cf7c 982 /* u = u - v, A = A - C, B = B - D */
wolfSSL 16:8e0d178b1d1e 983 fp_sub (u, v, u);
wolfSSL 16:8e0d178b1d1e 984 fp_sub (A, C, A);
wolfSSL 16:8e0d178b1d1e 985 fp_sub (B, D, B);
wolfSSL 15:117db924cf7c 986 } else {
wolfSSL 15:117db924cf7c 987 /* v - v - u, C = C - A, D = D - B */
wolfSSL 16:8e0d178b1d1e 988 fp_sub (v, u, v);
wolfSSL 16:8e0d178b1d1e 989 fp_sub (C, A, C);
wolfSSL 16:8e0d178b1d1e 990 fp_sub (D, B, D);
wolfSSL 15:117db924cf7c 991 }
wolfSSL 15:117db924cf7c 992
wolfSSL 15:117db924cf7c 993 /* if not zero goto step 4 */
wolfSSL 16:8e0d178b1d1e 994 if (fp_iszero (u) == FP_NO)
wolfSSL 15:117db924cf7c 995 goto top;
wolfSSL 15:117db924cf7c 996
wolfSSL 15:117db924cf7c 997 /* now a = C, b = D, gcd == g*v */
wolfSSL 15:117db924cf7c 998
wolfSSL 15:117db924cf7c 999 /* if v != 1 then there is no inverse */
wolfSSL 16:8e0d178b1d1e 1000 if (fp_cmp_d (v, 1) != FP_EQ) {
wolfSSL 16:8e0d178b1d1e 1001 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1002 XFREE(x, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1003 #endif
wolfSSL 15:117db924cf7c 1004 return FP_VAL;
wolfSSL 15:117db924cf7c 1005 }
wolfSSL 15:117db924cf7c 1006
wolfSSL 15:117db924cf7c 1007 /* if its too low */
wolfSSL 16:8e0d178b1d1e 1008 while (fp_cmp_d(C, 0) == FP_LT) {
wolfSSL 16:8e0d178b1d1e 1009 fp_add(C, b, C);
wolfSSL 15:117db924cf7c 1010 }
wolfSSL 15:117db924cf7c 1011
wolfSSL 15:117db924cf7c 1012 /* too big */
wolfSSL 16:8e0d178b1d1e 1013 while (fp_cmp_mag(C, b) != FP_LT) {
wolfSSL 16:8e0d178b1d1e 1014 fp_sub(C, b, C);
wolfSSL 15:117db924cf7c 1015 }
wolfSSL 15:117db924cf7c 1016
wolfSSL 15:117db924cf7c 1017 /* C is now the inverse */
wolfSSL 16:8e0d178b1d1e 1018 fp_copy(C, c);
wolfSSL 16:8e0d178b1d1e 1019 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1020 XFREE(x, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1021 #endif
wolfSSL 15:117db924cf7c 1022 return FP_OKAY;
wolfSSL 15:117db924cf7c 1023 }
wolfSSL 15:117db924cf7c 1024
wolfSSL 15:117db924cf7c 1025 /* c = 1/a (mod b) for odd b only */
wolfSSL 15:117db924cf7c 1026 int fp_invmod(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 15:117db924cf7c 1027 {
wolfSSL 16:8e0d178b1d1e 1028 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1029 fp_int x[1], y[1], u[1], v[1], B[1], D[1];
wolfSSL 16:8e0d178b1d1e 1030 #else
wolfSSL 16:8e0d178b1d1e 1031 fp_int *x, *y, *u, *v, *B, *D;
wolfSSL 16:8e0d178b1d1e 1032 #endif
wolfSSL 15:117db924cf7c 1033 int neg;
wolfSSL 16:8e0d178b1d1e 1034 int err;
wolfSSL 16:8e0d178b1d1e 1035
wolfSSL 16:8e0d178b1d1e 1036 if (b->sign == FP_NEG || fp_iszero(b) == FP_YES) {
wolfSSL 16:8e0d178b1d1e 1037 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 1038 }
wolfSSL 16:8e0d178b1d1e 1039
wolfSSL 16:8e0d178b1d1e 1040 /* [modified] sanity check on "a" */
wolfSSL 16:8e0d178b1d1e 1041 if (fp_iszero(a) == FP_YES) {
wolfSSL 16:8e0d178b1d1e 1042 return FP_VAL; /* can not divide by 0 here */
wolfSSL 16:8e0d178b1d1e 1043 }
wolfSSL 15:117db924cf7c 1044
wolfSSL 15:117db924cf7c 1045 /* 2. [modified] b must be odd */
wolfSSL 16:8e0d178b1d1e 1046 if (fp_iseven(b) == FP_YES) {
wolfSSL 15:117db924cf7c 1047 return fp_invmod_slow(a,b,c);
wolfSSL 15:117db924cf7c 1048 }
wolfSSL 15:117db924cf7c 1049
wolfSSL 16:8e0d178b1d1e 1050 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1051 x = (fp_int*)XMALLOC(sizeof(fp_int) * 6, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1052 if (x == NULL) {
wolfSSL 16:8e0d178b1d1e 1053 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 1054 }
wolfSSL 16:8e0d178b1d1e 1055 y = &x[1]; u = &x[2]; v = &x[3]; B = &x[4]; D = &x[5];
wolfSSL 16:8e0d178b1d1e 1056 #endif
wolfSSL 16:8e0d178b1d1e 1057
wolfSSL 15:117db924cf7c 1058 /* init all our temps */
wolfSSL 16:8e0d178b1d1e 1059 fp_init(x); fp_init(y);
wolfSSL 16:8e0d178b1d1e 1060 fp_init(u); fp_init(v);
wolfSSL 16:8e0d178b1d1e 1061 fp_init(B); fp_init(D);
wolfSSL 16:8e0d178b1d1e 1062
wolfSSL 16:8e0d178b1d1e 1063 if (fp_cmp(a, b) != MP_LT) {
wolfSSL 16:8e0d178b1d1e 1064 err = mp_mod(a, b, y);
wolfSSL 16:8e0d178b1d1e 1065 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1066 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1067 XFREE(x, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1068 #endif
wolfSSL 16:8e0d178b1d1e 1069 return err;
wolfSSL 16:8e0d178b1d1e 1070 }
wolfSSL 16:8e0d178b1d1e 1071 a = y;
wolfSSL 16:8e0d178b1d1e 1072 }
wolfSSL 16:8e0d178b1d1e 1073
wolfSSL 16:8e0d178b1d1e 1074 if (fp_iszero(a) == FP_YES) {
wolfSSL 16:8e0d178b1d1e 1075 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1076 XFREE(x, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1077 #endif
wolfSSL 16:8e0d178b1d1e 1078 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 1079 }
wolfSSL 15:117db924cf7c 1080
wolfSSL 15:117db924cf7c 1081 /* x == modulus, y == value to invert */
wolfSSL 16:8e0d178b1d1e 1082 fp_copy(b, x);
wolfSSL 15:117db924cf7c 1083
wolfSSL 15:117db924cf7c 1084 /* we need y = |a| */
wolfSSL 16:8e0d178b1d1e 1085 fp_abs(a, y);
wolfSSL 15:117db924cf7c 1086
wolfSSL 15:117db924cf7c 1087 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
wolfSSL 16:8e0d178b1d1e 1088 fp_copy(x, u);
wolfSSL 16:8e0d178b1d1e 1089 fp_copy(y, v);
wolfSSL 16:8e0d178b1d1e 1090 fp_set (D, 1);
wolfSSL 15:117db924cf7c 1091
wolfSSL 15:117db924cf7c 1092 top:
wolfSSL 15:117db924cf7c 1093 /* 4. while u is even do */
wolfSSL 16:8e0d178b1d1e 1094 while (fp_iseven (u) == FP_YES) {
wolfSSL 15:117db924cf7c 1095 /* 4.1 u = u/2 */
wolfSSL 16:8e0d178b1d1e 1096 fp_div_2 (u, u);
wolfSSL 15:117db924cf7c 1097
wolfSSL 15:117db924cf7c 1098 /* 4.2 if B is odd then */
wolfSSL 16:8e0d178b1d1e 1099 if (fp_isodd (B) == FP_YES) {
wolfSSL 16:8e0d178b1d1e 1100 fp_sub (B, x, B);
wolfSSL 15:117db924cf7c 1101 }
wolfSSL 15:117db924cf7c 1102 /* B = B/2 */
wolfSSL 16:8e0d178b1d1e 1103 fp_div_2 (B, B);
wolfSSL 15:117db924cf7c 1104 }
wolfSSL 15:117db924cf7c 1105
wolfSSL 15:117db924cf7c 1106 /* 5. while v is even do */
wolfSSL 16:8e0d178b1d1e 1107 while (fp_iseven (v) == FP_YES) {
wolfSSL 15:117db924cf7c 1108 /* 5.1 v = v/2 */
wolfSSL 16:8e0d178b1d1e 1109 fp_div_2 (v, v);
wolfSSL 15:117db924cf7c 1110
wolfSSL 15:117db924cf7c 1111 /* 5.2 if D is odd then */
wolfSSL 16:8e0d178b1d1e 1112 if (fp_isodd (D) == FP_YES) {
wolfSSL 15:117db924cf7c 1113 /* D = (D-x)/2 */
wolfSSL 16:8e0d178b1d1e 1114 fp_sub (D, x, D);
wolfSSL 15:117db924cf7c 1115 }
wolfSSL 15:117db924cf7c 1116 /* D = D/2 */
wolfSSL 16:8e0d178b1d1e 1117 fp_div_2 (D, D);
wolfSSL 15:117db924cf7c 1118 }
wolfSSL 15:117db924cf7c 1119
wolfSSL 15:117db924cf7c 1120 /* 6. if u >= v then */
wolfSSL 16:8e0d178b1d1e 1121 if (fp_cmp (u, v) != FP_LT) {
wolfSSL 15:117db924cf7c 1122 /* u = u - v, B = B - D */
wolfSSL 16:8e0d178b1d1e 1123 fp_sub (u, v, u);
wolfSSL 16:8e0d178b1d1e 1124 fp_sub (B, D, B);
wolfSSL 15:117db924cf7c 1125 } else {
wolfSSL 15:117db924cf7c 1126 /* v - v - u, D = D - B */
wolfSSL 16:8e0d178b1d1e 1127 fp_sub (v, u, v);
wolfSSL 16:8e0d178b1d1e 1128 fp_sub (D, B, D);
wolfSSL 15:117db924cf7c 1129 }
wolfSSL 15:117db924cf7c 1130
wolfSSL 15:117db924cf7c 1131 /* if not zero goto step 4 */
wolfSSL 16:8e0d178b1d1e 1132 if (fp_iszero (u) == FP_NO) {
wolfSSL 15:117db924cf7c 1133 goto top;
wolfSSL 15:117db924cf7c 1134 }
wolfSSL 15:117db924cf7c 1135
wolfSSL 15:117db924cf7c 1136 /* now a = C, b = D, gcd == g*v */
wolfSSL 15:117db924cf7c 1137
wolfSSL 15:117db924cf7c 1138 /* if v != 1 then there is no inverse */
wolfSSL 16:8e0d178b1d1e 1139 if (fp_cmp_d (v, 1) != FP_EQ) {
wolfSSL 16:8e0d178b1d1e 1140 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1141 XFREE(x, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1142 #endif
wolfSSL 15:117db924cf7c 1143 return FP_VAL;
wolfSSL 15:117db924cf7c 1144 }
wolfSSL 15:117db924cf7c 1145
wolfSSL 15:117db924cf7c 1146 /* b is now the inverse */
wolfSSL 15:117db924cf7c 1147 neg = a->sign;
wolfSSL 16:8e0d178b1d1e 1148 while (D->sign == FP_NEG) {
wolfSSL 16:8e0d178b1d1e 1149 fp_add (D, b, D);
wolfSSL 15:117db924cf7c 1150 }
wolfSSL 15:117db924cf7c 1151 /* too big */
wolfSSL 16:8e0d178b1d1e 1152 while (fp_cmp_mag(D, b) != FP_LT) {
wolfSSL 16:8e0d178b1d1e 1153 fp_sub(D, b, D);
wolfSSL 15:117db924cf7c 1154 }
wolfSSL 16:8e0d178b1d1e 1155 fp_copy (D, c);
wolfSSL 15:117db924cf7c 1156 c->sign = neg;
wolfSSL 16:8e0d178b1d1e 1157 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1158 XFREE(x, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1159 #endif
wolfSSL 16:8e0d178b1d1e 1160 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 1161 }
wolfSSL 16:8e0d178b1d1e 1162
wolfSSL 16:8e0d178b1d1e 1163 #define CT_INV_MOD_PRE_CNT 8
wolfSSL 16:8e0d178b1d1e 1164
wolfSSL 16:8e0d178b1d1e 1165 /* modulus (b) must be greater than 2 and a prime */
wolfSSL 16:8e0d178b1d1e 1166 int fp_invmod_mont_ct(fp_int *a, fp_int *b, fp_int *c, fp_digit mp)
wolfSSL 16:8e0d178b1d1e 1167 {
wolfSSL 16:8e0d178b1d1e 1168 int i, j;
wolfSSL 16:8e0d178b1d1e 1169 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1170 fp_int t[1], e[1];
wolfSSL 16:8e0d178b1d1e 1171 fp_int pre[CT_INV_MOD_PRE_CNT];
wolfSSL 16:8e0d178b1d1e 1172 #else
wolfSSL 16:8e0d178b1d1e 1173 fp_int* t;
wolfSSL 16:8e0d178b1d1e 1174 fp_int* e;
wolfSSL 16:8e0d178b1d1e 1175 fp_int* pre;
wolfSSL 16:8e0d178b1d1e 1176 #endif
wolfSSL 16:8e0d178b1d1e 1177
wolfSSL 16:8e0d178b1d1e 1178 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1179 t = (fp_int*)XMALLOC(sizeof(fp_int) * (2 + CT_INV_MOD_PRE_CNT), NULL,
wolfSSL 16:8e0d178b1d1e 1180 DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1181 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 1182 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 1183 e = t + 1;
wolfSSL 16:8e0d178b1d1e 1184 pre = t + 2;
wolfSSL 16:8e0d178b1d1e 1185 #endif
wolfSSL 16:8e0d178b1d1e 1186
wolfSSL 16:8e0d178b1d1e 1187 fp_init(t);
wolfSSL 16:8e0d178b1d1e 1188 fp_init(e);
wolfSSL 16:8e0d178b1d1e 1189
wolfSSL 16:8e0d178b1d1e 1190 fp_init(&pre[0]);
wolfSSL 16:8e0d178b1d1e 1191 fp_copy(a, &pre[0]);
wolfSSL 16:8e0d178b1d1e 1192 for (i = 1; i < CT_INV_MOD_PRE_CNT; i++) {
wolfSSL 16:8e0d178b1d1e 1193 fp_init(&pre[i]);
wolfSSL 16:8e0d178b1d1e 1194 fp_sqr(&pre[i-1], &pre[i]);
wolfSSL 16:8e0d178b1d1e 1195 fp_montgomery_reduce(&pre[i], b, mp);
wolfSSL 16:8e0d178b1d1e 1196 fp_mul(&pre[i], a, &pre[i]);
wolfSSL 16:8e0d178b1d1e 1197 fp_montgomery_reduce(&pre[i], b, mp);
wolfSSL 16:8e0d178b1d1e 1198 }
wolfSSL 16:8e0d178b1d1e 1199
wolfSSL 16:8e0d178b1d1e 1200 fp_sub_d(b, 2, e);
wolfSSL 16:8e0d178b1d1e 1201 /* Highest bit is always set. */
wolfSSL 16:8e0d178b1d1e 1202 for (i = fp_count_bits(e)-2, j = 1; i >= 0; i--, j++) {
wolfSSL 16:8e0d178b1d1e 1203 if (!fp_is_bit_set(e, i) || j == CT_INV_MOD_PRE_CNT)
wolfSSL 16:8e0d178b1d1e 1204 break;
wolfSSL 16:8e0d178b1d1e 1205 }
wolfSSL 16:8e0d178b1d1e 1206 fp_copy(&pre[j-1], t);
wolfSSL 16:8e0d178b1d1e 1207 for (j = 0; i >= 0; i--) {
wolfSSL 16:8e0d178b1d1e 1208 int set = fp_is_bit_set(e, i);
wolfSSL 16:8e0d178b1d1e 1209
wolfSSL 16:8e0d178b1d1e 1210 if ((j == CT_INV_MOD_PRE_CNT) || (!set && j > 0)) {
wolfSSL 16:8e0d178b1d1e 1211 fp_mul(t, &pre[j-1], t);
wolfSSL 16:8e0d178b1d1e 1212 fp_montgomery_reduce(t, b, mp);
wolfSSL 16:8e0d178b1d1e 1213 j = 0;
wolfSSL 16:8e0d178b1d1e 1214 }
wolfSSL 16:8e0d178b1d1e 1215 fp_sqr(t, t);
wolfSSL 16:8e0d178b1d1e 1216 fp_montgomery_reduce(t, b, mp);
wolfSSL 16:8e0d178b1d1e 1217 j += set;
wolfSSL 16:8e0d178b1d1e 1218 }
wolfSSL 16:8e0d178b1d1e 1219 if (j > 0) {
wolfSSL 16:8e0d178b1d1e 1220 fp_mul(t, &pre[j-1], c);
wolfSSL 16:8e0d178b1d1e 1221 fp_montgomery_reduce(c, b, mp);
wolfSSL 16:8e0d178b1d1e 1222 }
wolfSSL 16:8e0d178b1d1e 1223 else
wolfSSL 16:8e0d178b1d1e 1224 fp_copy(t, c);
wolfSSL 16:8e0d178b1d1e 1225
wolfSSL 16:8e0d178b1d1e 1226 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1227 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1228 #endif
wolfSSL 15:117db924cf7c 1229 return FP_OKAY;
wolfSSL 15:117db924cf7c 1230 }
wolfSSL 15:117db924cf7c 1231
wolfSSL 15:117db924cf7c 1232 /* d = a * b (mod c) */
wolfSSL 15:117db924cf7c 1233 int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
wolfSSL 15:117db924cf7c 1234 {
wolfSSL 15:117db924cf7c 1235 int err;
wolfSSL 16:8e0d178b1d1e 1236 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1237 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 1238 #else
wolfSSL 16:8e0d178b1d1e 1239 fp_int *t;
wolfSSL 16:8e0d178b1d1e 1240 #endif
wolfSSL 16:8e0d178b1d1e 1241
wolfSSL 16:8e0d178b1d1e 1242 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1243 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1244 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 1245 return FP_MEM;
wolfSSL 15:117db924cf7c 1246 #endif
wolfSSL 16:8e0d178b1d1e 1247
wolfSSL 16:8e0d178b1d1e 1248 fp_init(t);
wolfSSL 16:8e0d178b1d1e 1249 err = fp_mul(a, b, t);
wolfSSL 16:8e0d178b1d1e 1250 if (err == FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1251 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 16:8e0d178b1d1e 1252 if (d->size < FP_SIZE) {
wolfSSL 16:8e0d178b1d1e 1253 err = fp_mod(t, c, t);
wolfSSL 16:8e0d178b1d1e 1254 fp_copy(t, d);
wolfSSL 16:8e0d178b1d1e 1255 } else
wolfSSL 16:8e0d178b1d1e 1256 #endif
wolfSSL 16:8e0d178b1d1e 1257 {
wolfSSL 16:8e0d178b1d1e 1258 err = fp_mod(t, c, d);
wolfSSL 16:8e0d178b1d1e 1259 }
wolfSSL 15:117db924cf7c 1260 }
wolfSSL 15:117db924cf7c 1261
wolfSSL 16:8e0d178b1d1e 1262 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1263 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1264 #endif
wolfSSL 15:117db924cf7c 1265 return err;
wolfSSL 15:117db924cf7c 1266 }
wolfSSL 15:117db924cf7c 1267
wolfSSL 15:117db924cf7c 1268 /* d = a - b (mod c) */
wolfSSL 15:117db924cf7c 1269 int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
wolfSSL 15:117db924cf7c 1270 {
wolfSSL 15:117db924cf7c 1271 int err;
wolfSSL 16:8e0d178b1d1e 1272 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1273 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 1274 #else
wolfSSL 16:8e0d178b1d1e 1275 fp_int *t;
wolfSSL 16:8e0d178b1d1e 1276 #endif
wolfSSL 16:8e0d178b1d1e 1277
wolfSSL 16:8e0d178b1d1e 1278 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1279 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1280 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 1281 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 1282 #endif
wolfSSL 16:8e0d178b1d1e 1283
wolfSSL 16:8e0d178b1d1e 1284 fp_init(t);
wolfSSL 16:8e0d178b1d1e 1285 fp_sub(a, b, t);
wolfSSL 15:117db924cf7c 1286 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 1287 if (d->size < FP_SIZE) {
wolfSSL 16:8e0d178b1d1e 1288 err = fp_mod(t, c, t);
wolfSSL 16:8e0d178b1d1e 1289 fp_copy(t, d);
wolfSSL 15:117db924cf7c 1290 } else
wolfSSL 15:117db924cf7c 1291 #endif
wolfSSL 15:117db924cf7c 1292 {
wolfSSL 16:8e0d178b1d1e 1293 err = fp_mod(t, c, d);
wolfSSL 15:117db924cf7c 1294 }
wolfSSL 15:117db924cf7c 1295
wolfSSL 16:8e0d178b1d1e 1296 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1297 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1298 #endif
wolfSSL 15:117db924cf7c 1299 return err;
wolfSSL 15:117db924cf7c 1300 }
wolfSSL 15:117db924cf7c 1301
wolfSSL 15:117db924cf7c 1302 /* d = a + b (mod c) */
wolfSSL 15:117db924cf7c 1303 int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
wolfSSL 15:117db924cf7c 1304 {
wolfSSL 15:117db924cf7c 1305 int err;
wolfSSL 16:8e0d178b1d1e 1306 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1307 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 1308 #else
wolfSSL 16:8e0d178b1d1e 1309 fp_int *t;
wolfSSL 16:8e0d178b1d1e 1310 #endif
wolfSSL 16:8e0d178b1d1e 1311
wolfSSL 16:8e0d178b1d1e 1312 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1313 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1314 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 1315 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 1316 #endif
wolfSSL 16:8e0d178b1d1e 1317
wolfSSL 16:8e0d178b1d1e 1318 fp_init(t);
wolfSSL 16:8e0d178b1d1e 1319 fp_add(a, b, t);
wolfSSL 15:117db924cf7c 1320 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 1321 if (d->size < FP_SIZE) {
wolfSSL 16:8e0d178b1d1e 1322 err = fp_mod(t, c, t);
wolfSSL 16:8e0d178b1d1e 1323 fp_copy(t, d);
wolfSSL 15:117db924cf7c 1324 } else
wolfSSL 15:117db924cf7c 1325 #endif
wolfSSL 15:117db924cf7c 1326 {
wolfSSL 16:8e0d178b1d1e 1327 err = fp_mod(t, c, d);
wolfSSL 15:117db924cf7c 1328 }
wolfSSL 15:117db924cf7c 1329
wolfSSL 16:8e0d178b1d1e 1330 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1331 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1332 #endif
wolfSSL 15:117db924cf7c 1333 return err;
wolfSSL 15:117db924cf7c 1334 }
wolfSSL 15:117db924cf7c 1335
wolfSSL 15:117db924cf7c 1336 #ifdef TFM_TIMING_RESISTANT
wolfSSL 15:117db924cf7c 1337
wolfSSL 16:8e0d178b1d1e 1338 #ifdef WC_RSA_NONBLOCK
wolfSSL 16:8e0d178b1d1e 1339
wolfSSL 16:8e0d178b1d1e 1340 #ifdef WC_RSA_NONBLOCK_TIME
wolfSSL 16:8e0d178b1d1e 1341 /* User can override the check-time at build-time using the
wolfSSL 16:8e0d178b1d1e 1342 * FP_EXPTMOD_NB_CHECKTIME macro to define your own function */
wolfSSL 16:8e0d178b1d1e 1343 #ifndef FP_EXPTMOD_NB_CHECKTIME
wolfSSL 16:8e0d178b1d1e 1344 /* instruction count for each type of operation */
wolfSSL 16:8e0d178b1d1e 1345 /* array lookup is using TFM_EXPTMOD_NB_* states */
wolfSSL 16:8e0d178b1d1e 1346 static const word32 exptModNbInst[TFM_EXPTMOD_NB_COUNT] = {
wolfSSL 16:8e0d178b1d1e 1347 #ifdef TFM_PPC32
wolfSSL 16:8e0d178b1d1e 1348 #ifdef _DEBUG
wolfSSL 16:8e0d178b1d1e 1349 11098, 8701, 3971, 178394, 858093, 1040, 822, 178056, 181574, 90883, 184339, 236813
wolfSSL 16:8e0d178b1d1e 1350 #else
wolfSSL 16:8e0d178b1d1e 1351 7050, 2554, 3187, 43178, 200422, 384, 275, 43024, 43550, 30450, 46270, 61376
wolfSSL 16:8e0d178b1d1e 1352 #endif
wolfSSL 16:8e0d178b1d1e 1353 #elif defined(TFM_X86_64)
wolfSSL 16:8e0d178b1d1e 1354 #ifdef _DEBUG
wolfSSL 16:8e0d178b1d1e 1355 954, 2377, 858, 19027, 90840, 287, 407, 20140, 7874, 11385, 8005, 6151
wolfSSL 16:8e0d178b1d1e 1356 #else
wolfSSL 16:8e0d178b1d1e 1357 765, 1007, 771, 5216, 34993, 248, 193, 4975, 4201, 3947, 4275, 3811
wolfSSL 16:8e0d178b1d1e 1358 #endif
wolfSSL 16:8e0d178b1d1e 1359 #else /* software only fast math */
wolfSSL 16:8e0d178b1d1e 1360 #ifdef _DEBUG
wolfSSL 16:8e0d178b1d1e 1361 798, 2245, 802, 16657, 66920, 352, 186, 16997, 16145, 12789, 16742, 15006
wolfSSL 16:8e0d178b1d1e 1362 #else
wolfSSL 16:8e0d178b1d1e 1363 775, 1084, 783, 4692, 37510, 207, 183, 4374, 4392, 3097, 4442, 4079
wolfSSL 16:8e0d178b1d1e 1364 #endif
wolfSSL 16:8e0d178b1d1e 1365 #endif
wolfSSL 16:8e0d178b1d1e 1366 };
wolfSSL 16:8e0d178b1d1e 1367
wolfSSL 16:8e0d178b1d1e 1368 static int fp_exptmod_nb_checktime(exptModNb_t* nb)
wolfSSL 16:8e0d178b1d1e 1369 {
wolfSSL 16:8e0d178b1d1e 1370 word32 totalInst;
wolfSSL 16:8e0d178b1d1e 1371
wolfSSL 16:8e0d178b1d1e 1372 /* if no max time has been set then stop (do not block) */
wolfSSL 16:8e0d178b1d1e 1373 if (nb->maxBlockInst == 0 || nb->state >= TFM_EXPTMOD_NB_COUNT) {
wolfSSL 16:8e0d178b1d1e 1374 return TFM_EXPTMOD_NB_STOP;
wolfSSL 16:8e0d178b1d1e 1375 }
wolfSSL 16:8e0d178b1d1e 1376
wolfSSL 16:8e0d178b1d1e 1377 /* if instruction table not set then use maxBlockInst as simple counter */
wolfSSL 16:8e0d178b1d1e 1378 if (exptModNbInst[nb->state] == 0) {
wolfSSL 16:8e0d178b1d1e 1379 if (++nb->totalInst < nb->maxBlockInst)
wolfSSL 16:8e0d178b1d1e 1380 return TFM_EXPTMOD_NB_CONTINUE;
wolfSSL 16:8e0d178b1d1e 1381
wolfSSL 16:8e0d178b1d1e 1382 nb->totalInst = 0; /* reset counter */
wolfSSL 16:8e0d178b1d1e 1383 return TFM_EXPTMOD_NB_STOP;
wolfSSL 16:8e0d178b1d1e 1384 }
wolfSSL 16:8e0d178b1d1e 1385
wolfSSL 16:8e0d178b1d1e 1386 /* get total instruction count including next operation */
wolfSSL 16:8e0d178b1d1e 1387 totalInst = nb->totalInst + exptModNbInst[nb->state];
wolfSSL 16:8e0d178b1d1e 1388 /* if the next operation can completed within the maximum then continue */
wolfSSL 16:8e0d178b1d1e 1389 if (totalInst <= nb->maxBlockInst) {
wolfSSL 16:8e0d178b1d1e 1390 return TFM_EXPTMOD_NB_CONTINUE;
wolfSSL 16:8e0d178b1d1e 1391 }
wolfSSL 16:8e0d178b1d1e 1392
wolfSSL 16:8e0d178b1d1e 1393 return TFM_EXPTMOD_NB_STOP;
wolfSSL 16:8e0d178b1d1e 1394 }
wolfSSL 16:8e0d178b1d1e 1395 #define FP_EXPTMOD_NB_CHECKTIME(nb) fp_exptmod_nb_checktime((nb))
wolfSSL 16:8e0d178b1d1e 1396 #endif /* !FP_EXPTMOD_NB_CHECKTIME */
wolfSSL 16:8e0d178b1d1e 1397 #endif /* WC_RSA_NONBLOCK_TIME */
wolfSSL 16:8e0d178b1d1e 1398
wolfSSL 16:8e0d178b1d1e 1399 /* non-blocking version of timing resistant fp_exptmod function */
wolfSSL 16:8e0d178b1d1e 1400 /* supports cache resistance */
wolfSSL 16:8e0d178b1d1e 1401 int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y)
wolfSSL 16:8e0d178b1d1e 1402 {
wolfSSL 16:8e0d178b1d1e 1403 int err, ret = FP_WOULDBLOCK;
wolfSSL 16:8e0d178b1d1e 1404
wolfSSL 16:8e0d178b1d1e 1405 if (nb == NULL)
wolfSSL 16:8e0d178b1d1e 1406 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 1407
wolfSSL 16:8e0d178b1d1e 1408 #ifdef WC_RSA_NONBLOCK_TIME
wolfSSL 16:8e0d178b1d1e 1409 nb->totalInst = 0;
wolfSSL 16:8e0d178b1d1e 1410 do {
wolfSSL 16:8e0d178b1d1e 1411 nb->totalInst += exptModNbInst[nb->state];
wolfSSL 16:8e0d178b1d1e 1412 #endif
wolfSSL 16:8e0d178b1d1e 1413
wolfSSL 16:8e0d178b1d1e 1414 switch (nb->state) {
wolfSSL 16:8e0d178b1d1e 1415 case TFM_EXPTMOD_NB_INIT:
wolfSSL 16:8e0d178b1d1e 1416 /* now setup montgomery */
wolfSSL 16:8e0d178b1d1e 1417 if ((err = fp_montgomery_setup(P, &nb->mp)) != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1418 nb->state = TFM_EXPTMOD_NB_INIT;
wolfSSL 16:8e0d178b1d1e 1419 return err;
wolfSSL 16:8e0d178b1d1e 1420 }
wolfSSL 16:8e0d178b1d1e 1421
wolfSSL 16:8e0d178b1d1e 1422 /* init ints */
wolfSSL 16:8e0d178b1d1e 1423 fp_init(&nb->R[0]);
wolfSSL 16:8e0d178b1d1e 1424 fp_init(&nb->R[1]);
wolfSSL 16:8e0d178b1d1e 1425 #ifndef WC_NO_CACHE_RESISTANT
wolfSSL 16:8e0d178b1d1e 1426 fp_init(&nb->R[2]);
wolfSSL 16:8e0d178b1d1e 1427 #endif
wolfSSL 16:8e0d178b1d1e 1428 nb->state = TFM_EXPTMOD_NB_MONT;
wolfSSL 16:8e0d178b1d1e 1429 break;
wolfSSL 16:8e0d178b1d1e 1430
wolfSSL 16:8e0d178b1d1e 1431 case TFM_EXPTMOD_NB_MONT:
wolfSSL 16:8e0d178b1d1e 1432 /* mod m -> R[0] */
wolfSSL 16:8e0d178b1d1e 1433 fp_montgomery_calc_normalization(&nb->R[0], P);
wolfSSL 16:8e0d178b1d1e 1434
wolfSSL 16:8e0d178b1d1e 1435 nb->state = TFM_EXPTMOD_NB_MONT_RED;
wolfSSL 16:8e0d178b1d1e 1436 break;
wolfSSL 16:8e0d178b1d1e 1437
wolfSSL 16:8e0d178b1d1e 1438 case TFM_EXPTMOD_NB_MONT_RED:
wolfSSL 16:8e0d178b1d1e 1439 /* reduce G -> R[1] */
wolfSSL 16:8e0d178b1d1e 1440 if (fp_cmp_mag(P, G) != FP_GT) {
wolfSSL 16:8e0d178b1d1e 1441 /* G > P so we reduce it first */
wolfSSL 16:8e0d178b1d1e 1442 fp_mod(G, P, &nb->R[1]);
wolfSSL 16:8e0d178b1d1e 1443 } else {
wolfSSL 16:8e0d178b1d1e 1444 fp_copy(G, &nb->R[1]);
wolfSSL 16:8e0d178b1d1e 1445 }
wolfSSL 16:8e0d178b1d1e 1446
wolfSSL 16:8e0d178b1d1e 1447 nb->state = TFM_EXPTMOD_NB_MONT_MUL;
wolfSSL 16:8e0d178b1d1e 1448 break;
wolfSSL 16:8e0d178b1d1e 1449
wolfSSL 16:8e0d178b1d1e 1450 case TFM_EXPTMOD_NB_MONT_MUL:
wolfSSL 16:8e0d178b1d1e 1451 /* G (R[1]) * m (R[0]) */
wolfSSL 16:8e0d178b1d1e 1452 err = fp_mul(&nb->R[1], &nb->R[0], &nb->R[1]);
wolfSSL 16:8e0d178b1d1e 1453 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1454 nb->state = TFM_EXPTMOD_NB_INIT;
wolfSSL 16:8e0d178b1d1e 1455 return err;
wolfSSL 16:8e0d178b1d1e 1456 }
wolfSSL 16:8e0d178b1d1e 1457
wolfSSL 16:8e0d178b1d1e 1458 nb->state = TFM_EXPTMOD_NB_MONT_MOD;
wolfSSL 16:8e0d178b1d1e 1459 break;
wolfSSL 16:8e0d178b1d1e 1460
wolfSSL 16:8e0d178b1d1e 1461 case TFM_EXPTMOD_NB_MONT_MOD:
wolfSSL 16:8e0d178b1d1e 1462 /* mod m */
wolfSSL 16:8e0d178b1d1e 1463 err = fp_div(&nb->R[1], P, NULL, &nb->R[1]);
wolfSSL 16:8e0d178b1d1e 1464 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1465 nb->state = TFM_EXPTMOD_NB_INIT;
wolfSSL 16:8e0d178b1d1e 1466 return err;
wolfSSL 16:8e0d178b1d1e 1467 }
wolfSSL 16:8e0d178b1d1e 1468
wolfSSL 16:8e0d178b1d1e 1469 nb->state = TFM_EXPTMOD_NB_MONT_MODCHK;
wolfSSL 16:8e0d178b1d1e 1470 break;
wolfSSL 16:8e0d178b1d1e 1471
wolfSSL 16:8e0d178b1d1e 1472 case TFM_EXPTMOD_NB_MONT_MODCHK:
wolfSSL 16:8e0d178b1d1e 1473 /* m matches sign of (G * R mod m) */
wolfSSL 16:8e0d178b1d1e 1474 if (nb->R[1].sign != P->sign) {
wolfSSL 16:8e0d178b1d1e 1475 fp_add(&nb->R[1], P, &nb->R[1]);
wolfSSL 16:8e0d178b1d1e 1476 }
wolfSSL 16:8e0d178b1d1e 1477
wolfSSL 16:8e0d178b1d1e 1478 /* set initial mode and bit cnt */
wolfSSL 16:8e0d178b1d1e 1479 nb->bitcnt = 1;
wolfSSL 16:8e0d178b1d1e 1480 nb->buf = 0;
wolfSSL 16:8e0d178b1d1e 1481 nb->digidx = X->used - 1;
wolfSSL 16:8e0d178b1d1e 1482
wolfSSL 16:8e0d178b1d1e 1483 nb->state = TFM_EXPTMOD_NB_NEXT;
wolfSSL 16:8e0d178b1d1e 1484 break;
wolfSSL 16:8e0d178b1d1e 1485
wolfSSL 16:8e0d178b1d1e 1486 case TFM_EXPTMOD_NB_NEXT:
wolfSSL 16:8e0d178b1d1e 1487 /* grab next digit as required */
wolfSSL 16:8e0d178b1d1e 1488 if (--nb->bitcnt == 0) {
wolfSSL 16:8e0d178b1d1e 1489 /* if nb->digidx == -1 we are out of digits so break */
wolfSSL 16:8e0d178b1d1e 1490 if (nb->digidx == -1) {
wolfSSL 16:8e0d178b1d1e 1491 nb->state = TFM_EXPTMOD_NB_RED;
wolfSSL 16:8e0d178b1d1e 1492 break;
wolfSSL 16:8e0d178b1d1e 1493 }
wolfSSL 16:8e0d178b1d1e 1494 /* read next digit and reset nb->bitcnt */
wolfSSL 16:8e0d178b1d1e 1495 nb->buf = X->dp[nb->digidx--];
wolfSSL 16:8e0d178b1d1e 1496 nb->bitcnt = (int)DIGIT_BIT;
wolfSSL 16:8e0d178b1d1e 1497 }
wolfSSL 16:8e0d178b1d1e 1498
wolfSSL 16:8e0d178b1d1e 1499 /* grab the next msb from the exponent */
wolfSSL 16:8e0d178b1d1e 1500 nb->y = (int)(nb->buf >> (DIGIT_BIT - 1)) & 1;
wolfSSL 16:8e0d178b1d1e 1501 nb->buf <<= (fp_digit)1;
wolfSSL 16:8e0d178b1d1e 1502 nb->state = TFM_EXPTMOD_NB_MUL;
wolfSSL 16:8e0d178b1d1e 1503 FALL_THROUGH;
wolfSSL 16:8e0d178b1d1e 1504
wolfSSL 16:8e0d178b1d1e 1505 case TFM_EXPTMOD_NB_MUL:
wolfSSL 16:8e0d178b1d1e 1506 fp_mul(&nb->R[0], &nb->R[1], &nb->R[nb->y^1]);
wolfSSL 16:8e0d178b1d1e 1507 nb->state = TFM_EXPTMOD_NB_MUL_RED;
wolfSSL 16:8e0d178b1d1e 1508 break;
wolfSSL 16:8e0d178b1d1e 1509
wolfSSL 16:8e0d178b1d1e 1510 case TFM_EXPTMOD_NB_MUL_RED:
wolfSSL 16:8e0d178b1d1e 1511 fp_montgomery_reduce(&nb->R[nb->y^1], P, nb->mp);
wolfSSL 16:8e0d178b1d1e 1512 nb->state = TFM_EXPTMOD_NB_SQR;
wolfSSL 16:8e0d178b1d1e 1513 break;
wolfSSL 16:8e0d178b1d1e 1514
wolfSSL 16:8e0d178b1d1e 1515 case TFM_EXPTMOD_NB_SQR:
wolfSSL 16:8e0d178b1d1e 1516 #ifdef WC_NO_CACHE_RESISTANT
wolfSSL 16:8e0d178b1d1e 1517 fp_sqr(&nb->R[nb->y], &nb->R[nb->y]);
wolfSSL 16:8e0d178b1d1e 1518 #else
wolfSSL 16:8e0d178b1d1e 1519 fp_copy((fp_int*) ( ((wolfssl_word)&nb->R[0] & wc_off_on_addr[nb->y^1]) +
wolfSSL 16:8e0d178b1d1e 1520 ((wolfssl_word)&nb->R[1] & wc_off_on_addr[nb->y]) ),
wolfSSL 16:8e0d178b1d1e 1521 &nb->R[2]);
wolfSSL 16:8e0d178b1d1e 1522 fp_sqr(&nb->R[2], &nb->R[2]);
wolfSSL 16:8e0d178b1d1e 1523 #endif /* WC_NO_CACHE_RESISTANT */
wolfSSL 16:8e0d178b1d1e 1524
wolfSSL 16:8e0d178b1d1e 1525 nb->state = TFM_EXPTMOD_NB_SQR_RED;
wolfSSL 16:8e0d178b1d1e 1526 break;
wolfSSL 16:8e0d178b1d1e 1527
wolfSSL 16:8e0d178b1d1e 1528 case TFM_EXPTMOD_NB_SQR_RED:
wolfSSL 16:8e0d178b1d1e 1529 #ifdef WC_NO_CACHE_RESISTANT
wolfSSL 16:8e0d178b1d1e 1530 fp_montgomery_reduce(&nb->R[nb->y], P, nb->mp);
wolfSSL 16:8e0d178b1d1e 1531 #else
wolfSSL 16:8e0d178b1d1e 1532 fp_montgomery_reduce(&nb->R[2], P, nb->mp);
wolfSSL 16:8e0d178b1d1e 1533 fp_copy(&nb->R[2],
wolfSSL 16:8e0d178b1d1e 1534 (fp_int*) ( ((wolfssl_word)&nb->R[0] & wc_off_on_addr[nb->y^1]) +
wolfSSL 16:8e0d178b1d1e 1535 ((wolfssl_word)&nb->R[1] & wc_off_on_addr[nb->y]) ) );
wolfSSL 16:8e0d178b1d1e 1536 #endif /* WC_NO_CACHE_RESISTANT */
wolfSSL 16:8e0d178b1d1e 1537
wolfSSL 16:8e0d178b1d1e 1538 nb->state = TFM_EXPTMOD_NB_NEXT;
wolfSSL 16:8e0d178b1d1e 1539 break;
wolfSSL 16:8e0d178b1d1e 1540
wolfSSL 16:8e0d178b1d1e 1541 case TFM_EXPTMOD_NB_RED:
wolfSSL 16:8e0d178b1d1e 1542 /* final reduce */
wolfSSL 16:8e0d178b1d1e 1543 fp_montgomery_reduce(&nb->R[0], P, nb->mp);
wolfSSL 16:8e0d178b1d1e 1544 fp_copy(&nb->R[0], Y);
wolfSSL 16:8e0d178b1d1e 1545
wolfSSL 16:8e0d178b1d1e 1546 nb->state = TFM_EXPTMOD_NB_INIT;
wolfSSL 16:8e0d178b1d1e 1547 ret = FP_OKAY;
wolfSSL 16:8e0d178b1d1e 1548 break;
wolfSSL 16:8e0d178b1d1e 1549 } /* switch */
wolfSSL 16:8e0d178b1d1e 1550
wolfSSL 16:8e0d178b1d1e 1551 #ifdef WC_RSA_NONBLOCK_TIME
wolfSSL 16:8e0d178b1d1e 1552 /* determine if maximum blocking time has been reached */
wolfSSL 16:8e0d178b1d1e 1553 } while (ret == FP_WOULDBLOCK &&
wolfSSL 16:8e0d178b1d1e 1554 FP_EXPTMOD_NB_CHECKTIME(nb) == TFM_EXPTMOD_NB_CONTINUE);
wolfSSL 16:8e0d178b1d1e 1555 #endif
wolfSSL 16:8e0d178b1d1e 1556
wolfSSL 16:8e0d178b1d1e 1557 return ret;
wolfSSL 16:8e0d178b1d1e 1558 }
wolfSSL 16:8e0d178b1d1e 1559
wolfSSL 16:8e0d178b1d1e 1560 #endif /* WC_RSA_NONBLOCK */
wolfSSL 16:8e0d178b1d1e 1561
wolfSSL 16:8e0d178b1d1e 1562
wolfSSL 15:117db924cf7c 1563 /* timing resistant montgomery ladder based exptmod
wolfSSL 15:117db924cf7c 1564 Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder",
wolfSSL 15:117db924cf7c 1565 Cryptographic Hardware and Embedded Systems, CHES 2002
wolfSSL 15:117db924cf7c 1566 */
wolfSSL 16:8e0d178b1d1e 1567 static int _fp_exptmod_ct(fp_int * G, fp_int * X, int digits, fp_int * P,
wolfSSL 16:8e0d178b1d1e 1568 fp_int * Y)
wolfSSL 15:117db924cf7c 1569 {
wolfSSL 16:8e0d178b1d1e 1570 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 15:117db924cf7c 1571 #ifdef WC_NO_CACHE_RESISTANT
wolfSSL 15:117db924cf7c 1572 fp_int R[2];
wolfSSL 15:117db924cf7c 1573 #else
wolfSSL 15:117db924cf7c 1574 fp_int R[3]; /* need a temp for cache resistance */
wolfSSL 15:117db924cf7c 1575 #endif
wolfSSL 16:8e0d178b1d1e 1576 #else
wolfSSL 16:8e0d178b1d1e 1577 fp_int *R;
wolfSSL 16:8e0d178b1d1e 1578 #endif
wolfSSL 15:117db924cf7c 1579 fp_digit buf, mp;
wolfSSL 15:117db924cf7c 1580 int err, bitcnt, digidx, y;
wolfSSL 15:117db924cf7c 1581
wolfSSL 15:117db924cf7c 1582 /* now setup montgomery */
wolfSSL 15:117db924cf7c 1583 if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) {
wolfSSL 15:117db924cf7c 1584 return err;
wolfSSL 15:117db924cf7c 1585 }
wolfSSL 15:117db924cf7c 1586
wolfSSL 16:8e0d178b1d1e 1587 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1588 #ifndef WC_NO_CACHE_RESISTANT
wolfSSL 16:8e0d178b1d1e 1589 R = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1590 #else
wolfSSL 16:8e0d178b1d1e 1591 R = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1592 #endif
wolfSSL 16:8e0d178b1d1e 1593 if (R == NULL)
wolfSSL 16:8e0d178b1d1e 1594 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 1595 #endif
wolfSSL 15:117db924cf7c 1596 fp_init(&R[0]);
wolfSSL 15:117db924cf7c 1597 fp_init(&R[1]);
wolfSSL 15:117db924cf7c 1598 #ifndef WC_NO_CACHE_RESISTANT
wolfSSL 15:117db924cf7c 1599 fp_init(&R[2]);
wolfSSL 15:117db924cf7c 1600 #endif
wolfSSL 15:117db924cf7c 1601
wolfSSL 15:117db924cf7c 1602 /* now we need R mod m */
wolfSSL 15:117db924cf7c 1603 fp_montgomery_calc_normalization (&R[0], P);
wolfSSL 15:117db924cf7c 1604
wolfSSL 15:117db924cf7c 1605 /* now set R[0][1] to G * R mod m */
wolfSSL 15:117db924cf7c 1606 if (fp_cmp_mag(P, G) != FP_GT) {
wolfSSL 15:117db924cf7c 1607 /* G > P so we reduce it first */
wolfSSL 15:117db924cf7c 1608 fp_mod(G, P, &R[1]);
wolfSSL 15:117db924cf7c 1609 } else {
wolfSSL 15:117db924cf7c 1610 fp_copy(G, &R[1]);
wolfSSL 15:117db924cf7c 1611 }
wolfSSL 15:117db924cf7c 1612 fp_mulmod (&R[1], &R[0], P, &R[1]);
wolfSSL 15:117db924cf7c 1613
wolfSSL 15:117db924cf7c 1614 /* for j = t-1 downto 0 do
wolfSSL 15:117db924cf7c 1615 r_!k = R0*R1; r_k = r_k^2
wolfSSL 15:117db924cf7c 1616 */
wolfSSL 15:117db924cf7c 1617
wolfSSL 15:117db924cf7c 1618 /* set initial mode and bit cnt */
wolfSSL 15:117db924cf7c 1619 bitcnt = 1;
wolfSSL 15:117db924cf7c 1620 buf = 0;
wolfSSL 16:8e0d178b1d1e 1621 digidx = digits - 1;
wolfSSL 15:117db924cf7c 1622
wolfSSL 15:117db924cf7c 1623 for (;;) {
wolfSSL 15:117db924cf7c 1624 /* grab next digit as required */
wolfSSL 15:117db924cf7c 1625 if (--bitcnt == 0) {
wolfSSL 15:117db924cf7c 1626 /* if digidx == -1 we are out of digits so break */
wolfSSL 15:117db924cf7c 1627 if (digidx == -1) {
wolfSSL 15:117db924cf7c 1628 break;
wolfSSL 15:117db924cf7c 1629 }
wolfSSL 15:117db924cf7c 1630 /* read next digit and reset bitcnt */
wolfSSL 15:117db924cf7c 1631 buf = X->dp[digidx--];
wolfSSL 15:117db924cf7c 1632 bitcnt = (int)DIGIT_BIT;
wolfSSL 15:117db924cf7c 1633 }
wolfSSL 15:117db924cf7c 1634
wolfSSL 15:117db924cf7c 1635 /* grab the next msb from the exponent */
wolfSSL 15:117db924cf7c 1636 y = (int)(buf >> (DIGIT_BIT - 1)) & 1;
wolfSSL 15:117db924cf7c 1637 buf <<= (fp_digit)1;
wolfSSL 15:117db924cf7c 1638
wolfSSL 15:117db924cf7c 1639 /* do ops */
wolfSSL 16:8e0d178b1d1e 1640 err = fp_mul(&R[0], &R[1], &R[y^1]);
wolfSSL 16:8e0d178b1d1e 1641 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1642 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1643 XFREE(R, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1644 #endif
wolfSSL 16:8e0d178b1d1e 1645 return err;
wolfSSL 16:8e0d178b1d1e 1646 }
wolfSSL 16:8e0d178b1d1e 1647 err = fp_montgomery_reduce(&R[y^1], P, mp);
wolfSSL 16:8e0d178b1d1e 1648 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1649 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1650 XFREE(R, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1651 #endif
wolfSSL 16:8e0d178b1d1e 1652 return err;
wolfSSL 16:8e0d178b1d1e 1653 }
wolfSSL 15:117db924cf7c 1654
wolfSSL 15:117db924cf7c 1655 #ifdef WC_NO_CACHE_RESISTANT
wolfSSL 16:8e0d178b1d1e 1656 err = fp_sqr(&R[y], &R[y]);
wolfSSL 16:8e0d178b1d1e 1657 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1658 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1659 XFREE(R, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1660 #endif
wolfSSL 16:8e0d178b1d1e 1661 return err;
wolfSSL 16:8e0d178b1d1e 1662 }
wolfSSL 16:8e0d178b1d1e 1663 err = fp_montgomery_reduce(&R[y], P, mp);
wolfSSL 16:8e0d178b1d1e 1664 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1665 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1666 XFREE(R, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1667 #endif
wolfSSL 16:8e0d178b1d1e 1668 return err;
wolfSSL 16:8e0d178b1d1e 1669 }
wolfSSL 15:117db924cf7c 1670 #else
wolfSSL 15:117db924cf7c 1671 /* instead of using R[y] for sqr, which leaks key bit to cache monitor,
wolfSSL 15:117db924cf7c 1672 * use R[2] as temp, make sure address calc is constant, keep
wolfSSL 15:117db924cf7c 1673 * &R[0] and &R[1] in cache */
wolfSSL 15:117db924cf7c 1674 fp_copy((fp_int*) ( ((wolfssl_word)&R[0] & wc_off_on_addr[y^1]) +
wolfSSL 15:117db924cf7c 1675 ((wolfssl_word)&R[1] & wc_off_on_addr[y]) ),
wolfSSL 15:117db924cf7c 1676 &R[2]);
wolfSSL 16:8e0d178b1d1e 1677 err = fp_sqr(&R[2], &R[2]);
wolfSSL 16:8e0d178b1d1e 1678 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1679 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1680 XFREE(R, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1681 #endif
wolfSSL 16:8e0d178b1d1e 1682 return err;
wolfSSL 16:8e0d178b1d1e 1683 }
wolfSSL 16:8e0d178b1d1e 1684 err = fp_montgomery_reduce(&R[2], P, mp);
wolfSSL 16:8e0d178b1d1e 1685 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1686 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1687 XFREE(R, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1688 #endif
wolfSSL 16:8e0d178b1d1e 1689 return err;
wolfSSL 16:8e0d178b1d1e 1690 }
wolfSSL 15:117db924cf7c 1691 fp_copy(&R[2],
wolfSSL 15:117db924cf7c 1692 (fp_int*) ( ((wolfssl_word)&R[0] & wc_off_on_addr[y^1]) +
wolfSSL 15:117db924cf7c 1693 ((wolfssl_word)&R[1] & wc_off_on_addr[y]) ) );
wolfSSL 15:117db924cf7c 1694 #endif /* WC_NO_CACHE_RESISTANT */
wolfSSL 15:117db924cf7c 1695 }
wolfSSL 15:117db924cf7c 1696
wolfSSL 16:8e0d178b1d1e 1697 err = fp_montgomery_reduce(&R[0], P, mp);
wolfSSL 15:117db924cf7c 1698 fp_copy(&R[0], Y);
wolfSSL 16:8e0d178b1d1e 1699 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1700 XFREE(R, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1701 #endif
wolfSSL 16:8e0d178b1d1e 1702 return err;
wolfSSL 15:117db924cf7c 1703 }
wolfSSL 15:117db924cf7c 1704
wolfSSL 16:8e0d178b1d1e 1705 #endif /* TFM_TIMING_RESISTANT */
wolfSSL 15:117db924cf7c 1706
wolfSSL 15:117db924cf7c 1707 /* y = g**x (mod b)
wolfSSL 15:117db924cf7c 1708 * Some restrictions... x must be positive and < b
wolfSSL 15:117db924cf7c 1709 */
wolfSSL 16:8e0d178b1d1e 1710 static int _fp_exptmod_nct(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
wolfSSL 15:117db924cf7c 1711 {
wolfSSL 16:8e0d178b1d1e 1712 fp_int *res;
wolfSSL 16:8e0d178b1d1e 1713 fp_int *M;
wolfSSL 15:117db924cf7c 1714 fp_digit buf, mp;
wolfSSL 15:117db924cf7c 1715 int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
wolfSSL 15:117db924cf7c 1716
wolfSSL 15:117db924cf7c 1717 /* find window size */
wolfSSL 15:117db924cf7c 1718 x = fp_count_bits (X);
wolfSSL 15:117db924cf7c 1719 if (x <= 21) {
wolfSSL 15:117db924cf7c 1720 winsize = 1;
wolfSSL 15:117db924cf7c 1721 } else if (x <= 36) {
wolfSSL 15:117db924cf7c 1722 winsize = 3;
wolfSSL 15:117db924cf7c 1723 } else if (x <= 140) {
wolfSSL 15:117db924cf7c 1724 winsize = 4;
wolfSSL 15:117db924cf7c 1725 } else if (x <= 450) {
wolfSSL 15:117db924cf7c 1726 winsize = 5;
wolfSSL 15:117db924cf7c 1727 } else {
wolfSSL 15:117db924cf7c 1728 winsize = 6;
wolfSSL 15:117db924cf7c 1729 }
wolfSSL 15:117db924cf7c 1730
wolfSSL 15:117db924cf7c 1731 /* now setup montgomery */
wolfSSL 15:117db924cf7c 1732 if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) {
wolfSSL 15:117db924cf7c 1733 return err;
wolfSSL 15:117db924cf7c 1734 }
wolfSSL 15:117db924cf7c 1735
wolfSSL 16:8e0d178b1d1e 1736 /* only allocate space for what's needed for window plus res */
wolfSSL 16:8e0d178b1d1e 1737 M = (fp_int*)XMALLOC(sizeof(fp_int)*((1 << winsize) + 1), NULL,
wolfSSL 16:8e0d178b1d1e 1738 DYNAMIC_TYPE_BIGINT);
wolfSSL 15:117db924cf7c 1739 if (M == NULL) {
wolfSSL 15:117db924cf7c 1740 return FP_MEM;
wolfSSL 15:117db924cf7c 1741 }
wolfSSL 16:8e0d178b1d1e 1742 res = &M[1 << winsize];
wolfSSL 15:117db924cf7c 1743
wolfSSL 15:117db924cf7c 1744 /* init M array */
wolfSSL 15:117db924cf7c 1745 for(x = 0; x < (1 << winsize); x++)
wolfSSL 15:117db924cf7c 1746 fp_init(&M[x]);
wolfSSL 15:117db924cf7c 1747
wolfSSL 15:117db924cf7c 1748 /* setup result */
wolfSSL 16:8e0d178b1d1e 1749 fp_init(res);
wolfSSL 15:117db924cf7c 1750
wolfSSL 15:117db924cf7c 1751 /* create M table
wolfSSL 15:117db924cf7c 1752 *
wolfSSL 15:117db924cf7c 1753 * The M table contains powers of the input base, e.g. M[x] = G^x mod P
wolfSSL 15:117db924cf7c 1754 *
wolfSSL 15:117db924cf7c 1755 * The first half of the table is not computed though except for M[0] and M[1]
wolfSSL 15:117db924cf7c 1756 */
wolfSSL 15:117db924cf7c 1757
wolfSSL 15:117db924cf7c 1758 /* now we need R mod m */
wolfSSL 16:8e0d178b1d1e 1759 fp_montgomery_calc_normalization (res, P);
wolfSSL 15:117db924cf7c 1760
wolfSSL 15:117db924cf7c 1761 /* now set M[1] to G * R mod m */
wolfSSL 15:117db924cf7c 1762 if (fp_cmp_mag(P, G) != FP_GT) {
wolfSSL 15:117db924cf7c 1763 /* G > P so we reduce it first */
wolfSSL 15:117db924cf7c 1764 fp_mod(G, P, &M[1]);
wolfSSL 15:117db924cf7c 1765 } else {
wolfSSL 15:117db924cf7c 1766 fp_copy(G, &M[1]);
wolfSSL 15:117db924cf7c 1767 }
wolfSSL 16:8e0d178b1d1e 1768 fp_mulmod (&M[1], res, P, &M[1]);
wolfSSL 15:117db924cf7c 1769
wolfSSL 15:117db924cf7c 1770 /* compute the value at M[1<<(winsize-1)] by
wolfSSL 15:117db924cf7c 1771 * squaring M[1] (winsize-1) times */
wolfSSL 15:117db924cf7c 1772 fp_copy (&M[1], &M[1 << (winsize - 1)]);
wolfSSL 15:117db924cf7c 1773 for (x = 0; x < (winsize - 1); x++) {
wolfSSL 15:117db924cf7c 1774 fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]);
wolfSSL 16:8e0d178b1d1e 1775 err = fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp);
wolfSSL 16:8e0d178b1d1e 1776 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1777 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1778 return err;
wolfSSL 16:8e0d178b1d1e 1779 }
wolfSSL 15:117db924cf7c 1780 }
wolfSSL 15:117db924cf7c 1781
wolfSSL 15:117db924cf7c 1782 /* create upper table */
wolfSSL 15:117db924cf7c 1783 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
wolfSSL 16:8e0d178b1d1e 1784 err = fp_mul(&M[x - 1], &M[1], &M[x]);
wolfSSL 16:8e0d178b1d1e 1785 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1786 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1787 return err;
wolfSSL 16:8e0d178b1d1e 1788 }
wolfSSL 16:8e0d178b1d1e 1789 err = fp_montgomery_reduce(&M[x], P, mp);
wolfSSL 16:8e0d178b1d1e 1790 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1791 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1792 return err;
wolfSSL 16:8e0d178b1d1e 1793 }
wolfSSL 15:117db924cf7c 1794 }
wolfSSL 15:117db924cf7c 1795
wolfSSL 15:117db924cf7c 1796 /* set initial mode and bit cnt */
wolfSSL 15:117db924cf7c 1797 mode = 0;
wolfSSL 16:8e0d178b1d1e 1798 bitcnt = (x % DIGIT_BIT) + 1;
wolfSSL 15:117db924cf7c 1799 buf = 0;
wolfSSL 15:117db924cf7c 1800 digidx = X->used - 1;
wolfSSL 15:117db924cf7c 1801 bitcpy = 0;
wolfSSL 15:117db924cf7c 1802 bitbuf = 0;
wolfSSL 15:117db924cf7c 1803
wolfSSL 15:117db924cf7c 1804 for (;;) {
wolfSSL 15:117db924cf7c 1805 /* grab next digit as required */
wolfSSL 15:117db924cf7c 1806 if (--bitcnt == 0) {
wolfSSL 15:117db924cf7c 1807 /* if digidx == -1 we are out of digits so break */
wolfSSL 15:117db924cf7c 1808 if (digidx == -1) {
wolfSSL 15:117db924cf7c 1809 break;
wolfSSL 15:117db924cf7c 1810 }
wolfSSL 15:117db924cf7c 1811 /* read next digit and reset bitcnt */
wolfSSL 15:117db924cf7c 1812 buf = X->dp[digidx--];
wolfSSL 15:117db924cf7c 1813 bitcnt = (int)DIGIT_BIT;
wolfSSL 15:117db924cf7c 1814 }
wolfSSL 15:117db924cf7c 1815
wolfSSL 15:117db924cf7c 1816 /* grab the next msb from the exponent */
wolfSSL 15:117db924cf7c 1817 y = (int)(buf >> (DIGIT_BIT - 1)) & 1;
wolfSSL 15:117db924cf7c 1818 buf <<= (fp_digit)1;
wolfSSL 15:117db924cf7c 1819
wolfSSL 15:117db924cf7c 1820 /* if the bit is zero and mode == 0 then we ignore it
wolfSSL 15:117db924cf7c 1821 * These represent the leading zero bits before the first 1 bit
wolfSSL 15:117db924cf7c 1822 * in the exponent. Technically this opt is not required but it
wolfSSL 15:117db924cf7c 1823 * does lower the # of trivial squaring/reductions used
wolfSSL 15:117db924cf7c 1824 */
wolfSSL 15:117db924cf7c 1825 if (mode == 0 && y == 0) {
wolfSSL 15:117db924cf7c 1826 continue;
wolfSSL 15:117db924cf7c 1827 }
wolfSSL 15:117db924cf7c 1828
wolfSSL 15:117db924cf7c 1829 /* if the bit is zero and mode == 1 then we square */
wolfSSL 15:117db924cf7c 1830 if (mode == 1 && y == 0) {
wolfSSL 16:8e0d178b1d1e 1831 err = fp_sqr(res, res);
wolfSSL 16:8e0d178b1d1e 1832 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1833 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1834 return err;
wolfSSL 16:8e0d178b1d1e 1835 }
wolfSSL 16:8e0d178b1d1e 1836 fp_montgomery_reduce(res, P, mp);
wolfSSL 16:8e0d178b1d1e 1837 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1838 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1839 return err;
wolfSSL 16:8e0d178b1d1e 1840 }
wolfSSL 15:117db924cf7c 1841 continue;
wolfSSL 15:117db924cf7c 1842 }
wolfSSL 15:117db924cf7c 1843
wolfSSL 15:117db924cf7c 1844 /* else we add it to the window */
wolfSSL 15:117db924cf7c 1845 bitbuf |= (y << (winsize - ++bitcpy));
wolfSSL 15:117db924cf7c 1846 mode = 2;
wolfSSL 15:117db924cf7c 1847
wolfSSL 15:117db924cf7c 1848 if (bitcpy == winsize) {
wolfSSL 15:117db924cf7c 1849 /* ok window is filled so square as required and multiply */
wolfSSL 15:117db924cf7c 1850 /* square first */
wolfSSL 15:117db924cf7c 1851 for (x = 0; x < winsize; x++) {
wolfSSL 16:8e0d178b1d1e 1852 err = fp_sqr(res, res);
wolfSSL 16:8e0d178b1d1e 1853 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1854 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1855 return err;
wolfSSL 16:8e0d178b1d1e 1856 }
wolfSSL 16:8e0d178b1d1e 1857 err = fp_montgomery_reduce(res, P, mp);
wolfSSL 16:8e0d178b1d1e 1858 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1859 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1860 return err;
wolfSSL 16:8e0d178b1d1e 1861 }
wolfSSL 15:117db924cf7c 1862 }
wolfSSL 15:117db924cf7c 1863
wolfSSL 15:117db924cf7c 1864 /* then multiply */
wolfSSL 16:8e0d178b1d1e 1865 err = fp_mul(res, &M[bitbuf], res);
wolfSSL 16:8e0d178b1d1e 1866 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1867 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1868 return err;
wolfSSL 16:8e0d178b1d1e 1869 }
wolfSSL 16:8e0d178b1d1e 1870 err = fp_montgomery_reduce(res, P, mp);
wolfSSL 16:8e0d178b1d1e 1871 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1872 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1873 return err;
wolfSSL 16:8e0d178b1d1e 1874 }
wolfSSL 15:117db924cf7c 1875
wolfSSL 15:117db924cf7c 1876 /* empty window and reset */
wolfSSL 15:117db924cf7c 1877 bitcpy = 0;
wolfSSL 15:117db924cf7c 1878 bitbuf = 0;
wolfSSL 15:117db924cf7c 1879 mode = 1;
wolfSSL 15:117db924cf7c 1880 }
wolfSSL 15:117db924cf7c 1881 }
wolfSSL 15:117db924cf7c 1882
wolfSSL 15:117db924cf7c 1883 /* if bits remain then square/multiply */
wolfSSL 15:117db924cf7c 1884 if (mode == 2 && bitcpy > 0) {
wolfSSL 15:117db924cf7c 1885 /* square then multiply if the bit is set */
wolfSSL 15:117db924cf7c 1886 for (x = 0; x < bitcpy; x++) {
wolfSSL 16:8e0d178b1d1e 1887 err = fp_sqr(res, res);
wolfSSL 16:8e0d178b1d1e 1888 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1889 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1890 return err;
wolfSSL 16:8e0d178b1d1e 1891 }
wolfSSL 16:8e0d178b1d1e 1892 err = fp_montgomery_reduce(res, P, mp);
wolfSSL 16:8e0d178b1d1e 1893 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1894 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1895 return err;
wolfSSL 16:8e0d178b1d1e 1896 }
wolfSSL 15:117db924cf7c 1897
wolfSSL 15:117db924cf7c 1898 /* get next bit of the window */
wolfSSL 15:117db924cf7c 1899 bitbuf <<= 1;
wolfSSL 15:117db924cf7c 1900 if ((bitbuf & (1 << winsize)) != 0) {
wolfSSL 15:117db924cf7c 1901 /* then multiply */
wolfSSL 16:8e0d178b1d1e 1902 err = fp_mul(res, &M[1], res);
wolfSSL 16:8e0d178b1d1e 1903 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1904 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1905 return err;
wolfSSL 16:8e0d178b1d1e 1906 }
wolfSSL 16:8e0d178b1d1e 1907 err = fp_montgomery_reduce(res, P, mp);
wolfSSL 16:8e0d178b1d1e 1908 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1909 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1910 return err;
wolfSSL 16:8e0d178b1d1e 1911 }
wolfSSL 15:117db924cf7c 1912 }
wolfSSL 15:117db924cf7c 1913 }
wolfSSL 15:117db924cf7c 1914 }
wolfSSL 15:117db924cf7c 1915
wolfSSL 15:117db924cf7c 1916 /* fixup result if Montgomery reduction is used
wolfSSL 15:117db924cf7c 1917 * recall that any value in a Montgomery system is
wolfSSL 15:117db924cf7c 1918 * actually multiplied by R mod n. So we have
wolfSSL 15:117db924cf7c 1919 * to reduce one more time to cancel out the factor
wolfSSL 15:117db924cf7c 1920 * of R.
wolfSSL 15:117db924cf7c 1921 */
wolfSSL 16:8e0d178b1d1e 1922 err = fp_montgomery_reduce(res, P, mp);
wolfSSL 15:117db924cf7c 1923
wolfSSL 15:117db924cf7c 1924 /* swap res with Y */
wolfSSL 16:8e0d178b1d1e 1925 fp_copy (res, Y);
wolfSSL 16:8e0d178b1d1e 1926
wolfSSL 16:8e0d178b1d1e 1927 XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 1928 return err;
wolfSSL 16:8e0d178b1d1e 1929 }
wolfSSL 16:8e0d178b1d1e 1930
wolfSSL 16:8e0d178b1d1e 1931
wolfSSL 16:8e0d178b1d1e 1932 #ifdef TFM_TIMING_RESISTANT
wolfSSL 16:8e0d178b1d1e 1933 #if DIGIT_BIT <= 16
wolfSSL 16:8e0d178b1d1e 1934 #define WINSIZE 2
wolfSSL 16:8e0d178b1d1e 1935 #elif DIGIT_BIT <= 32
wolfSSL 16:8e0d178b1d1e 1936 #define WINSIZE 3
wolfSSL 16:8e0d178b1d1e 1937 #elif DIGIT_BIT <= 64
wolfSSL 16:8e0d178b1d1e 1938 #define WINSIZE 4
wolfSSL 16:8e0d178b1d1e 1939 #elif DIGIT_BIT <= 128
wolfSSL 16:8e0d178b1d1e 1940 #define WINSIZE 5
wolfSSL 16:8e0d178b1d1e 1941 #endif
wolfSSL 16:8e0d178b1d1e 1942
wolfSSL 16:8e0d178b1d1e 1943 /* y = 2**x (mod b)
wolfSSL 16:8e0d178b1d1e 1944 * Some restrictions... x must be positive and < b
wolfSSL 16:8e0d178b1d1e 1945 */
wolfSSL 16:8e0d178b1d1e 1946 static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P,
wolfSSL 16:8e0d178b1d1e 1947 fp_int * Y)
wolfSSL 16:8e0d178b1d1e 1948 {
wolfSSL 16:8e0d178b1d1e 1949 fp_digit buf, mp;
wolfSSL 16:8e0d178b1d1e 1950 int err, bitbuf, bitcpy, bitcnt, digidx, x, y;
wolfSSL 16:8e0d178b1d1e 1951 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1952 fp_int *res;
wolfSSL 16:8e0d178b1d1e 1953 fp_int *tmp;
wolfSSL 16:8e0d178b1d1e 1954 #else
wolfSSL 16:8e0d178b1d1e 1955 fp_int res[1];
wolfSSL 16:8e0d178b1d1e 1956 fp_int tmp[1];
wolfSSL 16:8e0d178b1d1e 1957 #endif
wolfSSL 15:117db924cf7c 1958
wolfSSL 15:117db924cf7c 1959 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1960 res = (fp_int*)XMALLOC(2*sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 1961 if (res == NULL) {
wolfSSL 16:8e0d178b1d1e 1962 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 1963 }
wolfSSL 16:8e0d178b1d1e 1964 tmp = &res[1];
wolfSSL 16:8e0d178b1d1e 1965 #endif
wolfSSL 16:8e0d178b1d1e 1966
wolfSSL 16:8e0d178b1d1e 1967 /* now setup montgomery */
wolfSSL 16:8e0d178b1d1e 1968 if ((err = fp_montgomery_setup(P, &mp)) != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1969 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1970 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 1971 #endif
wolfSSL 16:8e0d178b1d1e 1972 return err;
wolfSSL 16:8e0d178b1d1e 1973 }
wolfSSL 16:8e0d178b1d1e 1974
wolfSSL 16:8e0d178b1d1e 1975 /* setup result */
wolfSSL 16:8e0d178b1d1e 1976 fp_init(res);
wolfSSL 16:8e0d178b1d1e 1977 fp_init(tmp);
wolfSSL 16:8e0d178b1d1e 1978
wolfSSL 16:8e0d178b1d1e 1979 fp_mul_2d(P, 1 << WINSIZE, tmp);
wolfSSL 16:8e0d178b1d1e 1980
wolfSSL 16:8e0d178b1d1e 1981 /* now we need R mod m */
wolfSSL 16:8e0d178b1d1e 1982 fp_montgomery_calc_normalization(res, P);
wolfSSL 16:8e0d178b1d1e 1983
wolfSSL 16:8e0d178b1d1e 1984 /* Get the top bits left over after taking WINSIZE bits starting at the
wolfSSL 16:8e0d178b1d1e 1985 * least-significant.
wolfSSL 16:8e0d178b1d1e 1986 */
wolfSSL 16:8e0d178b1d1e 1987 digidx = digits - 1;
wolfSSL 16:8e0d178b1d1e 1988 bitcpy = (digits * DIGIT_BIT) % WINSIZE;
wolfSSL 16:8e0d178b1d1e 1989 if (bitcpy > 0) {
wolfSSL 16:8e0d178b1d1e 1990 bitcnt = (int)DIGIT_BIT - bitcpy;
wolfSSL 16:8e0d178b1d1e 1991 buf = X->dp[digidx--];
wolfSSL 16:8e0d178b1d1e 1992 bitbuf = (int)(buf >> bitcnt);
wolfSSL 16:8e0d178b1d1e 1993 /* Multiply montgomery representation of 1 by 2 ^ top */
wolfSSL 16:8e0d178b1d1e 1994 fp_mul_2d(res, bitbuf, res);
wolfSSL 16:8e0d178b1d1e 1995 fp_add(res, tmp, res);
wolfSSL 16:8e0d178b1d1e 1996 err = fp_mod(res, P, res);
wolfSSL 16:8e0d178b1d1e 1997 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 1998 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 1999 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2000 #endif
wolfSSL 16:8e0d178b1d1e 2001 return err;
wolfSSL 16:8e0d178b1d1e 2002 }
wolfSSL 16:8e0d178b1d1e 2003 /* Move out bits used */
wolfSSL 16:8e0d178b1d1e 2004 buf <<= bitcpy;
wolfSSL 16:8e0d178b1d1e 2005 bitcnt++;
wolfSSL 16:8e0d178b1d1e 2006 }
wolfSSL 16:8e0d178b1d1e 2007 else {
wolfSSL 16:8e0d178b1d1e 2008 bitcnt = 1;
wolfSSL 16:8e0d178b1d1e 2009 buf = 0;
wolfSSL 16:8e0d178b1d1e 2010 }
wolfSSL 16:8e0d178b1d1e 2011
wolfSSL 16:8e0d178b1d1e 2012 /* empty window and reset */
wolfSSL 16:8e0d178b1d1e 2013 bitbuf = 0;
wolfSSL 16:8e0d178b1d1e 2014 bitcpy = 0;
wolfSSL 16:8e0d178b1d1e 2015
wolfSSL 16:8e0d178b1d1e 2016 for (;;) {
wolfSSL 16:8e0d178b1d1e 2017 /* grab next digit as required */
wolfSSL 16:8e0d178b1d1e 2018 if (--bitcnt == 0) {
wolfSSL 16:8e0d178b1d1e 2019 /* if digidx == -1 we are out of digits so break */
wolfSSL 16:8e0d178b1d1e 2020 if (digidx == -1) {
wolfSSL 16:8e0d178b1d1e 2021 break;
wolfSSL 16:8e0d178b1d1e 2022 }
wolfSSL 16:8e0d178b1d1e 2023 /* read next digit and reset bitcnt */
wolfSSL 16:8e0d178b1d1e 2024 buf = X->dp[digidx--];
wolfSSL 16:8e0d178b1d1e 2025 bitcnt = (int)DIGIT_BIT;
wolfSSL 16:8e0d178b1d1e 2026 }
wolfSSL 16:8e0d178b1d1e 2027
wolfSSL 16:8e0d178b1d1e 2028 /* grab the next msb from the exponent */
wolfSSL 16:8e0d178b1d1e 2029 y = (int)(buf >> (DIGIT_BIT - 1)) & 1;
wolfSSL 16:8e0d178b1d1e 2030 buf <<= (fp_digit)1;
wolfSSL 16:8e0d178b1d1e 2031 /* add bit to the window */
wolfSSL 16:8e0d178b1d1e 2032 bitbuf |= (y << (WINSIZE - ++bitcpy));
wolfSSL 16:8e0d178b1d1e 2033
wolfSSL 16:8e0d178b1d1e 2034 if (bitcpy == WINSIZE) {
wolfSSL 16:8e0d178b1d1e 2035 /* ok window is filled so square as required and multiply */
wolfSSL 16:8e0d178b1d1e 2036 /* square first */
wolfSSL 16:8e0d178b1d1e 2037 for (x = 0; x < WINSIZE; x++) {
wolfSSL 16:8e0d178b1d1e 2038 err = fp_sqr(res, res);
wolfSSL 16:8e0d178b1d1e 2039 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2040 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2041 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2042 #endif
wolfSSL 16:8e0d178b1d1e 2043 return err;
wolfSSL 16:8e0d178b1d1e 2044 }
wolfSSL 16:8e0d178b1d1e 2045 err = fp_montgomery_reduce(res, P, mp);
wolfSSL 16:8e0d178b1d1e 2046 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2047 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2048 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2049 #endif
wolfSSL 16:8e0d178b1d1e 2050 return err;
wolfSSL 16:8e0d178b1d1e 2051 }
wolfSSL 16:8e0d178b1d1e 2052 }
wolfSSL 16:8e0d178b1d1e 2053
wolfSSL 16:8e0d178b1d1e 2054 /* then multiply by 2^bitbuf */
wolfSSL 16:8e0d178b1d1e 2055 fp_mul_2d(res, bitbuf, res);
wolfSSL 16:8e0d178b1d1e 2056 /* Add in value to make mod operation take same time */
wolfSSL 16:8e0d178b1d1e 2057 fp_add(res, tmp, res);
wolfSSL 16:8e0d178b1d1e 2058 err = fp_mod(res, P, res);
wolfSSL 16:8e0d178b1d1e 2059 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2060 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2061 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2062 #endif
wolfSSL 16:8e0d178b1d1e 2063 return err;
wolfSSL 16:8e0d178b1d1e 2064 }
wolfSSL 16:8e0d178b1d1e 2065
wolfSSL 16:8e0d178b1d1e 2066 /* empty window and reset */
wolfSSL 16:8e0d178b1d1e 2067 bitcpy = 0;
wolfSSL 16:8e0d178b1d1e 2068 bitbuf = 0;
wolfSSL 16:8e0d178b1d1e 2069 }
wolfSSL 16:8e0d178b1d1e 2070 }
wolfSSL 16:8e0d178b1d1e 2071
wolfSSL 16:8e0d178b1d1e 2072 /* fixup result if Montgomery reduction is used
wolfSSL 16:8e0d178b1d1e 2073 * recall that any value in a Montgomery system is
wolfSSL 16:8e0d178b1d1e 2074 * actually multiplied by R mod n. So we have
wolfSSL 16:8e0d178b1d1e 2075 * to reduce one more time to cancel out the factor
wolfSSL 16:8e0d178b1d1e 2076 * of R.
wolfSSL 16:8e0d178b1d1e 2077 */
wolfSSL 16:8e0d178b1d1e 2078 err = fp_montgomery_reduce(res, P, mp);
wolfSSL 16:8e0d178b1d1e 2079
wolfSSL 16:8e0d178b1d1e 2080 /* swap res with Y */
wolfSSL 16:8e0d178b1d1e 2081 fp_copy(res, Y);
wolfSSL 16:8e0d178b1d1e 2082
wolfSSL 16:8e0d178b1d1e 2083 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2084 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 15:117db924cf7c 2085 #endif
wolfSSL 16:8e0d178b1d1e 2086 return err;
wolfSSL 15:117db924cf7c 2087 }
wolfSSL 15:117db924cf7c 2088
wolfSSL 16:8e0d178b1d1e 2089 #undef WINSIZE
wolfSSL 16:8e0d178b1d1e 2090 #else
wolfSSL 16:8e0d178b1d1e 2091 #if DIGIT_BIT < 16
wolfSSL 16:8e0d178b1d1e 2092 #define WINSIZE 3
wolfSSL 16:8e0d178b1d1e 2093 #elif DIGIT_BIT < 32
wolfSSL 16:8e0d178b1d1e 2094 #define WINSIZE 4
wolfSSL 16:8e0d178b1d1e 2095 #elif DIGIT_BIT < 64
wolfSSL 16:8e0d178b1d1e 2096 #define WINSIZE 5
wolfSSL 16:8e0d178b1d1e 2097 #elif DIGIT_BIT < 128
wolfSSL 16:8e0d178b1d1e 2098 #define WINSIZE 6
wolfSSL 16:8e0d178b1d1e 2099 #elif DIGIT_BIT == 128
wolfSSL 16:8e0d178b1d1e 2100 #define WINSIZE 7
wolfSSL 16:8e0d178b1d1e 2101 #endif
wolfSSL 16:8e0d178b1d1e 2102
wolfSSL 16:8e0d178b1d1e 2103 /* y = 2**x (mod b)
wolfSSL 16:8e0d178b1d1e 2104 * Some restrictions... x must be positive and < b
wolfSSL 16:8e0d178b1d1e 2105 */
wolfSSL 16:8e0d178b1d1e 2106 static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P,
wolfSSL 16:8e0d178b1d1e 2107 fp_int * Y)
wolfSSL 16:8e0d178b1d1e 2108 {
wolfSSL 16:8e0d178b1d1e 2109 fp_digit buf, mp;
wolfSSL 16:8e0d178b1d1e 2110 int err, bitbuf, bitcpy, bitcnt, digidx, x, y;
wolfSSL 16:8e0d178b1d1e 2111 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2112 fp_int *res;
wolfSSL 16:8e0d178b1d1e 2113 #else
wolfSSL 16:8e0d178b1d1e 2114 fp_int res[1];
wolfSSL 16:8e0d178b1d1e 2115 #endif
wolfSSL 16:8e0d178b1d1e 2116
wolfSSL 16:8e0d178b1d1e 2117 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2118 res = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2119 if (res == NULL) {
wolfSSL 16:8e0d178b1d1e 2120 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 2121 }
wolfSSL 16:8e0d178b1d1e 2122 #endif
wolfSSL 16:8e0d178b1d1e 2123
wolfSSL 16:8e0d178b1d1e 2124 /* now setup montgomery */
wolfSSL 16:8e0d178b1d1e 2125 if ((err = fp_montgomery_setup(P, &mp)) != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2126 return err;
wolfSSL 16:8e0d178b1d1e 2127 }
wolfSSL 16:8e0d178b1d1e 2128
wolfSSL 16:8e0d178b1d1e 2129 /* setup result */
wolfSSL 16:8e0d178b1d1e 2130 fp_init(res);
wolfSSL 16:8e0d178b1d1e 2131
wolfSSL 16:8e0d178b1d1e 2132 /* now we need R mod m */
wolfSSL 16:8e0d178b1d1e 2133 fp_montgomery_calc_normalization(res, P);
wolfSSL 16:8e0d178b1d1e 2134
wolfSSL 16:8e0d178b1d1e 2135 /* Get the top bits left over after taking WINSIZE bits starting at the
wolfSSL 16:8e0d178b1d1e 2136 * least-significant.
wolfSSL 16:8e0d178b1d1e 2137 */
wolfSSL 16:8e0d178b1d1e 2138 digidx = digits - 1;
wolfSSL 16:8e0d178b1d1e 2139 bitcpy = (digits * DIGIT_BIT) % WINSIZE;
wolfSSL 16:8e0d178b1d1e 2140 if (bitcpy > 0) {
wolfSSL 16:8e0d178b1d1e 2141 bitcnt = (int)DIGIT_BIT - bitcpy;
wolfSSL 16:8e0d178b1d1e 2142 buf = X->dp[digidx--];
wolfSSL 16:8e0d178b1d1e 2143 bitbuf = (int)(buf >> bitcnt);
wolfSSL 16:8e0d178b1d1e 2144 /* Multiply montgomery representation of 1 by 2 ^ top */
wolfSSL 16:8e0d178b1d1e 2145 fp_mul_2d(res, bitbuf, res);
wolfSSL 16:8e0d178b1d1e 2146 err = fp_mod(res, P, res);
wolfSSL 16:8e0d178b1d1e 2147 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2148 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2149 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2150 #endif
wolfSSL 16:8e0d178b1d1e 2151 return err;
wolfSSL 16:8e0d178b1d1e 2152 }
wolfSSL 16:8e0d178b1d1e 2153 /* Move out bits used */
wolfSSL 16:8e0d178b1d1e 2154 buf <<= bitcpy;
wolfSSL 16:8e0d178b1d1e 2155 bitcnt++;
wolfSSL 16:8e0d178b1d1e 2156 }
wolfSSL 16:8e0d178b1d1e 2157 else {
wolfSSL 16:8e0d178b1d1e 2158 bitcnt = 1;
wolfSSL 16:8e0d178b1d1e 2159 buf = 0;
wolfSSL 16:8e0d178b1d1e 2160 }
wolfSSL 16:8e0d178b1d1e 2161
wolfSSL 16:8e0d178b1d1e 2162 /* empty window and reset */
wolfSSL 16:8e0d178b1d1e 2163 bitbuf = 0;
wolfSSL 16:8e0d178b1d1e 2164 bitcpy = 0;
wolfSSL 16:8e0d178b1d1e 2165
wolfSSL 16:8e0d178b1d1e 2166 for (;;) {
wolfSSL 16:8e0d178b1d1e 2167 /* grab next digit as required */
wolfSSL 16:8e0d178b1d1e 2168 if (--bitcnt == 0) {
wolfSSL 16:8e0d178b1d1e 2169 /* if digidx == -1 we are out of digits so break */
wolfSSL 16:8e0d178b1d1e 2170 if (digidx == -1) {
wolfSSL 16:8e0d178b1d1e 2171 break;
wolfSSL 16:8e0d178b1d1e 2172 }
wolfSSL 16:8e0d178b1d1e 2173 /* read next digit and reset bitcnt */
wolfSSL 16:8e0d178b1d1e 2174 buf = X->dp[digidx--];
wolfSSL 16:8e0d178b1d1e 2175 bitcnt = (int)DIGIT_BIT;
wolfSSL 16:8e0d178b1d1e 2176 }
wolfSSL 16:8e0d178b1d1e 2177
wolfSSL 16:8e0d178b1d1e 2178 /* grab the next msb from the exponent */
wolfSSL 16:8e0d178b1d1e 2179 y = (int)(buf >> (DIGIT_BIT - 1)) & 1;
wolfSSL 16:8e0d178b1d1e 2180 buf <<= (fp_digit)1;
wolfSSL 16:8e0d178b1d1e 2181 /* add bit to the window */
wolfSSL 16:8e0d178b1d1e 2182 bitbuf |= (y << (WINSIZE - ++bitcpy));
wolfSSL 16:8e0d178b1d1e 2183
wolfSSL 16:8e0d178b1d1e 2184 if (bitcpy == WINSIZE) {
wolfSSL 16:8e0d178b1d1e 2185 /* ok window is filled so square as required and multiply */
wolfSSL 16:8e0d178b1d1e 2186 /* square first */
wolfSSL 16:8e0d178b1d1e 2187 for (x = 0; x < WINSIZE; x++) {
wolfSSL 16:8e0d178b1d1e 2188 err = fp_sqr(res, res);
wolfSSL 16:8e0d178b1d1e 2189 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2190 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2191 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2192 #endif
wolfSSL 16:8e0d178b1d1e 2193 return err;
wolfSSL 16:8e0d178b1d1e 2194 }
wolfSSL 16:8e0d178b1d1e 2195 err = fp_montgomery_reduce(res, P, mp);
wolfSSL 16:8e0d178b1d1e 2196 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2197 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2198 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2199 #endif
wolfSSL 16:8e0d178b1d1e 2200 return err;
wolfSSL 16:8e0d178b1d1e 2201 }
wolfSSL 16:8e0d178b1d1e 2202 }
wolfSSL 16:8e0d178b1d1e 2203
wolfSSL 16:8e0d178b1d1e 2204 /* then multiply by 2^bitbuf */
wolfSSL 16:8e0d178b1d1e 2205 fp_mul_2d(res, bitbuf, res);
wolfSSL 16:8e0d178b1d1e 2206 err = fp_mod(res, P, res);
wolfSSL 16:8e0d178b1d1e 2207 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2208 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2209 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2210 #endif
wolfSSL 16:8e0d178b1d1e 2211 return err;
wolfSSL 16:8e0d178b1d1e 2212 }
wolfSSL 16:8e0d178b1d1e 2213
wolfSSL 16:8e0d178b1d1e 2214 /* empty window and reset */
wolfSSL 16:8e0d178b1d1e 2215 bitcpy = 0;
wolfSSL 16:8e0d178b1d1e 2216 bitbuf = 0;
wolfSSL 16:8e0d178b1d1e 2217 }
wolfSSL 16:8e0d178b1d1e 2218 }
wolfSSL 16:8e0d178b1d1e 2219
wolfSSL 16:8e0d178b1d1e 2220 /* fixup result if Montgomery reduction is used
wolfSSL 16:8e0d178b1d1e 2221 * recall that any value in a Montgomery system is
wolfSSL 16:8e0d178b1d1e 2222 * actually multiplied by R mod n. So we have
wolfSSL 16:8e0d178b1d1e 2223 * to reduce one more time to cancel out the factor
wolfSSL 16:8e0d178b1d1e 2224 * of R.
wolfSSL 16:8e0d178b1d1e 2225 */
wolfSSL 16:8e0d178b1d1e 2226 err = fp_montgomery_reduce(res, P, mp);
wolfSSL 16:8e0d178b1d1e 2227
wolfSSL 16:8e0d178b1d1e 2228 /* swap res with Y */
wolfSSL 16:8e0d178b1d1e 2229 fp_copy(res, Y);
wolfSSL 16:8e0d178b1d1e 2230
wolfSSL 16:8e0d178b1d1e 2231 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2232 XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2233 #endif
wolfSSL 16:8e0d178b1d1e 2234 return err;
wolfSSL 16:8e0d178b1d1e 2235 }
wolfSSL 16:8e0d178b1d1e 2236
wolfSSL 16:8e0d178b1d1e 2237 #undef WINSIZE
wolfSSL 16:8e0d178b1d1e 2238 #endif
wolfSSL 16:8e0d178b1d1e 2239
wolfSSL 15:117db924cf7c 2240
wolfSSL 15:117db924cf7c 2241 int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
wolfSSL 15:117db924cf7c 2242 {
wolfSSL 16:8e0d178b1d1e 2243
wolfSSL 16:8e0d178b1d1e 2244 #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
wolfSSL 16:8e0d178b1d1e 2245 !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
wolfSSL 16:8e0d178b1d1e 2246 int x = fp_count_bits (X);
wolfSSL 16:8e0d178b1d1e 2247 #endif
wolfSSL 16:8e0d178b1d1e 2248
wolfSSL 16:8e0d178b1d1e 2249 /* handle modulus of zero and prevent overflows */
wolfSSL 16:8e0d178b1d1e 2250 if (fp_iszero(P) || (P->used > (FP_SIZE/2))) {
wolfSSL 16:8e0d178b1d1e 2251 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 2252 }
wolfSSL 16:8e0d178b1d1e 2253 if (fp_isone(P)) {
wolfSSL 16:8e0d178b1d1e 2254 fp_set(Y, 0);
wolfSSL 16:8e0d178b1d1e 2255 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 2256 }
wolfSSL 16:8e0d178b1d1e 2257 if (fp_iszero(X)) {
wolfSSL 16:8e0d178b1d1e 2258 fp_set(Y, 1);
wolfSSL 16:8e0d178b1d1e 2259 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 2260 }
wolfSSL 16:8e0d178b1d1e 2261 if (fp_iszero(G)) {
wolfSSL 16:8e0d178b1d1e 2262 fp_set(Y, 0);
wolfSSL 16:8e0d178b1d1e 2263 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 2264 }
wolfSSL 16:8e0d178b1d1e 2265
wolfSSL 16:8e0d178b1d1e 2266 #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
wolfSSL 16:8e0d178b1d1e 2267 !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
wolfSSL 16:8e0d178b1d1e 2268 if(x > EPS_RSA_EXPT_XBTIS) {
wolfSSL 16:8e0d178b1d1e 2269 return esp_mp_exptmod(G, X, x, P, Y);
wolfSSL 16:8e0d178b1d1e 2270 }
wolfSSL 16:8e0d178b1d1e 2271 #endif
wolfSSL 16:8e0d178b1d1e 2272
wolfSSL 16:8e0d178b1d1e 2273 if (X->sign == FP_NEG) {
wolfSSL 16:8e0d178b1d1e 2274 #ifndef POSITIVE_EXP_ONLY /* reduce stack if assume no negatives */
wolfSSL 16:8e0d178b1d1e 2275 int err;
wolfSSL 16:8e0d178b1d1e 2276 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2277 fp_int tmp[2];
wolfSSL 16:8e0d178b1d1e 2278 #else
wolfSSL 16:8e0d178b1d1e 2279 fp_int *tmp;
wolfSSL 16:8e0d178b1d1e 2280 #endif
wolfSSL 16:8e0d178b1d1e 2281
wolfSSL 16:8e0d178b1d1e 2282 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2283 tmp = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 2284 if (tmp == NULL)
wolfSSL 16:8e0d178b1d1e 2285 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 2286 #endif
wolfSSL 16:8e0d178b1d1e 2287
wolfSSL 16:8e0d178b1d1e 2288 /* yes, copy G and invmod it */
wolfSSL 16:8e0d178b1d1e 2289 fp_init_copy(&tmp[0], G);
wolfSSL 16:8e0d178b1d1e 2290 fp_init_copy(&tmp[1], P);
wolfSSL 16:8e0d178b1d1e 2291 tmp[1].sign = FP_ZPOS;
wolfSSL 16:8e0d178b1d1e 2292 err = fp_invmod(&tmp[0], &tmp[1], &tmp[0]);
wolfSSL 16:8e0d178b1d1e 2293 if (err == FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2294 fp_copy(X, &tmp[1]);
wolfSSL 16:8e0d178b1d1e 2295 tmp[1].sign = FP_ZPOS;
wolfSSL 16:8e0d178b1d1e 2296 #ifdef TFM_TIMING_RESISTANT
wolfSSL 16:8e0d178b1d1e 2297 err = _fp_exptmod_ct(&tmp[0], &tmp[1], tmp[1].used, P, Y);
wolfSSL 16:8e0d178b1d1e 2298 #else
wolfSSL 16:8e0d178b1d1e 2299 err = _fp_exptmod_nct(&tmp[0], &tmp[1], P, Y);
wolfSSL 16:8e0d178b1d1e 2300 #endif
wolfSSL 16:8e0d178b1d1e 2301 if (P->sign == FP_NEG) {
wolfSSL 16:8e0d178b1d1e 2302 fp_add(Y, P, Y);
wolfSSL 16:8e0d178b1d1e 2303 }
wolfSSL 16:8e0d178b1d1e 2304 }
wolfSSL 16:8e0d178b1d1e 2305 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2306 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2307 #endif
wolfSSL 16:8e0d178b1d1e 2308 return err;
wolfSSL 16:8e0d178b1d1e 2309 #else
wolfSSL 16:8e0d178b1d1e 2310 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 2311 #endif
wolfSSL 16:8e0d178b1d1e 2312 }
wolfSSL 16:8e0d178b1d1e 2313 else if (G->used == 1 && G->dp[0] == 2) {
wolfSSL 16:8e0d178b1d1e 2314 return _fp_exptmod_base_2(X, X->used, P, Y);
wolfSSL 16:8e0d178b1d1e 2315 }
wolfSSL 16:8e0d178b1d1e 2316 else {
wolfSSL 16:8e0d178b1d1e 2317 /* Positive exponent so just exptmod */
wolfSSL 16:8e0d178b1d1e 2318 #ifdef TFM_TIMING_RESISTANT
wolfSSL 16:8e0d178b1d1e 2319 return _fp_exptmod_ct(G, X, X->used, P, Y);
wolfSSL 16:8e0d178b1d1e 2320 #else
wolfSSL 16:8e0d178b1d1e 2321 return _fp_exptmod_nct(G, X, P, Y);
wolfSSL 16:8e0d178b1d1e 2322 #endif
wolfSSL 16:8e0d178b1d1e 2323 }
wolfSSL 16:8e0d178b1d1e 2324 }
wolfSSL 16:8e0d178b1d1e 2325
wolfSSL 16:8e0d178b1d1e 2326 int fp_exptmod_ex(fp_int * G, fp_int * X, int digits, fp_int * P, fp_int * Y)
wolfSSL 16:8e0d178b1d1e 2327 {
wolfSSL 16:8e0d178b1d1e 2328
wolfSSL 16:8e0d178b1d1e 2329 #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
wolfSSL 16:8e0d178b1d1e 2330 !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
wolfSSL 16:8e0d178b1d1e 2331 int x = fp_count_bits (X);
wolfSSL 16:8e0d178b1d1e 2332 #endif
wolfSSL 16:8e0d178b1d1e 2333
wolfSSL 16:8e0d178b1d1e 2334 if (fp_iszero(G)) {
wolfSSL 16:8e0d178b1d1e 2335 fp_set(G, 0);
wolfSSL 16:8e0d178b1d1e 2336 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 2337 }
wolfSSL 16:8e0d178b1d1e 2338
wolfSSL 15:117db924cf7c 2339 /* prevent overflows */
wolfSSL 15:117db924cf7c 2340 if (P->used > (FP_SIZE/2)) {
wolfSSL 15:117db924cf7c 2341 return FP_VAL;
wolfSSL 15:117db924cf7c 2342 }
wolfSSL 15:117db924cf7c 2343
wolfSSL 16:8e0d178b1d1e 2344 #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
wolfSSL 16:8e0d178b1d1e 2345 !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
wolfSSL 16:8e0d178b1d1e 2346 if(x > EPS_RSA_EXPT_XBTIS) {
wolfSSL 16:8e0d178b1d1e 2347 return esp_mp_exptmod(G, X, x, P, Y);
wolfSSL 16:8e0d178b1d1e 2348 }
wolfSSL 16:8e0d178b1d1e 2349 #endif
wolfSSL 16:8e0d178b1d1e 2350
wolfSSL 15:117db924cf7c 2351 if (X->sign == FP_NEG) {
wolfSSL 15:117db924cf7c 2352 #ifndef POSITIVE_EXP_ONLY /* reduce stack if assume no negatives */
wolfSSL 15:117db924cf7c 2353 int err;
wolfSSL 16:8e0d178b1d1e 2354 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2355 fp_int tmp[2];
wolfSSL 16:8e0d178b1d1e 2356 #else
wolfSSL 16:8e0d178b1d1e 2357 fp_int *tmp;
wolfSSL 16:8e0d178b1d1e 2358 #endif
wolfSSL 16:8e0d178b1d1e 2359
wolfSSL 16:8e0d178b1d1e 2360 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2361 tmp = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2362 if (tmp == NULL)
wolfSSL 16:8e0d178b1d1e 2363 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 2364 #endif
wolfSSL 15:117db924cf7c 2365
wolfSSL 15:117db924cf7c 2366 /* yes, copy G and invmod it */
wolfSSL 16:8e0d178b1d1e 2367 fp_init_copy(&tmp[0], G);
wolfSSL 16:8e0d178b1d1e 2368 fp_init_copy(&tmp[1], P);
wolfSSL 16:8e0d178b1d1e 2369 tmp[1].sign = FP_ZPOS;
wolfSSL 16:8e0d178b1d1e 2370 err = fp_invmod(&tmp[0], &tmp[1], &tmp[0]);
wolfSSL 16:8e0d178b1d1e 2371 if (err == FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2372 X->sign = FP_ZPOS;
wolfSSL 16:8e0d178b1d1e 2373 #ifdef TFM_TIMING_RESISTANT
wolfSSL 16:8e0d178b1d1e 2374 err = _fp_exptmod_ct(&tmp[0], X, digits, P, Y);
wolfSSL 16:8e0d178b1d1e 2375 #else
wolfSSL 16:8e0d178b1d1e 2376 err = _fp_exptmod_nct(&tmp[0], X, P, Y);
wolfSSL 16:8e0d178b1d1e 2377 (void)digits;
wolfSSL 16:8e0d178b1d1e 2378 #endif
wolfSSL 16:8e0d178b1d1e 2379 if (X != Y) {
wolfSSL 16:8e0d178b1d1e 2380 X->sign = FP_NEG;
wolfSSL 16:8e0d178b1d1e 2381 }
wolfSSL 16:8e0d178b1d1e 2382 if (P->sign == FP_NEG) {
wolfSSL 16:8e0d178b1d1e 2383 fp_add(Y, P, Y);
wolfSSL 16:8e0d178b1d1e 2384 }
wolfSSL 15:117db924cf7c 2385 }
wolfSSL 16:8e0d178b1d1e 2386 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2387 XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 2388 #endif
wolfSSL 15:117db924cf7c 2389 return err;
wolfSSL 15:117db924cf7c 2390 #else
wolfSSL 15:117db924cf7c 2391 return FP_VAL;
wolfSSL 15:117db924cf7c 2392 #endif
wolfSSL 15:117db924cf7c 2393 }
wolfSSL 15:117db924cf7c 2394 else {
wolfSSL 15:117db924cf7c 2395 /* Positive exponent so just exptmod */
wolfSSL 16:8e0d178b1d1e 2396 #ifdef TFM_TIMING_RESISTANT
wolfSSL 16:8e0d178b1d1e 2397 return _fp_exptmod_ct(G, X, digits, P, Y);
wolfSSL 16:8e0d178b1d1e 2398 #else
wolfSSL 16:8e0d178b1d1e 2399 return _fp_exptmod_nct(G, X, P, Y);
wolfSSL 16:8e0d178b1d1e 2400 #endif
wolfSSL 16:8e0d178b1d1e 2401 }
wolfSSL 16:8e0d178b1d1e 2402 }
wolfSSL 16:8e0d178b1d1e 2403
wolfSSL 16:8e0d178b1d1e 2404 int fp_exptmod_nct(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
wolfSSL 16:8e0d178b1d1e 2405 {
wolfSSL 16:8e0d178b1d1e 2406 #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
wolfSSL 16:8e0d178b1d1e 2407 !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
wolfSSL 16:8e0d178b1d1e 2408 int x = fp_count_bits (X);
wolfSSL 16:8e0d178b1d1e 2409 #endif
wolfSSL 16:8e0d178b1d1e 2410
wolfSSL 16:8e0d178b1d1e 2411 if (fp_iszero(G)) {
wolfSSL 16:8e0d178b1d1e 2412 fp_set(G, 0);
wolfSSL 16:8e0d178b1d1e 2413 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 2414 }
wolfSSL 16:8e0d178b1d1e 2415
wolfSSL 16:8e0d178b1d1e 2416 /* prevent overflows */
wolfSSL 16:8e0d178b1d1e 2417 if (P->used > (FP_SIZE/2)) {
wolfSSL 16:8e0d178b1d1e 2418 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 2419 }
wolfSSL 16:8e0d178b1d1e 2420
wolfSSL 16:8e0d178b1d1e 2421 #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
wolfSSL 16:8e0d178b1d1e 2422 !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
wolfSSL 16:8e0d178b1d1e 2423 if(x > EPS_RSA_EXPT_XBTIS) {
wolfSSL 16:8e0d178b1d1e 2424 return esp_mp_exptmod(G, X, x, P, Y);
wolfSSL 16:8e0d178b1d1e 2425 }
wolfSSL 16:8e0d178b1d1e 2426 #endif
wolfSSL 16:8e0d178b1d1e 2427
wolfSSL 16:8e0d178b1d1e 2428 if (X->sign == FP_NEG) {
wolfSSL 16:8e0d178b1d1e 2429 #ifndef POSITIVE_EXP_ONLY /* reduce stack if assume no negatives */
wolfSSL 16:8e0d178b1d1e 2430 int err;
wolfSSL 16:8e0d178b1d1e 2431 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2432 fp_int tmp[2];
wolfSSL 16:8e0d178b1d1e 2433 #else
wolfSSL 16:8e0d178b1d1e 2434 fp_int *tmp;
wolfSSL 16:8e0d178b1d1e 2435 #endif
wolfSSL 16:8e0d178b1d1e 2436
wolfSSL 16:8e0d178b1d1e 2437 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2438 tmp = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 2439 if (tmp == NULL)
wolfSSL 16:8e0d178b1d1e 2440 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 2441 #endif
wolfSSL 16:8e0d178b1d1e 2442
wolfSSL 16:8e0d178b1d1e 2443 /* yes, copy G and invmod it */
wolfSSL 16:8e0d178b1d1e 2444 fp_init_copy(&tmp[0], G);
wolfSSL 16:8e0d178b1d1e 2445 fp_init_copy(&tmp[1], P);
wolfSSL 16:8e0d178b1d1e 2446 tmp[1].sign = FP_ZPOS;
wolfSSL 16:8e0d178b1d1e 2447 err = fp_invmod(&tmp[0], &tmp[1], &tmp[0]);
wolfSSL 16:8e0d178b1d1e 2448 if (err == FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 2449 X->sign = FP_ZPOS;
wolfSSL 16:8e0d178b1d1e 2450 err = _fp_exptmod_nct(&tmp[0], X, P, Y);
wolfSSL 16:8e0d178b1d1e 2451 if (X != Y) {
wolfSSL 16:8e0d178b1d1e 2452 X->sign = FP_NEG;
wolfSSL 16:8e0d178b1d1e 2453 }
wolfSSL 16:8e0d178b1d1e 2454 if (P->sign == FP_NEG) {
wolfSSL 16:8e0d178b1d1e 2455 fp_add(Y, P, Y);
wolfSSL 16:8e0d178b1d1e 2456 }
wolfSSL 16:8e0d178b1d1e 2457 }
wolfSSL 16:8e0d178b1d1e 2458 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2459 XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 2460 #endif
wolfSSL 16:8e0d178b1d1e 2461 return err;
wolfSSL 16:8e0d178b1d1e 2462 #else
wolfSSL 16:8e0d178b1d1e 2463 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 2464 #endif
wolfSSL 16:8e0d178b1d1e 2465 }
wolfSSL 16:8e0d178b1d1e 2466 else {
wolfSSL 16:8e0d178b1d1e 2467 /* Positive exponent so just exptmod */
wolfSSL 16:8e0d178b1d1e 2468 return _fp_exptmod_nct(G, X, P, Y);
wolfSSL 15:117db924cf7c 2469 }
wolfSSL 15:117db924cf7c 2470 }
wolfSSL 15:117db924cf7c 2471
wolfSSL 15:117db924cf7c 2472 /* computes a = 2**b */
wolfSSL 15:117db924cf7c 2473 void fp_2expt(fp_int *a, int b)
wolfSSL 15:117db924cf7c 2474 {
wolfSSL 15:117db924cf7c 2475 int z;
wolfSSL 15:117db924cf7c 2476
wolfSSL 15:117db924cf7c 2477 /* zero a as per default */
wolfSSL 15:117db924cf7c 2478 fp_zero (a);
wolfSSL 15:117db924cf7c 2479
wolfSSL 15:117db924cf7c 2480 if (b < 0) {
wolfSSL 15:117db924cf7c 2481 return;
wolfSSL 15:117db924cf7c 2482 }
wolfSSL 15:117db924cf7c 2483
wolfSSL 15:117db924cf7c 2484 z = b / DIGIT_BIT;
wolfSSL 15:117db924cf7c 2485 if (z >= FP_SIZE) {
wolfSSL 15:117db924cf7c 2486 return;
wolfSSL 15:117db924cf7c 2487 }
wolfSSL 15:117db924cf7c 2488
wolfSSL 15:117db924cf7c 2489 /* set the used count of where the bit will go */
wolfSSL 15:117db924cf7c 2490 a->used = z + 1;
wolfSSL 15:117db924cf7c 2491
wolfSSL 15:117db924cf7c 2492 /* put the single bit in its place */
wolfSSL 15:117db924cf7c 2493 a->dp[z] = ((fp_digit)1) << (b % DIGIT_BIT);
wolfSSL 15:117db924cf7c 2494 }
wolfSSL 15:117db924cf7c 2495
wolfSSL 15:117db924cf7c 2496 /* b = a*a */
wolfSSL 16:8e0d178b1d1e 2497 int fp_sqr(fp_int *A, fp_int *B)
wolfSSL 15:117db924cf7c 2498 {
wolfSSL 16:8e0d178b1d1e 2499 int err;
wolfSSL 15:117db924cf7c 2500 int y, oldused;
wolfSSL 15:117db924cf7c 2501
wolfSSL 15:117db924cf7c 2502 oldused = B->used;
wolfSSL 15:117db924cf7c 2503 y = A->used;
wolfSSL 15:117db924cf7c 2504
wolfSSL 15:117db924cf7c 2505 /* call generic if we're out of range */
wolfSSL 15:117db924cf7c 2506 if (y + y > FP_SIZE) {
wolfSSL 16:8e0d178b1d1e 2507 err = fp_sqr_comba(A, B);
wolfSSL 15:117db924cf7c 2508 goto clean;
wolfSSL 15:117db924cf7c 2509 }
wolfSSL 15:117db924cf7c 2510
wolfSSL 15:117db924cf7c 2511 #if defined(TFM_SQR3) && FP_SIZE >= 6
wolfSSL 15:117db924cf7c 2512 if (y <= 3) {
wolfSSL 16:8e0d178b1d1e 2513 err = fp_sqr_comba3(A,B);
wolfSSL 15:117db924cf7c 2514 goto clean;
wolfSSL 15:117db924cf7c 2515 }
wolfSSL 15:117db924cf7c 2516 #endif
wolfSSL 15:117db924cf7c 2517 #if defined(TFM_SQR4) && FP_SIZE >= 8
wolfSSL 15:117db924cf7c 2518 if (y == 4) {
wolfSSL 16:8e0d178b1d1e 2519 err = fp_sqr_comba4(A,B);
wolfSSL 15:117db924cf7c 2520 goto clean;
wolfSSL 15:117db924cf7c 2521 }
wolfSSL 15:117db924cf7c 2522 #endif
wolfSSL 15:117db924cf7c 2523 #if defined(TFM_SQR6) && FP_SIZE >= 12
wolfSSL 15:117db924cf7c 2524 if (y <= 6) {
wolfSSL 16:8e0d178b1d1e 2525 err = fp_sqr_comba6(A,B);
wolfSSL 15:117db924cf7c 2526 goto clean;
wolfSSL 15:117db924cf7c 2527 }
wolfSSL 15:117db924cf7c 2528 #endif
wolfSSL 15:117db924cf7c 2529 #if defined(TFM_SQR7) && FP_SIZE >= 14
wolfSSL 15:117db924cf7c 2530 if (y == 7) {
wolfSSL 16:8e0d178b1d1e 2531 err = fp_sqr_comba7(A,B);
wolfSSL 15:117db924cf7c 2532 goto clean;
wolfSSL 15:117db924cf7c 2533 }
wolfSSL 15:117db924cf7c 2534 #endif
wolfSSL 15:117db924cf7c 2535 #if defined(TFM_SQR8) && FP_SIZE >= 16
wolfSSL 15:117db924cf7c 2536 if (y == 8) {
wolfSSL 16:8e0d178b1d1e 2537 err = fp_sqr_comba8(A,B);
wolfSSL 15:117db924cf7c 2538 goto clean;
wolfSSL 15:117db924cf7c 2539 }
wolfSSL 15:117db924cf7c 2540 #endif
wolfSSL 15:117db924cf7c 2541 #if defined(TFM_SQR9) && FP_SIZE >= 18
wolfSSL 15:117db924cf7c 2542 if (y == 9) {
wolfSSL 16:8e0d178b1d1e 2543 err = fp_sqr_comba9(A,B);
wolfSSL 15:117db924cf7c 2544 goto clean;
wolfSSL 15:117db924cf7c 2545 }
wolfSSL 15:117db924cf7c 2546 #endif
wolfSSL 15:117db924cf7c 2547 #if defined(TFM_SQR12) && FP_SIZE >= 24
wolfSSL 15:117db924cf7c 2548 if (y <= 12) {
wolfSSL 16:8e0d178b1d1e 2549 err = fp_sqr_comba12(A,B);
wolfSSL 15:117db924cf7c 2550 goto clean;
wolfSSL 15:117db924cf7c 2551 }
wolfSSL 15:117db924cf7c 2552 #endif
wolfSSL 15:117db924cf7c 2553 #if defined(TFM_SQR17) && FP_SIZE >= 34
wolfSSL 15:117db924cf7c 2554 if (y <= 17) {
wolfSSL 16:8e0d178b1d1e 2555 err = fp_sqr_comba17(A,B);
wolfSSL 15:117db924cf7c 2556 goto clean;
wolfSSL 15:117db924cf7c 2557 }
wolfSSL 15:117db924cf7c 2558 #endif
wolfSSL 15:117db924cf7c 2559 #if defined(TFM_SMALL_SET)
wolfSSL 15:117db924cf7c 2560 if (y <= 16) {
wolfSSL 16:8e0d178b1d1e 2561 err = fp_sqr_comba_small(A,B);
wolfSSL 15:117db924cf7c 2562 goto clean;
wolfSSL 15:117db924cf7c 2563 }
wolfSSL 15:117db924cf7c 2564 #endif
wolfSSL 15:117db924cf7c 2565 #if defined(TFM_SQR20) && FP_SIZE >= 40
wolfSSL 15:117db924cf7c 2566 if (y <= 20) {
wolfSSL 16:8e0d178b1d1e 2567 err = fp_sqr_comba20(A,B);
wolfSSL 15:117db924cf7c 2568 goto clean;
wolfSSL 15:117db924cf7c 2569 }
wolfSSL 15:117db924cf7c 2570 #endif
wolfSSL 15:117db924cf7c 2571 #if defined(TFM_SQR24) && FP_SIZE >= 48
wolfSSL 15:117db924cf7c 2572 if (y <= 24) {
wolfSSL 16:8e0d178b1d1e 2573 err = fp_sqr_comba24(A,B);
wolfSSL 15:117db924cf7c 2574 goto clean;
wolfSSL 15:117db924cf7c 2575 }
wolfSSL 15:117db924cf7c 2576 #endif
wolfSSL 15:117db924cf7c 2577 #if defined(TFM_SQR28) && FP_SIZE >= 56
wolfSSL 15:117db924cf7c 2578 if (y <= 28) {
wolfSSL 16:8e0d178b1d1e 2579 err = fp_sqr_comba28(A,B);
wolfSSL 15:117db924cf7c 2580 goto clean;
wolfSSL 15:117db924cf7c 2581 }
wolfSSL 15:117db924cf7c 2582 #endif
wolfSSL 15:117db924cf7c 2583 #if defined(TFM_SQR32) && FP_SIZE >= 64
wolfSSL 15:117db924cf7c 2584 if (y <= 32) {
wolfSSL 16:8e0d178b1d1e 2585 err = fp_sqr_comba32(A,B);
wolfSSL 15:117db924cf7c 2586 goto clean;
wolfSSL 15:117db924cf7c 2587 }
wolfSSL 15:117db924cf7c 2588 #endif
wolfSSL 15:117db924cf7c 2589 #if defined(TFM_SQR48) && FP_SIZE >= 96
wolfSSL 15:117db924cf7c 2590 if (y <= 48) {
wolfSSL 16:8e0d178b1d1e 2591 err = fp_sqr_comba48(A,B);
wolfSSL 15:117db924cf7c 2592 goto clean;
wolfSSL 15:117db924cf7c 2593 }
wolfSSL 15:117db924cf7c 2594 #endif
wolfSSL 15:117db924cf7c 2595 #if defined(TFM_SQR64) && FP_SIZE >= 128
wolfSSL 15:117db924cf7c 2596 if (y <= 64) {
wolfSSL 16:8e0d178b1d1e 2597 err = fp_sqr_comba64(A,B);
wolfSSL 15:117db924cf7c 2598 goto clean;
wolfSSL 15:117db924cf7c 2599 }
wolfSSL 15:117db924cf7c 2600 #endif
wolfSSL 16:8e0d178b1d1e 2601 err = fp_sqr_comba(A, B);
wolfSSL 15:117db924cf7c 2602
wolfSSL 15:117db924cf7c 2603 clean:
wolfSSL 15:117db924cf7c 2604 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 15:117db924cf7c 2605 for (y = B->used; y >= 0 && y < oldused; y++) {
wolfSSL 15:117db924cf7c 2606 B->dp[y] = 0;
wolfSSL 15:117db924cf7c 2607 }
wolfSSL 16:8e0d178b1d1e 2608
wolfSSL 16:8e0d178b1d1e 2609 return err;
wolfSSL 15:117db924cf7c 2610 }
wolfSSL 15:117db924cf7c 2611
wolfSSL 15:117db924cf7c 2612 /* generic comba squarer */
wolfSSL 16:8e0d178b1d1e 2613 int fp_sqr_comba(fp_int *A, fp_int *B)
wolfSSL 15:117db924cf7c 2614 {
wolfSSL 15:117db924cf7c 2615 int pa, ix, iz;
wolfSSL 15:117db924cf7c 2616 fp_digit c0, c1, c2;
wolfSSL 15:117db924cf7c 2617 #ifdef TFM_ISO
wolfSSL 15:117db924cf7c 2618 fp_word tt;
wolfSSL 15:117db924cf7c 2619 #endif
wolfSSL 16:8e0d178b1d1e 2620 fp_int *dst;
wolfSSL 16:8e0d178b1d1e 2621 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2622 fp_int tmp[1];
wolfSSL 16:8e0d178b1d1e 2623 #else
wolfSSL 16:8e0d178b1d1e 2624 fp_int *tmp;
wolfSSL 16:8e0d178b1d1e 2625 #endif
wolfSSL 16:8e0d178b1d1e 2626
wolfSSL 16:8e0d178b1d1e 2627 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2628 tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 2629 if (tmp == NULL)
wolfSSL 16:8e0d178b1d1e 2630 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 2631 #endif
wolfSSL 15:117db924cf7c 2632
wolfSSL 15:117db924cf7c 2633 /* get size of output and trim */
wolfSSL 15:117db924cf7c 2634 pa = A->used + A->used;
wolfSSL 15:117db924cf7c 2635 if (pa >= FP_SIZE) {
wolfSSL 15:117db924cf7c 2636 pa = FP_SIZE-1;
wolfSSL 15:117db924cf7c 2637 }
wolfSSL 15:117db924cf7c 2638
wolfSSL 15:117db924cf7c 2639 /* number of output digits to produce */
wolfSSL 15:117db924cf7c 2640 COMBA_START;
wolfSSL 15:117db924cf7c 2641 COMBA_CLEAR;
wolfSSL 15:117db924cf7c 2642
wolfSSL 15:117db924cf7c 2643 if (A == B) {
wolfSSL 16:8e0d178b1d1e 2644 fp_init(tmp);
wolfSSL 16:8e0d178b1d1e 2645 dst = tmp;
wolfSSL 15:117db924cf7c 2646 } else {
wolfSSL 15:117db924cf7c 2647 fp_zero(B);
wolfSSL 15:117db924cf7c 2648 dst = B;
wolfSSL 15:117db924cf7c 2649 }
wolfSSL 15:117db924cf7c 2650
wolfSSL 15:117db924cf7c 2651 for (ix = 0; ix < pa; ix++) {
wolfSSL 15:117db924cf7c 2652 int tx, ty, iy;
wolfSSL 15:117db924cf7c 2653 fp_digit *tmpy, *tmpx;
wolfSSL 15:117db924cf7c 2654
wolfSSL 15:117db924cf7c 2655 /* get offsets into the two bignums */
wolfSSL 15:117db924cf7c 2656 ty = MIN(A->used-1, ix);
wolfSSL 15:117db924cf7c 2657 tx = ix - ty;
wolfSSL 15:117db924cf7c 2658
wolfSSL 15:117db924cf7c 2659 /* setup temp aliases */
wolfSSL 15:117db924cf7c 2660 tmpx = A->dp + tx;
wolfSSL 15:117db924cf7c 2661 tmpy = A->dp + ty;
wolfSSL 15:117db924cf7c 2662
wolfSSL 15:117db924cf7c 2663 /* this is the number of times the loop will iterate,
wolfSSL 15:117db924cf7c 2664 while (tx++ < a->used && ty-- >= 0) { ... }
wolfSSL 15:117db924cf7c 2665 */
wolfSSL 15:117db924cf7c 2666 iy = MIN(A->used-tx, ty+1);
wolfSSL 15:117db924cf7c 2667
wolfSSL 15:117db924cf7c 2668 /* now for squaring tx can never equal ty
wolfSSL 15:117db924cf7c 2669 * we halve the distance since they approach
wolfSSL 15:117db924cf7c 2670 * at a rate of 2x and we have to round because
wolfSSL 15:117db924cf7c 2671 * odd cases need to be executed
wolfSSL 15:117db924cf7c 2672 */
wolfSSL 15:117db924cf7c 2673 iy = MIN(iy, (ty-tx+1)>>1);
wolfSSL 15:117db924cf7c 2674
wolfSSL 15:117db924cf7c 2675 /* forward carries */
wolfSSL 15:117db924cf7c 2676 COMBA_FORWARD;
wolfSSL 15:117db924cf7c 2677
wolfSSL 15:117db924cf7c 2678 /* execute loop */
wolfSSL 15:117db924cf7c 2679 for (iz = 0; iz < iy; iz++) {
wolfSSL 15:117db924cf7c 2680 SQRADD2(*tmpx++, *tmpy--);
wolfSSL 15:117db924cf7c 2681 }
wolfSSL 15:117db924cf7c 2682
wolfSSL 15:117db924cf7c 2683 /* even columns have the square term in them */
wolfSSL 15:117db924cf7c 2684 if ((ix&1) == 0) {
wolfSSL 15:117db924cf7c 2685 /* TAO change COMBA_ADD back to SQRADD */
wolfSSL 15:117db924cf7c 2686 SQRADD(A->dp[ix>>1], A->dp[ix>>1]);
wolfSSL 15:117db924cf7c 2687 }
wolfSSL 15:117db924cf7c 2688
wolfSSL 15:117db924cf7c 2689 /* store it */
wolfSSL 15:117db924cf7c 2690 COMBA_STORE(dst->dp[ix]);
wolfSSL 15:117db924cf7c 2691 }
wolfSSL 15:117db924cf7c 2692
wolfSSL 15:117db924cf7c 2693 COMBA_FINI;
wolfSSL 15:117db924cf7c 2694
wolfSSL 15:117db924cf7c 2695 /* setup dest */
wolfSSL 15:117db924cf7c 2696 dst->used = pa;
wolfSSL 15:117db924cf7c 2697 fp_clamp (dst);
wolfSSL 15:117db924cf7c 2698 if (dst != B) {
wolfSSL 15:117db924cf7c 2699 fp_copy(dst, B);
wolfSSL 15:117db924cf7c 2700 }
wolfSSL 16:8e0d178b1d1e 2701
wolfSSL 16:8e0d178b1d1e 2702 /* Variables used but not seen by cppcheck. */
wolfSSL 16:8e0d178b1d1e 2703 (void)c0; (void)c1; (void)c2;
wolfSSL 16:8e0d178b1d1e 2704 #ifdef TFM_ISO
wolfSSL 16:8e0d178b1d1e 2705 (void)tt;
wolfSSL 16:8e0d178b1d1e 2706 #endif
wolfSSL 16:8e0d178b1d1e 2707
wolfSSL 16:8e0d178b1d1e 2708 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2709 XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 2710 #endif
wolfSSL 16:8e0d178b1d1e 2711 return FP_OKAY;
wolfSSL 15:117db924cf7c 2712 }
wolfSSL 15:117db924cf7c 2713
wolfSSL 15:117db924cf7c 2714 int fp_cmp(fp_int *a, fp_int *b)
wolfSSL 15:117db924cf7c 2715 {
wolfSSL 15:117db924cf7c 2716 if (a->sign == FP_NEG && b->sign == FP_ZPOS) {
wolfSSL 15:117db924cf7c 2717 return FP_LT;
wolfSSL 15:117db924cf7c 2718 } else if (a->sign == FP_ZPOS && b->sign == FP_NEG) {
wolfSSL 15:117db924cf7c 2719 return FP_GT;
wolfSSL 15:117db924cf7c 2720 } else {
wolfSSL 15:117db924cf7c 2721 /* compare digits */
wolfSSL 15:117db924cf7c 2722 if (a->sign == FP_NEG) {
wolfSSL 15:117db924cf7c 2723 /* if negative compare opposite direction */
wolfSSL 15:117db924cf7c 2724 return fp_cmp_mag(b, a);
wolfSSL 15:117db924cf7c 2725 } else {
wolfSSL 15:117db924cf7c 2726 return fp_cmp_mag(a, b);
wolfSSL 15:117db924cf7c 2727 }
wolfSSL 15:117db924cf7c 2728 }
wolfSSL 15:117db924cf7c 2729 }
wolfSSL 15:117db924cf7c 2730
wolfSSL 15:117db924cf7c 2731 /* compare against a single digit */
wolfSSL 15:117db924cf7c 2732 int fp_cmp_d(fp_int *a, fp_digit b)
wolfSSL 15:117db924cf7c 2733 {
wolfSSL 15:117db924cf7c 2734 /* special case for zero*/
wolfSSL 15:117db924cf7c 2735 if (a->used == 0 && b == 0)
wolfSSL 15:117db924cf7c 2736 return FP_EQ;
wolfSSL 15:117db924cf7c 2737
wolfSSL 15:117db924cf7c 2738 /* compare based on sign */
wolfSSL 15:117db924cf7c 2739 if ((b && a->used == 0) || a->sign == FP_NEG) {
wolfSSL 15:117db924cf7c 2740 return FP_LT;
wolfSSL 15:117db924cf7c 2741 }
wolfSSL 15:117db924cf7c 2742
wolfSSL 15:117db924cf7c 2743 /* compare based on magnitude */
wolfSSL 15:117db924cf7c 2744 if (a->used > 1) {
wolfSSL 15:117db924cf7c 2745 return FP_GT;
wolfSSL 15:117db924cf7c 2746 }
wolfSSL 15:117db924cf7c 2747
wolfSSL 15:117db924cf7c 2748 /* compare the only digit of a to b */
wolfSSL 15:117db924cf7c 2749 if (a->dp[0] > b) {
wolfSSL 15:117db924cf7c 2750 return FP_GT;
wolfSSL 15:117db924cf7c 2751 } else if (a->dp[0] < b) {
wolfSSL 15:117db924cf7c 2752 return FP_LT;
wolfSSL 15:117db924cf7c 2753 } else {
wolfSSL 15:117db924cf7c 2754 return FP_EQ;
wolfSSL 15:117db924cf7c 2755 }
wolfSSL 15:117db924cf7c 2756
wolfSSL 15:117db924cf7c 2757 }
wolfSSL 15:117db924cf7c 2758
wolfSSL 15:117db924cf7c 2759 int fp_cmp_mag(fp_int *a, fp_int *b)
wolfSSL 15:117db924cf7c 2760 {
wolfSSL 15:117db924cf7c 2761 int x;
wolfSSL 15:117db924cf7c 2762
wolfSSL 15:117db924cf7c 2763 if (a->used > b->used) {
wolfSSL 15:117db924cf7c 2764 return FP_GT;
wolfSSL 15:117db924cf7c 2765 } else if (a->used < b->used) {
wolfSSL 15:117db924cf7c 2766 return FP_LT;
wolfSSL 15:117db924cf7c 2767 } else {
wolfSSL 15:117db924cf7c 2768 for (x = a->used - 1; x >= 0; x--) {
wolfSSL 15:117db924cf7c 2769 if (a->dp[x] > b->dp[x]) {
wolfSSL 15:117db924cf7c 2770 return FP_GT;
wolfSSL 15:117db924cf7c 2771 } else if (a->dp[x] < b->dp[x]) {
wolfSSL 15:117db924cf7c 2772 return FP_LT;
wolfSSL 15:117db924cf7c 2773 }
wolfSSL 15:117db924cf7c 2774 }
wolfSSL 15:117db924cf7c 2775 }
wolfSSL 15:117db924cf7c 2776 return FP_EQ;
wolfSSL 15:117db924cf7c 2777 }
wolfSSL 15:117db924cf7c 2778
wolfSSL 15:117db924cf7c 2779 /* sets up the montgomery reduction */
wolfSSL 15:117db924cf7c 2780 int fp_montgomery_setup(fp_int *a, fp_digit *rho)
wolfSSL 15:117db924cf7c 2781 {
wolfSSL 15:117db924cf7c 2782 fp_digit x, b;
wolfSSL 15:117db924cf7c 2783
wolfSSL 15:117db924cf7c 2784 /* fast inversion mod 2**k
wolfSSL 15:117db924cf7c 2785 *
wolfSSL 15:117db924cf7c 2786 * Based on the fact that
wolfSSL 15:117db924cf7c 2787 *
wolfSSL 15:117db924cf7c 2788 * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
wolfSSL 15:117db924cf7c 2789 * => 2*X*A - X*X*A*A = 1
wolfSSL 15:117db924cf7c 2790 * => 2*(1) - (1) = 1
wolfSSL 15:117db924cf7c 2791 */
wolfSSL 15:117db924cf7c 2792 b = a->dp[0];
wolfSSL 15:117db924cf7c 2793
wolfSSL 15:117db924cf7c 2794 if ((b & 1) == 0) {
wolfSSL 15:117db924cf7c 2795 return FP_VAL;
wolfSSL 15:117db924cf7c 2796 }
wolfSSL 15:117db924cf7c 2797
wolfSSL 15:117db924cf7c 2798 x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
wolfSSL 15:117db924cf7c 2799 x *= 2 - b * x; /* here x*a==1 mod 2**8 */
wolfSSL 15:117db924cf7c 2800 x *= 2 - b * x; /* here x*a==1 mod 2**16 */
wolfSSL 15:117db924cf7c 2801 x *= 2 - b * x; /* here x*a==1 mod 2**32 */
wolfSSL 15:117db924cf7c 2802 #ifdef FP_64BIT
wolfSSL 15:117db924cf7c 2803 x *= 2 - b * x; /* here x*a==1 mod 2**64 */
wolfSSL 15:117db924cf7c 2804 #endif
wolfSSL 15:117db924cf7c 2805
wolfSSL 15:117db924cf7c 2806 /* rho = -1/m mod b */
wolfSSL 15:117db924cf7c 2807 *rho = (fp_digit) (((fp_word) 1 << ((fp_word) DIGIT_BIT)) - ((fp_word)x));
wolfSSL 15:117db924cf7c 2808
wolfSSL 15:117db924cf7c 2809 return FP_OKAY;
wolfSSL 15:117db924cf7c 2810 }
wolfSSL 15:117db924cf7c 2811
wolfSSL 15:117db924cf7c 2812 /* computes a = B**n mod b without division or multiplication useful for
wolfSSL 15:117db924cf7c 2813 * normalizing numbers in a Montgomery system.
wolfSSL 15:117db924cf7c 2814 */
wolfSSL 15:117db924cf7c 2815 void fp_montgomery_calc_normalization(fp_int *a, fp_int *b)
wolfSSL 15:117db924cf7c 2816 {
wolfSSL 15:117db924cf7c 2817 int x, bits;
wolfSSL 15:117db924cf7c 2818
wolfSSL 15:117db924cf7c 2819 /* how many bits of last digit does b use */
wolfSSL 15:117db924cf7c 2820 bits = fp_count_bits (b) % DIGIT_BIT;
wolfSSL 15:117db924cf7c 2821 if (!bits) bits = DIGIT_BIT;
wolfSSL 15:117db924cf7c 2822
wolfSSL 15:117db924cf7c 2823 /* compute A = B^(n-1) * 2^(bits-1) */
wolfSSL 15:117db924cf7c 2824 if (b->used > 1) {
wolfSSL 15:117db924cf7c 2825 fp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1);
wolfSSL 15:117db924cf7c 2826 } else {
wolfSSL 15:117db924cf7c 2827 fp_set(a, 1);
wolfSSL 15:117db924cf7c 2828 bits = 1;
wolfSSL 15:117db924cf7c 2829 }
wolfSSL 15:117db924cf7c 2830
wolfSSL 15:117db924cf7c 2831 /* now compute C = A * B mod b */
wolfSSL 15:117db924cf7c 2832 for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
wolfSSL 15:117db924cf7c 2833 fp_mul_2 (a, a);
wolfSSL 15:117db924cf7c 2834 if (fp_cmp_mag (a, b) != FP_LT) {
wolfSSL 15:117db924cf7c 2835 s_fp_sub (a, b, a);
wolfSSL 15:117db924cf7c 2836 }
wolfSSL 15:117db924cf7c 2837 }
wolfSSL 15:117db924cf7c 2838 }
wolfSSL 15:117db924cf7c 2839
wolfSSL 15:117db924cf7c 2840
wolfSSL 15:117db924cf7c 2841 #ifdef TFM_SMALL_MONT_SET
wolfSSL 15:117db924cf7c 2842 #include "fp_mont_small.i"
wolfSSL 15:117db924cf7c 2843 #endif
wolfSSL 15:117db924cf7c 2844
wolfSSL 15:117db924cf7c 2845 #ifdef HAVE_INTEL_MULX
wolfSSL 15:117db924cf7c 2846 static WC_INLINE void innermul8_mulx(fp_digit *c_mulx, fp_digit *cy_mulx, fp_digit *tmpm, fp_digit mu)
wolfSSL 15:117db924cf7c 2847 {
wolfSSL 15:117db924cf7c 2848 fp_digit cy = *cy_mulx ;
wolfSSL 15:117db924cf7c 2849 INNERMUL8_MULX ;
wolfSSL 15:117db924cf7c 2850 *cy_mulx = cy ;
wolfSSL 15:117db924cf7c 2851 }
wolfSSL 15:117db924cf7c 2852
wolfSSL 15:117db924cf7c 2853 /* computes x/R == x (mod N) via Montgomery Reduction */
wolfSSL 16:8e0d178b1d1e 2854 static int fp_montgomery_reduce_mulx(fp_int *a, fp_int *m, fp_digit mp)
wolfSSL 15:117db924cf7c 2855 {
wolfSSL 16:8e0d178b1d1e 2856 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2857 fp_digit c[FP_SIZE+1];
wolfSSL 16:8e0d178b1d1e 2858 #else
wolfSSL 16:8e0d178b1d1e 2859 fp_digit *c;
wolfSSL 16:8e0d178b1d1e 2860 #endif
wolfSSL 16:8e0d178b1d1e 2861 fp_digit *_c, *tmpm, mu = 0;
wolfSSL 15:117db924cf7c 2862 int oldused, x, y, pa;
wolfSSL 15:117db924cf7c 2863
wolfSSL 15:117db924cf7c 2864 /* bail if too large */
wolfSSL 15:117db924cf7c 2865 if (m->used > (FP_SIZE/2)) {
wolfSSL 15:117db924cf7c 2866 (void)mu; /* shut up compiler */
wolfSSL 16:8e0d178b1d1e 2867 return FP_OKAY;
wolfSSL 15:117db924cf7c 2868 }
wolfSSL 15:117db924cf7c 2869
wolfSSL 15:117db924cf7c 2870 #ifdef TFM_SMALL_MONT_SET
wolfSSL 15:117db924cf7c 2871 if (m->used <= 16) {
wolfSSL 16:8e0d178b1d1e 2872 return fp_montgomery_reduce_small(a, m, mp);
wolfSSL 15:117db924cf7c 2873 }
wolfSSL 15:117db924cf7c 2874 #endif
wolfSSL 15:117db924cf7c 2875
wolfSSL 16:8e0d178b1d1e 2876 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2877 /* only allocate space for what's needed for window plus res */
wolfSSL 16:8e0d178b1d1e 2878 c = (fp_digit*)XMALLOC(sizeof(fp_digit)*(FP_SIZE + 1), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 2879 if (c == NULL) {
wolfSSL 16:8e0d178b1d1e 2880 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 2881 }
wolfSSL 16:8e0d178b1d1e 2882 #endif
wolfSSL 15:117db924cf7c 2883
wolfSSL 15:117db924cf7c 2884 /* now zero the buff */
wolfSSL 16:8e0d178b1d1e 2885 XMEMSET(c, 0, sizeof(fp_digit)*(FP_SIZE + 1));
wolfSSL 15:117db924cf7c 2886 pa = m->used;
wolfSSL 15:117db924cf7c 2887
wolfSSL 15:117db924cf7c 2888 /* copy the input */
wolfSSL 15:117db924cf7c 2889 oldused = a->used;
wolfSSL 15:117db924cf7c 2890 for (x = 0; x < oldused; x++) {
wolfSSL 15:117db924cf7c 2891 c[x] = a->dp[x];
wolfSSL 15:117db924cf7c 2892 }
wolfSSL 15:117db924cf7c 2893 MONT_START;
wolfSSL 15:117db924cf7c 2894
wolfSSL 15:117db924cf7c 2895 for (x = 0; x < pa; x++) {
wolfSSL 15:117db924cf7c 2896 fp_digit cy = 0;
wolfSSL 15:117db924cf7c 2897 /* get Mu for this round */
wolfSSL 15:117db924cf7c 2898 LOOP_START;
wolfSSL 15:117db924cf7c 2899 _c = c + x;
wolfSSL 15:117db924cf7c 2900 tmpm = m->dp;
wolfSSL 15:117db924cf7c 2901 y = 0;
wolfSSL 15:117db924cf7c 2902 for (; y < (pa & ~7); y += 8) {
wolfSSL 15:117db924cf7c 2903 innermul8_mulx(_c, &cy, tmpm, mu) ;
wolfSSL 15:117db924cf7c 2904 _c += 8;
wolfSSL 15:117db924cf7c 2905 tmpm += 8;
wolfSSL 15:117db924cf7c 2906 }
wolfSSL 15:117db924cf7c 2907 for (; y < pa; y++) {
wolfSSL 15:117db924cf7c 2908 INNERMUL;
wolfSSL 15:117db924cf7c 2909 ++_c;
wolfSSL 15:117db924cf7c 2910 }
wolfSSL 15:117db924cf7c 2911 LOOP_END;
wolfSSL 15:117db924cf7c 2912 while (cy) {
wolfSSL 15:117db924cf7c 2913 PROPCARRY;
wolfSSL 15:117db924cf7c 2914 ++_c;
wolfSSL 15:117db924cf7c 2915 }
wolfSSL 15:117db924cf7c 2916 }
wolfSSL 15:117db924cf7c 2917
wolfSSL 15:117db924cf7c 2918 /* now copy out */
wolfSSL 15:117db924cf7c 2919 _c = c + pa;
wolfSSL 15:117db924cf7c 2920 tmpm = a->dp;
wolfSSL 15:117db924cf7c 2921 for (x = 0; x < pa+1; x++) {
wolfSSL 15:117db924cf7c 2922 *tmpm++ = *_c++;
wolfSSL 15:117db924cf7c 2923 }
wolfSSL 15:117db924cf7c 2924
wolfSSL 15:117db924cf7c 2925 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 15:117db924cf7c 2926 for (; x < oldused; x++) {
wolfSSL 15:117db924cf7c 2927 *tmpm++ = 0;
wolfSSL 15:117db924cf7c 2928 }
wolfSSL 15:117db924cf7c 2929
wolfSSL 15:117db924cf7c 2930 MONT_FINI;
wolfSSL 15:117db924cf7c 2931
wolfSSL 15:117db924cf7c 2932 a->used = pa+1;
wolfSSL 15:117db924cf7c 2933 fp_clamp(a);
wolfSSL 15:117db924cf7c 2934
wolfSSL 15:117db924cf7c 2935 /* if A >= m then A = A - m */
wolfSSL 15:117db924cf7c 2936 if (fp_cmp_mag (a, m) != FP_LT) {
wolfSSL 15:117db924cf7c 2937 s_fp_sub (a, m, a);
wolfSSL 15:117db924cf7c 2938 }
wolfSSL 16:8e0d178b1d1e 2939
wolfSSL 16:8e0d178b1d1e 2940 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2941 XFREE(c, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 2942 #endif
wolfSSL 16:8e0d178b1d1e 2943 return FP_OKAY;
wolfSSL 15:117db924cf7c 2944 }
wolfSSL 15:117db924cf7c 2945 #endif
wolfSSL 15:117db924cf7c 2946
wolfSSL 15:117db924cf7c 2947 /* computes x/R == x (mod N) via Montgomery Reduction */
wolfSSL 16:8e0d178b1d1e 2948 int fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp)
wolfSSL 15:117db924cf7c 2949 {
wolfSSL 16:8e0d178b1d1e 2950 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2951 fp_digit c[FP_SIZE+1];
wolfSSL 16:8e0d178b1d1e 2952 #else
wolfSSL 16:8e0d178b1d1e 2953 fp_digit *c;
wolfSSL 16:8e0d178b1d1e 2954 #endif
wolfSSL 16:8e0d178b1d1e 2955 fp_digit *_c, *tmpm, mu = 0;
wolfSSL 16:8e0d178b1d1e 2956 int oldused, x, y, pa, err = 0;
wolfSSL 16:8e0d178b1d1e 2957
wolfSSL 16:8e0d178b1d1e 2958 IF_HAVE_INTEL_MULX(err = fp_montgomery_reduce_mulx(a, m, mp), return err) ;
wolfSSL 16:8e0d178b1d1e 2959 (void)err;
wolfSSL 15:117db924cf7c 2960
wolfSSL 15:117db924cf7c 2961 /* bail if too large */
wolfSSL 15:117db924cf7c 2962 if (m->used > (FP_SIZE/2)) {
wolfSSL 15:117db924cf7c 2963 (void)mu; /* shut up compiler */
wolfSSL 16:8e0d178b1d1e 2964 return FP_OKAY;
wolfSSL 15:117db924cf7c 2965 }
wolfSSL 15:117db924cf7c 2966
wolfSSL 15:117db924cf7c 2967 #ifdef TFM_SMALL_MONT_SET
wolfSSL 15:117db924cf7c 2968 if (m->used <= 16) {
wolfSSL 16:8e0d178b1d1e 2969 return fp_montgomery_reduce_small(a, m, mp);
wolfSSL 15:117db924cf7c 2970 }
wolfSSL 15:117db924cf7c 2971 #endif
wolfSSL 15:117db924cf7c 2972
wolfSSL 16:8e0d178b1d1e 2973 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 2974 /* only allocate space for what's needed for window plus res */
wolfSSL 16:8e0d178b1d1e 2975 c = (fp_digit*)XMALLOC(sizeof(fp_digit)*(FP_SIZE + 1), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 2976 if (c == NULL) {
wolfSSL 16:8e0d178b1d1e 2977 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 2978 }
wolfSSL 16:8e0d178b1d1e 2979 #endif
wolfSSL 15:117db924cf7c 2980
wolfSSL 15:117db924cf7c 2981 /* now zero the buff */
wolfSSL 16:8e0d178b1d1e 2982 XMEMSET(c, 0, sizeof(fp_digit)*(FP_SIZE + 1));
wolfSSL 15:117db924cf7c 2983 pa = m->used;
wolfSSL 15:117db924cf7c 2984
wolfSSL 15:117db924cf7c 2985 /* copy the input */
wolfSSL 15:117db924cf7c 2986 oldused = a->used;
wolfSSL 15:117db924cf7c 2987 for (x = 0; x < oldused; x++) {
wolfSSL 15:117db924cf7c 2988 c[x] = a->dp[x];
wolfSSL 15:117db924cf7c 2989 }
wolfSSL 15:117db924cf7c 2990 MONT_START;
wolfSSL 15:117db924cf7c 2991
wolfSSL 15:117db924cf7c 2992 for (x = 0; x < pa; x++) {
wolfSSL 15:117db924cf7c 2993 fp_digit cy = 0;
wolfSSL 15:117db924cf7c 2994 /* get Mu for this round */
wolfSSL 15:117db924cf7c 2995 LOOP_START;
wolfSSL 15:117db924cf7c 2996 _c = c + x;
wolfSSL 15:117db924cf7c 2997 tmpm = m->dp;
wolfSSL 15:117db924cf7c 2998 y = 0;
wolfSSL 15:117db924cf7c 2999 #if defined(INNERMUL8)
wolfSSL 15:117db924cf7c 3000 for (; y < (pa & ~7); y += 8) {
wolfSSL 15:117db924cf7c 3001 INNERMUL8 ;
wolfSSL 15:117db924cf7c 3002 _c += 8;
wolfSSL 15:117db924cf7c 3003 tmpm += 8;
wolfSSL 15:117db924cf7c 3004 }
wolfSSL 15:117db924cf7c 3005 #endif
wolfSSL 15:117db924cf7c 3006 for (; y < pa; y++) {
wolfSSL 15:117db924cf7c 3007 INNERMUL;
wolfSSL 15:117db924cf7c 3008 ++_c;
wolfSSL 15:117db924cf7c 3009 }
wolfSSL 15:117db924cf7c 3010 LOOP_END;
wolfSSL 15:117db924cf7c 3011 while (cy) {
wolfSSL 15:117db924cf7c 3012 PROPCARRY;
wolfSSL 15:117db924cf7c 3013 ++_c;
wolfSSL 15:117db924cf7c 3014 }
wolfSSL 15:117db924cf7c 3015 }
wolfSSL 15:117db924cf7c 3016
wolfSSL 15:117db924cf7c 3017 /* now copy out */
wolfSSL 15:117db924cf7c 3018 _c = c + pa;
wolfSSL 15:117db924cf7c 3019 tmpm = a->dp;
wolfSSL 15:117db924cf7c 3020 for (x = 0; x < pa+1; x++) {
wolfSSL 15:117db924cf7c 3021 *tmpm++ = *_c++;
wolfSSL 15:117db924cf7c 3022 }
wolfSSL 15:117db924cf7c 3023
wolfSSL 15:117db924cf7c 3024 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 15:117db924cf7c 3025 for (; x < oldused; x++) {
wolfSSL 15:117db924cf7c 3026 *tmpm++ = 0;
wolfSSL 15:117db924cf7c 3027 }
wolfSSL 15:117db924cf7c 3028
wolfSSL 15:117db924cf7c 3029 MONT_FINI;
wolfSSL 15:117db924cf7c 3030
wolfSSL 15:117db924cf7c 3031 a->used = pa+1;
wolfSSL 15:117db924cf7c 3032 fp_clamp(a);
wolfSSL 15:117db924cf7c 3033
wolfSSL 15:117db924cf7c 3034 /* if A >= m then A = A - m */
wolfSSL 15:117db924cf7c 3035 if (fp_cmp_mag (a, m) != FP_LT) {
wolfSSL 15:117db924cf7c 3036 s_fp_sub (a, m, a);
wolfSSL 15:117db924cf7c 3037 }
wolfSSL 16:8e0d178b1d1e 3038
wolfSSL 16:8e0d178b1d1e 3039 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3040 XFREE(c, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3041 #endif
wolfSSL 16:8e0d178b1d1e 3042 return FP_OKAY;
wolfSSL 15:117db924cf7c 3043 }
wolfSSL 15:117db924cf7c 3044
wolfSSL 15:117db924cf7c 3045 void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c)
wolfSSL 15:117db924cf7c 3046 {
wolfSSL 15:117db924cf7c 3047 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 3048 const word32 maxC = (a->size * sizeof(fp_digit));
wolfSSL 15:117db924cf7c 3049 #else
wolfSSL 15:117db924cf7c 3050 const word32 maxC = (FP_SIZE * sizeof(fp_digit));
wolfSSL 15:117db924cf7c 3051 #endif
wolfSSL 15:117db924cf7c 3052
wolfSSL 15:117db924cf7c 3053 /* zero the int */
wolfSSL 15:117db924cf7c 3054 fp_zero (a);
wolfSSL 15:117db924cf7c 3055
wolfSSL 15:117db924cf7c 3056 /* if input b excess max, then truncate */
wolfSSL 15:117db924cf7c 3057 if (c > 0 && (word32)c > maxC) {
wolfSSL 15:117db924cf7c 3058 int excess = (c - maxC);
wolfSSL 15:117db924cf7c 3059 c -= excess;
wolfSSL 15:117db924cf7c 3060 b += excess;
wolfSSL 15:117db924cf7c 3061 }
wolfSSL 15:117db924cf7c 3062
wolfSSL 15:117db924cf7c 3063 /* If we know the endianness of this architecture, and we're using
wolfSSL 15:117db924cf7c 3064 32-bit fp_digits, we can optimize this */
wolfSSL 15:117db924cf7c 3065 #if (defined(LITTLE_ENDIAN_ORDER) || defined(BIG_ENDIAN_ORDER)) && \
wolfSSL 15:117db924cf7c 3066 defined(FP_32BIT)
wolfSSL 15:117db924cf7c 3067 /* But not for both simultaneously */
wolfSSL 15:117db924cf7c 3068 #if defined(LITTLE_ENDIAN_ORDER) && defined(BIG_ENDIAN_ORDER)
wolfSSL 15:117db924cf7c 3069 #error Both LITTLE_ENDIAN_ORDER and BIG_ENDIAN_ORDER defined.
wolfSSL 15:117db924cf7c 3070 #endif
wolfSSL 15:117db924cf7c 3071 {
wolfSSL 15:117db924cf7c 3072 unsigned char *pd = (unsigned char *)a->dp;
wolfSSL 15:117db924cf7c 3073
wolfSSL 15:117db924cf7c 3074 a->used = (c + sizeof(fp_digit) - 1)/sizeof(fp_digit);
wolfSSL 15:117db924cf7c 3075 /* read the bytes in */
wolfSSL 15:117db924cf7c 3076 #ifdef BIG_ENDIAN_ORDER
wolfSSL 15:117db924cf7c 3077 {
wolfSSL 15:117db924cf7c 3078 /* Use Duff's device to unroll the loop. */
wolfSSL 15:117db924cf7c 3079 int idx = (c - 1) & ~3;
wolfSSL 15:117db924cf7c 3080 switch (c % 4) {
wolfSSL 16:8e0d178b1d1e 3081 case 0: do { pd[idx+0] = *b++; // fallthrough
wolfSSL 16:8e0d178b1d1e 3082 case 3: pd[idx+1] = *b++; // fallthrough
wolfSSL 16:8e0d178b1d1e 3083 case 2: pd[idx+2] = *b++; // fallthrough
wolfSSL 16:8e0d178b1d1e 3084 case 1: pd[idx+3] = *b++; // fallthrough
wolfSSL 15:117db924cf7c 3085 idx -= 4;
wolfSSL 15:117db924cf7c 3086 } while ((c -= 4) > 0);
wolfSSL 15:117db924cf7c 3087 }
wolfSSL 15:117db924cf7c 3088 }
wolfSSL 15:117db924cf7c 3089 #else
wolfSSL 15:117db924cf7c 3090 for (c -= 1; c >= 0; c -= 1) {
wolfSSL 15:117db924cf7c 3091 pd[c] = *b++;
wolfSSL 15:117db924cf7c 3092 }
wolfSSL 15:117db924cf7c 3093 #endif
wolfSSL 15:117db924cf7c 3094 }
wolfSSL 15:117db924cf7c 3095 #else
wolfSSL 15:117db924cf7c 3096 /* read the bytes in */
wolfSSL 15:117db924cf7c 3097 for (; c > 0; c--) {
wolfSSL 15:117db924cf7c 3098 fp_mul_2d (a, 8, a);
wolfSSL 15:117db924cf7c 3099 a->dp[0] |= *b++;
wolfSSL 15:117db924cf7c 3100
wolfSSL 15:117db924cf7c 3101 if (a->used == 0) {
wolfSSL 15:117db924cf7c 3102 a->used = 1;
wolfSSL 15:117db924cf7c 3103 }
wolfSSL 15:117db924cf7c 3104 }
wolfSSL 15:117db924cf7c 3105 #endif
wolfSSL 15:117db924cf7c 3106 fp_clamp (a);
wolfSSL 15:117db924cf7c 3107 }
wolfSSL 15:117db924cf7c 3108
wolfSSL 15:117db924cf7c 3109 int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b)
wolfSSL 15:117db924cf7c 3110 {
wolfSSL 15:117db924cf7c 3111 #if DIGIT_BIT == 64 || DIGIT_BIT == 32
wolfSSL 15:117db924cf7c 3112 int i, j;
wolfSSL 15:117db924cf7c 3113 fp_digit n;
wolfSSL 15:117db924cf7c 3114
wolfSSL 15:117db924cf7c 3115 for (j=0,i=0; i<t->used-1; ) {
wolfSSL 15:117db924cf7c 3116 b[x++] = (unsigned char)(t->dp[i] >> j);
wolfSSL 15:117db924cf7c 3117 j += 8;
wolfSSL 15:117db924cf7c 3118 i += j == DIGIT_BIT;
wolfSSL 15:117db924cf7c 3119 j &= DIGIT_BIT - 1;
wolfSSL 15:117db924cf7c 3120 }
wolfSSL 15:117db924cf7c 3121 n = t->dp[i];
wolfSSL 15:117db924cf7c 3122 while (n != 0) {
wolfSSL 15:117db924cf7c 3123 b[x++] = (unsigned char)n;
wolfSSL 15:117db924cf7c 3124 n >>= 8;
wolfSSL 15:117db924cf7c 3125 }
wolfSSL 15:117db924cf7c 3126 return x;
wolfSSL 15:117db924cf7c 3127 #else
wolfSSL 15:117db924cf7c 3128 while (fp_iszero (t) == FP_NO) {
wolfSSL 15:117db924cf7c 3129 b[x++] = (unsigned char) (t->dp[0] & 255);
wolfSSL 15:117db924cf7c 3130 fp_div_2d (t, 8, t, NULL);
wolfSSL 15:117db924cf7c 3131 }
wolfSSL 15:117db924cf7c 3132 return x;
wolfSSL 15:117db924cf7c 3133 #endif
wolfSSL 15:117db924cf7c 3134 }
wolfSSL 15:117db924cf7c 3135
wolfSSL 16:8e0d178b1d1e 3136 int fp_to_unsigned_bin(fp_int *a, unsigned char *b)
wolfSSL 15:117db924cf7c 3137 {
wolfSSL 15:117db924cf7c 3138 int x;
wolfSSL 16:8e0d178b1d1e 3139 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3140 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 3141 #else
wolfSSL 16:8e0d178b1d1e 3142 fp_int *t;
wolfSSL 16:8e0d178b1d1e 3143 #endif
wolfSSL 16:8e0d178b1d1e 3144
wolfSSL 16:8e0d178b1d1e 3145 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3146 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3147 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 3148 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 3149 #endif
wolfSSL 16:8e0d178b1d1e 3150
wolfSSL 16:8e0d178b1d1e 3151 fp_init_copy(t, a);
wolfSSL 16:8e0d178b1d1e 3152
wolfSSL 16:8e0d178b1d1e 3153 x = fp_to_unsigned_bin_at_pos(0, t, b);
wolfSSL 15:117db924cf7c 3154 fp_reverse (b, x);
wolfSSL 16:8e0d178b1d1e 3155
wolfSSL 16:8e0d178b1d1e 3156 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3157 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3158 #endif
wolfSSL 16:8e0d178b1d1e 3159 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 3160 }
wolfSSL 16:8e0d178b1d1e 3161
wolfSSL 16:8e0d178b1d1e 3162 int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c)
wolfSSL 16:8e0d178b1d1e 3163 {
wolfSSL 16:8e0d178b1d1e 3164 #if DIGIT_BIT == 64 || DIGIT_BIT == 32
wolfSSL 16:8e0d178b1d1e 3165 int i, j, x;
wolfSSL 16:8e0d178b1d1e 3166
wolfSSL 16:8e0d178b1d1e 3167 for (x=c-1,j=0,i=0; x >= 0; x--) {
wolfSSL 16:8e0d178b1d1e 3168 b[x] = (unsigned char)(a->dp[i] >> j);
wolfSSL 16:8e0d178b1d1e 3169 j += 8;
wolfSSL 16:8e0d178b1d1e 3170 i += j == DIGIT_BIT;
wolfSSL 16:8e0d178b1d1e 3171 j &= DIGIT_BIT - 1;
wolfSSL 16:8e0d178b1d1e 3172 }
wolfSSL 16:8e0d178b1d1e 3173
wolfSSL 16:8e0d178b1d1e 3174 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 3175 #else
wolfSSL 16:8e0d178b1d1e 3176 int x;
wolfSSL 16:8e0d178b1d1e 3177 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3178 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 3179 #else
wolfSSL 16:8e0d178b1d1e 3180 fp_int *t;
wolfSSL 16:8e0d178b1d1e 3181 #endif
wolfSSL 16:8e0d178b1d1e 3182
wolfSSL 16:8e0d178b1d1e 3183 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3184 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3185 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 3186 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 3187 #endif
wolfSSL 16:8e0d178b1d1e 3188
wolfSSL 16:8e0d178b1d1e 3189 fp_init_copy(t, a);
wolfSSL 16:8e0d178b1d1e 3190
wolfSSL 16:8e0d178b1d1e 3191 for (x = 0; x < c; x++) {
wolfSSL 16:8e0d178b1d1e 3192 b[x] = (unsigned char) (t->dp[0] & 255);
wolfSSL 16:8e0d178b1d1e 3193 fp_div_2d (t, 8, t, NULL);
wolfSSL 16:8e0d178b1d1e 3194 }
wolfSSL 16:8e0d178b1d1e 3195 fp_reverse (b, x);
wolfSSL 16:8e0d178b1d1e 3196
wolfSSL 16:8e0d178b1d1e 3197 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3198 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3199 #endif
wolfSSL 16:8e0d178b1d1e 3200 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 3201 #endif
wolfSSL 15:117db924cf7c 3202 }
wolfSSL 15:117db924cf7c 3203
wolfSSL 15:117db924cf7c 3204 int fp_unsigned_bin_size(fp_int *a)
wolfSSL 15:117db924cf7c 3205 {
wolfSSL 15:117db924cf7c 3206 int size = fp_count_bits (a);
wolfSSL 15:117db924cf7c 3207 return (size / 8 + ((size & 7) != 0 ? 1 : 0));
wolfSSL 15:117db924cf7c 3208 }
wolfSSL 15:117db924cf7c 3209
wolfSSL 15:117db924cf7c 3210 void fp_set(fp_int *a, fp_digit b)
wolfSSL 15:117db924cf7c 3211 {
wolfSSL 15:117db924cf7c 3212 fp_zero(a);
wolfSSL 15:117db924cf7c 3213 a->dp[0] = b;
wolfSSL 15:117db924cf7c 3214 a->used = a->dp[0] ? 1 : 0;
wolfSSL 15:117db924cf7c 3215 }
wolfSSL 15:117db924cf7c 3216
wolfSSL 15:117db924cf7c 3217
wolfSSL 15:117db924cf7c 3218 #ifndef MP_SET_CHUNK_BITS
wolfSSL 15:117db924cf7c 3219 #define MP_SET_CHUNK_BITS 4
wolfSSL 15:117db924cf7c 3220 #endif
wolfSSL 15:117db924cf7c 3221 void fp_set_int(fp_int *a, unsigned long b)
wolfSSL 15:117db924cf7c 3222 {
wolfSSL 15:117db924cf7c 3223 int x;
wolfSSL 15:117db924cf7c 3224
wolfSSL 15:117db924cf7c 3225 /* use direct fp_set if b is less than fp_digit max */
wolfSSL 15:117db924cf7c 3226 if (b < FP_DIGIT_MAX) {
wolfSSL 15:117db924cf7c 3227 fp_set (a, (fp_digit)b);
wolfSSL 15:117db924cf7c 3228 return;
wolfSSL 15:117db924cf7c 3229 }
wolfSSL 15:117db924cf7c 3230
wolfSSL 15:117db924cf7c 3231 fp_zero (a);
wolfSSL 15:117db924cf7c 3232
wolfSSL 15:117db924cf7c 3233 /* set chunk bits at a time */
wolfSSL 15:117db924cf7c 3234 for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) {
wolfSSL 15:117db924cf7c 3235 fp_mul_2d (a, MP_SET_CHUNK_BITS, a);
wolfSSL 15:117db924cf7c 3236
wolfSSL 15:117db924cf7c 3237 /* OR in the top bits of the source */
wolfSSL 15:117db924cf7c 3238 a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) &
wolfSSL 15:117db924cf7c 3239 ((1 << MP_SET_CHUNK_BITS) - 1);
wolfSSL 15:117db924cf7c 3240
wolfSSL 15:117db924cf7c 3241 /* shift the source up to the next chunk bits */
wolfSSL 15:117db924cf7c 3242 b <<= MP_SET_CHUNK_BITS;
wolfSSL 15:117db924cf7c 3243
wolfSSL 15:117db924cf7c 3244 /* ensure that digits are not clamped off */
wolfSSL 15:117db924cf7c 3245 a->used += 1;
wolfSSL 15:117db924cf7c 3246 }
wolfSSL 15:117db924cf7c 3247
wolfSSL 15:117db924cf7c 3248 /* clamp digits */
wolfSSL 15:117db924cf7c 3249 fp_clamp(a);
wolfSSL 15:117db924cf7c 3250 }
wolfSSL 15:117db924cf7c 3251
wolfSSL 15:117db924cf7c 3252 /* check if a bit is set */
wolfSSL 15:117db924cf7c 3253 int fp_is_bit_set (fp_int *a, fp_digit b)
wolfSSL 15:117db924cf7c 3254 {
wolfSSL 15:117db924cf7c 3255 fp_digit i;
wolfSSL 15:117db924cf7c 3256
wolfSSL 15:117db924cf7c 3257 if (b > FP_MAX_BITS)
wolfSSL 15:117db924cf7c 3258 return 0;
wolfSSL 15:117db924cf7c 3259 else
wolfSSL 15:117db924cf7c 3260 i = b/DIGIT_BIT;
wolfSSL 15:117db924cf7c 3261
wolfSSL 15:117db924cf7c 3262 if ((fp_digit)a->used < i)
wolfSSL 15:117db924cf7c 3263 return 0;
wolfSSL 15:117db924cf7c 3264
wolfSSL 15:117db924cf7c 3265 return (int)((a->dp[i] >> b%DIGIT_BIT) & (fp_digit)1);
wolfSSL 15:117db924cf7c 3266 }
wolfSSL 15:117db924cf7c 3267
wolfSSL 15:117db924cf7c 3268 /* set the b bit of a */
wolfSSL 15:117db924cf7c 3269 int fp_set_bit (fp_int * a, fp_digit b)
wolfSSL 15:117db924cf7c 3270 {
wolfSSL 15:117db924cf7c 3271 fp_digit i;
wolfSSL 15:117db924cf7c 3272
wolfSSL 15:117db924cf7c 3273 if (b > FP_MAX_BITS)
wolfSSL 15:117db924cf7c 3274 return 0;
wolfSSL 15:117db924cf7c 3275 else
wolfSSL 15:117db924cf7c 3276 i = b/DIGIT_BIT;
wolfSSL 15:117db924cf7c 3277
wolfSSL 15:117db924cf7c 3278 /* set the used count of where the bit will go if required */
wolfSSL 15:117db924cf7c 3279 if (a->used < (int)(i+1))
wolfSSL 15:117db924cf7c 3280 a->used = (int)(i+1);
wolfSSL 15:117db924cf7c 3281
wolfSSL 15:117db924cf7c 3282 /* put the single bit in its place */
wolfSSL 15:117db924cf7c 3283 a->dp[i] |= ((fp_digit)1) << (b % DIGIT_BIT);
wolfSSL 15:117db924cf7c 3284
wolfSSL 15:117db924cf7c 3285 return MP_OKAY;
wolfSSL 15:117db924cf7c 3286 }
wolfSSL 15:117db924cf7c 3287
wolfSSL 15:117db924cf7c 3288 int fp_count_bits (fp_int * a)
wolfSSL 15:117db924cf7c 3289 {
wolfSSL 15:117db924cf7c 3290 int r;
wolfSSL 15:117db924cf7c 3291 fp_digit q;
wolfSSL 15:117db924cf7c 3292
wolfSSL 15:117db924cf7c 3293 /* shortcut */
wolfSSL 15:117db924cf7c 3294 if (a->used == 0) {
wolfSSL 15:117db924cf7c 3295 return 0;
wolfSSL 15:117db924cf7c 3296 }
wolfSSL 15:117db924cf7c 3297
wolfSSL 15:117db924cf7c 3298 /* get number of digits and add that */
wolfSSL 15:117db924cf7c 3299 r = (a->used - 1) * DIGIT_BIT;
wolfSSL 15:117db924cf7c 3300
wolfSSL 15:117db924cf7c 3301 /* take the last digit and count the bits in it */
wolfSSL 15:117db924cf7c 3302 q = a->dp[a->used - 1];
wolfSSL 15:117db924cf7c 3303 while (q > ((fp_digit) 0)) {
wolfSSL 15:117db924cf7c 3304 ++r;
wolfSSL 15:117db924cf7c 3305 q >>= ((fp_digit) 1);
wolfSSL 15:117db924cf7c 3306 }
wolfSSL 15:117db924cf7c 3307
wolfSSL 15:117db924cf7c 3308 return r;
wolfSSL 15:117db924cf7c 3309 }
wolfSSL 15:117db924cf7c 3310
wolfSSL 15:117db924cf7c 3311 int fp_leading_bit(fp_int *a)
wolfSSL 15:117db924cf7c 3312 {
wolfSSL 15:117db924cf7c 3313 int bit = 0;
wolfSSL 15:117db924cf7c 3314
wolfSSL 15:117db924cf7c 3315 if (a->used != 0) {
wolfSSL 15:117db924cf7c 3316 fp_digit q = a->dp[a->used - 1];
wolfSSL 15:117db924cf7c 3317 int qSz = sizeof(fp_digit);
wolfSSL 15:117db924cf7c 3318
wolfSSL 15:117db924cf7c 3319 while (qSz > 0) {
wolfSSL 15:117db924cf7c 3320 if ((unsigned char)q != 0)
wolfSSL 15:117db924cf7c 3321 bit = (q & 0x80) != 0;
wolfSSL 15:117db924cf7c 3322 q >>= 8;
wolfSSL 15:117db924cf7c 3323 qSz--;
wolfSSL 15:117db924cf7c 3324 }
wolfSSL 15:117db924cf7c 3325 }
wolfSSL 15:117db924cf7c 3326
wolfSSL 15:117db924cf7c 3327 return bit;
wolfSSL 15:117db924cf7c 3328 }
wolfSSL 15:117db924cf7c 3329
wolfSSL 15:117db924cf7c 3330 void fp_lshd(fp_int *a, int x)
wolfSSL 15:117db924cf7c 3331 {
wolfSSL 15:117db924cf7c 3332 int y;
wolfSSL 15:117db924cf7c 3333
wolfSSL 15:117db924cf7c 3334 /* move up and truncate as required */
wolfSSL 15:117db924cf7c 3335 y = MIN(a->used + x - 1, (int)(FP_SIZE-1));
wolfSSL 15:117db924cf7c 3336
wolfSSL 15:117db924cf7c 3337 /* store new size */
wolfSSL 15:117db924cf7c 3338 a->used = y + 1;
wolfSSL 15:117db924cf7c 3339
wolfSSL 15:117db924cf7c 3340 /* move digits */
wolfSSL 15:117db924cf7c 3341 for (; y >= x; y--) {
wolfSSL 15:117db924cf7c 3342 a->dp[y] = a->dp[y-x];
wolfSSL 15:117db924cf7c 3343 }
wolfSSL 15:117db924cf7c 3344
wolfSSL 15:117db924cf7c 3345 /* zero lower digits */
wolfSSL 15:117db924cf7c 3346 for (; y >= 0; y--) {
wolfSSL 15:117db924cf7c 3347 a->dp[y] = 0;
wolfSSL 15:117db924cf7c 3348 }
wolfSSL 15:117db924cf7c 3349
wolfSSL 15:117db924cf7c 3350 /* clamp digits */
wolfSSL 15:117db924cf7c 3351 fp_clamp(a);
wolfSSL 15:117db924cf7c 3352 }
wolfSSL 15:117db924cf7c 3353
wolfSSL 15:117db924cf7c 3354
wolfSSL 15:117db924cf7c 3355 /* right shift by bit count */
wolfSSL 15:117db924cf7c 3356 void fp_rshb(fp_int *c, int x)
wolfSSL 15:117db924cf7c 3357 {
wolfSSL 15:117db924cf7c 3358 fp_digit *tmpc, mask, shift;
wolfSSL 15:117db924cf7c 3359 fp_digit r, rr;
wolfSSL 15:117db924cf7c 3360 fp_digit D = x;
wolfSSL 15:117db924cf7c 3361
wolfSSL 16:8e0d178b1d1e 3362 if (fp_iszero(c)) return;
wolfSSL 16:8e0d178b1d1e 3363
wolfSSL 15:117db924cf7c 3364 /* mask */
wolfSSL 15:117db924cf7c 3365 mask = (((fp_digit)1) << D) - 1;
wolfSSL 15:117db924cf7c 3366
wolfSSL 15:117db924cf7c 3367 /* shift for lsb */
wolfSSL 15:117db924cf7c 3368 shift = DIGIT_BIT - D;
wolfSSL 15:117db924cf7c 3369
wolfSSL 15:117db924cf7c 3370 /* alias */
wolfSSL 15:117db924cf7c 3371 tmpc = c->dp + (c->used - 1);
wolfSSL 15:117db924cf7c 3372
wolfSSL 15:117db924cf7c 3373 /* carry */
wolfSSL 15:117db924cf7c 3374 r = 0;
wolfSSL 15:117db924cf7c 3375 for (x = c->used - 1; x >= 0; x--) {
wolfSSL 15:117db924cf7c 3376 /* get the lower bits of this word in a temp */
wolfSSL 15:117db924cf7c 3377 rr = *tmpc & mask;
wolfSSL 15:117db924cf7c 3378
wolfSSL 15:117db924cf7c 3379 /* shift the current word and mix in the carry bits from previous word */
wolfSSL 15:117db924cf7c 3380 *tmpc = (*tmpc >> D) | (r << shift);
wolfSSL 15:117db924cf7c 3381 --tmpc;
wolfSSL 15:117db924cf7c 3382
wolfSSL 15:117db924cf7c 3383 /* set the carry to the carry bits of the current word found above */
wolfSSL 15:117db924cf7c 3384 r = rr;
wolfSSL 15:117db924cf7c 3385 }
wolfSSL 15:117db924cf7c 3386
wolfSSL 15:117db924cf7c 3387 /* clamp digits */
wolfSSL 15:117db924cf7c 3388 fp_clamp(c);
wolfSSL 15:117db924cf7c 3389 }
wolfSSL 15:117db924cf7c 3390
wolfSSL 15:117db924cf7c 3391
wolfSSL 15:117db924cf7c 3392 void fp_rshd(fp_int *a, int x)
wolfSSL 15:117db924cf7c 3393 {
wolfSSL 15:117db924cf7c 3394 int y;
wolfSSL 15:117db924cf7c 3395
wolfSSL 15:117db924cf7c 3396 /* too many digits just zero and return */
wolfSSL 15:117db924cf7c 3397 if (x >= a->used) {
wolfSSL 15:117db924cf7c 3398 fp_zero(a);
wolfSSL 15:117db924cf7c 3399 return;
wolfSSL 15:117db924cf7c 3400 }
wolfSSL 15:117db924cf7c 3401
wolfSSL 15:117db924cf7c 3402 /* shift */
wolfSSL 15:117db924cf7c 3403 for (y = 0; y < a->used - x; y++) {
wolfSSL 15:117db924cf7c 3404 a->dp[y] = a->dp[y+x];
wolfSSL 15:117db924cf7c 3405 }
wolfSSL 15:117db924cf7c 3406
wolfSSL 15:117db924cf7c 3407 /* zero rest */
wolfSSL 15:117db924cf7c 3408 for (; y < a->used; y++) {
wolfSSL 15:117db924cf7c 3409 a->dp[y] = 0;
wolfSSL 15:117db924cf7c 3410 }
wolfSSL 15:117db924cf7c 3411
wolfSSL 15:117db924cf7c 3412 /* decrement count */
wolfSSL 15:117db924cf7c 3413 a->used -= x;
wolfSSL 15:117db924cf7c 3414 fp_clamp(a);
wolfSSL 15:117db924cf7c 3415 }
wolfSSL 15:117db924cf7c 3416
wolfSSL 15:117db924cf7c 3417 /* reverse an array, used for radix code */
wolfSSL 15:117db924cf7c 3418 void fp_reverse (unsigned char *s, int len)
wolfSSL 15:117db924cf7c 3419 {
wolfSSL 15:117db924cf7c 3420 int ix, iy;
wolfSSL 15:117db924cf7c 3421 unsigned char t;
wolfSSL 15:117db924cf7c 3422
wolfSSL 15:117db924cf7c 3423 ix = 0;
wolfSSL 15:117db924cf7c 3424 iy = len - 1;
wolfSSL 15:117db924cf7c 3425 while (ix < iy) {
wolfSSL 15:117db924cf7c 3426 t = s[ix];
wolfSSL 15:117db924cf7c 3427 s[ix] = s[iy];
wolfSSL 15:117db924cf7c 3428 s[iy] = t;
wolfSSL 15:117db924cf7c 3429 ++ix;
wolfSSL 15:117db924cf7c 3430 --iy;
wolfSSL 15:117db924cf7c 3431 }
wolfSSL 15:117db924cf7c 3432 }
wolfSSL 15:117db924cf7c 3433
wolfSSL 15:117db924cf7c 3434
wolfSSL 15:117db924cf7c 3435 /* c = a - b */
wolfSSL 16:8e0d178b1d1e 3436 int fp_sub_d(fp_int *a, fp_digit b, fp_int *c)
wolfSSL 15:117db924cf7c 3437 {
wolfSSL 16:8e0d178b1d1e 3438 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3439 fp_int tmp[1];
wolfSSL 16:8e0d178b1d1e 3440 #else
wolfSSL 16:8e0d178b1d1e 3441 fp_int *tmp;
wolfSSL 16:8e0d178b1d1e 3442 #endif
wolfSSL 16:8e0d178b1d1e 3443
wolfSSL 16:8e0d178b1d1e 3444 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3445 tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3446 if (tmp == NULL)
wolfSSL 16:8e0d178b1d1e 3447 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 3448 #endif
wolfSSL 16:8e0d178b1d1e 3449
wolfSSL 16:8e0d178b1d1e 3450 fp_init(tmp);
wolfSSL 16:8e0d178b1d1e 3451 fp_set(tmp, b);
wolfSSL 15:117db924cf7c 3452 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 3453 if (c->size < FP_SIZE) {
wolfSSL 16:8e0d178b1d1e 3454 fp_sub(a, tmp, tmp);
wolfSSL 16:8e0d178b1d1e 3455 fp_copy(tmp, c);
wolfSSL 15:117db924cf7c 3456 } else
wolfSSL 15:117db924cf7c 3457 #endif
wolfSSL 15:117db924cf7c 3458 {
wolfSSL 16:8e0d178b1d1e 3459 fp_sub(a, tmp, c);
wolfSSL 15:117db924cf7c 3460 }
wolfSSL 16:8e0d178b1d1e 3461
wolfSSL 16:8e0d178b1d1e 3462 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3463 XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3464 #endif
wolfSSL 16:8e0d178b1d1e 3465 return FP_OKAY;
wolfSSL 15:117db924cf7c 3466 }
wolfSSL 15:117db924cf7c 3467
wolfSSL 15:117db924cf7c 3468
wolfSSL 15:117db924cf7c 3469 /* wolfSSL callers from normal lib */
wolfSSL 15:117db924cf7c 3470
wolfSSL 15:117db924cf7c 3471 /* init a new mp_int */
wolfSSL 15:117db924cf7c 3472 int mp_init (mp_int * a)
wolfSSL 15:117db924cf7c 3473 {
wolfSSL 15:117db924cf7c 3474 if (a)
wolfSSL 15:117db924cf7c 3475 fp_init(a);
wolfSSL 15:117db924cf7c 3476 return MP_OKAY;
wolfSSL 15:117db924cf7c 3477 }
wolfSSL 15:117db924cf7c 3478
wolfSSL 15:117db924cf7c 3479 void fp_init(fp_int *a)
wolfSSL 15:117db924cf7c 3480 {
wolfSSL 15:117db924cf7c 3481 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 3482 a->size = FP_SIZE;
wolfSSL 15:117db924cf7c 3483 #endif
wolfSSL 15:117db924cf7c 3484 #ifdef HAVE_WOLF_BIGINT
wolfSSL 15:117db924cf7c 3485 wc_bigint_init(&a->raw);
wolfSSL 15:117db924cf7c 3486 #endif
wolfSSL 15:117db924cf7c 3487 fp_zero(a);
wolfSSL 15:117db924cf7c 3488 }
wolfSSL 15:117db924cf7c 3489
wolfSSL 15:117db924cf7c 3490 void fp_zero(fp_int *a)
wolfSSL 15:117db924cf7c 3491 {
wolfSSL 16:8e0d178b1d1e 3492 int size;
wolfSSL 15:117db924cf7c 3493 a->used = 0;
wolfSSL 15:117db924cf7c 3494 a->sign = FP_ZPOS;
wolfSSL 15:117db924cf7c 3495 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 3496 size = a->size;
wolfSSL 16:8e0d178b1d1e 3497 #else
wolfSSL 16:8e0d178b1d1e 3498 size = FP_SIZE;
wolfSSL 15:117db924cf7c 3499 #endif
wolfSSL 15:117db924cf7c 3500 XMEMSET(a->dp, 0, size * sizeof(fp_digit));
wolfSSL 15:117db924cf7c 3501 }
wolfSSL 15:117db924cf7c 3502
wolfSSL 15:117db924cf7c 3503 void fp_clear(fp_int *a)
wolfSSL 15:117db924cf7c 3504 {
wolfSSL 16:8e0d178b1d1e 3505 int size;
wolfSSL 15:117db924cf7c 3506 a->used = 0;
wolfSSL 15:117db924cf7c 3507 a->sign = FP_ZPOS;
wolfSSL 15:117db924cf7c 3508 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 3509 size = a->size;
wolfSSL 16:8e0d178b1d1e 3510 #else
wolfSSL 16:8e0d178b1d1e 3511 size = FP_SIZE;
wolfSSL 15:117db924cf7c 3512 #endif
wolfSSL 15:117db924cf7c 3513 XMEMSET(a->dp, 0, size * sizeof(fp_digit));
wolfSSL 15:117db924cf7c 3514 fp_free(a);
wolfSSL 15:117db924cf7c 3515 }
wolfSSL 15:117db924cf7c 3516
wolfSSL 15:117db924cf7c 3517 void fp_forcezero (mp_int * a)
wolfSSL 15:117db924cf7c 3518 {
wolfSSL 16:8e0d178b1d1e 3519 int size;
wolfSSL 15:117db924cf7c 3520 a->used = 0;
wolfSSL 15:117db924cf7c 3521 a->sign = FP_ZPOS;
wolfSSL 15:117db924cf7c 3522 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 3523 size = a->size;
wolfSSL 16:8e0d178b1d1e 3524 #else
wolfSSL 16:8e0d178b1d1e 3525 size = FP_SIZE;
wolfSSL 15:117db924cf7c 3526 #endif
wolfSSL 15:117db924cf7c 3527 ForceZero(a->dp, size * sizeof(fp_digit));
wolfSSL 15:117db924cf7c 3528 #ifdef HAVE_WOLF_BIGINT
wolfSSL 15:117db924cf7c 3529 wc_bigint_zero(&a->raw);
wolfSSL 15:117db924cf7c 3530 #endif
wolfSSL 15:117db924cf7c 3531 fp_free(a);
wolfSSL 15:117db924cf7c 3532 }
wolfSSL 15:117db924cf7c 3533
wolfSSL 15:117db924cf7c 3534 void mp_forcezero (mp_int * a)
wolfSSL 15:117db924cf7c 3535 {
wolfSSL 15:117db924cf7c 3536 fp_forcezero(a);
wolfSSL 15:117db924cf7c 3537 }
wolfSSL 15:117db924cf7c 3538
wolfSSL 15:117db924cf7c 3539 void fp_free(fp_int* a)
wolfSSL 15:117db924cf7c 3540 {
wolfSSL 15:117db924cf7c 3541 #ifdef HAVE_WOLF_BIGINT
wolfSSL 15:117db924cf7c 3542 wc_bigint_free(&a->raw);
wolfSSL 15:117db924cf7c 3543 #else
wolfSSL 15:117db924cf7c 3544 (void)a;
wolfSSL 15:117db924cf7c 3545 #endif
wolfSSL 15:117db924cf7c 3546 }
wolfSSL 15:117db924cf7c 3547
wolfSSL 15:117db924cf7c 3548
wolfSSL 15:117db924cf7c 3549 /* clear one (frees) */
wolfSSL 15:117db924cf7c 3550 void mp_clear (mp_int * a)
wolfSSL 15:117db924cf7c 3551 {
wolfSSL 15:117db924cf7c 3552 if (a == NULL)
wolfSSL 15:117db924cf7c 3553 return;
wolfSSL 15:117db924cf7c 3554 fp_clear(a);
wolfSSL 15:117db924cf7c 3555 }
wolfSSL 15:117db924cf7c 3556
wolfSSL 15:117db924cf7c 3557 void mp_free(mp_int* a)
wolfSSL 15:117db924cf7c 3558 {
wolfSSL 15:117db924cf7c 3559 fp_free(a);
wolfSSL 15:117db924cf7c 3560 }
wolfSSL 15:117db924cf7c 3561
wolfSSL 15:117db924cf7c 3562 /* handle up to 6 inits */
wolfSSL 15:117db924cf7c 3563 int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d,
wolfSSL 15:117db924cf7c 3564 mp_int* e, mp_int* f)
wolfSSL 15:117db924cf7c 3565 {
wolfSSL 15:117db924cf7c 3566 if (a)
wolfSSL 15:117db924cf7c 3567 fp_init(a);
wolfSSL 15:117db924cf7c 3568 if (b)
wolfSSL 15:117db924cf7c 3569 fp_init(b);
wolfSSL 15:117db924cf7c 3570 if (c)
wolfSSL 15:117db924cf7c 3571 fp_init(c);
wolfSSL 15:117db924cf7c 3572 if (d)
wolfSSL 15:117db924cf7c 3573 fp_init(d);
wolfSSL 15:117db924cf7c 3574 if (e)
wolfSSL 15:117db924cf7c 3575 fp_init(e);
wolfSSL 15:117db924cf7c 3576 if (f)
wolfSSL 15:117db924cf7c 3577 fp_init(f);
wolfSSL 15:117db924cf7c 3578
wolfSSL 15:117db924cf7c 3579 return MP_OKAY;
wolfSSL 15:117db924cf7c 3580 }
wolfSSL 15:117db924cf7c 3581
wolfSSL 15:117db924cf7c 3582 /* high level addition (handles signs) */
wolfSSL 15:117db924cf7c 3583 int mp_add (mp_int * a, mp_int * b, mp_int * c)
wolfSSL 15:117db924cf7c 3584 {
wolfSSL 15:117db924cf7c 3585 fp_add(a, b, c);
wolfSSL 15:117db924cf7c 3586 return MP_OKAY;
wolfSSL 15:117db924cf7c 3587 }
wolfSSL 15:117db924cf7c 3588
wolfSSL 15:117db924cf7c 3589 /* high level subtraction (handles signs) */
wolfSSL 15:117db924cf7c 3590 int mp_sub (mp_int * a, mp_int * b, mp_int * c)
wolfSSL 15:117db924cf7c 3591 {
wolfSSL 15:117db924cf7c 3592 fp_sub(a, b, c);
wolfSSL 15:117db924cf7c 3593 return MP_OKAY;
wolfSSL 15:117db924cf7c 3594 }
wolfSSL 15:117db924cf7c 3595
wolfSSL 15:117db924cf7c 3596 /* high level multiplication (handles sign) */
wolfSSL 15:117db924cf7c 3597 #if defined(FREESCALE_LTC_TFM)
wolfSSL 15:117db924cf7c 3598 int wolfcrypt_mp_mul(mp_int * a, mp_int * b, mp_int * c)
wolfSSL 15:117db924cf7c 3599 #else
wolfSSL 15:117db924cf7c 3600 int mp_mul (mp_int * a, mp_int * b, mp_int * c)
wolfSSL 15:117db924cf7c 3601 #endif
wolfSSL 15:117db924cf7c 3602 {
wolfSSL 16:8e0d178b1d1e 3603 return fp_mul(a, b, c);
wolfSSL 15:117db924cf7c 3604 }
wolfSSL 15:117db924cf7c 3605
wolfSSL 15:117db924cf7c 3606 int mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
wolfSSL 15:117db924cf7c 3607 {
wolfSSL 15:117db924cf7c 3608 fp_mul_d(a, b, c);
wolfSSL 15:117db924cf7c 3609 return MP_OKAY;
wolfSSL 15:117db924cf7c 3610 }
wolfSSL 15:117db924cf7c 3611
wolfSSL 15:117db924cf7c 3612 /* d = a * b (mod c) */
wolfSSL 15:117db924cf7c 3613 #if defined(FREESCALE_LTC_TFM)
wolfSSL 15:117db924cf7c 3614 int wolfcrypt_mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
wolfSSL 15:117db924cf7c 3615 #else
wolfSSL 15:117db924cf7c 3616 int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
wolfSSL 15:117db924cf7c 3617 #endif
wolfSSL 15:117db924cf7c 3618 {
wolfSSL 16:8e0d178b1d1e 3619 #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
wolfSSL 16:8e0d178b1d1e 3620 !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
wolfSSL 16:8e0d178b1d1e 3621 int A = fp_count_bits (a);
wolfSSL 16:8e0d178b1d1e 3622 int B = fp_count_bits (b);
wolfSSL 16:8e0d178b1d1e 3623
wolfSSL 16:8e0d178b1d1e 3624 if( A >= ESP_RSA_MULM_BITS && B >= ESP_RSA_MULM_BITS)
wolfSSL 16:8e0d178b1d1e 3625 return esp_mp_mulmod(a, b, c, d);
wolfSSL 16:8e0d178b1d1e 3626 else
wolfSSL 16:8e0d178b1d1e 3627 #endif
wolfSSL 16:8e0d178b1d1e 3628 return fp_mulmod(a, b, c, d);
wolfSSL 15:117db924cf7c 3629 }
wolfSSL 15:117db924cf7c 3630
wolfSSL 15:117db924cf7c 3631 /* d = a - b (mod c) */
wolfSSL 15:117db924cf7c 3632 int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d)
wolfSSL 15:117db924cf7c 3633 {
wolfSSL 15:117db924cf7c 3634 return fp_submod(a, b, c, d);
wolfSSL 15:117db924cf7c 3635 }
wolfSSL 15:117db924cf7c 3636
wolfSSL 15:117db924cf7c 3637 /* d = a + b (mod c) */
wolfSSL 15:117db924cf7c 3638 int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d)
wolfSSL 15:117db924cf7c 3639 {
wolfSSL 15:117db924cf7c 3640 return fp_addmod(a, b, c, d);
wolfSSL 15:117db924cf7c 3641 }
wolfSSL 15:117db924cf7c 3642
wolfSSL 15:117db924cf7c 3643 /* c = a mod b, 0 <= c < b */
wolfSSL 15:117db924cf7c 3644 #if defined(FREESCALE_LTC_TFM)
wolfSSL 15:117db924cf7c 3645 int wolfcrypt_mp_mod (mp_int * a, mp_int * b, mp_int * c)
wolfSSL 15:117db924cf7c 3646 #else
wolfSSL 15:117db924cf7c 3647 int mp_mod (mp_int * a, mp_int * b, mp_int * c)
wolfSSL 15:117db924cf7c 3648 #endif
wolfSSL 15:117db924cf7c 3649 {
wolfSSL 15:117db924cf7c 3650 return fp_mod (a, b, c);
wolfSSL 15:117db924cf7c 3651 }
wolfSSL 15:117db924cf7c 3652
wolfSSL 15:117db924cf7c 3653 /* hac 14.61, pp608 */
wolfSSL 15:117db924cf7c 3654 #if defined(FREESCALE_LTC_TFM)
wolfSSL 15:117db924cf7c 3655 int wolfcrypt_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
wolfSSL 15:117db924cf7c 3656 #else
wolfSSL 15:117db924cf7c 3657 int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
wolfSSL 15:117db924cf7c 3658 #endif
wolfSSL 15:117db924cf7c 3659 {
wolfSSL 15:117db924cf7c 3660 return fp_invmod(a, b, c);
wolfSSL 15:117db924cf7c 3661 }
wolfSSL 15:117db924cf7c 3662
wolfSSL 16:8e0d178b1d1e 3663 /* hac 14.61, pp608 */
wolfSSL 16:8e0d178b1d1e 3664 int mp_invmod_mont_ct (mp_int * a, mp_int * b, mp_int * c, mp_digit mp)
wolfSSL 16:8e0d178b1d1e 3665 {
wolfSSL 16:8e0d178b1d1e 3666 return fp_invmod_mont_ct(a, b, c, mp);
wolfSSL 16:8e0d178b1d1e 3667 }
wolfSSL 16:8e0d178b1d1e 3668
wolfSSL 15:117db924cf7c 3669 /* this is a shell function that calls either the normal or Montgomery
wolfSSL 15:117db924cf7c 3670 * exptmod functions. Originally the call to the montgomery code was
wolfSSL 16:8e0d178b1d1e 3671 * embedded in the normal function but that wasted a lot of stack space
wolfSSL 15:117db924cf7c 3672 * for nothing (since 99% of the time the Montgomery code would be called)
wolfSSL 15:117db924cf7c 3673 */
wolfSSL 15:117db924cf7c 3674 #if defined(FREESCALE_LTC_TFM)
wolfSSL 15:117db924cf7c 3675 int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
wolfSSL 15:117db924cf7c 3676 #else
wolfSSL 15:117db924cf7c 3677 int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
wolfSSL 15:117db924cf7c 3678 #endif
wolfSSL 15:117db924cf7c 3679 {
wolfSSL 15:117db924cf7c 3680 return fp_exptmod(G, X, P, Y);
wolfSSL 15:117db924cf7c 3681 }
wolfSSL 15:117db924cf7c 3682
wolfSSL 16:8e0d178b1d1e 3683 int mp_exptmod_ex (mp_int * G, mp_int * X, int digits, mp_int * P, mp_int * Y)
wolfSSL 16:8e0d178b1d1e 3684 {
wolfSSL 16:8e0d178b1d1e 3685 return fp_exptmod_ex(G, X, digits, P, Y);
wolfSSL 16:8e0d178b1d1e 3686 }
wolfSSL 16:8e0d178b1d1e 3687
wolfSSL 16:8e0d178b1d1e 3688 int mp_exptmod_nct (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
wolfSSL 16:8e0d178b1d1e 3689 {
wolfSSL 16:8e0d178b1d1e 3690 return fp_exptmod_nct(G, X, P, Y);
wolfSSL 16:8e0d178b1d1e 3691 }
wolfSSL 16:8e0d178b1d1e 3692
wolfSSL 16:8e0d178b1d1e 3693
wolfSSL 15:117db924cf7c 3694 /* compare two ints (signed)*/
wolfSSL 15:117db924cf7c 3695 int mp_cmp (mp_int * a, mp_int * b)
wolfSSL 15:117db924cf7c 3696 {
wolfSSL 15:117db924cf7c 3697 return fp_cmp(a, b);
wolfSSL 15:117db924cf7c 3698 }
wolfSSL 15:117db924cf7c 3699
wolfSSL 15:117db924cf7c 3700 /* compare a digit */
wolfSSL 15:117db924cf7c 3701 int mp_cmp_d(mp_int * a, mp_digit b)
wolfSSL 15:117db924cf7c 3702 {
wolfSSL 15:117db924cf7c 3703 return fp_cmp_d(a, b);
wolfSSL 15:117db924cf7c 3704 }
wolfSSL 15:117db924cf7c 3705
wolfSSL 15:117db924cf7c 3706 /* get the size for an unsigned equivalent */
wolfSSL 15:117db924cf7c 3707 int mp_unsigned_bin_size (mp_int * a)
wolfSSL 15:117db924cf7c 3708 {
wolfSSL 15:117db924cf7c 3709 return fp_unsigned_bin_size(a);
wolfSSL 15:117db924cf7c 3710 }
wolfSSL 15:117db924cf7c 3711
wolfSSL 15:117db924cf7c 3712 int mp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b)
wolfSSL 15:117db924cf7c 3713 {
wolfSSL 15:117db924cf7c 3714 return fp_to_unsigned_bin_at_pos(x, t, b);
wolfSSL 15:117db924cf7c 3715 }
wolfSSL 15:117db924cf7c 3716
wolfSSL 15:117db924cf7c 3717 /* store in unsigned [big endian] format */
wolfSSL 15:117db924cf7c 3718 int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
wolfSSL 15:117db924cf7c 3719 {
wolfSSL 16:8e0d178b1d1e 3720 return fp_to_unsigned_bin(a,b);
wolfSSL 15:117db924cf7c 3721 }
wolfSSL 15:117db924cf7c 3722
wolfSSL 16:8e0d178b1d1e 3723 int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c)
wolfSSL 16:8e0d178b1d1e 3724 {
wolfSSL 16:8e0d178b1d1e 3725 return fp_to_unsigned_bin_len(a, b, c);
wolfSSL 16:8e0d178b1d1e 3726 }
wolfSSL 15:117db924cf7c 3727 /* reads a unsigned char array, assumes the msb is stored first [big endian] */
wolfSSL 15:117db924cf7c 3728 int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
wolfSSL 15:117db924cf7c 3729 {
wolfSSL 15:117db924cf7c 3730 fp_read_unsigned_bin(a, b, c);
wolfSSL 15:117db924cf7c 3731 return MP_OKAY;
wolfSSL 15:117db924cf7c 3732 }
wolfSSL 15:117db924cf7c 3733
wolfSSL 15:117db924cf7c 3734
wolfSSL 15:117db924cf7c 3735 int mp_sub_d(fp_int *a, fp_digit b, fp_int *c)
wolfSSL 15:117db924cf7c 3736 {
wolfSSL 16:8e0d178b1d1e 3737 return fp_sub_d(a, b, c);
wolfSSL 15:117db924cf7c 3738 }
wolfSSL 15:117db924cf7c 3739
wolfSSL 15:117db924cf7c 3740 int mp_mul_2d(fp_int *a, int b, fp_int *c)
wolfSSL 15:117db924cf7c 3741 {
wolfSSL 15:117db924cf7c 3742 fp_mul_2d(a, b, c);
wolfSSL 15:117db924cf7c 3743 return MP_OKAY;
wolfSSL 15:117db924cf7c 3744 }
wolfSSL 15:117db924cf7c 3745
wolfSSL 15:117db924cf7c 3746 int mp_2expt(fp_int* a, int b)
wolfSSL 15:117db924cf7c 3747 {
wolfSSL 15:117db924cf7c 3748 fp_2expt(a, b);
wolfSSL 15:117db924cf7c 3749 return MP_OKAY;
wolfSSL 15:117db924cf7c 3750 }
wolfSSL 15:117db924cf7c 3751
wolfSSL 15:117db924cf7c 3752 int mp_div(fp_int * a, fp_int * b, fp_int * c, fp_int * d)
wolfSSL 15:117db924cf7c 3753 {
wolfSSL 15:117db924cf7c 3754 return fp_div(a, b, c, d);
wolfSSL 15:117db924cf7c 3755 }
wolfSSL 15:117db924cf7c 3756
wolfSSL 15:117db924cf7c 3757 int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d)
wolfSSL 15:117db924cf7c 3758 {
wolfSSL 15:117db924cf7c 3759 fp_div_2d(a, b, c, d);
wolfSSL 15:117db924cf7c 3760 return MP_OKAY;
wolfSSL 15:117db924cf7c 3761 }
wolfSSL 15:117db924cf7c 3762
wolfSSL 15:117db924cf7c 3763 void fp_copy(fp_int *a, fp_int *b)
wolfSSL 15:117db924cf7c 3764 {
wolfSSL 15:117db924cf7c 3765 /* if source and destination are different */
wolfSSL 15:117db924cf7c 3766 if (a != b) {
wolfSSL 15:117db924cf7c 3767 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 3768 /* verify a will fit in b */
wolfSSL 15:117db924cf7c 3769 if (b->size >= a->used) {
wolfSSL 15:117db924cf7c 3770 int x, oldused;
wolfSSL 15:117db924cf7c 3771 oldused = b->used;
wolfSSL 15:117db924cf7c 3772 b->used = a->used;
wolfSSL 15:117db924cf7c 3773 b->sign = a->sign;
wolfSSL 15:117db924cf7c 3774
wolfSSL 15:117db924cf7c 3775 XMEMCPY(b->dp, a->dp, a->used * sizeof(fp_digit));
wolfSSL 15:117db924cf7c 3776
wolfSSL 15:117db924cf7c 3777 /* zero any excess digits on the destination that we didn't write to */
wolfSSL 15:117db924cf7c 3778 for (x = b->used; x >= 0 && x < oldused; x++) {
wolfSSL 15:117db924cf7c 3779 b->dp[x] = 0;
wolfSSL 15:117db924cf7c 3780 }
wolfSSL 15:117db924cf7c 3781 }
wolfSSL 15:117db924cf7c 3782 else {
wolfSSL 15:117db924cf7c 3783 /* TODO: Handle error case */
wolfSSL 15:117db924cf7c 3784 }
wolfSSL 15:117db924cf7c 3785 #else
wolfSSL 15:117db924cf7c 3786 /* all dp's are same size, so do straight copy */
wolfSSL 15:117db924cf7c 3787 b->used = a->used;
wolfSSL 15:117db924cf7c 3788 b->sign = a->sign;
wolfSSL 15:117db924cf7c 3789 XMEMCPY(b->dp, a->dp, FP_SIZE * sizeof(fp_digit));
wolfSSL 15:117db924cf7c 3790 #endif
wolfSSL 15:117db924cf7c 3791 }
wolfSSL 15:117db924cf7c 3792 }
wolfSSL 15:117db924cf7c 3793
wolfSSL 15:117db924cf7c 3794 void fp_init_copy(fp_int *a, fp_int* b)
wolfSSL 15:117db924cf7c 3795 {
wolfSSL 15:117db924cf7c 3796 if (a != b) {
wolfSSL 15:117db924cf7c 3797 fp_init(a);
wolfSSL 15:117db924cf7c 3798 fp_copy(b, a);
wolfSSL 15:117db924cf7c 3799 }
wolfSSL 15:117db924cf7c 3800 }
wolfSSL 15:117db924cf7c 3801
wolfSSL 15:117db924cf7c 3802 /* fast math wrappers */
wolfSSL 15:117db924cf7c 3803 int mp_copy(fp_int* a, fp_int* b)
wolfSSL 15:117db924cf7c 3804 {
wolfSSL 15:117db924cf7c 3805 fp_copy(a, b);
wolfSSL 15:117db924cf7c 3806 return MP_OKAY;
wolfSSL 15:117db924cf7c 3807 }
wolfSSL 15:117db924cf7c 3808
wolfSSL 15:117db924cf7c 3809 int mp_isodd(mp_int* a)
wolfSSL 15:117db924cf7c 3810 {
wolfSSL 15:117db924cf7c 3811 return fp_isodd(a);
wolfSSL 15:117db924cf7c 3812 }
wolfSSL 15:117db924cf7c 3813
wolfSSL 15:117db924cf7c 3814 int mp_iszero(mp_int* a)
wolfSSL 15:117db924cf7c 3815 {
wolfSSL 15:117db924cf7c 3816 return fp_iszero(a);
wolfSSL 15:117db924cf7c 3817 }
wolfSSL 15:117db924cf7c 3818
wolfSSL 15:117db924cf7c 3819 int mp_count_bits (mp_int* a)
wolfSSL 15:117db924cf7c 3820 {
wolfSSL 15:117db924cf7c 3821 return fp_count_bits(a);
wolfSSL 15:117db924cf7c 3822 }
wolfSSL 15:117db924cf7c 3823
wolfSSL 15:117db924cf7c 3824 int mp_leading_bit (mp_int* a)
wolfSSL 15:117db924cf7c 3825 {
wolfSSL 15:117db924cf7c 3826 return fp_leading_bit(a);
wolfSSL 15:117db924cf7c 3827 }
wolfSSL 15:117db924cf7c 3828
wolfSSL 15:117db924cf7c 3829 void mp_rshb (mp_int* a, int x)
wolfSSL 15:117db924cf7c 3830 {
wolfSSL 15:117db924cf7c 3831 fp_rshb(a, x);
wolfSSL 15:117db924cf7c 3832 }
wolfSSL 15:117db924cf7c 3833
wolfSSL 15:117db924cf7c 3834 void mp_rshd (mp_int* a, int x)
wolfSSL 15:117db924cf7c 3835 {
wolfSSL 15:117db924cf7c 3836 fp_rshd(a, x);
wolfSSL 15:117db924cf7c 3837 }
wolfSSL 15:117db924cf7c 3838
wolfSSL 15:117db924cf7c 3839 int mp_set_int(mp_int *a, unsigned long b)
wolfSSL 15:117db924cf7c 3840 {
wolfSSL 15:117db924cf7c 3841 fp_set_int(a, b);
wolfSSL 15:117db924cf7c 3842 return MP_OKAY;
wolfSSL 15:117db924cf7c 3843 }
wolfSSL 15:117db924cf7c 3844
wolfSSL 15:117db924cf7c 3845 int mp_is_bit_set (mp_int *a, mp_digit b)
wolfSSL 15:117db924cf7c 3846 {
wolfSSL 15:117db924cf7c 3847 return fp_is_bit_set(a, b);
wolfSSL 15:117db924cf7c 3848 }
wolfSSL 15:117db924cf7c 3849
wolfSSL 15:117db924cf7c 3850 int mp_set_bit(mp_int *a, mp_digit b)
wolfSSL 15:117db924cf7c 3851 {
wolfSSL 15:117db924cf7c 3852 return fp_set_bit(a, b);
wolfSSL 15:117db924cf7c 3853 }
wolfSSL 15:117db924cf7c 3854
wolfSSL 16:8e0d178b1d1e 3855 #if defined(WOLFSSL_KEY_GEN) || defined (HAVE_ECC) || !defined(NO_DH) || \
wolfSSL 16:8e0d178b1d1e 3856 !defined(NO_DSA) || !defined(NO_RSA)
wolfSSL 15:117db924cf7c 3857
wolfSSL 15:117db924cf7c 3858 /* c = a * a (mod b) */
wolfSSL 15:117db924cf7c 3859 int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 15:117db924cf7c 3860 {
wolfSSL 15:117db924cf7c 3861 int err;
wolfSSL 16:8e0d178b1d1e 3862 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3863 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 3864 #else
wolfSSL 16:8e0d178b1d1e 3865 fp_int *t;
wolfSSL 16:8e0d178b1d1e 3866 #endif
wolfSSL 16:8e0d178b1d1e 3867
wolfSSL 16:8e0d178b1d1e 3868 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3869 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3870 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 3871 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 3872 #endif
wolfSSL 16:8e0d178b1d1e 3873
wolfSSL 16:8e0d178b1d1e 3874 fp_init(t);
wolfSSL 16:8e0d178b1d1e 3875 err = fp_sqr(a, t);
wolfSSL 16:8e0d178b1d1e 3876 if (err == FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 3877 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 16:8e0d178b1d1e 3878 if (c->size < FP_SIZE) {
wolfSSL 16:8e0d178b1d1e 3879 err = fp_mod(t, b, t);
wolfSSL 16:8e0d178b1d1e 3880 fp_copy(t, c);
wolfSSL 16:8e0d178b1d1e 3881 }
wolfSSL 16:8e0d178b1d1e 3882 else
wolfSSL 16:8e0d178b1d1e 3883 #endif
wolfSSL 16:8e0d178b1d1e 3884 {
wolfSSL 16:8e0d178b1d1e 3885 err = fp_mod(t, b, c);
wolfSSL 16:8e0d178b1d1e 3886 }
wolfSSL 15:117db924cf7c 3887 }
wolfSSL 16:8e0d178b1d1e 3888
wolfSSL 16:8e0d178b1d1e 3889 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3890 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 15:117db924cf7c 3891 #endif
wolfSSL 15:117db924cf7c 3892 return err;
wolfSSL 15:117db924cf7c 3893 }
wolfSSL 15:117db924cf7c 3894
wolfSSL 15:117db924cf7c 3895 /* fast math conversion */
wolfSSL 15:117db924cf7c 3896 int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c)
wolfSSL 15:117db924cf7c 3897 {
wolfSSL 15:117db924cf7c 3898 return fp_sqrmod(a, b, c);
wolfSSL 15:117db924cf7c 3899 }
wolfSSL 15:117db924cf7c 3900
wolfSSL 15:117db924cf7c 3901 /* fast math conversion */
wolfSSL 15:117db924cf7c 3902 int mp_montgomery_calc_normalization(mp_int *a, mp_int *b)
wolfSSL 15:117db924cf7c 3903 {
wolfSSL 15:117db924cf7c 3904 fp_montgomery_calc_normalization(a, b);
wolfSSL 15:117db924cf7c 3905 return MP_OKAY;
wolfSSL 15:117db924cf7c 3906 }
wolfSSL 15:117db924cf7c 3907
wolfSSL 15:117db924cf7c 3908 #endif /* WOLFSSL_KEYGEN || HAVE_ECC */
wolfSSL 15:117db924cf7c 3909
wolfSSL 15:117db924cf7c 3910
wolfSSL 16:8e0d178b1d1e 3911 #if defined(WC_MP_TO_RADIX) || !defined(NO_DH) || !defined(NO_DSA) || \
wolfSSL 16:8e0d178b1d1e 3912 !defined(NO_RSA)
wolfSSL 15:117db924cf7c 3913
wolfSSL 15:117db924cf7c 3914 #ifdef WOLFSSL_KEY_GEN
wolfSSL 15:117db924cf7c 3915 /* swap the elements of two integers, for cases where you can't simply swap the
wolfSSL 15:117db924cf7c 3916 * mp_int pointers around
wolfSSL 15:117db924cf7c 3917 */
wolfSSL 16:8e0d178b1d1e 3918 static int fp_exch (fp_int * a, fp_int * b)
wolfSSL 15:117db924cf7c 3919 {
wolfSSL 16:8e0d178b1d1e 3920 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3921 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 3922 #else
wolfSSL 16:8e0d178b1d1e 3923 fp_int *t;
wolfSSL 16:8e0d178b1d1e 3924 #endif
wolfSSL 16:8e0d178b1d1e 3925
wolfSSL 16:8e0d178b1d1e 3926 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3927 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3928 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 3929 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 3930 #endif
wolfSSL 16:8e0d178b1d1e 3931
wolfSSL 16:8e0d178b1d1e 3932 *t = *a;
wolfSSL 15:117db924cf7c 3933 *a = *b;
wolfSSL 16:8e0d178b1d1e 3934 *b = *t;
wolfSSL 16:8e0d178b1d1e 3935
wolfSSL 16:8e0d178b1d1e 3936 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3937 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 3938 #endif
wolfSSL 16:8e0d178b1d1e 3939 return FP_OKAY;
wolfSSL 15:117db924cf7c 3940 }
wolfSSL 15:117db924cf7c 3941 #endif
wolfSSL 15:117db924cf7c 3942
wolfSSL 15:117db924cf7c 3943 static const int lnz[16] = {
wolfSSL 15:117db924cf7c 3944 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
wolfSSL 15:117db924cf7c 3945 };
wolfSSL 15:117db924cf7c 3946
wolfSSL 15:117db924cf7c 3947 /* Counts the number of lsbs which are zero before the first zero bit */
wolfSSL 15:117db924cf7c 3948 int fp_cnt_lsb(fp_int *a)
wolfSSL 15:117db924cf7c 3949 {
wolfSSL 15:117db924cf7c 3950 int x;
wolfSSL 15:117db924cf7c 3951 fp_digit q, qq;
wolfSSL 15:117db924cf7c 3952
wolfSSL 15:117db924cf7c 3953 /* easy out */
wolfSSL 15:117db924cf7c 3954 if (fp_iszero(a) == FP_YES) {
wolfSSL 15:117db924cf7c 3955 return 0;
wolfSSL 15:117db924cf7c 3956 }
wolfSSL 15:117db924cf7c 3957
wolfSSL 15:117db924cf7c 3958 /* scan lower digits until non-zero */
wolfSSL 15:117db924cf7c 3959 for (x = 0; x < a->used && a->dp[x] == 0; x++) {}
wolfSSL 15:117db924cf7c 3960 q = a->dp[x];
wolfSSL 15:117db924cf7c 3961 x *= DIGIT_BIT;
wolfSSL 15:117db924cf7c 3962
wolfSSL 15:117db924cf7c 3963 /* now scan this digit until a 1 is found */
wolfSSL 15:117db924cf7c 3964 if ((q & 1) == 0) {
wolfSSL 15:117db924cf7c 3965 do {
wolfSSL 15:117db924cf7c 3966 qq = q & 15;
wolfSSL 15:117db924cf7c 3967 x += lnz[qq];
wolfSSL 15:117db924cf7c 3968 q >>= 4;
wolfSSL 15:117db924cf7c 3969 } while (qq == 0);
wolfSSL 15:117db924cf7c 3970 }
wolfSSL 15:117db924cf7c 3971 return x;
wolfSSL 15:117db924cf7c 3972 }
wolfSSL 15:117db924cf7c 3973
wolfSSL 15:117db924cf7c 3974
wolfSSL 15:117db924cf7c 3975 static int s_is_power_of_two(fp_digit b, int *p)
wolfSSL 15:117db924cf7c 3976 {
wolfSSL 15:117db924cf7c 3977 int x;
wolfSSL 15:117db924cf7c 3978
wolfSSL 15:117db924cf7c 3979 /* fast return if no power of two */
wolfSSL 15:117db924cf7c 3980 if ((b==0) || (b & (b-1))) {
wolfSSL 15:117db924cf7c 3981 return FP_NO;
wolfSSL 15:117db924cf7c 3982 }
wolfSSL 15:117db924cf7c 3983
wolfSSL 15:117db924cf7c 3984 for (x = 0; x < DIGIT_BIT; x++) {
wolfSSL 15:117db924cf7c 3985 if (b == (((fp_digit)1)<<x)) {
wolfSSL 15:117db924cf7c 3986 *p = x;
wolfSSL 15:117db924cf7c 3987 return FP_YES;
wolfSSL 15:117db924cf7c 3988 }
wolfSSL 15:117db924cf7c 3989 }
wolfSSL 15:117db924cf7c 3990 return FP_NO;
wolfSSL 15:117db924cf7c 3991 }
wolfSSL 15:117db924cf7c 3992
wolfSSL 15:117db924cf7c 3993 /* a/b => cb + d == a */
wolfSSL 15:117db924cf7c 3994 static int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d)
wolfSSL 15:117db924cf7c 3995 {
wolfSSL 16:8e0d178b1d1e 3996 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 3997 fp_int q[1];
wolfSSL 16:8e0d178b1d1e 3998 #else
wolfSSL 16:8e0d178b1d1e 3999 fp_int *q;
wolfSSL 16:8e0d178b1d1e 4000 #endif
wolfSSL 15:117db924cf7c 4001 fp_word w;
wolfSSL 15:117db924cf7c 4002 fp_digit t;
wolfSSL 15:117db924cf7c 4003 int ix;
wolfSSL 15:117db924cf7c 4004
wolfSSL 15:117db924cf7c 4005 /* cannot divide by zero */
wolfSSL 15:117db924cf7c 4006 if (b == 0) {
wolfSSL 15:117db924cf7c 4007 return FP_VAL;
wolfSSL 15:117db924cf7c 4008 }
wolfSSL 15:117db924cf7c 4009
wolfSSL 15:117db924cf7c 4010 /* quick outs */
wolfSSL 15:117db924cf7c 4011 if (b == 1 || fp_iszero(a) == FP_YES) {
wolfSSL 15:117db924cf7c 4012 if (d != NULL) {
wolfSSL 15:117db924cf7c 4013 *d = 0;
wolfSSL 15:117db924cf7c 4014 }
wolfSSL 15:117db924cf7c 4015 if (c != NULL) {
wolfSSL 15:117db924cf7c 4016 fp_copy(a, c);
wolfSSL 15:117db924cf7c 4017 }
wolfSSL 15:117db924cf7c 4018 return FP_OKAY;
wolfSSL 15:117db924cf7c 4019 }
wolfSSL 15:117db924cf7c 4020
wolfSSL 15:117db924cf7c 4021 /* power of two ? */
wolfSSL 15:117db924cf7c 4022 if (s_is_power_of_two(b, &ix) == FP_YES) {
wolfSSL 15:117db924cf7c 4023 if (d != NULL) {
wolfSSL 15:117db924cf7c 4024 *d = a->dp[0] & ((((fp_digit)1)<<ix) - 1);
wolfSSL 15:117db924cf7c 4025 }
wolfSSL 15:117db924cf7c 4026 if (c != NULL) {
wolfSSL 15:117db924cf7c 4027 fp_div_2d(a, ix, c, NULL);
wolfSSL 15:117db924cf7c 4028 }
wolfSSL 15:117db924cf7c 4029 return FP_OKAY;
wolfSSL 15:117db924cf7c 4030 }
wolfSSL 15:117db924cf7c 4031
wolfSSL 16:8e0d178b1d1e 4032 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4033 q = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4034 if (q == NULL)
wolfSSL 16:8e0d178b1d1e 4035 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 4036 #endif
wolfSSL 16:8e0d178b1d1e 4037
wolfSSL 16:8e0d178b1d1e 4038 fp_init(q);
wolfSSL 16:8e0d178b1d1e 4039
wolfSSL 15:117db924cf7c 4040 if (c != NULL) {
wolfSSL 16:8e0d178b1d1e 4041 q->used = a->used;
wolfSSL 16:8e0d178b1d1e 4042 q->sign = a->sign;
wolfSSL 15:117db924cf7c 4043 }
wolfSSL 15:117db924cf7c 4044
wolfSSL 15:117db924cf7c 4045 w = 0;
wolfSSL 15:117db924cf7c 4046 for (ix = a->used - 1; ix >= 0; ix--) {
wolfSSL 15:117db924cf7c 4047 w = (w << ((fp_word)DIGIT_BIT)) | ((fp_word)a->dp[ix]);
wolfSSL 15:117db924cf7c 4048
wolfSSL 15:117db924cf7c 4049 if (w >= b) {
wolfSSL 15:117db924cf7c 4050 t = (fp_digit)(w / b);
wolfSSL 15:117db924cf7c 4051 w -= ((fp_word)t) * ((fp_word)b);
wolfSSL 15:117db924cf7c 4052 } else {
wolfSSL 15:117db924cf7c 4053 t = 0;
wolfSSL 15:117db924cf7c 4054 }
wolfSSL 15:117db924cf7c 4055 if (c != NULL)
wolfSSL 16:8e0d178b1d1e 4056 q->dp[ix] = (fp_digit)t;
wolfSSL 15:117db924cf7c 4057 }
wolfSSL 15:117db924cf7c 4058
wolfSSL 15:117db924cf7c 4059 if (d != NULL) {
wolfSSL 15:117db924cf7c 4060 *d = (fp_digit)w;
wolfSSL 15:117db924cf7c 4061 }
wolfSSL 15:117db924cf7c 4062
wolfSSL 15:117db924cf7c 4063 if (c != NULL) {
wolfSSL 16:8e0d178b1d1e 4064 fp_clamp(q);
wolfSSL 16:8e0d178b1d1e 4065 fp_copy(q, c);
wolfSSL 15:117db924cf7c 4066 }
wolfSSL 15:117db924cf7c 4067
wolfSSL 16:8e0d178b1d1e 4068 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4069 XFREE(q, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4070 #endif
wolfSSL 15:117db924cf7c 4071 return FP_OKAY;
wolfSSL 15:117db924cf7c 4072 }
wolfSSL 15:117db924cf7c 4073
wolfSSL 15:117db924cf7c 4074
wolfSSL 15:117db924cf7c 4075 /* c = a mod b, 0 <= c < b */
wolfSSL 15:117db924cf7c 4076 static int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c)
wolfSSL 15:117db924cf7c 4077 {
wolfSSL 15:117db924cf7c 4078 return fp_div_d(a, b, NULL, c);
wolfSSL 15:117db924cf7c 4079 }
wolfSSL 15:117db924cf7c 4080
wolfSSL 15:117db924cf7c 4081 int mp_mod_d(fp_int *a, fp_digit b, fp_digit *c)
wolfSSL 15:117db924cf7c 4082 {
wolfSSL 15:117db924cf7c 4083 return fp_mod_d(a, b, c);
wolfSSL 15:117db924cf7c 4084 }
wolfSSL 15:117db924cf7c 4085
wolfSSL 16:8e0d178b1d1e 4086 #endif /* WC_MP_TO_RADIX || !NO_DH || !NO_DSA || !NO_RSA */
wolfSSL 16:8e0d178b1d1e 4087
wolfSSL 16:8e0d178b1d1e 4088
wolfSSL 16:8e0d178b1d1e 4089 #if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || \
wolfSSL 16:8e0d178b1d1e 4090 defined(WOLFSSL_KEY_GEN)
wolfSSL 16:8e0d178b1d1e 4091
wolfSSL 16:8e0d178b1d1e 4092 static int fp_isprime_ex(fp_int *a, int t, int* result);
wolfSSL 15:117db924cf7c 4093
wolfSSL 15:117db924cf7c 4094
wolfSSL 15:117db924cf7c 4095 int mp_prime_is_prime(mp_int* a, int t, int* result)
wolfSSL 15:117db924cf7c 4096 {
wolfSSL 16:8e0d178b1d1e 4097 return fp_isprime_ex(a, t, result);
wolfSSL 15:117db924cf7c 4098 }
wolfSSL 15:117db924cf7c 4099
wolfSSL 15:117db924cf7c 4100 /* Miller-Rabin test of "a" to the base of "b" as described in
wolfSSL 15:117db924cf7c 4101 * HAC pp. 139 Algorithm 4.24
wolfSSL 15:117db924cf7c 4102 *
wolfSSL 15:117db924cf7c 4103 * Sets result to 0 if definitely composite or 1 if probably prime.
wolfSSL 15:117db924cf7c 4104 * Randomly the chance of error is no more than 1/4 and often
wolfSSL 15:117db924cf7c 4105 * very much lower.
wolfSSL 15:117db924cf7c 4106 */
wolfSSL 16:8e0d178b1d1e 4107 static int fp_prime_miller_rabin_ex(fp_int * a, fp_int * b, int *result,
wolfSSL 16:8e0d178b1d1e 4108 fp_int *n1, fp_int *y, fp_int *r)
wolfSSL 15:117db924cf7c 4109 {
wolfSSL 16:8e0d178b1d1e 4110 int s, j;
wolfSSL 16:8e0d178b1d1e 4111 int err;
wolfSSL 15:117db924cf7c 4112
wolfSSL 15:117db924cf7c 4113 /* default */
wolfSSL 15:117db924cf7c 4114 *result = FP_NO;
wolfSSL 15:117db924cf7c 4115
wolfSSL 15:117db924cf7c 4116 /* ensure b > 1 */
wolfSSL 15:117db924cf7c 4117 if (fp_cmp_d(b, 1) != FP_GT) {
wolfSSL 16:8e0d178b1d1e 4118 return FP_OKAY;
wolfSSL 15:117db924cf7c 4119 }
wolfSSL 15:117db924cf7c 4120
wolfSSL 15:117db924cf7c 4121 /* get n1 = a - 1 */
wolfSSL 16:8e0d178b1d1e 4122 fp_copy(a, n1);
wolfSSL 16:8e0d178b1d1e 4123 err = fp_sub_d(n1, 1, n1);
wolfSSL 16:8e0d178b1d1e 4124 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 4125 return err;
wolfSSL 16:8e0d178b1d1e 4126 }
wolfSSL 15:117db924cf7c 4127
wolfSSL 15:117db924cf7c 4128 /* set 2**s * r = n1 */
wolfSSL 16:8e0d178b1d1e 4129 fp_copy(n1, r);
wolfSSL 15:117db924cf7c 4130
wolfSSL 15:117db924cf7c 4131 /* count the number of least significant bits
wolfSSL 15:117db924cf7c 4132 * which are zero
wolfSSL 15:117db924cf7c 4133 */
wolfSSL 16:8e0d178b1d1e 4134 s = fp_cnt_lsb(r);
wolfSSL 15:117db924cf7c 4135
wolfSSL 15:117db924cf7c 4136 /* now divide n - 1 by 2**s */
wolfSSL 16:8e0d178b1d1e 4137 fp_div_2d (r, s, r, NULL);
wolfSSL 15:117db924cf7c 4138
wolfSSL 15:117db924cf7c 4139 /* compute y = b**r mod a */
wolfSSL 16:8e0d178b1d1e 4140 fp_zero(y);
wolfSSL 16:8e0d178b1d1e 4141 #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
wolfSSL 16:8e0d178b1d1e 4142 defined(WOLFSSL_HAVE_SP_DH)
wolfSSL 16:8e0d178b1d1e 4143 #ifndef WOLFSSL_SP_NO_2048
wolfSSL 16:8e0d178b1d1e 4144 if (fp_count_bits(a) == 1024)
wolfSSL 16:8e0d178b1d1e 4145 sp_ModExp_1024(b, r, a, y);
wolfSSL 16:8e0d178b1d1e 4146 else if (fp_count_bits(a) == 2048)
wolfSSL 16:8e0d178b1d1e 4147 sp_ModExp_2048(b, r, a, y);
wolfSSL 16:8e0d178b1d1e 4148 else
wolfSSL 16:8e0d178b1d1e 4149 #endif
wolfSSL 16:8e0d178b1d1e 4150 #ifndef WOLFSSL_SP_NO_3072
wolfSSL 16:8e0d178b1d1e 4151 if (fp_count_bits(a) == 1536)
wolfSSL 16:8e0d178b1d1e 4152 sp_ModExp_1536(b, r, a, y);
wolfSSL 16:8e0d178b1d1e 4153 else if (fp_count_bits(a) == 3072)
wolfSSL 16:8e0d178b1d1e 4154 sp_ModExp_3072(b, r, a, y);
wolfSSL 16:8e0d178b1d1e 4155 else
wolfSSL 16:8e0d178b1d1e 4156 #endif
wolfSSL 16:8e0d178b1d1e 4157 #ifdef WOLFSSL_SP_4096
wolfSSL 16:8e0d178b1d1e 4158 if (fp_count_bits(a) == 4096)
wolfSSL 16:8e0d178b1d1e 4159 sp_ModExp_4096(b, r, a, y);
wolfSSL 16:8e0d178b1d1e 4160 else
wolfSSL 16:8e0d178b1d1e 4161 #endif
wolfSSL 16:8e0d178b1d1e 4162 #endif
wolfSSL 16:8e0d178b1d1e 4163 fp_exptmod(b, r, a, y);
wolfSSL 15:117db924cf7c 4164
wolfSSL 15:117db924cf7c 4165 /* if y != 1 and y != n1 do */
wolfSSL 16:8e0d178b1d1e 4166 if (fp_cmp_d (y, 1) != FP_EQ && fp_cmp (y, n1) != FP_EQ) {
wolfSSL 15:117db924cf7c 4167 j = 1;
wolfSSL 15:117db924cf7c 4168 /* while j <= s-1 and y != n1 */
wolfSSL 16:8e0d178b1d1e 4169 while ((j <= (s - 1)) && fp_cmp (y, n1) != FP_EQ) {
wolfSSL 16:8e0d178b1d1e 4170 fp_sqrmod (y, a, y);
wolfSSL 15:117db924cf7c 4171
wolfSSL 15:117db924cf7c 4172 /* if y == 1 then composite */
wolfSSL 16:8e0d178b1d1e 4173 if (fp_cmp_d (y, 1) == FP_EQ) {
wolfSSL 16:8e0d178b1d1e 4174 return FP_OKAY;
wolfSSL 15:117db924cf7c 4175 }
wolfSSL 15:117db924cf7c 4176 ++j;
wolfSSL 15:117db924cf7c 4177 }
wolfSSL 15:117db924cf7c 4178
wolfSSL 15:117db924cf7c 4179 /* if y != n1 then composite */
wolfSSL 16:8e0d178b1d1e 4180 if (fp_cmp (y, n1) != FP_EQ) {
wolfSSL 16:8e0d178b1d1e 4181 return FP_OKAY;
wolfSSL 15:117db924cf7c 4182 }
wolfSSL 15:117db924cf7c 4183 }
wolfSSL 15:117db924cf7c 4184
wolfSSL 15:117db924cf7c 4185 /* probably prime now */
wolfSSL 15:117db924cf7c 4186 *result = FP_YES;
wolfSSL 16:8e0d178b1d1e 4187
wolfSSL 16:8e0d178b1d1e 4188 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 4189 }
wolfSSL 16:8e0d178b1d1e 4190
wolfSSL 16:8e0d178b1d1e 4191 static int fp_prime_miller_rabin(fp_int * a, fp_int * b, int *result)
wolfSSL 16:8e0d178b1d1e 4192 {
wolfSSL 16:8e0d178b1d1e 4193 int err;
wolfSSL 16:8e0d178b1d1e 4194 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4195 fp_int n1[1], y[1], r[1];
wolfSSL 16:8e0d178b1d1e 4196 #else
wolfSSL 16:8e0d178b1d1e 4197 fp_int *n1, *y, *r;
wolfSSL 16:8e0d178b1d1e 4198 #endif
wolfSSL 16:8e0d178b1d1e 4199
wolfSSL 16:8e0d178b1d1e 4200 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4201 n1 = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4202 if (n1 == NULL) {
wolfSSL 16:8e0d178b1d1e 4203 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 4204 }
wolfSSL 16:8e0d178b1d1e 4205 y = &n1[1]; r = &n1[2];
wolfSSL 16:8e0d178b1d1e 4206 #endif
wolfSSL 16:8e0d178b1d1e 4207
wolfSSL 16:8e0d178b1d1e 4208 fp_init(n1);
wolfSSL 16:8e0d178b1d1e 4209 fp_init(y);
wolfSSL 16:8e0d178b1d1e 4210 fp_init(r);
wolfSSL 16:8e0d178b1d1e 4211
wolfSSL 16:8e0d178b1d1e 4212 err = fp_prime_miller_rabin_ex(a, b, result, n1, y, r);
wolfSSL 16:8e0d178b1d1e 4213
wolfSSL 16:8e0d178b1d1e 4214 fp_clear(n1);
wolfSSL 16:8e0d178b1d1e 4215 fp_clear(y);
wolfSSL 16:8e0d178b1d1e 4216 fp_clear(r);
wolfSSL 16:8e0d178b1d1e 4217
wolfSSL 16:8e0d178b1d1e 4218 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4219 XFREE(n1, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4220 #endif
wolfSSL 16:8e0d178b1d1e 4221
wolfSSL 16:8e0d178b1d1e 4222 return err;
wolfSSL 15:117db924cf7c 4223 }
wolfSSL 15:117db924cf7c 4224
wolfSSL 15:117db924cf7c 4225
wolfSSL 15:117db924cf7c 4226 /* a few primes */
wolfSSL 15:117db924cf7c 4227 static const fp_digit primes[FP_PRIME_SIZE] = {
wolfSSL 15:117db924cf7c 4228 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
wolfSSL 15:117db924cf7c 4229 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
wolfSSL 15:117db924cf7c 4230 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
wolfSSL 15:117db924cf7c 4231 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083,
wolfSSL 15:117db924cf7c 4232 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
wolfSSL 15:117db924cf7c 4233 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
wolfSSL 15:117db924cf7c 4234 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
wolfSSL 15:117db924cf7c 4235 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
wolfSSL 15:117db924cf7c 4236
wolfSSL 15:117db924cf7c 4237 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
wolfSSL 15:117db924cf7c 4238 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
wolfSSL 15:117db924cf7c 4239 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
wolfSSL 15:117db924cf7c 4240 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
wolfSSL 15:117db924cf7c 4241 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
wolfSSL 15:117db924cf7c 4242 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
wolfSSL 15:117db924cf7c 4243 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
wolfSSL 15:117db924cf7c 4244 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
wolfSSL 15:117db924cf7c 4245
wolfSSL 15:117db924cf7c 4246 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
wolfSSL 15:117db924cf7c 4247 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
wolfSSL 15:117db924cf7c 4248 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
wolfSSL 15:117db924cf7c 4249 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
wolfSSL 15:117db924cf7c 4250 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
wolfSSL 15:117db924cf7c 4251 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
wolfSSL 15:117db924cf7c 4252 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
wolfSSL 15:117db924cf7c 4253 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
wolfSSL 15:117db924cf7c 4254
wolfSSL 15:117db924cf7c 4255 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
wolfSSL 15:117db924cf7c 4256 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
wolfSSL 15:117db924cf7c 4257 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
wolfSSL 15:117db924cf7c 4258 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
wolfSSL 15:117db924cf7c 4259 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
wolfSSL 15:117db924cf7c 4260 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
wolfSSL 15:117db924cf7c 4261 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
wolfSSL 15:117db924cf7c 4262 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
wolfSSL 15:117db924cf7c 4263 };
wolfSSL 15:117db924cf7c 4264
wolfSSL 16:8e0d178b1d1e 4265 int fp_isprime_ex(fp_int *a, int t, int* result)
wolfSSL 15:117db924cf7c 4266 {
wolfSSL 16:8e0d178b1d1e 4267 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4268 fp_int b[1];
wolfSSL 16:8e0d178b1d1e 4269 #else
wolfSSL 16:8e0d178b1d1e 4270 fp_int *b;
wolfSSL 16:8e0d178b1d1e 4271 #endif
wolfSSL 15:117db924cf7c 4272 fp_digit d;
wolfSSL 15:117db924cf7c 4273 int r, res;
wolfSSL 15:117db924cf7c 4274
wolfSSL 15:117db924cf7c 4275 if (t <= 0 || t > FP_PRIME_SIZE) {
wolfSSL 16:8e0d178b1d1e 4276 *result = FP_NO;
wolfSSL 16:8e0d178b1d1e 4277 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 4278 }
wolfSSL 16:8e0d178b1d1e 4279
wolfSSL 16:8e0d178b1d1e 4280 if (fp_isone(a)) {
wolfSSL 16:8e0d178b1d1e 4281 *result = FP_NO;
wolfSSL 16:8e0d178b1d1e 4282 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 4283 }
wolfSSL 16:8e0d178b1d1e 4284
wolfSSL 16:8e0d178b1d1e 4285 /* check against primes table */
wolfSSL 16:8e0d178b1d1e 4286 for (r = 0; r < FP_PRIME_SIZE; r++) {
wolfSSL 16:8e0d178b1d1e 4287 if (fp_cmp_d(a, primes[r]) == FP_EQ) {
wolfSSL 16:8e0d178b1d1e 4288 *result = FP_YES;
wolfSSL 16:8e0d178b1d1e 4289 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 4290 }
wolfSSL 15:117db924cf7c 4291 }
wolfSSL 15:117db924cf7c 4292
wolfSSL 15:117db924cf7c 4293 /* do trial division */
wolfSSL 15:117db924cf7c 4294 for (r = 0; r < FP_PRIME_SIZE; r++) {
wolfSSL 15:117db924cf7c 4295 res = fp_mod_d(a, primes[r], &d);
wolfSSL 15:117db924cf7c 4296 if (res != MP_OKAY || d == 0) {
wolfSSL 16:8e0d178b1d1e 4297 *result = FP_NO;
wolfSSL 16:8e0d178b1d1e 4298 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 4299 }
wolfSSL 16:8e0d178b1d1e 4300 }
wolfSSL 16:8e0d178b1d1e 4301
wolfSSL 16:8e0d178b1d1e 4302 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4303 b = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4304 if (b == NULL)
wolfSSL 16:8e0d178b1d1e 4305 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 4306 #endif
wolfSSL 16:8e0d178b1d1e 4307 /* now do 't' miller rabins */
wolfSSL 16:8e0d178b1d1e 4308 fp_init(b);
wolfSSL 16:8e0d178b1d1e 4309 for (r = 0; r < t; r++) {
wolfSSL 16:8e0d178b1d1e 4310 fp_set(b, primes[r]);
wolfSSL 16:8e0d178b1d1e 4311 fp_prime_miller_rabin(a, b, &res);
wolfSSL 16:8e0d178b1d1e 4312 if (res == FP_NO) {
wolfSSL 16:8e0d178b1d1e 4313 *result = FP_NO;
wolfSSL 16:8e0d178b1d1e 4314 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4315 XFREE(b, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4316 #endif
wolfSSL 16:8e0d178b1d1e 4317 return FP_OKAY;
wolfSSL 15:117db924cf7c 4318 }
wolfSSL 15:117db924cf7c 4319 }
wolfSSL 16:8e0d178b1d1e 4320 *result = FP_YES;
wolfSSL 16:8e0d178b1d1e 4321 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4322 XFREE(b, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4323 #endif
wolfSSL 16:8e0d178b1d1e 4324 return FP_OKAY;
wolfSSL 15:117db924cf7c 4325 }
wolfSSL 15:117db924cf7c 4326
wolfSSL 16:8e0d178b1d1e 4327
wolfSSL 16:8e0d178b1d1e 4328 int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
wolfSSL 15:117db924cf7c 4329 {
wolfSSL 16:8e0d178b1d1e 4330 int ret = FP_YES;
wolfSSL 16:8e0d178b1d1e 4331 fp_digit d;
wolfSSL 16:8e0d178b1d1e 4332 int i;
wolfSSL 16:8e0d178b1d1e 4333
wolfSSL 16:8e0d178b1d1e 4334 if (a == NULL || result == NULL || rng == NULL)
wolfSSL 16:8e0d178b1d1e 4335 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 4336
wolfSSL 16:8e0d178b1d1e 4337 if (fp_isone(a)) {
wolfSSL 16:8e0d178b1d1e 4338 *result = FP_NO;
wolfSSL 16:8e0d178b1d1e 4339 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 4340 }
wolfSSL 16:8e0d178b1d1e 4341
wolfSSL 16:8e0d178b1d1e 4342 /* check against primes table */
wolfSSL 16:8e0d178b1d1e 4343 for (i = 0; i < FP_PRIME_SIZE; i++) {
wolfSSL 16:8e0d178b1d1e 4344 if (fp_cmp_d(a, primes[i]) == FP_EQ) {
wolfSSL 16:8e0d178b1d1e 4345 *result = FP_YES;
wolfSSL 16:8e0d178b1d1e 4346 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 4347 }
wolfSSL 16:8e0d178b1d1e 4348 }
wolfSSL 16:8e0d178b1d1e 4349
wolfSSL 16:8e0d178b1d1e 4350 /* do trial division */
wolfSSL 16:8e0d178b1d1e 4351 for (i = 0; i < FP_PRIME_SIZE; i++) {
wolfSSL 16:8e0d178b1d1e 4352 if (fp_mod_d(a, primes[i], &d) == MP_OKAY) {
wolfSSL 16:8e0d178b1d1e 4353 if (d == 0) {
wolfSSL 16:8e0d178b1d1e 4354 *result = FP_NO;
wolfSSL 16:8e0d178b1d1e 4355 return FP_OKAY;
wolfSSL 16:8e0d178b1d1e 4356 }
wolfSSL 16:8e0d178b1d1e 4357 }
wolfSSL 16:8e0d178b1d1e 4358 else
wolfSSL 16:8e0d178b1d1e 4359 return FP_VAL;
wolfSSL 16:8e0d178b1d1e 4360 }
wolfSSL 16:8e0d178b1d1e 4361
wolfSSL 16:8e0d178b1d1e 4362 #ifndef WC_NO_RNG
wolfSSL 16:8e0d178b1d1e 4363 /* now do a miller rabin with up to t random numbers, this should
wolfSSL 16:8e0d178b1d1e 4364 * give a (1/4)^t chance of a false prime. */
wolfSSL 16:8e0d178b1d1e 4365 {
wolfSSL 16:8e0d178b1d1e 4366 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4367 fp_int b[1], c[1], n1[1], y[1], r[1];
wolfSSL 16:8e0d178b1d1e 4368 byte base[FP_MAX_PRIME_SIZE];
wolfSSL 16:8e0d178b1d1e 4369 #else
wolfSSL 16:8e0d178b1d1e 4370 fp_int *b, *c, *n1, *y, *r;
wolfSSL 16:8e0d178b1d1e 4371 byte* base;
wolfSSL 16:8e0d178b1d1e 4372 #endif
wolfSSL 16:8e0d178b1d1e 4373 word32 baseSz;
wolfSSL 16:8e0d178b1d1e 4374 int err;
wolfSSL 16:8e0d178b1d1e 4375
wolfSSL 16:8e0d178b1d1e 4376 baseSz = fp_count_bits(a);
wolfSSL 16:8e0d178b1d1e 4377 /* The base size is the number of bits / 8. One is added if the number
wolfSSL 16:8e0d178b1d1e 4378 * of bits isn't an even 8. */
wolfSSL 16:8e0d178b1d1e 4379 baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0);
wolfSSL 16:8e0d178b1d1e 4380
wolfSSL 16:8e0d178b1d1e 4381 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4382 if (baseSz > sizeof(base))
wolfSSL 16:8e0d178b1d1e 4383 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 4384 #else
wolfSSL 16:8e0d178b1d1e 4385 base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 4386 if (base == NULL)
wolfSSL 16:8e0d178b1d1e 4387 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 4388
wolfSSL 16:8e0d178b1d1e 4389 b = (fp_int*)XMALLOC(sizeof(fp_int) * 5, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4390 if (b == NULL) {
wolfSSL 16:8e0d178b1d1e 4391 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 4392 }
wolfSSL 16:8e0d178b1d1e 4393 c = &b[1]; n1 = &b[2]; y= &b[3]; r = &b[4];
wolfSSL 16:8e0d178b1d1e 4394 #endif
wolfSSL 16:8e0d178b1d1e 4395
wolfSSL 16:8e0d178b1d1e 4396 fp_init(b);
wolfSSL 16:8e0d178b1d1e 4397 fp_init(c);
wolfSSL 16:8e0d178b1d1e 4398 fp_init(n1);
wolfSSL 16:8e0d178b1d1e 4399 fp_init(y);
wolfSSL 16:8e0d178b1d1e 4400 fp_init(r);
wolfSSL 16:8e0d178b1d1e 4401
wolfSSL 16:8e0d178b1d1e 4402 err = fp_sub_d(a, 2, c);
wolfSSL 16:8e0d178b1d1e 4403 if (err != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 4404 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4405 XFREE(b, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4406 XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 4407 #endif
wolfSSL 16:8e0d178b1d1e 4408 return err;
wolfSSL 16:8e0d178b1d1e 4409 }
wolfSSL 16:8e0d178b1d1e 4410 while (t > 0) {
wolfSSL 16:8e0d178b1d1e 4411 if ((err = wc_RNG_GenerateBlock(rng, base, baseSz)) != 0) {
wolfSSL 16:8e0d178b1d1e 4412 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4413 XFREE(b, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4414 XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 4415 #endif
wolfSSL 16:8e0d178b1d1e 4416 return err;
wolfSSL 16:8e0d178b1d1e 4417 }
wolfSSL 16:8e0d178b1d1e 4418
wolfSSL 16:8e0d178b1d1e 4419 fp_read_unsigned_bin(b, base, baseSz);
wolfSSL 16:8e0d178b1d1e 4420 if (fp_cmp_d(b, 2) != FP_GT || fp_cmp(b, c) != FP_LT) {
wolfSSL 16:8e0d178b1d1e 4421 continue;
wolfSSL 16:8e0d178b1d1e 4422 }
wolfSSL 16:8e0d178b1d1e 4423
wolfSSL 16:8e0d178b1d1e 4424 fp_prime_miller_rabin_ex(a, b, &ret, n1, y, r);
wolfSSL 16:8e0d178b1d1e 4425 if (ret == FP_NO)
wolfSSL 16:8e0d178b1d1e 4426 break;
wolfSSL 16:8e0d178b1d1e 4427 fp_zero(b);
wolfSSL 16:8e0d178b1d1e 4428 t--;
wolfSSL 16:8e0d178b1d1e 4429 }
wolfSSL 16:8e0d178b1d1e 4430
wolfSSL 16:8e0d178b1d1e 4431 fp_clear(n1);
wolfSSL 16:8e0d178b1d1e 4432 fp_clear(y);
wolfSSL 16:8e0d178b1d1e 4433 fp_clear(r);
wolfSSL 16:8e0d178b1d1e 4434 fp_clear(b);
wolfSSL 16:8e0d178b1d1e 4435 fp_clear(c);
wolfSSL 16:8e0d178b1d1e 4436 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4437 XFREE(b, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4438 XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 16:8e0d178b1d1e 4439 #endif
wolfSSL 16:8e0d178b1d1e 4440 }
wolfSSL 16:8e0d178b1d1e 4441 #else
wolfSSL 16:8e0d178b1d1e 4442 (void)t;
wolfSSL 16:8e0d178b1d1e 4443 #endif /* !WC_NO_RNG */
wolfSSL 16:8e0d178b1d1e 4444
wolfSSL 16:8e0d178b1d1e 4445 *result = ret;
wolfSSL 16:8e0d178b1d1e 4446 return FP_OKAY;
wolfSSL 15:117db924cf7c 4447 }
wolfSSL 16:8e0d178b1d1e 4448 #endif /* !NO_RSA || !NO_DSA || !NO_DH || WOLFSSL_KEY_GEN */
wolfSSL 16:8e0d178b1d1e 4449
wolfSSL 16:8e0d178b1d1e 4450
wolfSSL 16:8e0d178b1d1e 4451 #ifdef WOLFSSL_KEY_GEN
wolfSSL 16:8e0d178b1d1e 4452
wolfSSL 16:8e0d178b1d1e 4453 static int fp_gcd(fp_int *a, fp_int *b, fp_int *c);
wolfSSL 16:8e0d178b1d1e 4454 static int fp_lcm(fp_int *a, fp_int *b, fp_int *c);
wolfSSL 16:8e0d178b1d1e 4455 static int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap);
wolfSSL 16:8e0d178b1d1e 4456
wolfSSL 16:8e0d178b1d1e 4457 int mp_gcd(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 16:8e0d178b1d1e 4458 {
wolfSSL 16:8e0d178b1d1e 4459 return fp_gcd(a, b, c);
wolfSSL 16:8e0d178b1d1e 4460 }
wolfSSL 16:8e0d178b1d1e 4461
wolfSSL 16:8e0d178b1d1e 4462
wolfSSL 16:8e0d178b1d1e 4463 int mp_lcm(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 16:8e0d178b1d1e 4464 {
wolfSSL 16:8e0d178b1d1e 4465 return fp_lcm(a, b, c);
wolfSSL 16:8e0d178b1d1e 4466 }
wolfSSL 16:8e0d178b1d1e 4467
wolfSSL 16:8e0d178b1d1e 4468 int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap)
wolfSSL 16:8e0d178b1d1e 4469 {
wolfSSL 16:8e0d178b1d1e 4470 int err;
wolfSSL 16:8e0d178b1d1e 4471
wolfSSL 16:8e0d178b1d1e 4472 err = fp_randprime(N, len, rng, heap);
wolfSSL 16:8e0d178b1d1e 4473 switch(err) {
wolfSSL 16:8e0d178b1d1e 4474 case FP_VAL:
wolfSSL 16:8e0d178b1d1e 4475 return MP_VAL;
wolfSSL 16:8e0d178b1d1e 4476 case FP_MEM:
wolfSSL 16:8e0d178b1d1e 4477 return MP_MEM;
wolfSSL 16:8e0d178b1d1e 4478 default:
wolfSSL 16:8e0d178b1d1e 4479 break;
wolfSSL 16:8e0d178b1d1e 4480 }
wolfSSL 16:8e0d178b1d1e 4481
wolfSSL 16:8e0d178b1d1e 4482 return MP_OKAY;
wolfSSL 16:8e0d178b1d1e 4483 }
wolfSSL 16:8e0d178b1d1e 4484
wolfSSL 16:8e0d178b1d1e 4485 int mp_exch (mp_int * a, mp_int * b)
wolfSSL 16:8e0d178b1d1e 4486 {
wolfSSL 16:8e0d178b1d1e 4487 return fp_exch(a, b);
wolfSSL 16:8e0d178b1d1e 4488 }
wolfSSL 16:8e0d178b1d1e 4489
wolfSSL 16:8e0d178b1d1e 4490
wolfSSL 15:117db924cf7c 4491
wolfSSL 15:117db924cf7c 4492 int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap)
wolfSSL 15:117db924cf7c 4493 {
wolfSSL 15:117db924cf7c 4494 static const int USE_BBS = 1;
wolfSSL 15:117db924cf7c 4495 int err, type;
wolfSSL 16:8e0d178b1d1e 4496 int isPrime = FP_YES;
wolfSSL 16:8e0d178b1d1e 4497 /* Assume the candidate is probably prime and then test until
wolfSSL 16:8e0d178b1d1e 4498 * it is proven composite. */
wolfSSL 15:117db924cf7c 4499 byte* buf;
wolfSSL 15:117db924cf7c 4500
wolfSSL 16:8e0d178b1d1e 4501 (void)heap;
wolfSSL 16:8e0d178b1d1e 4502
wolfSSL 15:117db924cf7c 4503 /* get type */
wolfSSL 15:117db924cf7c 4504 if (len < 0) {
wolfSSL 15:117db924cf7c 4505 type = USE_BBS;
wolfSSL 15:117db924cf7c 4506 len = -len;
wolfSSL 15:117db924cf7c 4507 } else {
wolfSSL 15:117db924cf7c 4508 type = 0;
wolfSSL 15:117db924cf7c 4509 }
wolfSSL 15:117db924cf7c 4510
wolfSSL 15:117db924cf7c 4511 /* allow sizes between 2 and 512 bytes for a prime size */
wolfSSL 15:117db924cf7c 4512 if (len < 2 || len > 512) {
wolfSSL 15:117db924cf7c 4513 return FP_VAL;
wolfSSL 15:117db924cf7c 4514 }
wolfSSL 15:117db924cf7c 4515
wolfSSL 15:117db924cf7c 4516 /* allocate buffer to work with */
wolfSSL 15:117db924cf7c 4517 buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 15:117db924cf7c 4518 if (buf == NULL) {
wolfSSL 15:117db924cf7c 4519 return FP_MEM;
wolfSSL 15:117db924cf7c 4520 }
wolfSSL 15:117db924cf7c 4521 XMEMSET(buf, 0, len);
wolfSSL 15:117db924cf7c 4522
wolfSSL 15:117db924cf7c 4523 do {
wolfSSL 15:117db924cf7c 4524 #ifdef SHOW_GEN
wolfSSL 15:117db924cf7c 4525 printf(".");
wolfSSL 15:117db924cf7c 4526 fflush(stdout);
wolfSSL 15:117db924cf7c 4527 #endif
wolfSSL 15:117db924cf7c 4528 /* generate value */
wolfSSL 15:117db924cf7c 4529 err = wc_RNG_GenerateBlock(rng, buf, len);
wolfSSL 15:117db924cf7c 4530 if (err != 0) {
wolfSSL 15:117db924cf7c 4531 XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 15:117db924cf7c 4532 return FP_VAL;
wolfSSL 15:117db924cf7c 4533 }
wolfSSL 15:117db924cf7c 4534
wolfSSL 15:117db924cf7c 4535 /* munge bits */
wolfSSL 15:117db924cf7c 4536 buf[0] |= 0x80 | 0x40;
wolfSSL 15:117db924cf7c 4537 buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
wolfSSL 15:117db924cf7c 4538
wolfSSL 15:117db924cf7c 4539 /* load value */
wolfSSL 15:117db924cf7c 4540 fp_read_unsigned_bin(N, buf, len);
wolfSSL 15:117db924cf7c 4541
wolfSSL 15:117db924cf7c 4542 /* test */
wolfSSL 16:8e0d178b1d1e 4543 /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance
wolfSSL 16:8e0d178b1d1e 4544 * of a 1024-bit candidate being a false positive, when it is our
wolfSSL 16:8e0d178b1d1e 4545 * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.)
wolfSSL 16:8e0d178b1d1e 4546 * Using 8 because we've always used 8 */
wolfSSL 16:8e0d178b1d1e 4547 mp_prime_is_prime_ex(N, 8, &isPrime, rng);
wolfSSL 16:8e0d178b1d1e 4548 } while (isPrime == FP_NO);
wolfSSL 15:117db924cf7c 4549
wolfSSL 15:117db924cf7c 4550 XMEMSET(buf, 0, len);
wolfSSL 15:117db924cf7c 4551 XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 15:117db924cf7c 4552
wolfSSL 15:117db924cf7c 4553 return FP_OKAY;
wolfSSL 15:117db924cf7c 4554 }
wolfSSL 15:117db924cf7c 4555
wolfSSL 15:117db924cf7c 4556 /* c = [a, b] */
wolfSSL 16:8e0d178b1d1e 4557 int fp_lcm(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 15:117db924cf7c 4558 {
wolfSSL 16:8e0d178b1d1e 4559 int err;
wolfSSL 16:8e0d178b1d1e 4560 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4561 fp_int t[2];
wolfSSL 16:8e0d178b1d1e 4562 #else
wolfSSL 16:8e0d178b1d1e 4563 fp_int *t;
wolfSSL 16:8e0d178b1d1e 4564 #endif
wolfSSL 16:8e0d178b1d1e 4565
wolfSSL 16:8e0d178b1d1e 4566 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4567 t = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4568 if (t == NULL) {
wolfSSL 16:8e0d178b1d1e 4569 return FP_MEM;
wolfSSL 15:117db924cf7c 4570 }
wolfSSL 16:8e0d178b1d1e 4571 #endif
wolfSSL 16:8e0d178b1d1e 4572
wolfSSL 16:8e0d178b1d1e 4573 fp_init(&t[0]);
wolfSSL 16:8e0d178b1d1e 4574 fp_init(&t[1]);
wolfSSL 16:8e0d178b1d1e 4575 err = fp_gcd(a, b, &t[0]);
wolfSSL 16:8e0d178b1d1e 4576 if (err == FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 4577 if (fp_cmp_mag(a, b) == FP_GT) {
wolfSSL 16:8e0d178b1d1e 4578 err = fp_div(a, &t[0], &t[1], NULL);
wolfSSL 16:8e0d178b1d1e 4579 if (err == FP_OKAY)
wolfSSL 16:8e0d178b1d1e 4580 err = fp_mul(b, &t[1], c);
wolfSSL 16:8e0d178b1d1e 4581 } else {
wolfSSL 16:8e0d178b1d1e 4582 err = fp_div(b, &t[0], &t[1], NULL);
wolfSSL 16:8e0d178b1d1e 4583 if (err == FP_OKAY)
wolfSSL 16:8e0d178b1d1e 4584 err = fp_mul(a, &t[1], c);
wolfSSL 16:8e0d178b1d1e 4585 }
wolfSSL 16:8e0d178b1d1e 4586 }
wolfSSL 16:8e0d178b1d1e 4587
wolfSSL 16:8e0d178b1d1e 4588 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4589 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4590 #endif
wolfSSL 16:8e0d178b1d1e 4591 return err;
wolfSSL 15:117db924cf7c 4592 }
wolfSSL 15:117db924cf7c 4593
wolfSSL 15:117db924cf7c 4594
wolfSSL 15:117db924cf7c 4595
wolfSSL 15:117db924cf7c 4596 /* c = (a, b) */
wolfSSL 16:8e0d178b1d1e 4597 int fp_gcd(fp_int *a, fp_int *b, fp_int *c)
wolfSSL 15:117db924cf7c 4598 {
wolfSSL 16:8e0d178b1d1e 4599 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4600 fp_int u[1], v[1], r[1];
wolfSSL 16:8e0d178b1d1e 4601 #else
wolfSSL 16:8e0d178b1d1e 4602 fp_int *u, *v, *r;
wolfSSL 16:8e0d178b1d1e 4603 #endif
wolfSSL 15:117db924cf7c 4604
wolfSSL 15:117db924cf7c 4605 /* either zero than gcd is the largest */
wolfSSL 15:117db924cf7c 4606 if (fp_iszero (a) == FP_YES && fp_iszero (b) == FP_NO) {
wolfSSL 15:117db924cf7c 4607 fp_abs (b, c);
wolfSSL 16:8e0d178b1d1e 4608 return FP_OKAY;
wolfSSL 15:117db924cf7c 4609 }
wolfSSL 15:117db924cf7c 4610 if (fp_iszero (a) == FP_NO && fp_iszero (b) == FP_YES) {
wolfSSL 15:117db924cf7c 4611 fp_abs (a, c);
wolfSSL 16:8e0d178b1d1e 4612 return FP_OKAY;
wolfSSL 15:117db924cf7c 4613 }
wolfSSL 15:117db924cf7c 4614
wolfSSL 15:117db924cf7c 4615 /* optimized. At this point if a == 0 then
wolfSSL 15:117db924cf7c 4616 * b must equal zero too
wolfSSL 15:117db924cf7c 4617 */
wolfSSL 15:117db924cf7c 4618 if (fp_iszero (a) == FP_YES) {
wolfSSL 15:117db924cf7c 4619 fp_zero(c);
wolfSSL 16:8e0d178b1d1e 4620 return FP_OKAY;
wolfSSL 15:117db924cf7c 4621 }
wolfSSL 15:117db924cf7c 4622
wolfSSL 16:8e0d178b1d1e 4623 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4624 u = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4625 if (u == NULL) {
wolfSSL 16:8e0d178b1d1e 4626 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 4627 }
wolfSSL 16:8e0d178b1d1e 4628 v = &u[1]; r = &u[2];
wolfSSL 16:8e0d178b1d1e 4629 #endif
wolfSSL 16:8e0d178b1d1e 4630
wolfSSL 15:117db924cf7c 4631 /* sort inputs */
wolfSSL 15:117db924cf7c 4632 if (fp_cmp_mag(a, b) != FP_LT) {
wolfSSL 16:8e0d178b1d1e 4633 fp_init_copy(u, a);
wolfSSL 16:8e0d178b1d1e 4634 fp_init_copy(v, b);
wolfSSL 15:117db924cf7c 4635 } else {
wolfSSL 16:8e0d178b1d1e 4636 fp_init_copy(u, b);
wolfSSL 16:8e0d178b1d1e 4637 fp_init_copy(v, a);
wolfSSL 15:117db924cf7c 4638 }
wolfSSL 15:117db924cf7c 4639
wolfSSL 16:8e0d178b1d1e 4640 u->sign = FP_ZPOS;
wolfSSL 16:8e0d178b1d1e 4641 v->sign = FP_ZPOS;
wolfSSL 16:8e0d178b1d1e 4642
wolfSSL 16:8e0d178b1d1e 4643 fp_init(r);
wolfSSL 16:8e0d178b1d1e 4644 while (fp_iszero(v) == FP_NO) {
wolfSSL 16:8e0d178b1d1e 4645 fp_mod(u, v, r);
wolfSSL 16:8e0d178b1d1e 4646 fp_copy(v, u);
wolfSSL 16:8e0d178b1d1e 4647 fp_copy(r, v);
wolfSSL 15:117db924cf7c 4648 }
wolfSSL 16:8e0d178b1d1e 4649 fp_copy(u, c);
wolfSSL 16:8e0d178b1d1e 4650
wolfSSL 16:8e0d178b1d1e 4651 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4652 XFREE(u, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4653 #endif
wolfSSL 16:8e0d178b1d1e 4654 return FP_OKAY;
wolfSSL 15:117db924cf7c 4655 }
wolfSSL 15:117db924cf7c 4656
wolfSSL 15:117db924cf7c 4657 #endif /* WOLFSSL_KEY_GEN */
wolfSSL 15:117db924cf7c 4658
wolfSSL 15:117db924cf7c 4659
wolfSSL 15:117db924cf7c 4660 #if defined(HAVE_ECC) || !defined(NO_PWDBASED) || defined(OPENSSL_EXTRA) || \
wolfSSL 16:8e0d178b1d1e 4661 defined(WC_RSA_BLINDING) || !defined(NO_DSA) || \
wolfSSL 16:8e0d178b1d1e 4662 (!defined(NO_RSA) && !defined(NO_RSA_BOUNDS_CHECK))
wolfSSL 15:117db924cf7c 4663 /* c = a + b */
wolfSSL 15:117db924cf7c 4664 void fp_add_d(fp_int *a, fp_digit b, fp_int *c)
wolfSSL 15:117db924cf7c 4665 {
wolfSSL 16:8e0d178b1d1e 4666 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 15:117db924cf7c 4667 fp_int tmp;
wolfSSL 15:117db924cf7c 4668 fp_init(&tmp);
wolfSSL 15:117db924cf7c 4669 fp_set(&tmp, b);
wolfSSL 15:117db924cf7c 4670 fp_add(a, &tmp, c);
wolfSSL 16:8e0d178b1d1e 4671 #else
wolfSSL 16:8e0d178b1d1e 4672 int i;
wolfSSL 16:8e0d178b1d1e 4673 fp_word t = b;
wolfSSL 16:8e0d178b1d1e 4674
wolfSSL 16:8e0d178b1d1e 4675 fp_copy(a, c);
wolfSSL 16:8e0d178b1d1e 4676 for (i = 0; t != 0 && i < FP_SIZE && i < c->used; i++) {
wolfSSL 16:8e0d178b1d1e 4677 t += c->dp[i];
wolfSSL 16:8e0d178b1d1e 4678 c->dp[i] = (fp_digit)t;
wolfSSL 16:8e0d178b1d1e 4679 t >>= DIGIT_BIT;
wolfSSL 16:8e0d178b1d1e 4680 }
wolfSSL 16:8e0d178b1d1e 4681 if (i == c->used && i < FP_SIZE && t != 0) {
wolfSSL 16:8e0d178b1d1e 4682 c->dp[i] = t;
wolfSSL 16:8e0d178b1d1e 4683 c->used++;
wolfSSL 16:8e0d178b1d1e 4684 }
wolfSSL 16:8e0d178b1d1e 4685 #endif
wolfSSL 15:117db924cf7c 4686 }
wolfSSL 15:117db924cf7c 4687
wolfSSL 15:117db924cf7c 4688 /* external compatibility */
wolfSSL 15:117db924cf7c 4689 int mp_add_d(fp_int *a, fp_digit b, fp_int *c)
wolfSSL 15:117db924cf7c 4690 {
wolfSSL 15:117db924cf7c 4691 fp_add_d(a, b, c);
wolfSSL 15:117db924cf7c 4692 return MP_OKAY;
wolfSSL 15:117db924cf7c 4693 }
wolfSSL 15:117db924cf7c 4694
wolfSSL 16:8e0d178b1d1e 4695 #endif /* HAVE_ECC || !NO_PWDBASED || OPENSSL_EXTRA || WC_RSA_BLINDING ||
wolfSSL 16:8e0d178b1d1e 4696 !NO_DSA || (!NO_RSA && !NO_RSA_BOUNDS_CHECK) */
wolfSSL 15:117db924cf7c 4697
wolfSSL 15:117db924cf7c 4698
wolfSSL 15:117db924cf7c 4699 #if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || \
wolfSSL 15:117db924cf7c 4700 defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) || \
wolfSSL 16:8e0d178b1d1e 4701 defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA) || defined(WC_MP_TO_RADIX)
wolfSSL 15:117db924cf7c 4702
wolfSSL 15:117db924cf7c 4703 /* chars used in radix conversions */
wolfSSL 16:8e0d178b1d1e 4704 static wcchar fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
wolfSSL 15:117db924cf7c 4705 "abcdefghijklmnopqrstuvwxyz+/";
wolfSSL 15:117db924cf7c 4706 #endif
wolfSSL 15:117db924cf7c 4707
wolfSSL 15:117db924cf7c 4708 #if !defined(NO_DSA) || defined(HAVE_ECC)
wolfSSL 15:117db924cf7c 4709 #if DIGIT_BIT == 64 || DIGIT_BIT == 32
wolfSSL 15:117db924cf7c 4710 static int fp_read_radix_16(fp_int *a, const char *str)
wolfSSL 15:117db924cf7c 4711 {
wolfSSL 15:117db924cf7c 4712 int i, j, k, neg;
wolfSSL 15:117db924cf7c 4713 char ch;
wolfSSL 15:117db924cf7c 4714
wolfSSL 15:117db924cf7c 4715 /* if the leading digit is a
wolfSSL 15:117db924cf7c 4716 * minus set the sign to negative.
wolfSSL 15:117db924cf7c 4717 */
wolfSSL 15:117db924cf7c 4718 if (*str == '-') {
wolfSSL 15:117db924cf7c 4719 ++str;
wolfSSL 15:117db924cf7c 4720 neg = FP_NEG;
wolfSSL 15:117db924cf7c 4721 } else {
wolfSSL 15:117db924cf7c 4722 neg = FP_ZPOS;
wolfSSL 15:117db924cf7c 4723 }
wolfSSL 15:117db924cf7c 4724
wolfSSL 15:117db924cf7c 4725 j = 0;
wolfSSL 15:117db924cf7c 4726 k = 0;
wolfSSL 15:117db924cf7c 4727 for (i = (int)(XSTRLEN(str) - 1); i >= 0; i--) {
wolfSSL 15:117db924cf7c 4728 ch = str[i];
wolfSSL 15:117db924cf7c 4729 if (ch >= '0' && ch <= '9')
wolfSSL 15:117db924cf7c 4730 ch -= '0';
wolfSSL 15:117db924cf7c 4731 else if (ch >= 'A' && ch <= 'F')
wolfSSL 15:117db924cf7c 4732 ch -= 'A' - 10;
wolfSSL 15:117db924cf7c 4733 else if (ch >= 'a' && ch <= 'f')
wolfSSL 15:117db924cf7c 4734 ch -= 'a' - 10;
wolfSSL 15:117db924cf7c 4735 else
wolfSSL 15:117db924cf7c 4736 return FP_VAL;
wolfSSL 15:117db924cf7c 4737
wolfSSL 15:117db924cf7c 4738 a->dp[k] |= ((fp_digit)ch) << j;
wolfSSL 15:117db924cf7c 4739 j += 4;
wolfSSL 15:117db924cf7c 4740 k += j == DIGIT_BIT;
wolfSSL 15:117db924cf7c 4741 j &= DIGIT_BIT - 1;
wolfSSL 15:117db924cf7c 4742 }
wolfSSL 15:117db924cf7c 4743
wolfSSL 15:117db924cf7c 4744 a->used = k + 1;
wolfSSL 15:117db924cf7c 4745 fp_clamp(a);
wolfSSL 15:117db924cf7c 4746 /* set the sign only if a != 0 */
wolfSSL 15:117db924cf7c 4747 if (fp_iszero(a) != FP_YES) {
wolfSSL 15:117db924cf7c 4748 a->sign = neg;
wolfSSL 15:117db924cf7c 4749 }
wolfSSL 15:117db924cf7c 4750 return FP_OKAY;
wolfSSL 15:117db924cf7c 4751 }
wolfSSL 15:117db924cf7c 4752 #endif
wolfSSL 15:117db924cf7c 4753
wolfSSL 15:117db924cf7c 4754 static int fp_read_radix(fp_int *a, const char *str, int radix)
wolfSSL 15:117db924cf7c 4755 {
wolfSSL 15:117db924cf7c 4756 int y, neg;
wolfSSL 15:117db924cf7c 4757 char ch;
wolfSSL 15:117db924cf7c 4758
wolfSSL 15:117db924cf7c 4759 /* set the integer to the default of zero */
wolfSSL 15:117db924cf7c 4760 fp_zero (a);
wolfSSL 15:117db924cf7c 4761
wolfSSL 15:117db924cf7c 4762 #if DIGIT_BIT == 64 || DIGIT_BIT == 32
wolfSSL 15:117db924cf7c 4763 if (radix == 16)
wolfSSL 15:117db924cf7c 4764 return fp_read_radix_16(a, str);
wolfSSL 15:117db924cf7c 4765 #endif
wolfSSL 15:117db924cf7c 4766
wolfSSL 15:117db924cf7c 4767 /* make sure the radix is ok */
wolfSSL 15:117db924cf7c 4768 if (radix < 2 || radix > 64) {
wolfSSL 15:117db924cf7c 4769 return FP_VAL;
wolfSSL 15:117db924cf7c 4770 }
wolfSSL 15:117db924cf7c 4771
wolfSSL 15:117db924cf7c 4772 /* if the leading digit is a
wolfSSL 15:117db924cf7c 4773 * minus set the sign to negative.
wolfSSL 15:117db924cf7c 4774 */
wolfSSL 15:117db924cf7c 4775 if (*str == '-') {
wolfSSL 15:117db924cf7c 4776 ++str;
wolfSSL 15:117db924cf7c 4777 neg = FP_NEG;
wolfSSL 15:117db924cf7c 4778 } else {
wolfSSL 15:117db924cf7c 4779 neg = FP_ZPOS;
wolfSSL 15:117db924cf7c 4780 }
wolfSSL 15:117db924cf7c 4781
wolfSSL 15:117db924cf7c 4782 /* process each digit of the string */
wolfSSL 15:117db924cf7c 4783 while (*str) {
wolfSSL 15:117db924cf7c 4784 /* if the radix <= 36 the conversion is case insensitive
wolfSSL 15:117db924cf7c 4785 * this allows numbers like 1AB and 1ab to represent the same value
wolfSSL 15:117db924cf7c 4786 * [e.g. in hex]
wolfSSL 15:117db924cf7c 4787 */
wolfSSL 15:117db924cf7c 4788 ch = (char)((radix <= 36) ? XTOUPPER((unsigned char)*str) : *str);
wolfSSL 15:117db924cf7c 4789 for (y = 0; y < 64; y++) {
wolfSSL 15:117db924cf7c 4790 if (ch == fp_s_rmap[y]) {
wolfSSL 15:117db924cf7c 4791 break;
wolfSSL 15:117db924cf7c 4792 }
wolfSSL 15:117db924cf7c 4793 }
wolfSSL 15:117db924cf7c 4794
wolfSSL 15:117db924cf7c 4795 /* if the char was found in the map
wolfSSL 15:117db924cf7c 4796 * and is less than the given radix add it
wolfSSL 15:117db924cf7c 4797 * to the number, otherwise exit the loop.
wolfSSL 15:117db924cf7c 4798 */
wolfSSL 15:117db924cf7c 4799 if (y < radix) {
wolfSSL 15:117db924cf7c 4800 fp_mul_d (a, (fp_digit) radix, a);
wolfSSL 15:117db924cf7c 4801 fp_add_d (a, (fp_digit) y, a);
wolfSSL 15:117db924cf7c 4802 } else {
wolfSSL 15:117db924cf7c 4803 break;
wolfSSL 15:117db924cf7c 4804 }
wolfSSL 15:117db924cf7c 4805 ++str;
wolfSSL 15:117db924cf7c 4806 }
wolfSSL 15:117db924cf7c 4807
wolfSSL 15:117db924cf7c 4808 /* set the sign only if a != 0 */
wolfSSL 15:117db924cf7c 4809 if (fp_iszero(a) != FP_YES) {
wolfSSL 15:117db924cf7c 4810 a->sign = neg;
wolfSSL 15:117db924cf7c 4811 }
wolfSSL 15:117db924cf7c 4812 return FP_OKAY;
wolfSSL 15:117db924cf7c 4813 }
wolfSSL 15:117db924cf7c 4814
wolfSSL 15:117db924cf7c 4815 /* fast math conversion */
wolfSSL 15:117db924cf7c 4816 int mp_read_radix(mp_int *a, const char *str, int radix)
wolfSSL 15:117db924cf7c 4817 {
wolfSSL 15:117db924cf7c 4818 return fp_read_radix(a, str, radix);
wolfSSL 15:117db924cf7c 4819 }
wolfSSL 15:117db924cf7c 4820
wolfSSL 15:117db924cf7c 4821 #endif /* !defined(NO_DSA) || defined(HAVE_ECC) */
wolfSSL 15:117db924cf7c 4822
wolfSSL 15:117db924cf7c 4823 #ifdef HAVE_ECC
wolfSSL 15:117db924cf7c 4824
wolfSSL 15:117db924cf7c 4825 /* fast math conversion */
wolfSSL 15:117db924cf7c 4826 int mp_sqr(fp_int *A, fp_int *B)
wolfSSL 15:117db924cf7c 4827 {
wolfSSL 16:8e0d178b1d1e 4828 return fp_sqr(A, B);
wolfSSL 15:117db924cf7c 4829 }
wolfSSL 15:117db924cf7c 4830
wolfSSL 15:117db924cf7c 4831 /* fast math conversion */
wolfSSL 15:117db924cf7c 4832 int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp)
wolfSSL 15:117db924cf7c 4833 {
wolfSSL 16:8e0d178b1d1e 4834 return fp_montgomery_reduce(a, m, mp);
wolfSSL 15:117db924cf7c 4835 }
wolfSSL 15:117db924cf7c 4836
wolfSSL 15:117db924cf7c 4837
wolfSSL 15:117db924cf7c 4838 /* fast math conversion */
wolfSSL 15:117db924cf7c 4839 int mp_montgomery_setup(fp_int *a, fp_digit *rho)
wolfSSL 15:117db924cf7c 4840 {
wolfSSL 15:117db924cf7c 4841 return fp_montgomery_setup(a, rho);
wolfSSL 15:117db924cf7c 4842 }
wolfSSL 15:117db924cf7c 4843
wolfSSL 15:117db924cf7c 4844 int mp_div_2(fp_int * a, fp_int * b)
wolfSSL 15:117db924cf7c 4845 {
wolfSSL 15:117db924cf7c 4846 fp_div_2(a, b);
wolfSSL 15:117db924cf7c 4847 return MP_OKAY;
wolfSSL 15:117db924cf7c 4848 }
wolfSSL 15:117db924cf7c 4849
wolfSSL 15:117db924cf7c 4850
wolfSSL 15:117db924cf7c 4851 int mp_init_copy(fp_int * a, fp_int * b)
wolfSSL 15:117db924cf7c 4852 {
wolfSSL 15:117db924cf7c 4853 fp_init_copy(a, b);
wolfSSL 15:117db924cf7c 4854 return MP_OKAY;
wolfSSL 15:117db924cf7c 4855 }
wolfSSL 15:117db924cf7c 4856
wolfSSL 15:117db924cf7c 4857 #ifdef HAVE_COMP_KEY
wolfSSL 15:117db924cf7c 4858
wolfSSL 15:117db924cf7c 4859 int mp_cnt_lsb(fp_int* a)
wolfSSL 15:117db924cf7c 4860 {
wolfSSL 15:117db924cf7c 4861 return fp_cnt_lsb(a);
wolfSSL 15:117db924cf7c 4862 }
wolfSSL 15:117db924cf7c 4863
wolfSSL 15:117db924cf7c 4864 #endif /* HAVE_COMP_KEY */
wolfSSL 15:117db924cf7c 4865
wolfSSL 15:117db924cf7c 4866 #endif /* HAVE_ECC */
wolfSSL 15:117db924cf7c 4867
wolfSSL 16:8e0d178b1d1e 4868 #if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA) || \
wolfSSL 16:8e0d178b1d1e 4869 defined(WOLFSSL_KEY_GEN)
wolfSSL 15:117db924cf7c 4870 /* fast math conversion */
wolfSSL 15:117db924cf7c 4871 int mp_set(fp_int *a, fp_digit b)
wolfSSL 15:117db924cf7c 4872 {
wolfSSL 15:117db924cf7c 4873 fp_set(a,b);
wolfSSL 15:117db924cf7c 4874 return MP_OKAY;
wolfSSL 15:117db924cf7c 4875 }
wolfSSL 15:117db924cf7c 4876 #endif
wolfSSL 15:117db924cf7c 4877
wolfSSL 16:8e0d178b1d1e 4878 #ifdef WC_MP_TO_RADIX
wolfSSL 15:117db924cf7c 4879
wolfSSL 15:117db924cf7c 4880 /* returns size of ASCII representation */
wolfSSL 15:117db924cf7c 4881 int mp_radix_size (mp_int *a, int radix, int *size)
wolfSSL 15:117db924cf7c 4882 {
wolfSSL 16:8e0d178b1d1e 4883 int res, digs;
wolfSSL 15:117db924cf7c 4884 fp_digit d;
wolfSSL 16:8e0d178b1d1e 4885 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4886 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 4887 #else
wolfSSL 16:8e0d178b1d1e 4888 fp_int *t;
wolfSSL 16:8e0d178b1d1e 4889 #endif
wolfSSL 15:117db924cf7c 4890
wolfSSL 15:117db924cf7c 4891 *size = 0;
wolfSSL 15:117db924cf7c 4892
wolfSSL 15:117db924cf7c 4893 /* special case for binary */
wolfSSL 15:117db924cf7c 4894 if (radix == 2) {
wolfSSL 15:117db924cf7c 4895 *size = fp_count_bits (a) + (a->sign == FP_NEG ? 1 : 0) + 1;
wolfSSL 15:117db924cf7c 4896 return FP_YES;
wolfSSL 15:117db924cf7c 4897 }
wolfSSL 15:117db924cf7c 4898
wolfSSL 15:117db924cf7c 4899 /* make sure the radix is in range */
wolfSSL 15:117db924cf7c 4900 if (radix < 2 || radix > 64) {
wolfSSL 15:117db924cf7c 4901 return FP_VAL;
wolfSSL 15:117db924cf7c 4902 }
wolfSSL 15:117db924cf7c 4903
wolfSSL 15:117db924cf7c 4904 if (fp_iszero(a) == MP_YES) {
wolfSSL 15:117db924cf7c 4905 *size = 2;
wolfSSL 15:117db924cf7c 4906 return FP_OKAY;
wolfSSL 15:117db924cf7c 4907 }
wolfSSL 15:117db924cf7c 4908
wolfSSL 15:117db924cf7c 4909 /* digs is the digit count */
wolfSSL 15:117db924cf7c 4910 digs = 0;
wolfSSL 15:117db924cf7c 4911
wolfSSL 15:117db924cf7c 4912 /* if it's negative add one for the sign */
wolfSSL 15:117db924cf7c 4913 if (a->sign == FP_NEG) {
wolfSSL 15:117db924cf7c 4914 ++digs;
wolfSSL 15:117db924cf7c 4915 }
wolfSSL 15:117db924cf7c 4916
wolfSSL 16:8e0d178b1d1e 4917 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4918 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4919 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 4920 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 4921 #endif
wolfSSL 16:8e0d178b1d1e 4922
wolfSSL 15:117db924cf7c 4923 /* init a copy of the input */
wolfSSL 16:8e0d178b1d1e 4924 fp_init_copy (t, a);
wolfSSL 15:117db924cf7c 4925
wolfSSL 15:117db924cf7c 4926 /* force temp to positive */
wolfSSL 16:8e0d178b1d1e 4927 t->sign = FP_ZPOS;
wolfSSL 15:117db924cf7c 4928
wolfSSL 15:117db924cf7c 4929 /* fetch out all of the digits */
wolfSSL 16:8e0d178b1d1e 4930 while (fp_iszero (t) == FP_NO) {
wolfSSL 16:8e0d178b1d1e 4931 if ((res = fp_div_d (t, (mp_digit) radix, t, &d)) != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 4932 fp_zero (t);
wolfSSL 16:8e0d178b1d1e 4933 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4934 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4935 #endif
wolfSSL 15:117db924cf7c 4936 return res;
wolfSSL 15:117db924cf7c 4937 }
wolfSSL 15:117db924cf7c 4938 ++digs;
wolfSSL 15:117db924cf7c 4939 }
wolfSSL 16:8e0d178b1d1e 4940 fp_zero (t);
wolfSSL 15:117db924cf7c 4941
wolfSSL 15:117db924cf7c 4942 /* return digs + 1, the 1 is for the NULL byte that would be required. */
wolfSSL 15:117db924cf7c 4943 *size = digs + 1;
wolfSSL 16:8e0d178b1d1e 4944 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4945 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4946 #endif
wolfSSL 15:117db924cf7c 4947 return FP_OKAY;
wolfSSL 15:117db924cf7c 4948 }
wolfSSL 15:117db924cf7c 4949
wolfSSL 15:117db924cf7c 4950 /* stores a bignum as a ASCII string in a given radix (2..64) */
wolfSSL 15:117db924cf7c 4951 int mp_toradix (mp_int *a, char *str, int radix)
wolfSSL 15:117db924cf7c 4952 {
wolfSSL 16:8e0d178b1d1e 4953 int res, digs;
wolfSSL 15:117db924cf7c 4954 fp_digit d;
wolfSSL 16:8e0d178b1d1e 4955 char *_s = str;
wolfSSL 16:8e0d178b1d1e 4956 #ifndef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4957 fp_int t[1];
wolfSSL 16:8e0d178b1d1e 4958 #else
wolfSSL 16:8e0d178b1d1e 4959 fp_int *t;
wolfSSL 16:8e0d178b1d1e 4960 #endif
wolfSSL 15:117db924cf7c 4961
wolfSSL 15:117db924cf7c 4962 /* check range of the radix */
wolfSSL 15:117db924cf7c 4963 if (radix < 2 || radix > 64) {
wolfSSL 15:117db924cf7c 4964 return FP_VAL;
wolfSSL 15:117db924cf7c 4965 }
wolfSSL 15:117db924cf7c 4966
wolfSSL 15:117db924cf7c 4967 /* quick out if its zero */
wolfSSL 15:117db924cf7c 4968 if (fp_iszero(a) == FP_YES) {
wolfSSL 15:117db924cf7c 4969 *str++ = '0';
wolfSSL 15:117db924cf7c 4970 *str = '\0';
wolfSSL 16:8e0d178b1d1e 4971 return FP_OKAY;
wolfSSL 15:117db924cf7c 4972 }
wolfSSL 15:117db924cf7c 4973
wolfSSL 16:8e0d178b1d1e 4974 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4975 t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4976 if (t == NULL)
wolfSSL 16:8e0d178b1d1e 4977 return FP_MEM;
wolfSSL 16:8e0d178b1d1e 4978 #endif
wolfSSL 16:8e0d178b1d1e 4979
wolfSSL 15:117db924cf7c 4980 /* init a copy of the input */
wolfSSL 16:8e0d178b1d1e 4981 fp_init_copy (t, a);
wolfSSL 15:117db924cf7c 4982
wolfSSL 15:117db924cf7c 4983 /* if it is negative output a - */
wolfSSL 16:8e0d178b1d1e 4984 if (t->sign == FP_NEG) {
wolfSSL 15:117db924cf7c 4985 ++_s;
wolfSSL 15:117db924cf7c 4986 *str++ = '-';
wolfSSL 16:8e0d178b1d1e 4987 t->sign = FP_ZPOS;
wolfSSL 15:117db924cf7c 4988 }
wolfSSL 15:117db924cf7c 4989
wolfSSL 15:117db924cf7c 4990 digs = 0;
wolfSSL 16:8e0d178b1d1e 4991 while (fp_iszero (t) == FP_NO) {
wolfSSL 16:8e0d178b1d1e 4992 if ((res = fp_div_d (t, (fp_digit) radix, t, &d)) != FP_OKAY) {
wolfSSL 16:8e0d178b1d1e 4993 fp_zero (t);
wolfSSL 16:8e0d178b1d1e 4994 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 4995 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 4996 #endif
wolfSSL 15:117db924cf7c 4997 return res;
wolfSSL 15:117db924cf7c 4998 }
wolfSSL 15:117db924cf7c 4999 *str++ = fp_s_rmap[d];
wolfSSL 15:117db924cf7c 5000 ++digs;
wolfSSL 15:117db924cf7c 5001 }
wolfSSL 16:8e0d178b1d1e 5002 #ifndef WC_DISABLE_RADIX_ZERO_PAD
wolfSSL 16:8e0d178b1d1e 5003 /* For hexadecimal output, add zero padding when number of digits is odd */
wolfSSL 16:8e0d178b1d1e 5004 if ((digs & 1) && (radix == 16)) {
wolfSSL 16:8e0d178b1d1e 5005 *str++ = fp_s_rmap[0];
wolfSSL 16:8e0d178b1d1e 5006 ++digs;
wolfSSL 16:8e0d178b1d1e 5007 }
wolfSSL 16:8e0d178b1d1e 5008 #endif
wolfSSL 15:117db924cf7c 5009 /* reverse the digits of the string. In this case _s points
wolfSSL 15:117db924cf7c 5010 * to the first digit [excluding the sign] of the number]
wolfSSL 15:117db924cf7c 5011 */
wolfSSL 15:117db924cf7c 5012 fp_reverse ((unsigned char *)_s, digs);
wolfSSL 15:117db924cf7c 5013
wolfSSL 15:117db924cf7c 5014 /* append a NULL so the string is properly terminated */
wolfSSL 15:117db924cf7c 5015 *str = '\0';
wolfSSL 15:117db924cf7c 5016
wolfSSL 16:8e0d178b1d1e 5017 fp_zero (t);
wolfSSL 16:8e0d178b1d1e 5018 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 16:8e0d178b1d1e 5019 XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
wolfSSL 16:8e0d178b1d1e 5020 #endif
wolfSSL 15:117db924cf7c 5021 return FP_OKAY;
wolfSSL 15:117db924cf7c 5022 }
wolfSSL 15:117db924cf7c 5023
wolfSSL 15:117db924cf7c 5024 #ifdef WOLFSSL_DEBUG_MATH
wolfSSL 15:117db924cf7c 5025 void mp_dump(const char* desc, mp_int* a, byte verbose)
wolfSSL 15:117db924cf7c 5026 {
wolfSSL 15:117db924cf7c 5027 char buffer[FP_SIZE * sizeof(fp_digit) * 2];
wolfSSL 16:8e0d178b1d1e 5028 int size;
wolfSSL 15:117db924cf7c 5029
wolfSSL 15:117db924cf7c 5030 #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
wolfSSL 15:117db924cf7c 5031 size = a->size;
wolfSSL 16:8e0d178b1d1e 5032 #else
wolfSSL 16:8e0d178b1d1e 5033 size = FP_SIZE;
wolfSSL 15:117db924cf7c 5034 #endif
wolfSSL 15:117db924cf7c 5035
wolfSSL 15:117db924cf7c 5036 printf("%s: ptr=%p, used=%d, sign=%d, size=%d, fpd=%d\n",
wolfSSL 15:117db924cf7c 5037 desc, a, a->used, a->sign, size, (int)sizeof(fp_digit));
wolfSSL 15:117db924cf7c 5038
wolfSSL 15:117db924cf7c 5039 mp_tohex(a, buffer);
wolfSSL 15:117db924cf7c 5040 printf(" %s\n ", buffer);
wolfSSL 15:117db924cf7c 5041
wolfSSL 15:117db924cf7c 5042 if (verbose) {
wolfSSL 15:117db924cf7c 5043 int i;
wolfSSL 15:117db924cf7c 5044 for(i=0; i<size * (int)sizeof(fp_digit); i++) {
wolfSSL 15:117db924cf7c 5045 printf("%x ", *(((byte*)a->dp) + i));
wolfSSL 15:117db924cf7c 5046 }
wolfSSL 15:117db924cf7c 5047 printf("\n");
wolfSSL 15:117db924cf7c 5048 }
wolfSSL 15:117db924cf7c 5049 }
wolfSSL 15:117db924cf7c 5050 #endif /* WOLFSSL_DEBUG_MATH */
wolfSSL 15:117db924cf7c 5051
wolfSSL 16:8e0d178b1d1e 5052 #endif /* WC_MP_TO_RADIX */
wolfSSL 15:117db924cf7c 5053
wolfSSL 15:117db924cf7c 5054
wolfSSL 15:117db924cf7c 5055 int mp_abs(mp_int* a, mp_int* b)
wolfSSL 15:117db924cf7c 5056 {
wolfSSL 15:117db924cf7c 5057 fp_abs(a, b);
wolfSSL 15:117db924cf7c 5058 return FP_OKAY;
wolfSSL 15:117db924cf7c 5059 }
wolfSSL 15:117db924cf7c 5060
wolfSSL 15:117db924cf7c 5061
wolfSSL 15:117db924cf7c 5062 int mp_lshd (mp_int * a, int b)
wolfSSL 15:117db924cf7c 5063 {
wolfSSL 15:117db924cf7c 5064 fp_lshd(a, b);
wolfSSL 15:117db924cf7c 5065 return FP_OKAY;
wolfSSL 15:117db924cf7c 5066 }
wolfSSL 15:117db924cf7c 5067
wolfSSL 15:117db924cf7c 5068 #endif /* USE_FAST_MATH */
wolfSSL 15:117db924cf7c 5069