CyaSSL changed for NucleoF401RE board: implemented random and time functions for build. (Has trouble with wildcard domains like *.google.com, *.yahoo.com)

Fork of CyaSSL by wolf SSL

Committer:
Vanger
Date:
Wed Jan 14 22:07:14 2015 +0000
Revision:
4:e505054279ed
Parent:
0:1239e9b70ca2
Implemented some platform specific functions in the Cyassl library code: time functions, seed random functions, and also changed the settings.h file to define settings specific to the platform being used

Who changed what in which revision?

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