1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay (at) cryptsoft.com). 6 * The implementation was written so as to conform with Netscapes SSL. 7 * 8 * This library is free for commercial and non-commercial use as long as 9 * the following conditions are aheared to. The following conditions 10 * apply to all code found in this distribution, be it the RC4, RSA, 11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12 * included with this distribution is covered by the same copyright terms 13 * except that the holder is Tim Hudson (tjh (at) cryptsoft.com). 14 * 15 * Copyright remains Eric Young's, and as such any Copyright notices in 16 * the code are not to be removed. 17 * If this package is used in a product, Eric Young should be given attribution 18 * as the author of the parts of the library used. 19 * This can be in the form of a textual message at program startup or 20 * in documentation (online or textual) provided with the package. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * "This product includes cryptographic software written by 33 * Eric Young (eay (at) cryptsoft.com)" 34 * The word 'cryptographic' can be left out if the rouines from the library 35 * being used are not cryptographic related :-). 36 * 4. If you include any Windows specific code (or a derivative thereof) from 37 * the apps directory (application code) you must include an acknowledgement: 38 * "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * 52 * The licence and distribution terms for any publically available version or 53 * derivative of this code cannot be changed. i.e. this code cannot simply be 54 * copied and put under another distribution licence 55 * [including the GNU Public Licence.] 56 */ 57 /* ==================================================================== 58 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 59 * 60 * Redistribution and use in source and binary forms, with or without 61 * modification, are permitted provided that the following conditions 62 * are met: 63 * 64 * 1. Redistributions of source code must retain the above copyright 65 * notice, this list of conditions and the following disclaimer. 66 * 67 * 2. Redistributions in binary form must reproduce the above copyright 68 * notice, this list of conditions and the following disclaimer in 69 * the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3. All advertising materials mentioning features or use of this 73 * software must display the following acknowledgment: 74 * "This product includes software developed by the OpenSSL Project 75 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 76 * 77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 78 * endorse or promote products derived from this software without 79 * prior written permission. For written permission, please contact 80 * openssl-core (at) openssl.org. 81 * 82 * 5. Products derived from this software may not be called "OpenSSL" 83 * nor may "OpenSSL" appear in their names without prior written 84 * permission of the OpenSSL Project. 85 * 86 * 6. Redistributions of any form whatsoever must retain the following 87 * acknowledgment: 88 * "This product includes software developed by the OpenSSL Project 89 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 90 * 91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 94 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 102 * OF THE POSSIBILITY OF SUCH DAMAGE. 103 * ==================================================================== 104 * 105 * This product includes cryptographic software written by Eric Young 106 * (eay (at) cryptsoft.com). This product includes software written by Tim 107 * Hudson (tjh (at) cryptsoft.com). */ 108 109 #include <openssl/bn.h> 110 111 #include <openssl/mem.h> 112 #include <openssl/thread.h> 113 114 #include "internal.h" 115 116 117 #if !defined(OPENSSL_NO_ASM) && \ 118 (defined(OPENSSL_X86) || defined(OPENSSL_X86_64)) 119 #define OPENSSL_BN_ASM_MONT 120 #endif 121 122 BN_MONT_CTX *BN_MONT_CTX_new(void) { 123 BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX)); 124 125 if (ret == NULL) { 126 return NULL; 127 } 128 129 BN_MONT_CTX_init(ret); 130 ret->flags = BN_FLG_MALLOCED; 131 return ret; 132 } 133 134 void BN_MONT_CTX_init(BN_MONT_CTX *mont) { 135 memset(mont, 0, sizeof(BN_MONT_CTX)); 136 BN_init(&mont->RR); 137 BN_init(&mont->N); 138 BN_init(&mont->Ni); 139 } 140 141 void BN_MONT_CTX_free(BN_MONT_CTX *mont) { 142 if (mont == NULL) { 143 return; 144 } 145 146 BN_free(&mont->RR); 147 BN_free(&mont->N); 148 BN_free(&mont->Ni); 149 if (mont->flags & BN_FLG_MALLOCED) { 150 OPENSSL_free(mont); 151 } 152 } 153 154 BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) { 155 if (to == from) { 156 return to; 157 } 158 159 if (!BN_copy(&to->RR, &from->RR) || 160 !BN_copy(&to->N, &from->N) || 161 !BN_copy(&to->Ni, &from->Ni)) { 162 return NULL; 163 } 164 to->ri = from->ri; 165 to->n0[0] = from->n0[0]; 166 to->n0[1] = from->n0[1]; 167 return to; 168 } 169 170 int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { 171 int ret = 0; 172 BIGNUM *Ri, *R; 173 BIGNUM tmod; 174 BN_ULONG buf[2]; 175 176 BN_CTX_start(ctx); 177 Ri = BN_CTX_get(ctx); 178 if (Ri == NULL) { 179 goto err; 180 } 181 R = &mont->RR; /* grab RR as a temp */ 182 if (!BN_copy(&mont->N, mod)) { 183 goto err; /* Set N */ 184 } 185 mont->N.neg = 0; 186 187 BN_init(&tmod); 188 tmod.d = buf; 189 tmod.dmax = 2; 190 tmod.neg = 0; 191 192 mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; 193 194 #if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32) 195 /* Only certain BN_BITS2<=32 platforms actually make use of 196 * n0[1], and we could use the #else case (with a shorter R 197 * value) for the others. However, currently only the assembler 198 * files do know which is which. */ 199 200 BN_zero(R); 201 if (!BN_set_bit(R, 2 * BN_BITS2)) { 202 goto err; 203 } 204 205 tmod.top = 0; 206 if ((buf[0] = mod->d[0])) { 207 tmod.top = 1; 208 } 209 if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) { 210 tmod.top = 2; 211 } 212 213 if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) { 214 goto err; 215 } 216 if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) { 217 goto err; /* R*Ri */ 218 } 219 if (!BN_is_zero(Ri)) { 220 if (!BN_sub_word(Ri, 1)) { 221 goto err; 222 } 223 } else { 224 /* if N mod word size == 1 */ 225 if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) { 226 goto err; 227 } 228 /* Ri-- (mod double word size) */ 229 Ri->neg = 0; 230 Ri->d[0] = BN_MASK2; 231 Ri->d[1] = BN_MASK2; 232 Ri->top = 2; 233 } 234 235 if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) { 236 goto err; 237 } 238 /* Ni = (R*Ri-1)/N, 239 * keep only couple of least significant words: */ 240 mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; 241 mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0; 242 #else 243 BN_zero(R); 244 if (!BN_set_bit(R, BN_BITS2)) { 245 goto err; /* R */ 246 } 247 248 buf[0] = mod->d[0]; /* tmod = N mod word size */ 249 buf[1] = 0; 250 tmod.top = buf[0] != 0 ? 1 : 0; 251 /* Ri = R^-1 mod N*/ 252 if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) { 253 goto err; 254 } 255 if (!BN_lshift(Ri, Ri, BN_BITS2)) { 256 goto err; /* R*Ri */ 257 } 258 if (!BN_is_zero(Ri)) { 259 if (!BN_sub_word(Ri, 1)) { 260 goto err; 261 } 262 } else { 263 /* if N mod word size == 1 */ 264 if (!BN_set_word(Ri, BN_MASK2)) { 265 goto err; /* Ri-- (mod word size) */ 266 } 267 } 268 if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) { 269 goto err; 270 } 271 /* Ni = (R*Ri-1)/N, 272 * keep only least significant word: */ 273 mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; 274 mont->n0[1] = 0; 275 #endif 276 277 /* setup RR for conversions */ 278 BN_zero(&(mont->RR)); 279 if (!BN_set_bit(&(mont->RR), mont->ri * 2)) { 280 goto err; 281 } 282 if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) { 283 goto err; 284 } 285 286 ret = 1; 287 288 err: 289 BN_CTX_end(ctx); 290 return ret; 291 } 292 293 BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock, 294 const BIGNUM *mod, BN_CTX *ctx) { 295 BN_MONT_CTX *ret; 296 297 CRYPTO_r_lock(lock); 298 ret = *pmont; 299 CRYPTO_r_unlock(lock); 300 if (ret) { 301 return ret; 302 } 303 304 /* We don't want to serialise globally while doing our lazy-init math in 305 * BN_MONT_CTX_set. That punishes threads that are doing independent 306 * things. Instead, punish the case where more than one thread tries to 307 * lazy-init the same 'pmont', by having each do the lazy-init math work 308 * independently and only use the one from the thread that wins the race 309 * (the losers throw away the work they've done). */ 310 ret = BN_MONT_CTX_new(); 311 if (!ret) { 312 return NULL; 313 } 314 if (!BN_MONT_CTX_set(ret, mod, ctx)) { 315 BN_MONT_CTX_free(ret); 316 return NULL; 317 } 318 319 /* The locked compare-and-set, after the local work is done. */ 320 CRYPTO_w_lock(lock); 321 if (*pmont) { 322 BN_MONT_CTX_free(ret); 323 ret = *pmont; 324 } else { 325 *pmont = ret; 326 } 327 328 CRYPTO_w_unlock(lock); 329 330 return ret; 331 } 332 333 int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont, 334 BN_CTX *ctx) { 335 return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx); 336 } 337 338 #if 0 339 static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, 340 const BN_MONT_CTX *mont) { 341 const BIGNUM *n; 342 BN_ULONG *ap, *np, *rp, n0, v, carry; 343 int nl, max, i; 344 345 n = &mont->N; 346 nl = n->top; 347 if (nl == 0) { 348 ret->top = 0; 349 return 1; 350 } 351 352 max = (2 * nl); /* carry is stored separately */ 353 if (bn_wexpand(r, max) == NULL) { 354 return 0; 355 } 356 357 r->neg ^= n->neg; 358 np = n->d; 359 rp = r->d; 360 361 /* clear the top words of T */ 362 if (max > r->top) { 363 memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG)); 364 } 365 366 r->top = max; 367 n0 = mont->n0[0]; 368 369 for (carry = 0, i = 0; i < nl; i++, rp++) { 370 v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); 371 v = (v + carry + rp[nl]) & BN_MASK2; 372 carry |= (v != rp[nl]); 373 carry &= (v <= rp[nl]); 374 rp[nl] = v; 375 } 376 377 if (bn_wexpand(ret, nl) == NULL) { 378 return 0; 379 } 380 ret->top = nl; 381 ret->neg = r->neg; 382 383 rp = ret->d; 384 ap = &(r->d[nl]); 385 386 { 387 BN_ULONG *nrp; 388 size_t m; 389 390 v = bn_sub_words(rp, ap, np, nl) - carry; 391 /* if subtraction result is real, then trick unconditional memcpy below to 392 * perform in-place "refresh" instead of actual copy. */ 393 m = (0 - (size_t)v); 394 nrp = (BN_ULONG *)(((intptr_t)rp & ~m) | ((intptr_t)ap & m)); 395 396 for (i = 0, nl -= 4; i < nl; i += 4) { 397 BN_ULONG t1, t2, t3, t4; 398 399 t1 = nrp[i + 0]; 400 t2 = nrp[i + 1]; 401 t3 = nrp[i + 2]; 402 ap[i + 0] = 0; 403 t4 = nrp[i + 3]; 404 ap[i + 1] = 0; 405 rp[i + 0] = t1; 406 ap[i + 2] = 0; 407 rp[i + 1] = t2; 408 ap[i + 3] = 0; 409 rp[i + 2] = t3; 410 rp[i + 3] = t4; 411 } 412 413 for (nl += 4; i < nl; i++) { 414 rp[i] = nrp[i], ap[i] = 0; 415 } 416 } 417 418 bn_correct_top(r); 419 bn_correct_top(ret); 420 421 return 1; 422 } 423 #endif 424 425 #define PTR_SIZE_INT size_t 426 427 static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont) 428 { 429 BIGNUM *n; 430 BN_ULONG *ap,*np,*rp,n0,v,carry; 431 int nl,max,i; 432 433 n= (BIGNUM*) &(mont->N); 434 nl=n->top; 435 if (nl == 0) { ret->top=0; return(1); } 436 437 max=(2*nl); /* carry is stored separately */ 438 if (bn_wexpand(r,max) == NULL) return(0); 439 440 r->neg^=n->neg; 441 np=n->d; 442 rp=r->d; 443 444 /* clear the top words of T */ 445 #if 1 446 for (i=r->top; i<max; i++) /* memset? XXX */ 447 rp[i]=0; 448 #else 449 memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 450 #endif 451 452 r->top=max; 453 n0=mont->n0[0]; 454 455 for (carry=0, i=0; i<nl; i++, rp++) 456 { 457 v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); 458 v = (v+carry+rp[nl])&BN_MASK2; 459 carry |= (v != rp[nl]); 460 carry &= (v <= rp[nl]); 461 rp[nl]=v; 462 } 463 464 if (bn_wexpand(ret,nl) == NULL) return(0); 465 ret->top=nl; 466 ret->neg=r->neg; 467 468 rp=ret->d; 469 ap=&(r->d[nl]); 470 471 { 472 BN_ULONG *nrp; 473 size_t m; 474 475 v=bn_sub_words(rp,ap,np,nl)-carry; 476 /* if subtraction result is real, then 477 * trick unconditional memcpy below to perform in-place 478 * "refresh" instead of actual copy. */ 479 m=(0-(size_t)v); 480 nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m)); 481 482 for (i=0,nl-=4; i<nl; i+=4) 483 { 484 BN_ULONG t1,t2,t3,t4; 485 486 t1=nrp[i+0]; 487 t2=nrp[i+1]; 488 t3=nrp[i+2]; ap[i+0]=0; 489 t4=nrp[i+3]; ap[i+1]=0; 490 rp[i+0]=t1; ap[i+2]=0; 491 rp[i+1]=t2; ap[i+3]=0; 492 rp[i+2]=t3; 493 rp[i+3]=t4; 494 } 495 for (nl+=4; i<nl; i++) 496 rp[i]=nrp[i], ap[i]=0; 497 } 498 bn_correct_top(r); 499 bn_correct_top(ret); 500 501 return(1); 502 } 503 504 int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont, 505 BN_CTX *ctx) { 506 int retn = 0; 507 BIGNUM *t; 508 509 BN_CTX_start(ctx); 510 t = BN_CTX_get(ctx); 511 if (t == NULL) { 512 return 0; 513 } 514 515 if (BN_copy(t, a)) 516 retn = BN_from_montgomery_word(ret, t, mont); 517 BN_CTX_end(ctx); 518 519 return retn; 520 } 521 522 int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, 523 const BN_MONT_CTX *mont, BN_CTX *ctx) { 524 BIGNUM *tmp; 525 int ret = 0; 526 527 #if defined(OPENSSL_BN_ASM_MONT) 528 int num = mont->N.top; 529 530 if (num > 1 && a->top == num && b->top == num) { 531 if (bn_wexpand(r, num) == NULL) { 532 return 0; 533 } 534 if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { 535 r->neg = a->neg ^ b->neg; 536 r->top = num; 537 bn_correct_top(r); 538 return 1; 539 } 540 } 541 #endif 542 543 BN_CTX_start(ctx); 544 tmp = BN_CTX_get(ctx); 545 if (tmp == NULL) { 546 goto err; 547 } 548 549 if (a == b) { 550 if (!BN_sqr(tmp, a, ctx)) { 551 goto err; 552 } 553 } else { 554 if (!BN_mul(tmp, a, b, ctx)) { 555 goto err; 556 } 557 } 558 559 /* reduce from aRR to aR */ 560 if (!BN_from_montgomery_word(r, tmp, mont)) { 561 goto err; 562 } 563 564 ret = 1; 565 566 err: 567 BN_CTX_end(ctx); 568 return ret; 569 } 570