Xuyi Wang / wolfSSL

Dependents:   OS

Committer:
sPymbed
Date:
Tue Nov 19 14:32:16 2019 +0000
Revision:
16:048e5e270a58
Parent:
15:117db924cf7c
working ssl

Who changed what in which revision?

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