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

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

Committer:
wolfSSL
Date:
Tue May 02 08:44:47 2017 +0000
Revision:
7:481bce714567
wolfSSL3.10.2

Who changed what in which revision?

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