diff options
Diffstat (limited to 'src/lib/libcrypto/bn/bn_recp.c')
-rw-r--r-- | src/lib/libcrypto/bn/bn_recp.c | 178 |
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 | ||
63 | int BN_mod_mul_reciprocal(r, x, y, m, i, nb, ctx) | 63 | void BN_RECP_CTX_init(BN_RECP_CTX *recp) |
64 | BIGNUM *r; | ||
65 | BIGNUM *x; | ||
66 | BIGNUM *y; | ||
67 | BIGNUM *m; | ||
68 | BIGNUM *i; | ||
69 | int nb; | ||
70 | BN_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 | |||
71 | BN_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 | |||
83 | void 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) | 94 | int 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 | |||
103 | int 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; | 122 | err: |
88 | if (!BN_sub(r,a,b)) goto err; | 123 | ctx->tos--; |
124 | return(ret); | ||
125 | } | ||
126 | |||
127 | int 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; |
101 | err: | 202 | err: |
102 | ctx->tos-=4; | 203 | ctx->tos=tos; |
103 | return(ret); | 204 | return(ret); |
104 | } | 205 | } |
105 | 206 | ||
106 | int BN_reciprocal(r, m,ctx) | 207 | /* len is the expected size of the result |
107 | BIGNUM *r; | 208 | * We actually calculate with an extra word of precision, so |
108 | BIGNUM *m; | 209 | * we can do faster division if the remainder is not required. |
109 | BN_CTX *ctx; | 210 | */ |
211 | int 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; |
121 | err: | 223 | err: |
122 | ctx->tos--; | 224 | BN_free(&t); |
123 | return(ret); | 225 | return(ret); |
124 | } | 226 | } |
125 | 227 | ||