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

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

Committer:
wolfSSL
Date:
Fri Jun 26 00:39:20 2015 +0000
Revision:
0:d92f9d21154c
wolfSSL 3.6.0

Who changed what in which revision?

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