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