summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_recp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bn/bn_recp.c')
-rw-r--r--src/lib/libcrypto/bn/bn_recp.c178
1 files changed, 140 insertions, 38 deletions
diff --git a/src/lib/libcrypto/bn/bn_recp.c b/src/lib/libcrypto/bn/bn_recp.c
index 72cd69d3fc..c1b0e230ea 100644
--- a/src/lib/libcrypto/bn/bn_recp.c
+++ b/src/lib/libcrypto/bn/bn_recp.c
@@ -60,66 +60,168 @@
60#include "cryptlib.h" 60#include "cryptlib.h"
61#include "bn_lcl.h" 61#include "bn_lcl.h"
62 62
63int BN_mod_mul_reciprocal(r, x, y, m, i, nb, ctx) 63void BN_RECP_CTX_init(BN_RECP_CTX *recp)
64BIGNUM *r;
65BIGNUM *x;
66BIGNUM *y;
67BIGNUM *m;
68BIGNUM *i;
69int nb;
70BN_CTX *ctx;
71 { 64 {
72 int ret=0,j; 65 BN_init(&(recp->N));
73 BIGNUM *a,*b,*c,*d; 66 BN_init(&(recp->Nr));
67 recp->num_bits=0;
68 recp->flags=0;
69 }
70
71BN_RECP_CTX *BN_RECP_CTX_new(void)
72 {
73 BN_RECP_CTX *ret;
74
75 if ((ret=(BN_RECP_CTX *)Malloc(sizeof(BN_RECP_CTX))) == NULL)
76 return(NULL);
77
78 BN_RECP_CTX_init(ret);
79 ret->flags=BN_FLG_MALLOCED;
80 return(ret);
81 }
82
83void BN_RECP_CTX_free(BN_RECP_CTX *recp)
84 {
85 if(recp == NULL)
86 return;
74 87
75 a=ctx->bn[ctx->tos++]; 88 BN_free(&(recp->N));
76 b=ctx->bn[ctx->tos++]; 89 BN_free(&(recp->Nr));
77 c=ctx->bn[ctx->tos++]; 90 if (recp->flags & BN_FLG_MALLOCED)
78 d=ctx->bn[ctx->tos++]; 91 Free(recp);
92 }
79 93
80 if (x == y) 94int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx)
81 { if (!BN_sqr(a,x,ctx)) goto err; } 95 {
96 BN_copy(&(recp->N),d);
97 BN_zero(&(recp->Nr));
98 recp->num_bits=BN_num_bits(d);
99 recp->shift=0;
100 return(1);
101 }
102
103int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y, BN_RECP_CTX *recp,
104 BN_CTX *ctx)
105 {
106 int ret=0;
107 BIGNUM *a;
108
109 a= &(ctx->bn[ctx->tos++]);
110 if (y != NULL)
111 {
112 if (x == y)
113 { if (!BN_sqr(a,x,ctx)) goto err; }
114 else
115 { if (!BN_mul(a,x,y,ctx)) goto err; }
116 }
82 else 117 else
83 { if (!BN_mul(a,x,y)) goto err; } 118 a=x; /* Just do the mod */
84 if (!BN_rshift(d,a,nb)) goto err; 119
85 if (!BN_mul(b,d,i)) goto err; 120 BN_div_recp(NULL,r,a,recp,ctx);
86 if (!BN_rshift(c,b,nb)) goto err; 121 ret=1;
87 if (!BN_mul(b,m,c)) goto err; 122err:
88 if (!BN_sub(r,a,b)) goto err; 123 ctx->tos--;
124 return(ret);
125 }
126
127int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BN_RECP_CTX *recp,
128 BN_CTX *ctx)
129 {
130 int i,j,tos,ret=0,ex;
131 BIGNUM *a,*b,*d,*r;
132
133 tos=ctx->tos;
134 a= &(ctx->bn[ctx->tos++]);
135 b= &(ctx->bn[ctx->tos++]);
136 if (dv != NULL)
137 d=dv;
138 else
139 d= &(ctx->bn[ctx->tos++]);
140 if (rem != NULL)
141 r=rem;
142 else
143 r= &(ctx->bn[ctx->tos++]);
144
145 if (BN_ucmp(m,&(recp->N)) < 0)
146 {
147 BN_zero(d);
148 BN_copy(r,m);
149 ctx->tos=tos;
150 return(1);
151 }
152
153 /* We want the remainder
154 * Given input of ABCDEF / ab
155 * we need multiply ABCDEF by 3 digests of the reciprocal of ab
156 *
157 */
158 i=BN_num_bits(m);
159
160 j=recp->num_bits*2;
161 if (j > i)
162 {
163 i=j;
164 ex=0;
165 }
166 else
167 {
168 ex=(i-j)/2;
169 }
170
171 j=i/2;
172
173 if (i != recp->shift)
174 recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N),
175 i,ctx);
176
177 if (!BN_rshift(a,m,j-ex)) goto err;
178 if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err;
179 if (!BN_rshift(d,b,j+ex)) goto err;
180 d->neg=0;
181 if (!BN_mul(b,&(recp->N),d,ctx)) goto err;
182 if (!BN_usub(r,m,b)) goto err;
183 r->neg=0;
184
89 j=0; 185 j=0;
90 while (BN_cmp(r,m) >= 0) 186#if 1
187 while (BN_ucmp(r,&(recp->N)) >= 0)
91 { 188 {
92 if (j++ > 2) 189 if (j++ > 2)
93 { 190 {
94 BNerr(BN_F_BN_MOD_MUL_RECIPROCAL,BN_R_BAD_RECIPROCAL); 191 BNerr(BN_F_BN_MOD_MUL_RECIPROCAL,BN_R_BAD_RECIPROCAL);
95 goto err; 192 goto err;
96 } 193 }
97 if (!BN_sub(r,r,m)) goto err; 194 if (!BN_usub(r,r,&(recp->N))) goto err;
195 if (!BN_add_word(d,1)) goto err;
98 } 196 }
197#endif
99 198
199 r->neg=BN_is_zero(r)?0:m->neg;
200 d->neg=m->neg^recp->N.neg;
100 ret=1; 201 ret=1;
101err: 202err:
102 ctx->tos-=4; 203 ctx->tos=tos;
103 return(ret); 204 return(ret);
104 } 205 }
105 206
106int BN_reciprocal(r, m,ctx) 207/* len is the expected size of the result
107BIGNUM *r; 208 * We actually calculate with an extra word of precision, so
108BIGNUM *m; 209 * we can do faster division if the remainder is not required.
109BN_CTX *ctx; 210 */
211int BN_reciprocal(BIGNUM *r, BIGNUM *m, int len, BN_CTX *ctx)
110 { 212 {
111 int nm,ret= -1; 213 int ret= -1;
112 BIGNUM *t; 214 BIGNUM t;
113 215
114 t=ctx->bn[ctx->tos++]; 216 BN_init(&t);
115 217
116 nm=BN_num_bits(m); 218 BN_zero(&t);
117 if (!BN_lshift(t,BN_value_one(),nm*2)) goto err; 219 if (!BN_set_bit(&t,len)) goto err;
118 220
119 if (!BN_div(r,NULL,t,m,ctx)) goto err; 221 if (!BN_div(r,NULL,&t,m,ctx)) goto err;
120 ret=nm; 222 ret=len;
121err: 223err:
122 ctx->tos--; 224 BN_free(&t);
123 return(ret); 225 return(ret);
124 } 226 }
125 227