void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) { BN_ULONG *rr; #ifdef BN_COUNT printf(" bn_mul_normal %d * %d\n",na,nb); #endif if (na < nb) { int itmp; BN_ULONG *ltmp; itmp=na; na=nb; nb=itmp; ltmp=a; a=b; b=ltmp; } rr= &(r[na]); rr[0]=bn_mul_words(r,a,na,b[0]); for (;;) { if (--nb <= 0) return; rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]); if (--nb <= 0) return; rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]); if (--nb <= 0) return; rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]); if (--nb <= 0) return; rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]); rr+=4; r+=4; b+=4; } }
/* tmp must have 2*n words */ void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp) { int i,j,max; BN_ULONG *ap,*rp; max=n*2; ap=a; rp=r; rp[0]=rp[max-1]=0; rp++; j=n; if (--j > 0) { ap++; rp[j]=bn_mul_words(rp,ap,j,ap[-1]); rp+=2; } for (i=n-2; i>0; i--) { j--; ap++; rp[j]=bn_mul_add_words(rp,ap,j,ap[-1]); rp+=2; } bn_add_words(r,r,r,max); /* There will not be a carry */ bn_sqr_words(tmp,a,n); bn_add_words(r,r,tmp,max); }
void bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, int na, const BN_ULONG *b, int nb) /* const - pcg */ { BN_ULONG *rr; #ifdef BN_COUNT fprintf(stderr, " bn_mul_normal %d * %d\n", na, nb); #endif if (na < nb) { int itmp; const BN_ULONG *ltmp; /* const - pcg */ itmp = na; na = nb; nb = itmp; ltmp = a; a = b; b = ltmp; } rr = &(r[na]); if (nb <= 0) { (void)bn_mul_words(r, a, na, 0); return; } else rr[0] = bn_mul_words(r, a, na, b[0]); for (;;) { if (--nb <= 0) return; rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]); if (--nb <= 0) return; rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]); if (--nb <= 0) return; rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]); if (--nb <= 0) return; rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]); rr += 4; r += 4; b += 4; } }
static void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) { BN_ULONG *rr; if (na < nb) { int itmp; BN_ULONG *ltmp; itmp = na; na = nb; nb = itmp; ltmp = a; a = b; b = ltmp; } rr = &(r[na]); if (nb <= 0) { (void)bn_mul_words(r, a, na, 0); return; } else { rr[0] = bn_mul_words(r, a, na, b[0]); } for (;;) { if (--nb <= 0) { return; } rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]); if (--nb <= 0) { return; } rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]); if (--nb <= 0) { return; } rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]); if (--nb <= 0) { return; } rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]); rr += 4; r += 4; b += 4; } }
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) { bn_mul_words(r,a,n,b[0]); for (;;) { if (--n <= 0) return; bn_mul_add_words(&(r[1]),a,n,b[1]); if (--n <= 0) return; bn_mul_add_words(&(r[2]),a,n,b[2]); if (--n <= 0) return; bn_mul_add_words(&(r[3]),a,n,b[3]); if (--n <= 0) return; bn_mul_add_words(&(r[4]),a,n,b[4]); r+=4; b+=4; } }
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) { #ifdef BN_COUNT fprintf(stderr," bn_mul_low_normal %d * %d\n",n,n); #endif bn_mul_words(r,a,n,b[0]); for (;;) { if (--n <= 0) return; bn_mul_add_words(&(r[1]),a,n,b[1]); if (--n <= 0) return; bn_mul_add_words(&(r[2]),a,n,b[2]); if (--n <= 0) return; bn_mul_add_words(&(r[3]),a,n,b[3]); if (--n <= 0) return; bn_mul_add_words(&(r[4]),a,n,b[4]); r+=4; b+=4; } }
static void bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, size_t na, const BN_ULONG *b, size_t nb) { if (na < nb) { size_t itmp = na; na = nb; nb = itmp; const BN_ULONG *ltmp = a; a = b; b = ltmp; } BN_ULONG *rr = &(r[na]); if (nb == 0) { OPENSSL_memset(r, 0, na * sizeof(BN_ULONG)); return; } rr[0] = bn_mul_words(r, a, na, b[0]); for (;;) { if (--nb == 0) { return; } rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]); if (--nb == 0) { return; } rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]); if (--nb == 0) { return; } rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]); if (--nb == 0) { return; } rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]); rr += 4; r += 4; b += 4; } }
// tmp must have 2*n words static void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, size_t n, BN_ULONG *tmp) { if (n == 0) { return; } size_t max = n * 2; const BN_ULONG *ap = a; BN_ULONG *rp = r; rp[0] = rp[max - 1] = 0; rp++; // Compute the contribution of a[i] * a[j] for all i < j. if (n > 1) { ap++; rp[n - 1] = bn_mul_words(rp, ap, n - 1, ap[-1]); rp += 2; } if (n > 2) { for (size_t i = n - 2; i > 0; i--) { ap++; rp[i] = bn_mul_add_words(rp, ap, i, ap[-1]); rp += 2; } } // The final result fits in |max| words, so none of the following operations // will overflow. // Double |r|, giving the contribution of a[i] * a[j] for all i != j. bn_add_words(r, r, r, max); // Add in the contribution of a[i] * a[i] for all i. bn_sqr_words(tmp, a, n); bn_add_words(r, r, tmp, max); }
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) { BIGNUM *n; BN_ULONG *ap, *np, *rp, n0, v, carry; int nl, max, i; n = &(mont->N); nl = n->top; if (nl == 0) { ret->top = 0; return (1); } max = (2 * nl); /* carry is stored separately */ if (bn_wexpand(r, max) == NULL) return (0); r->neg ^= n->neg; np = n->d; rp = r->d; /* clear the top words of T */ #if 1 for (i=r->top; i<max; i++) /* memset? XXX */ rp[i] = 0; #else memset(&(rp[r->top]), 0, (max - r->top) * sizeof(BN_ULONG)); #endif r->top = max; n0 = mont->n0[0]; #ifdef BN_COUNT fprintf(stderr, "word BN_from_montgomery_word %d * %d\n", nl, nl); #endif for (carry = 0, i = 0; i < nl; i++, rp++) { v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); v = (v + carry + rp[nl]) & BN_MASK2; carry |= (v != rp[nl]); carry &= (v <= rp[nl]); rp[nl] = v; } if (bn_wexpand(ret, nl) == NULL) return (0); ret->top = nl; ret->neg = r->neg; rp = ret->d; ap = &(r->d[nl]); #define BRANCH_FREE 1 #if BRANCH_FREE { BN_ULONG *nrp; size_t m; v = bn_sub_words(rp, ap, np, nl) - carry; /* if subtraction result is real, then * trick unconditional memcpy below to perform in-place * "refresh" instead of actual copy. */ m = (0 - (size_t)v); nrp = (BN_ULONG *)(((uintptr_t)rp & ~m)|((uintptr_t)ap & m)); for (i = 0, nl -= 4; i < nl; i += 4) { BN_ULONG t1, t2, t3, t4; t1 = nrp[i + 0]; t2 = nrp[i + 1]; t3 = nrp[i + 2]; ap[i + 0] = 0; t4 = nrp[i + 3]; ap[i + 1] = 0; rp[i + 0] = t1; ap[i + 2] = 0; rp[i + 1] = t2; ap[i + 3] = 0; rp[i + 2] = t3; rp[i + 3] = t4; } for (nl += 4; i < nl; i++) rp[i] = nrp[i], ap[i] = 0; } #else if (bn_sub_words (rp, ap, np, nl) - carry) memcpy(rp, ap, nl*sizeof(BN_ULONG)); #endif bn_correct_top(r); bn_correct_top(ret); bn_check_top(ret); return (1); }
int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) { int retn=0; #ifdef MONT_WORD BIGNUM *n,*r; BN_ULONG *ap,*np,*rp,n0,v,*nrp; int al,nl,max,i,x,ri; BN_CTX_start(ctx); if ((r = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_copy(r,a)) goto err; n= &(mont->N); ap=a->d; /* mont->ri is the size of mont->N in bits (rounded up to the word size) */ al=ri=mont->ri/BN_BITS2; 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 err; r->neg=a->neg^n->neg; np=n->d; rp=r->d; nrp= &(r->d[nl]); /* clear the top words of T */ #if 1 for (i=r->top; i<max; i++) /* memset? XXX */ r->d[i]=0; #else memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); #endif r->top=max; n0=mont->n0; #ifdef BN_COUNT fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl); #endif for (i=0; i<nl; i++) { #ifdef __TANDEM { long long t1; long long t2; long long t3; t1 = rp[0] * (n0 & 0177777); t2 = 037777600000l; t2 = n0 & t2; t3 = rp[0] & 0177777; t2 = (t3 * t2) & BN_MASK2; t1 = t1 + t2; v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1); } #else v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); #endif nrp++; rp++; if (((nrp[-1]+=v)&BN_MASK2) >= v) continue; else { if (((++nrp[0])&BN_MASK2) != 0) continue; if (((++nrp[1])&BN_MASK2) != 0) continue; for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; } } bn_correct_top(r); /* mont->ri will be a multiple of the word size and below code * is kind of BN_rshift(ret,r,mont->ri) equivalent */ if (r->top <= ri) { ret->top=0; retn=1; goto err; } al=r->top-ri; # define BRANCH_FREE 1 # if BRANCH_FREE if (bn_wexpand(ret,ri) == NULL) goto err; x=0-(((al-ri)>>(sizeof(al)*8-1))&1); ret->top=x=(ri&~x)|(al&x); /* min(ri,al) */ ret->neg=r->neg; rp=ret->d; ap=&(r->d[ri]); { size_t m1,m2; v=bn_sub_words(rp,ap,np,ri); /* this ----------------^^ works even in al<ri case * thanks to zealous zeroing of top of the vector in the * beginning. */ /* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */ /* in other words if subtraction result is real, then * trick unconditional memcpy below to perform in-place * "refresh" instead of actual copy. */ m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1); /* al<ri */ m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1); /* al>ri */ m1|=m2; /* (al!=ri) */ m1|=(0-(size_t)v); /* (al!=ri || v) */ m1&=~m2; /* (al!=ri || v) && !al>ri */ nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1)); } /* 'i<ri' is chosen to eliminate dependency on input data, even * though it results in redundant copy in al<ri case. */ for (i=0,ri-=4; i<ri; i+=4) { BN_ULONG t1,t2,t3,t4; t1=nrp[i+0]; t2=nrp[i+1]; t3=nrp[i+2]; ap[i+0]=0; t4=nrp[i+3]; ap[i+1]=0; rp[i+0]=t1; ap[i+2]=0; rp[i+1]=t2; ap[i+3]=0; rp[i+2]=t3; rp[i+3]=t4; } for (ri+=4; i<ri; i++) rp[i]=nrp[i], ap[i]=0; bn_correct_top(r); bn_correct_top(ret); # else if (bn_wexpand(ret,al) == NULL) goto err; ret->top=al; ret->neg=r->neg; rp=ret->d; ap=&(r->d[ri]); al-=4; for (i=0; i<al; i+=4) { BN_ULONG t1,t2,t3,t4; t1=ap[i+0]; t2=ap[i+1]; t3=ap[i+2]; t4=ap[i+3]; rp[i+0]=t1; rp[i+1]=t2; rp[i+2]=t3; rp[i+3]=t4; } al+=4; for (; i<al; i++) rp[i]=ap[i]; # endif #else /* !MONT_WORD */ BIGNUM *t1,*t2; BN_CTX_start(ctx); t1 = BN_CTX_get(ctx); t2 = BN_CTX_get(ctx); if (t1 == NULL || t2 == NULL) goto err; if (!BN_copy(t1,a)) goto err; BN_mask_bits(t1,mont->ri); if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err; BN_mask_bits(t2,mont->ri); if (!BN_mul(t1,t2,&mont->N,ctx)) goto err; if (!BN_add(t2,a,t1)) goto err; if (!BN_rshift(ret,t2,mont->ri)) goto err; #endif /* MONT_WORD */ #if !defined(BRANCH_FREE) || BRANCH_FREE==0 if (BN_ucmp(ret, &(mont->N)) >= 0) { if (!BN_usub(ret,ret,&(mont->N))) goto err; } #endif retn=1; bn_check_top(ret); err: BN_CTX_end(ctx); return(retn); }
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont) { BN_ULONG *ap, *np, *rp, n0, v, carry; int nl, max, i; const BIGNUM *n = &mont->N; nl = n->top; if (nl == 0) { ret->top = 0; return 1; } max = (2 * nl); /* carry is stored separately */ if (bn_wexpand(r, max) == NULL) { return 0; } r->neg ^= n->neg; np = n->d; rp = r->d; /* clear the top words of T */ if (max > r->top) { memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG)); } r->top = max; n0 = mont->n0[0]; for (carry = 0, i = 0; i < nl; i++, rp++) { v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); v = (v + carry + rp[nl]) & BN_MASK2; carry |= (v != rp[nl]); carry &= (v <= rp[nl]); rp[nl] = v; } if (bn_wexpand(ret, nl) == NULL) { return 0; } ret->top = nl; ret->neg = r->neg; rp = ret->d; ap = &(r->d[nl]); { BN_ULONG *nrp; uintptr_t m; v = bn_sub_words(rp, ap, np, nl) - carry; /* if subtraction result is real, then trick unconditional memcpy below to * perform in-place "refresh" instead of actual copy. */ m = (0u - (uintptr_t)v); nrp = (BN_ULONG *)(((uintptr_t)rp & ~m) | ((uintptr_t)ap & m)); for (i = 0, nl -= 4; i < nl; i += 4) { BN_ULONG t1, t2, t3, t4; t1 = nrp[i + 0]; t2 = nrp[i + 1]; t3 = nrp[i + 2]; ap[i + 0] = 0; t4 = nrp[i + 3]; ap[i + 1] = 0; rp[i + 0] = t1; ap[i + 2] = 0; rp[i + 1] = t2; ap[i + 3] = 0; rp[i + 2] = t3; rp[i + 3] = t4; } for (nl += 4; i < nl; i++) { rp[i] = nrp[i], ap[i] = 0; } } bn_correct_top(r); bn_correct_top(ret); return 1; }
int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) { int retn=0; #ifdef MONT_WORD BIGNUM *n,*r; BN_ULONG *ap,*np,*rp,n0,v,*nrp; int al,nl,max,i,x,ri; BN_CTX_start(ctx); if ((r = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_copy(r,a)) goto err; n= &(mont->N); ap=a->d; /* mont->ri is the size of mont->N in bits (rounded up to the word size) */ al=ri=mont->ri/BN_BITS2; 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 err; if (bn_wexpand(ret,max) == NULL) goto err; r->neg=a->neg^n->neg; np=n->d; rp=r->d; nrp= &(r->d[nl]); /* clear the top words of T */ #if 1 for (i=r->top; i<max; i++) /* memset? XXX */ r->d[i]=0; #else memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); #endif r->top=max; n0=mont->n0; #ifdef BN_COUNT fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl); #endif for (i=0; i<nl; i++) { #ifdef __TANDEM { long long t1; long long t2; long long t3; t1 = rp[0] * (n0 & 0177777); t2 = 037777600000l; t2 = n0 & t2; t3 = rp[0] & 0177777; t2 = (t3 * t2) & BN_MASK2; t1 = t1 + t2; v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1); } #else v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); #endif nrp++; rp++; if (((nrp[-1]+=v)&BN_MASK2) >= v) continue; else { if (((++nrp[0])&BN_MASK2) != 0) continue; if (((++nrp[1])&BN_MASK2) != 0) continue; for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; } } bn_fix_top(r); /* mont->ri will be a multiple of the word size */ #if 0 BN_rshift(ret,r,mont->ri); #else ret->neg = r->neg; x=ri; rp=ret->d; ap= &(r->d[x]); if (r->top < x) al=0; else al=r->top-x; ret->top=al; al-=4; for (i=0; i<al; i+=4) { BN_ULONG t1,t2,t3,t4; t1=ap[i+0]; t2=ap[i+1]; t3=ap[i+2]; t4=ap[i+3]; rp[i+0]=t1; rp[i+1]=t2; rp[i+2]=t3; rp[i+3]=t4; } al+=4; for (; i<al; i++) rp[i]=ap[i]; #endif #else /* !MONT_WORD */ BIGNUM *t1,*t2; BN_CTX_start(ctx); t1 = BN_CTX_get(ctx); t2 = BN_CTX_get(ctx); if (t1 == NULL || t2 == NULL) goto err; if (!BN_copy(t1,a)) goto err; BN_mask_bits(t1,mont->ri); if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err; BN_mask_bits(t2,mont->ri); if (!BN_mul(t1,t2,&mont->N,ctx)) goto err; if (!BN_add(t2,a,t1)) goto err; if (!BN_rshift(ret,t2,mont->ri)) goto err; #endif /* MONT_WORD */ if (BN_ucmp(ret, &(mont->N)) >= 0) { if (!BN_usub(ret,ret,&(mont->N))) goto err; } retn=1; err: BN_CTX_end(ctx); return(retn); }
int BN_from_montgomery(BIGNUM *ret, BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) { int retn=0; BIGNUM *n,*r; BN_ULONG *ap,*np,*rp,n0,v,*nrp; int al,nl,max,i,x,ri; BN_CTX_start(ctx); if ((r = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_copy(r,a)) goto err; n= &(mont->N); ap=a->d; /* mont->ri is the size of mont->N in bits (rounded up to the word size) */ al=ri=mont->ri/BN_BITS2; 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 err; if (bn_wexpand(ret,max) == NULL) goto err; 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; i<max; i++) /* memset? XXX */ r->d[i]=0; r->top=max; n0=mont->n0; for (i=0; i<nl; i++) { v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); nrp++; rp++; if (((nrp[-1]+=v)&BN_MASK2) >= v) continue; else { if (((++nrp[0])&BN_MASK2) != 0) continue; if (((++nrp[1])&BN_MASK2) != 0) continue; for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; } } bn_fix_top(r); /* mont->ri will be a multiple of the word size */ ret->neg = r->neg; x=ri; rp=ret->d; ap= &(r->d[x]); if (r->top < x) al=0; else al=r->top-x; ret->top=al; al-=4; for (i=0; i<al; i+=4) { BN_ULONG t1,t2,t3,t4; t1=ap[i+0]; t2=ap[i+1]; t3=ap[i+2]; t4=ap[i+3]; rp[i+0]=t1; rp[i+1]=t2; rp[i+2]=t3; rp[i+3]=t4; } al+=4; for (; i<al; i++) rp[i]=ap[i]; if (BN_ucmp(ret, &(mont->N)) >= 0) { BN_usub(ret,ret,&(mont->N)); } retn=1; err: BN_CTX_end(ctx); return(retn); }
static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) { BIGNUM *n; BN_ULONG *ap, *np, *rp, n0, v, carry; int nl, max, i; n = &(mont->N); nl = n->top; if (nl == 0) { ret->top = 0; return (1); } max = (2 * nl); /* carry is stored separately */ if (bn_wexpand(r, max) == NULL) return (0); r->neg ^= n->neg; np = n->d; rp = r->d; /* clear the top words of T */ i = max - r->top; if (i) memset(&rp[r->top], 0, sizeof(*rp) * i); r->top = max; r->flags |= BN_FLG_FIXED_TOP; n0 = mont->n0[0]; /* * Add multiples of |n| to |r| until R = 2^(nl * BN_BITS2) divides it. On * input, we had |r| < |n| * R, so now |r| < 2 * |n| * R. Note that |r| * includes |carry| which is stored separately. */ for (carry = 0, i = 0; i < nl; i++, rp++) { v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); v = (v + carry + rp[nl]) & BN_MASK2; carry |= (v != rp[nl]); carry &= (v <= rp[nl]); rp[nl] = v; } if (bn_wexpand(ret, nl) == NULL) return (0); ret->top = nl; ret->flags |= BN_FLG_FIXED_TOP; ret->neg = r->neg; rp = ret->d; /* * Shift |nl| words to divide by R. We have |ap| < 2 * |n|. Note that |ap| * includes |carry| which is stored separately. */ ap = &(r->d[nl]); carry -= bn_sub_words(rp, ap, np, nl); /* * |carry| is -1 if |ap| - |np| underflowed or zero if it did not. Note * |carry| cannot be 1. That would imply the subtraction did not fit in * |nl| words, and we know at most one subtraction is needed. */ for (i = 0; i < nl; i++) { rp[i] = (carry & ap[i]) | (~carry & rp[i]); ap[i] = 0; } return (1); }