/* $Id$ */ /* * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. * * This work contains proprietary information of RSA Security. * Distribution is limited to authorized licensees of RSA * Security. Any unauthorized reproduction, distribution or * modification of this work is strictly prohibited. * */ #undef BN_DEBUG #include "bn_lcl.h" #if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) #ifdef NO_SPLIT #define SPLIT_BN_MOD_MUL_MONTGOMERY #define SPLIT_BN_FROM_MONTGOMERY #define SPLIT_BN_MONT_CTX_NEW #define SPLIT_BN_MONT_CTX_INIT #define SPLIT_BN_MONT_CTX_FREE #define SPLIT_BN_MONT_CTX_COPY #endif /* NO_SPLIT */ /* #define DEBUG */ #ifdef SPLIT_BN_MOD_MUL_MONTGOMERY /* We multiply a by b, generating a number 2n words long. * This is then reduced by the montogmery number, which is * n words. */ int BN_mod_mul_montgomery(r,a,b,mont,ctx) BIGNUM *r,*a,*b; BN_MONT_CTX *mont; BN_CTX *ctx; { BIGNUM *tmp,*tmp2; int ret=0,w; int i; bn_check_top(a); bn_check_top(b); w=mont->riw; tmp= &(ctx->bn[ctx->tos++]); tmp2= &(ctx->bn[ctx->tos++]); bn_check_top(tmp); bn_check_top(tmp2); if (bn_wexpand(tmp,w+w) == NULL) goto err; if (bn_wexpand(r,w+w) == NULL) goto err; if (a == b) { if (bn_wexpand(tmp2,w+w) == NULL) goto err; #ifdef BN_SQR_COMBA if ((a->top == 8) && (a->top == b->top)) bn_sqr_comba8(tmp->d,a->d); else #endif { bn_sqr_normal(tmp->d,a->d,a->top,tmp2->d); } } else { #ifdef BN_MUL_COMBA if (a->top == 8) bn_mul_comba8(tmp->d,a->d,b->d); else #endif { bn_mul_normal(tmp->d,a->d,a->top,b->d,b->top); } } i=a->top+b->top; while (i<(w+w)) { tmp->d[i]=0; i++; } tmp->top=w+w; tmp->neg=0; /* reduce from aRR to aR */ /* tmp->d is 2w words */ #if 0 bn_fix_top(tmp); BN_from_montgomery_words(r,tmp,mont,ctx); #else bn_from_montgomery_words(r->d,tmp->d,mont->N.d,w,mont->n0); #endif r->top=w; r->neg=0; bn_fix_top(r); ret=1; err: ctx->tos-=2; return(ret); } #endif #ifdef SPLIT_BN_FROM_MONTGOMERY int BN_from_montgomery(ret,a,mont,ctx) BIGNUM *ret; BIGNUM *a; BN_MONT_CTX *mont; BN_CTX *ctx; { BIGNUM *n,*r; BN_ULONG *np,*rp,n0,v0,v1,*nrp; int al,nl,max,i; int retn=0; bn_check_top(a); r= &(ctx->bn[ctx->tos]); if (!BN_copy(r,a)) goto err1; n= &(mont->N); /* mont->riw is the size of mont->N in bits/words */ al=mont->riw; nl=n->top; if ((al == 0) || (nl == 0)) { r->top=0; return(1); } max=(nl+al+1); /* allow for overflow (no?) XXX */ if (bn_wexpand(r,max) == NULL) goto err1; if (bn_wexpand(ret,max) == NULL) goto err1; r->neg=a->neg^n->neg; np=n->d; rp=r->d; nrp= &(r->d[nl]); /* clear the top words of T */ for (i=r->top; id[i]=0; r->top=max; n0=mont->n0; v1=0; for (i=0; iriw will be a multiple of the word size */ (void)BN_rshift(ret,r,mont->riw*BN_BITS2); if (BN_ucmp(ret, &(mont->N)) >= 0) { (void)BN_usub(ret,ret,&(mont->N)); /* XXX */ } retn=1; err1: return(retn); } #endif #ifdef SPLIT_BN_MONT_CTX_NEW BN_MONT_CTX *BN_MONT_CTX_new() { BN_MONT_CTX *ret; if ((ret=(BN_MONT_CTX *)Malloc(sizeof(BN_MONT_CTX))) == NULL) return(NULL); BN_MONT_CTX_init(ret); ret->flags=BN_FLG_MALLOCED; return(ret); } #endif #ifdef SPLIT_BN_MONT_CTX_INIT void BN_MONT_CTX_init(ctx) BN_MONT_CTX *ctx; { ctx->use_word=0; ctx->riw=0; BN_init(&(ctx->RR)); BN_init(&(ctx->N)); BN_init(&(ctx->Ni)); ctx->flags=0; } #endif #ifdef SPLIT_BN_MONT_CTX_FREE void BN_MONT_CTX_free(mont) BN_MONT_CTX *mont; { BN_free(&(mont->RR)); BN_free(&(mont->N)); BN_free(&(mont->Ni)); if (mont->flags & BN_FLG_MALLOCED) Free(mont); } #endif #ifdef SPLIT_BN_MONT_CTX_COPY BN_MONT_CTX *BN_MONT_CTX_copy(to, from) BN_MONT_CTX *to, *from; { if (to == from) return(to); (void)BN_copy(&(to->RR),&(from->RR)); (void)BN_copy(&(to->N),&(from->N)); (void)BN_copy(&(to->Ni),&(from->Ni)); bn_zexpand(&(to->RR),from->riw); bn_zexpand(&(to->Ni),from->riw); to->use_word=from->use_word; to->riw=from->riw; to->n0=from->n0; return(to); } #endif #endif