OpenSSL
1.0.1c
Main Page
Classes
Files
File List
File Members
All
Classes
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
crypto
bn
bn_recp.c
Go to the documentation of this file.
1
/* crypto/bn/bn_recp.c */
2
/* Copyright (C) 1995-1998 Eric Young (
[email protected]
)
3
* All rights reserved.
4
*
5
* This package is an SSL implementation written
6
* by Eric Young (
[email protected]
).
7
* The implementation was written so as to conform with Netscapes SSL.
8
*
9
* This library is free for commercial and non-commercial use as long as
10
* the following conditions are aheared to. The following conditions
11
* apply to all code found in this distribution, be it the RC4, RSA,
12
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
13
* included with this distribution is covered by the same copyright terms
14
* except that the holder is Tim Hudson (
[email protected]
).
15
*
16
* Copyright remains Eric Young's, and as such any Copyright notices in
17
* the code are not to be removed.
18
* If this package is used in a product, Eric Young should be given attribution
19
* as the author of the parts of the library used.
20
* This can be in the form of a textual message at program startup or
21
* in documentation (online or textual) provided with the package.
22
*
23
* Redistribution and use in source and binary forms, with or without
24
* modification, are permitted provided that the following conditions
25
* are met:
26
* 1. Redistributions of source code must retain the copyright
27
* notice, this list of conditions and the following disclaimer.
28
* 2. Redistributions in binary form must reproduce the above copyright
29
* notice, this list of conditions and the following disclaimer in the
30
* documentation and/or other materials provided with the distribution.
31
* 3. All advertising materials mentioning features or use of this software
32
* must display the following acknowledgement:
33
* "This product includes cryptographic software written by
34
* Eric Young (
[email protected]
)"
35
* The word 'cryptographic' can be left out if the rouines from the library
36
* being used are not cryptographic related :-).
37
* 4. If you include any Windows specific code (or a derivative thereof) from
38
* the apps directory (application code) you must include an acknowledgement:
39
* "This product includes software written by Tim Hudson (
[email protected]
)"
40
*
41
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
* SUCH DAMAGE.
52
*
53
* The licence and distribution terms for any publically available version or
54
* derivative of this code cannot be changed. i.e. this code cannot simply be
55
* copied and put under another distribution licence
56
* [including the GNU Public Licence.]
57
*/
58
59
#include <stdio.h>
60
#include "
cryptlib.h
"
61
#include "
bn_lcl.h
"
62
63
void
BN_RECP_CTX_init
(
BN_RECP_CTX
*recp)
64
{
65
BN_init
(&(recp->
N
));
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
*)
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
83
void
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
}
93
94
int
BN_RECP_CTX_set
(
BN_RECP_CTX
*recp,
const
BIGNUM
*d,
BN_CTX
*ctx)
95
{
96
if
(!
BN_copy
(&(recp->
N
),d))
return
0;
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,
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;
109
110
BN_CTX_start
(ctx);
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
}
120
else
121
ca=x;
/* Just do the mod */
122
123
ret =
BN_div_recp
(NULL,r,ca,recp,ctx);
124
err:
125
BN_CTX_end
(ctx);
126
bn_check_top
(r);
127
return
(ret);
128
}
129
130
int
BN_div_recp
(
BIGNUM
*dv,
BIGNUM
*rem,
const
BIGNUM
*m,
131
BN_RECP_CTX
*recp,
BN_CTX
*ctx)
132
{
133
int
i,j,ret=0;
134
BIGNUM
*
a
,*
b
,*d,*r;
135
136
BN_CTX_start
(ctx);
137
a=
BN_CTX_get
(ctx);
138
b=
BN_CTX_get
(ctx);
139
if
(dv != NULL)
140
d=dv;
141
else
142
d=
BN_CTX_get
(ctx);
143
if
(rem != NULL)
144
r=rem;
145
else
146
r=
BN_CTX_get
(ctx);
147
if
(a == NULL || b == NULL || d == NULL || r == NULL)
goto
err;
148
149
if
(
BN_ucmp
(m,&(recp->
N
)) < 0)
150
{
151
BN_zero
(d);
152
if
(!
BN_copy
(r,m))
return
0;
153
BN_CTX_end
(ctx);
154
return
(1);
155
}
156
157
/* We want the remainder
158
* Given input of ABCDEF / ab
159
* we need multiply ABCDEF by 3 digests of the reciprocal of ab
160
*
161
*/
162
163
/* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */
164
i=
BN_num_bits
(m);
165
j=recp->
num_bits
<<1;
166
if
(j>i) i=j;
167
168
/* Nr := round(2^i / N) */
169
if
(i != recp->
shift
)
170
recp->
shift
=
BN_reciprocal
(&(recp->
Nr
),&(recp->
N
),
171
i,ctx);
/* BN_reciprocal returns i, or -1 for an error */
172
if
(recp->
shift
== -1)
goto
err;
173
174
/* d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))|
175
* = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))|
176
* <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)|
177
* = |m/N|
178
*/
179
if
(!
BN_rshift
(a,m,recp->
num_bits
))
goto
err;
180
if
(!
BN_mul
(b,a,&(recp->
Nr
),ctx))
goto
err;
181
if
(!
BN_rshift
(d,b,i-recp->
num_bits
))
goto
err;
182
d->
neg
=0;
183
184
if
(!
BN_mul
(b,&(recp->
N
),d,ctx))
goto
err;
185
if
(!
BN_usub
(r,m,b))
goto
err;
186
r->
neg
=0;
187
188
#if 1
189
j=0;
190
while
(
BN_ucmp
(r,&(recp->
N
)) >= 0)
191
{
192
if
(j++ > 2)
193
{
194
BNerr
(
BN_F_BN_DIV_RECP
,
BN_R_BAD_RECIPROCAL
);
195
goto
err;
196
}
197
if
(!
BN_usub
(r,r,&(recp->
N
)))
goto
err;
198
if
(!
BN_add_word
(d,1))
goto
err;
199
}
200
#endif
201
202
r->
neg
=
BN_is_zero
(r)?0:m->
neg
;
203
d->
neg
=m->
neg
^recp->
N
.
neg
;
204
ret=1;
205
err:
206
BN_CTX_end
(ctx);
207
bn_check_top
(dv);
208
bn_check_top
(rem);
209
return
(ret);
210
}
211
212
/* len is the expected size of the result
213
* We actually calculate with an extra word of precision, so
214
* we can do faster division if the remainder is not required.
215
*/
216
/* r := 2^len / m */
217
int
BN_reciprocal
(
BIGNUM
*r,
const
BIGNUM
*m,
int
len
,
BN_CTX
*ctx)
218
{
219
int
ret= -1;
220
BIGNUM
*
t
;
221
222
BN_CTX_start
(ctx);
223
if
((t =
BN_CTX_get
(ctx)) == NULL)
goto
err;
224
225
if
(!
BN_set_bit
(t,len))
goto
err;
226
227
if
(!
BN_div
(r,NULL,t,m,ctx))
goto
err;
228
229
ret=
len
;
230
err:
231
bn_check_top
(r);
232
BN_CTX_end
(ctx);
233
return
(ret);
234
}
Generated on Thu Jan 10 2013 09:53:34 for OpenSSL by
1.8.2