2 * Copyright (c) 2000-2001 Apple Computer, 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.
19 /* crypto/bn/bn_exp.c */
20 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
21 * All rights reserved.
23 * This package is an SSL implementation written
24 * by Eric Young (eay@cryptsoft.com).
25 * The implementation was written so as to conform with Netscapes SSL.
27 * This library is free for commercial and non-commercial use as long as
28 * the following conditions are aheared to. The following conditions
29 * apply to all code found in this distribution, be it the RC4, RSA,
30 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
31 * included with this distribution is covered by the same copyright terms
32 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
34 * Copyright remains Eric Young's, and as such any Copyright notices in
35 * the code are not to be removed.
36 * If this package is used in a product, Eric Young should be given attribution
37 * as the author of the parts of the library used.
38 * This can be in the form of a textual message at program startup or
39 * in documentation (online or textual) provided with the package.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * "This product includes cryptographic software written by
52 * Eric Young (eay@cryptsoft.com)"
53 * The word 'cryptographic' can be left out if the rouines from the library
54 * being used are not cryptographic related :-).
55 * 4. If you include any Windows specific code (or a derivative thereof) from
56 * the apps directory (application code) you must include an acknowledgement:
57 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
59 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * The licence and distribution terms for any publically available version or
72 * derivative of this code cannot be changed. i.e. this code cannot simply be
73 * copied and put under another distribution licence
74 * [including the GNU Public Licence.]
90 int BN_mod_mul(BIGNUM
*ret
, BIGNUM
*a
, BIGNUM
*b
, const BIGNUM
*m
, BN_CTX
*ctx
)
100 if ((t
= BN_CTX_get(ctx
)) == NULL
) goto err
;
102 { if (!BN_sqr(t
,a
,ctx
)) goto err
; }
104 { if (!BN_mul(t
,a
,b
,ctx
)) goto err
; }
105 if (!BN_mod(ret
,t
,m
,ctx
)) goto err
;
113 /* this one works - simple but works */
114 int BN_mod_exp(BIGNUM
*r
, BIGNUM
*a
, BIGNUM
*p
, BIGNUM
*m
, BN_CTX
*ctx
)
121 tmp
= BN_CTX_get(ctx
);
122 if (v
== NULL
|| tmp
== NULL
) goto err
;
124 if (BN_copy(v
,a
) == NULL
) goto err
;
128 { if (BN_copy(r
,a
) == NULL
) goto err
; }
129 else { if (!BN_one(r
)) goto err
; }
131 for (i
=1; i
<bits
; i
++)
133 if (!BN_sqr(tmp
,v
,ctx
)) goto err
;
134 if (!BN_mod(v
,tmp
,m
,ctx
)) goto err
;
135 if (BN_is_bit_set(p
,i
))
137 if (!BN_mul(tmp
,r
,v
,ctx
)) goto err
;
138 if (!BN_mod(r
,tmp
,m
,ctx
)) goto err
;
149 /* this one works - simple but works */
150 int BN_exp(BIGNUM
*r
, BIGNUM
*a
, BIGNUM
*p
, BN_CTX
*ctx
)
156 if ((r
== a
) || (r
== p
))
157 rr
= BN_CTX_get(ctx
);
160 if ((v
= BN_CTX_get(ctx
)) == NULL
) goto err
;
162 if (BN_copy(v
,a
) == NULL
) goto err
;
166 { if (BN_copy(rr
,a
) == NULL
) goto err
; }
167 else { if (!BN_one(rr
)) goto err
; }
169 for (i
=1; i
<bits
; i
++)
171 if (!BN_sqr(v
,v
,ctx
)) goto err
;
172 if (BN_is_bit_set(p
,i
))
174 if (!BN_mul(rr
,rr
,v
,ctx
)) goto err
;
179 if (r
!= rr
) BN_copy(r
,rr
);
187 * This routine will dynamically check for the existance of an Atalla AXL-200
188 * SSL accelerator module. If one is found, the variable
189 * asi_accelerator_present is set to 1 and the function pointers
190 * ptr_ASI_xxxxxx above will be initialized to corresponding ASI API calls.
192 typedef int tfnASI_GetPerformanceStatistics(int reset_flag
,
193 unsigned int *ret_buf
);
194 typedef int tfnASI_GetHardwareConfig(long card_num
, unsigned int *ret_buf
);
195 typedef int tfnASI_RSAPrivateKeyOpFn(RSAPrivateKey
* rsaKey
,
196 unsigned char *output
,
197 unsigned char *input
,
198 unsigned int modulus_len
);
200 static tfnASI_GetHardwareConfig
*ptr_ASI_GetHardwareConfig
;
201 static tfnASI_RSAPrivateKeyOpFn
*ptr_ASI_RSAPrivateKeyOpFn
;
202 static tfnASI_GetPerformanceStatistics
*ptr_ASI_GetPerformanceStatistics
;
203 static int asi_accelerator_present
;
204 static int tried_atalla
;
206 void atalla_initialize_accelerator_handle(void)
210 unsigned int config_buf
[1024];
218 bzero((void *)config_buf
, 1024);
221 * Check to see if the library is present on the system
223 dl_handle
= dlopen("atasi.so", RTLD_NOW
);
224 if (dl_handle
== (void *) NULL
)
226 /* printf("atasi.so library is not present on the system\n");
227 printf("No HW acceleration available\n");*/
232 * The library is present. Now we'll check to insure that the
233 * LDM is up and running. First we'll get the address of the
234 * function in the atasi library that we need to see if the
238 ptr_ASI_GetHardwareConfig
=
239 (tfnASI_GetHardwareConfig
*)dlsym(dl_handle
,"ASI_GetHardwareConfig");
241 if (ptr_ASI_GetHardwareConfig
)
244 * We found the call, now we'll get our config
245 * status. If we get a non 0 result, the LDM is not
246 * running and we cannot use the Atalla ASI *
249 status
= (*ptr_ASI_GetHardwareConfig
)(0L, config_buf
);
252 printf("atasi.so library is present but not initialized\n");
253 printf("No HW acceleration available\n");
259 /* printf("We found the library, but not the function. Very Strange!\n");*/
264 * It looks like we have acceleration capabilities. Load up the
265 * pointers to our ASI API calls.
267 ptr_ASI_RSAPrivateKeyOpFn
=
268 (tfnASI_RSAPrivateKeyOpFn
*)dlsym(dl_handle
, "ASI_RSAPrivateKeyOpFn");
269 if (ptr_ASI_RSAPrivateKeyOpFn
== NULL
)
271 /* printf("We found the library, but no RSA function. Very Strange!\n");*/
275 ptr_ASI_GetPerformanceStatistics
=
276 (tfnASI_GetPerformanceStatistics
*)dlsym(dl_handle
, "ASI_GetPerformanceStatistics");
277 if (ptr_ASI_GetPerformanceStatistics
== NULL
)
279 /* printf("We found the library, but no stat function. Very Strange!\n");*/
284 * Indicate that acceleration is available
286 asi_accelerator_present
= 1;
288 /* printf("This system has acceleration!\n");*/
293 /* make sure this only gets called once when bn_mod_exp calls bn_mod_exp_mont */
294 int BN_mod_exp_atalla(BIGNUM
*r
, BIGNUM
*a
, const BIGNUM
*p
, const BIGNUM
*m
)
301 RSAPrivateKey keydata
;
303 atalla_initialize_accelerator_handle();
304 if(!asi_accelerator_present
)
308 /* We should be able to run without size testing */
314 if(an
<= ASIZE
&& pn
<= ASIZE
&& mn
<= ASIZE
)
320 memset(abin
,'\0',mn
);
321 BN_bn2bin(a
,abin
+size
-an
);
327 memset(mbin
,'\0',mn
);
328 BN_bn2bin(m
,mbin
+size
-mn
);
332 memset(&keydata
,'\0',sizeof keydata
);
333 keydata
.privateExponent
.data
=pbin
;
334 keydata
.privateExponent
.len
=pn
;
335 keydata
.modulus
.data
=mbin
;
336 keydata
.modulus
.len
=size
;
338 ret
=(*ptr_ASI_RSAPrivateKeyOpFn
)(&keydata
,rbin
,abin
,keydata
.modulus
.len
);
339 /*fprintf(stderr,"!%s\n",BN_bn2hex(a));*/
342 BN_bin2bn(rbin
,keydata
.modulus
.len
,r
);
343 /*fprintf(stderr,"?%s\n",BN_bn2hex(r));*/
349 #endif /* def ATALLA */
351 int BN_mod_exp(BIGNUM
*r
, BIGNUM
*a
, const BIGNUM
*p
, const BIGNUM
*m
,
361 if(BN_mod_exp_atalla(r
,a
,p
,m
))
363 /* If it fails, try the other methods (but don't try atalla again) */
368 /* I have finally been able to take out this pre-condition of
369 * the top bit being set. It was caused by an error in BN_div
370 * with negatives. There was also another problem when for a^b%m
371 * a >= m. eay 07-May-97 */
372 /* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */
375 { ret
=BN_mod_exp_mont(r
,a
,p
,m
,ctx
,NULL
); }
379 { ret
=BN_mod_exp_recp(r
,a
,p
,m
,ctx
); }
381 { ret
=BN_mod_exp_simple(r
,a
,p
,m
,ctx
); }
391 /* #ifdef RECP_MUL_MOD */
392 int BN_mod_exp_recp(BIGNUM
*r
, const BIGNUM
*a
, const BIGNUM
*p
,
393 const BIGNUM
*m
, BN_CTX
*ctx
)
395 int i
,j
,bits
,ret
=0,wstart
,wend
,window
,wvalue
;
398 BIGNUM val
[TABLE_SIZE
];
410 if ((aa
= BN_CTX_get(ctx
)) == NULL
) goto err
;
412 BN_RECP_CTX_init(&recp
);
413 if (BN_RECP_CTX_set(&recp
,m
,ctx
) <= 0) goto err
;
418 if (!BN_mod(&(val
[0]),a
,m
,ctx
)) goto err
; /* 1 */
419 if (!BN_mod_mul_reciprocal(aa
,&(val
[0]),&(val
[0]),&recp
,ctx
))
422 if (bits
<= 17) /* This is probably 3 or 0x10001, so just do singles */
424 else if (bits
>= 256)
425 window
=5; /* max size of window */
426 else if (bits
>= 128)
435 if (!BN_mod_mul_reciprocal(&(val
[i
]),&(val
[i
-1]),aa
,&recp
,ctx
))
440 start
=1; /* This is used to avoid multiplication etc
441 * when there is only the value '1' in the
443 wvalue
=0; /* The 'value' of the window */
444 wstart
=bits
-1; /* The top bit of the window */
445 wend
=0; /* The bottom bit of the window */
447 if (!BN_one(r
)) goto err
;
451 if (BN_is_bit_set(p
,wstart
) == 0)
454 if (!BN_mod_mul_reciprocal(r
,r
,r
,&recp
,ctx
))
456 if (wstart
== 0) break;
460 /* We now have wstart on a 'set' bit, we now need to work out
461 * how bit a window to do. To do this we need to scan
462 * forward until the last set bit before the end of the
467 for (i
=1; i
<window
; i
++)
469 if (wstart
-i
< 0) break;
470 if (BN_is_bit_set(p
,wstart
-i
))
478 /* wend is the size of the current window */
480 /* add the 'bytes above' */
484 if (!BN_mod_mul_reciprocal(r
,r
,r
,&recp
,ctx
))
488 /* wvalue will be an odd number < 2^window */
489 if (!BN_mod_mul_reciprocal(r
,r
,&(val
[wvalue
>>1]),&recp
,ctx
))
492 /* move the 'window' down further */
496 if (wstart
< 0) break;
502 BN_clear_free(&(val
[i
]));
503 BN_RECP_CTX_free(&recp
);
508 /* #ifdef MONT_MUL_MOD */
509 int BN_mod_exp_mont(BIGNUM
*rr
, BIGNUM
*a
, const BIGNUM
*p
,
510 const BIGNUM
*m
, BN_CTX
*ctx
, BN_MONT_CTX
*in_mont
)
512 int i
,j
,bits
,ret
=0,wstart
,wend
,window
,wvalue
;
516 BIGNUM val
[TABLE_SIZE
];
517 BN_MONT_CTX
*mont
=NULL
;
524 if(!tried_atalla
&& BN_mod_exp_atalla(rr
,a
,p
,m
))
526 /* If it fails, try the other methods */
531 BNerr(BN_F_BN_MOD_EXP_MONT
,BN_R_CALLED_WITH_EVEN_MODULUS
);
543 if (d
== NULL
|| r
== NULL
) goto err
;
545 /* If this is not done, things will break in the montgomery
554 if ((mont
=BN_MONT_CTX_new()) == NULL
) goto err
;
555 if (!BN_MONT_CTX_set(mont
,m
,ctx
)) goto err
;
560 if (BN_ucmp(a
,m
) >= 0)
562 BN_mod(&(val
[0]),a
,m
,ctx
);
567 if (!BN_to_montgomery(&(val
[0]),aa
,mont
,ctx
)) goto err
; /* 1 */
568 if (!BN_mod_mul_montgomery(d
,&(val
[0]),&(val
[0]),mont
,ctx
)) goto err
; /* 2 */
570 if (bits
<= 20) /* This is probably 3 or 0x10001, so just do singles */
572 else if (bits
>= 256)
573 window
=5; /* max size of window */
574 else if (bits
>= 128)
583 if (!BN_mod_mul_montgomery(&(val
[i
]),&(val
[i
-1]),d
,mont
,ctx
))
588 start
=1; /* This is used to avoid multiplication etc
589 * when there is only the value '1' in the
591 wvalue
=0; /* The 'value' of the window */
592 wstart
=bits
-1; /* The top bit of the window */
593 wend
=0; /* The bottom bit of the window */
595 if (!BN_to_montgomery(r
,BN_value_one(),mont
,ctx
)) goto err
;
598 if (BN_is_bit_set(p
,wstart
) == 0)
602 if (!BN_mod_mul_montgomery(r
,r
,r
,mont
,ctx
))
605 if (wstart
== 0) break;
609 /* We now have wstart on a 'set' bit, we now need to work out
610 * how bit a window to do. To do this we need to scan
611 * forward until the last set bit before the end of the
616 for (i
=1; i
<window
; i
++)
618 if (wstart
-i
< 0) break;
619 if (BN_is_bit_set(p
,wstart
-i
))
627 /* wend is the size of the current window */
629 /* add the 'bytes above' */
633 if (!BN_mod_mul_montgomery(r
,r
,r
,mont
,ctx
))
637 /* wvalue will be an odd number < 2^window */
638 if (!BN_mod_mul_montgomery(r
,r
,&(val
[wvalue
>>1]),mont
,ctx
))
641 /* move the 'window' down further */
645 if (wstart
< 0) break;
647 BN_from_montgomery(rr
,r
,mont
,ctx
);
650 if ((in_mont
== NULL
) && (mont
!= NULL
)) BN_MONT_CTX_free(mont
);
653 BN_clear_free(&(val
[i
]));
658 /* The old fallback, simple version :-) */
659 int BN_mod_exp_simple(BIGNUM
*r
, BIGNUM
*a
, BIGNUM
*p
, BIGNUM
*m
,
662 int i
,j
,bits
,ret
=0,wstart
,wend
,window
,wvalue
,ts
=0;
665 BIGNUM val
[TABLE_SIZE
];
676 if ((d
= BN_CTX_get(ctx
)) == NULL
) goto err
;
680 if (!BN_mod(&(val
[0]),a
,m
,ctx
)) goto err
; /* 1 */
681 if (!BN_mod_mul(d
,&(val
[0]),&(val
[0]),m
,ctx
))
684 if (bits
<= 17) /* This is probably 3 or 0x10001, so just do singles */
686 else if (bits
>= 256)
687 window
=5; /* max size of window */
688 else if (bits
>= 128)
697 if (!BN_mod_mul(&(val
[i
]),&(val
[i
-1]),d
,m
,ctx
))
702 start
=1; /* This is used to avoid multiplication etc
703 * when there is only the value '1' in the
705 wvalue
=0; /* The 'value' of the window */
706 wstart
=bits
-1; /* The top bit of the window */
707 wend
=0; /* The bottom bit of the window */
709 if (!BN_one(r
)) goto err
;
713 if (BN_is_bit_set(p
,wstart
) == 0)
716 if (!BN_mod_mul(r
,r
,r
,m
,ctx
))
718 if (wstart
== 0) break;
722 /* We now have wstart on a 'set' bit, we now need to work out
723 * how bit a window to do. To do this we need to scan
724 * forward until the last set bit before the end of the
729 for (i
=1; i
<window
; i
++)
731 if (wstart
-i
< 0) break;
732 if (BN_is_bit_set(p
,wstart
-i
))
740 /* wend is the size of the current window */
742 /* add the 'bytes above' */
746 if (!BN_mod_mul(r
,r
,r
,m
,ctx
))
750 /* wvalue will be an odd number < 2^window */
751 if (!BN_mod_mul(r
,r
,&(val
[wvalue
>>1]),m
,ctx
))
754 /* move the 'window' down further */
758 if (wstart
< 0) break;
764 BN_clear_free(&(val
[i
]));