2 * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
23 /* I've done some timing with different table sizes.
24 * The main hassle is that even with bits set at 3, this requires
25 * 63 BIGNUMs to store the pre-calculated values.
30 * The lack of speed improvement is also a function of the pre-calculation
31 * which could be removed.
33 #define EXP2_TABLE_BITS 2 /* 1 2 3 4 5 */
34 #define EXP2_TABLE_SIZE 4 /* 2 4 8 16 32 */
36 int BN_mod_exp2_mont(BIGNUM
*rr
, BIGNUM
*a1
, BIGNUM
*p1
, BIGNUM
*a2
,
37 BIGNUM
*p2
, BIGNUM
*m
, BN_CTX
*ctx
, BN_MONT_CTX
*in_mont
)
39 int i
,j
,k
,bits
,bits1
,bits2
,ret
=0,wstart
,wend
,window
,xvalue
,yvalue
;
41 BIGNUM
*d
,*aa1
,*aa2
,*r
;
42 BIGNUM val
[EXP2_TABLE_SIZE
][EXP2_TABLE_SIZE
];
43 BN_MONT_CTX
*mont
=NULL
;
53 BNerr(BN_F_BN_MOD_EXP_MONT
,BN_R_CALLED_WITH_EVEN_MODULUS
);
56 bits1
=BN_num_bits(p1
);
57 bits2
=BN_num_bits(p2
);
58 if ((bits1
== 0) && (bits2
== 0))
67 if (d
== NULL
|| r
== NULL
) goto err
;
69 bits
=(bits1
> bits2
)?bits1
:bits2
;
71 /* If this is not done, things will break in the montgomery
78 if ((mont
=BN_MONT_CTX_new()) == NULL
) goto err
;
79 if (!BN_MONT_CTX_set(mont
,m
,ctx
)) goto err
;
82 BN_init(&(val
[0][0]));
83 BN_init(&(val
[1][1]));
84 BN_init(&(val
[0][1]));
85 BN_init(&(val
[1][0]));
87 if (BN_ucmp(a1
,m
) >= 0)
89 BN_mod(&(val
[1][0]),a1
,m
,ctx
);
94 if (BN_ucmp(a2
,m
) >= 0)
96 BN_mod(&(val
[0][1]),a2
,m
,ctx
);
101 if (!BN_to_montgomery(&(val
[1][0]),aa1
,mont
,ctx
)) goto err
;
102 if (!BN_to_montgomery(&(val
[0][1]),aa2
,mont
,ctx
)) goto err
;
103 if (!BN_mod_mul_montgomery(&(val
[1][1]),
104 &(val
[1][0]),&(val
[0][1]),mont
,ctx
))
108 if (bits
<= 20) /* This is probably 3 or 0x10001, so just do singles */
111 window
=5; /* max size of window */
112 else if (bits
>= 120)
117 window
=EXP2_TABLE_BITS
;
125 BN_init(&(val
[x
][0]));
126 BN_init(&(val
[x
][1]));
127 if (!BN_mod_mul_montgomery(&(val
[x
][0]),
128 &(val
[1][0]),&(val
[x
-1][0]),mont
,ctx
)) goto err
;
129 if (!BN_mod_mul_montgomery(&(val
[x
][1]),
130 &(val
[1][0]),&(val
[x
-1][1]),mont
,ctx
)) goto err
;
134 BN_init(&(val
[x
][y
]));
135 if (!BN_mod_mul_montgomery(&(val
[x
][y
]),
136 &(val
[x
][y
-1]),&(val
[0][1]),mont
,ctx
))
142 start
=1; /* This is used to avoid multiplication etc
143 * when there is only the value '1' in the
145 xvalue
=0; /* The 'x value' of the window */
146 yvalue
=0; /* The 'y value' of the window */
147 wstart
=bits
-1; /* The top bit of the window */
148 wend
=0; /* The bottom bit of the window */
150 if (!BN_to_montgomery(r
,BN_value_one(),mont
,ctx
)) goto err
;
153 xvalue
=BN_is_bit_set(p1
,wstart
);
154 yvalue
=BN_is_bit_set(p2
,wstart
);
155 if (!(xvalue
|| yvalue
))
159 if (!BN_mod_mul_montgomery(r
,r
,r
,mont
,ctx
))
163 if (wstart
< 0) break;
166 /* We now have wstart on a 'set' bit, we now need to work out
167 * how bit a window to do. To do this we need to scan
168 * forward until the last set bit before the end of the
171 /* xvalue=BN_is_bit_set(p1,wstart); already set */
172 /* yvalue=BN_is_bit_set(p1,wstart); already set */
174 for (i
=1; i
<window
; i
++)
176 if (wstart
-i
< 0) break;
178 xvalue
|=BN_is_bit_set(p1
,wstart
-i
);
180 yvalue
|=BN_is_bit_set(p2
,wstart
-i
);
183 /* i is the size of the current window */
184 /* add the 'bytes above' */
188 if (!BN_mod_mul_montgomery(r
,r
,r
,mont
,ctx
))
192 /* wvalue will be an odd number < 2^window */
193 if (xvalue
|| yvalue
)
195 if (!BN_mod_mul_montgomery(r
,r
,&(val
[xvalue
][yvalue
]),
199 /* move the 'window' down further */
202 if (wstart
< 0) break;
204 BN_from_montgomery(rr
,r
,mont
,ctx
);
207 if ((in_mont
== NULL
) && (mont
!= NULL
)) BN_MONT_CTX_free(mont
);
213 BN_clear_free(&(val
[i
][j
]));