This is a port of cyaSSL 2.7.0.

Dependents:   CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet

Committer:
ashleymills
Date:
Thu Sep 05 10:33:04 2013 +0000
Revision:
0:714293de3836
Initial commit

Who changed what in which revision?

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