]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
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 | |
8 | * using this file. | |
9 | * | |
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. | |
16 | */ | |
17 | ||
18 | ||
19 | /* crypto/bn/bn_lib.c */ | |
20 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | |
21 | * All rights reserved. | |
22 | * | |
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. | |
26 | * | |
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). | |
33 | * | |
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. | |
40 | * | |
41 | * Redistribution and use in source and binary forms, with or without | |
42 | * modification, are permitted provided that the following conditions | |
43 | * are met: | |
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)" | |
58 | * | |
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 | |
69 | * SUCH DAMAGE. | |
70 | * | |
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.] | |
75 | */ | |
76 | ||
77 | #include <stdio.h> | |
78 | #include "cryptlib.h" | |
79 | #include "bn_lcl.h" | |
80 | ||
81 | const char *BN_version="Big Number" OPENSSL_VERSION_PTEXT; | |
82 | ||
83 | #if BN_PARAMS_ENABLE | |
84 | ||
85 | /* For a 32 bit machine | |
86 | * 2 - 4 == 128 | |
87 | * 3 - 8 == 256 | |
88 | * 4 - 16 == 512 | |
89 | * 5 - 32 == 1024 | |
90 | * 6 - 64 == 2048 | |
91 | * 7 - 128 == 4096 | |
92 | * 8 - 256 == 8192 | |
93 | */ | |
94 | static int bn_limit_bits=0; | |
95 | static int bn_limit_num=8; /* (1<<bn_limit_bits) */ | |
96 | static int bn_limit_bits_low=0; | |
97 | static int bn_limit_num_low=8; /* (1<<bn_limit_bits_low) */ | |
98 | static int bn_limit_bits_high=0; | |
99 | static int bn_limit_num_high=8; /* (1<<bn_limit_bits_high) */ | |
100 | static int bn_limit_bits_mont=0; | |
101 | static int bn_limit_num_mont=8; /* (1<<bn_limit_bits_mont) */ | |
102 | ||
103 | void BN_set_params(int mult, int high, int low, int mont) | |
104 | { | |
105 | if (mult >= 0) | |
106 | { | |
107 | if (mult > (sizeof(int)*8)-1) | |
108 | mult=sizeof(int)*8-1; | |
109 | bn_limit_bits=mult; | |
110 | bn_limit_num=1<<mult; | |
111 | } | |
112 | if (high >= 0) | |
113 | { | |
114 | if (high > (sizeof(int)*8)-1) | |
115 | high=sizeof(int)*8-1; | |
116 | bn_limit_bits_high=high; | |
117 | bn_limit_num_high=1<<high; | |
118 | } | |
119 | if (low >= 0) | |
120 | { | |
121 | if (low > (sizeof(int)*8)-1) | |
122 | low=sizeof(int)*8-1; | |
123 | bn_limit_bits_low=low; | |
124 | bn_limit_num_low=1<<low; | |
125 | } | |
126 | if (mont >= 0) | |
127 | { | |
128 | if (mont > (sizeof(int)*8)-1) | |
129 | mont=sizeof(int)*8-1; | |
130 | bn_limit_bits_mont=mont; | |
131 | bn_limit_num_mont=1<<mont; | |
132 | } | |
133 | } | |
134 | ||
135 | int BN_get_params(int which) | |
136 | { | |
137 | if (which == 0) return(bn_limit_bits); | |
138 | else if (which == 1) return(bn_limit_bits_high); | |
139 | else if (which == 2) return(bn_limit_bits_low); | |
140 | else if (which == 3) return(bn_limit_bits_mont); | |
141 | else return(0); | |
142 | } | |
143 | #endif /* BN_PARAMS_ENABLE */ | |
144 | ||
145 | BIGNUM *BN_value_one(void) | |
146 | { | |
147 | static BN_ULONG data_one=1L; | |
148 | static BIGNUM const_one={&data_one,1,1,0}; | |
149 | ||
150 | return(&const_one); | |
151 | } | |
152 | ||
153 | char *BN_options(void) | |
154 | { | |
155 | static int init=0; | |
156 | static char data[16]; | |
157 | ||
158 | if (!init) | |
159 | { | |
160 | init++; | |
161 | #ifdef BN_LLONG | |
162 | sprintf(data,"bn(%d,%d)",(int)sizeof(BN_ULLONG)*8, | |
163 | (int)sizeof(BN_ULONG)*8); | |
164 | #else | |
165 | sprintf(data,"bn(%d,%d)",(int)sizeof(BN_ULONG)*8, | |
166 | (int)sizeof(BN_ULONG)*8); | |
167 | #endif | |
168 | } | |
169 | return(data); | |
170 | } | |
171 | ||
172 | int BN_num_bits_word(BN_ULONG l) | |
173 | { | |
174 | static const char bits[256]={ | |
175 | 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4, | |
176 | 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, | |
177 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | |
178 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | |
179 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | |
180 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | |
181 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | |
182 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | |
183 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
184 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
185 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
186 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
187 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
188 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
189 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
190 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
191 | }; | |
192 | ||
193 | #if defined(SIXTY_FOUR_BIT_LONG) | |
194 | if (l & 0xffffffff00000000L) | |
195 | { | |
196 | if (l & 0xffff000000000000L) | |
197 | { | |
198 | if (l & 0xff00000000000000L) | |
199 | { | |
200 | return(bits[(int)(l>>56)]+56); | |
201 | } | |
202 | else return(bits[(int)(l>>48)]+48); | |
203 | } | |
204 | else | |
205 | { | |
206 | if (l & 0x0000ff0000000000L) | |
207 | { | |
208 | return(bits[(int)(l>>40)]+40); | |
209 | } | |
210 | else return(bits[(int)(l>>32)]+32); | |
211 | } | |
212 | } | |
213 | else | |
214 | #else | |
215 | #ifdef SIXTY_FOUR_BIT | |
216 | if (l & 0xffffffff00000000LL) | |
217 | { | |
218 | if (l & 0xffff000000000000LL) | |
219 | { | |
220 | if (l & 0xff00000000000000LL) | |
221 | { | |
222 | return(bits[(int)(l>>56)]+56); | |
223 | } | |
224 | else return(bits[(int)(l>>48)]+48); | |
225 | } | |
226 | else | |
227 | { | |
228 | if (l & 0x0000ff0000000000LL) | |
229 | { | |
230 | return(bits[(int)(l>>40)]+40); | |
231 | } | |
232 | else return(bits[(int)(l>>32)]+32); | |
233 | } | |
234 | } | |
235 | else | |
236 | #endif | |
237 | #endif | |
238 | { | |
239 | #if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) | |
240 | if (l & 0xffff0000L) | |
241 | { | |
242 | if (l & 0xff000000L) | |
243 | return(bits[(int)(l>>24L)]+24); | |
244 | else return(bits[(int)(l>>16L)]+16); | |
245 | } | |
246 | else | |
247 | #endif | |
248 | { | |
249 | #if defined(SIXTEEN_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) | |
250 | if (l & 0xff00L) | |
251 | return(bits[(int)(l>>8)]+8); | |
252 | else | |
253 | #endif | |
254 | return(bits[(int)(l )] ); | |
255 | } | |
256 | } | |
257 | } | |
258 | ||
259 | int BN_num_bits(const BIGNUM *a) | |
260 | { | |
261 | BN_ULONG l; | |
262 | int i; | |
263 | ||
264 | bn_check_top(a); | |
265 | ||
266 | if (a->top == 0) return(0); | |
267 | l=a->d[a->top-1]; | |
268 | i=(a->top-1)*BN_BITS2; | |
269 | if (l == 0) | |
270 | { | |
271 | #if !defined(NO_STDIO) && !defined(WIN16) | |
272 | fprintf(stderr,"BAD TOP VALUE\n"); | |
273 | #endif | |
274 | abort(); | |
275 | } | |
276 | return(i+BN_num_bits_word(l)); | |
277 | } | |
278 | ||
279 | void BN_clear_free(BIGNUM *a) | |
280 | { | |
281 | int i; | |
282 | ||
283 | if (a == NULL) return; | |
284 | if (a->d != NULL) | |
285 | { | |
286 | memset(a->d,0,a->max*sizeof(a->d[0])); | |
287 | if (!(BN_get_flags(a,BN_FLG_STATIC_DATA))) | |
288 | Free(a->d); | |
289 | } | |
290 | i=BN_get_flags(a,BN_FLG_MALLOCED); | |
291 | memset(a,0,sizeof(BIGNUM)); | |
292 | if (i) | |
293 | Free(a); | |
294 | } | |
295 | ||
296 | void BN_free(BIGNUM *a) | |
297 | { | |
298 | if (a == NULL) return; | |
299 | if ((a->d != NULL) && !(BN_get_flags(a,BN_FLG_STATIC_DATA))) | |
300 | Free(a->d); | |
301 | a->flags|=BN_FLG_FREE; /* REMOVE? */ | |
302 | if (a->flags & BN_FLG_MALLOCED) | |
303 | Free(a); | |
304 | } | |
305 | ||
306 | void BN_init(BIGNUM *a) | |
307 | { | |
308 | memset(a,0,sizeof(BIGNUM)); | |
309 | } | |
310 | ||
311 | BIGNUM *BN_new(void) | |
312 | { | |
313 | BIGNUM *ret; | |
314 | ||
315 | if ((ret=(BIGNUM *)Malloc(sizeof(BIGNUM))) == NULL) | |
316 | { | |
317 | BNerr(BN_F_BN_NEW,ERR_R_MALLOC_FAILURE); | |
318 | return(NULL); | |
319 | } | |
320 | ret->flags=BN_FLG_MALLOCED; | |
321 | ret->top=0; | |
322 | ret->neg=0; | |
323 | ret->max=0; | |
324 | ret->d=NULL; | |
325 | return(ret); | |
326 | } | |
327 | ||
328 | /* This is an internal function that should not be used in applications. | |
329 | * It ensures that 'b' has enough room for a 'words' word number number. | |
330 | * It is mostly used by the various BIGNUM routines. If there is an error, | |
331 | * NULL is returned. If not, 'b' is returned. */ | |
332 | ||
333 | BIGNUM *bn_expand2(BIGNUM *b, int words) | |
334 | { | |
335 | BN_ULONG *A,*a; | |
336 | const BN_ULONG *B; | |
337 | int i; | |
338 | ||
339 | bn_check_top(b); | |
340 | ||
341 | if (words > b->max) | |
342 | { | |
343 | bn_check_top(b); | |
344 | if (BN_get_flags(b,BN_FLG_STATIC_DATA)) | |
345 | { | |
346 | BNerr(BN_F_BN_EXPAND2,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); | |
347 | return(NULL); | |
348 | } | |
349 | a=A=(BN_ULONG *)Malloc(sizeof(BN_ULONG)*(words+1)); | |
350 | if (A == NULL) | |
351 | { | |
352 | BNerr(BN_F_BN_EXPAND2,ERR_R_MALLOC_FAILURE); | |
353 | return(NULL); | |
354 | } | |
355 | #if 1 | |
356 | B=b->d; | |
357 | /* Check if the previous number needs to be copied */ | |
358 | if (B != NULL) | |
359 | { | |
360 | #if 0 | |
361 | /* This lot is an unrolled loop to copy b->top | |
362 | * BN_ULONGs from B to A | |
363 | */ | |
364 | /* | |
365 | * I have nothing against unrolling but it's usually done for | |
366 | * several reasons, namely: | |
367 | * - minimize percentage of decision making code, i.e. branches; | |
368 | * - avoid cache trashing; | |
369 | * - make it possible to schedule loads earlier; | |
370 | * Now let's examine the code below. The cornerstone of C is | |
371 | * "programmer is always right" and that's what we love it for:-) | |
372 | * For this very reason C compilers have to be paranoid when it | |
373 | * comes to data aliasing and assume the worst. Yeah, but what | |
374 | * does it mean in real life? This means that loop body below will | |
375 | * be compiled to sequence of loads immediately followed by stores | |
376 | * as compiler assumes the worst, something in A==B+1 style. As a | |
377 | * result CPU pipeline is going to starve for incoming data. Secondly | |
378 | * if A and B happen to share same cache line such code is going to | |
379 | * cause severe cache trashing. Both factors have severe impact on | |
380 | * performance of modern CPUs and this is the reason why this | |
381 | * particular piece of code is #ifdefed away and replaced by more | |
382 | * "friendly" version found in #else section below. This comment | |
383 | * also applies to BN_copy function. | |
384 | * | |
385 | * <appro@fy.chalmers.se> | |
386 | */ | |
387 | for (i=b->top&(~7); i>0; i-=8) | |
388 | { | |
389 | A[0]=B[0]; A[1]=B[1]; A[2]=B[2]; A[3]=B[3]; | |
390 | A[4]=B[4]; A[5]=B[5]; A[6]=B[6]; A[7]=B[7]; | |
391 | A+=8; | |
392 | B+=8; | |
393 | } | |
394 | switch (b->top&7) | |
395 | { | |
396 | case 7: | |
397 | A[6]=B[6]; | |
398 | case 6: | |
399 | A[5]=B[5]; | |
400 | case 5: | |
401 | A[4]=B[4]; | |
402 | case 4: | |
403 | A[3]=B[3]; | |
404 | case 3: | |
405 | A[2]=B[2]; | |
406 | case 2: | |
407 | A[1]=B[1]; | |
408 | case 1: | |
409 | A[0]=B[0]; | |
410 | case 0: | |
411 | /* I need the 'case 0' entry for utrix cc. | |
412 | * If the optimizer is turned on, it does the | |
413 | * switch table by doing | |
414 | * a=top&7 | |
415 | * a--; | |
416 | * goto jump_table[a]; | |
417 | * If top is 0, this makes us jump to 0xffffffc | |
418 | * which is rather bad :-(. | |
419 | * eric 23-Apr-1998 | |
420 | */ | |
421 | ; | |
422 | } | |
423 | #else | |
424 | for (i=b->top>>2; i>0; i--,A+=4,B+=4) | |
425 | { | |
426 | /* | |
427 | * The fact that the loop is unrolled | |
428 | * 4-wise is a tribute to Intel. It's | |
429 | * the one that doesn't have enough | |
430 | * registers to accomodate more data. | |
431 | * I'd unroll it 8-wise otherwise:-) | |
432 | * | |
433 | * <appro@fy.chalmers.se> | |
434 | */ | |
435 | BN_ULONG a0,a1,a2,a3; | |
436 | a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3]; | |
437 | A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3; | |
438 | } | |
439 | switch (b->top&3) | |
440 | { | |
441 | case 3: A[2]=B[2]; | |
442 | case 2: A[1]=B[1]; | |
443 | case 1: A[0]=B[0]; | |
444 | case 0: ; /* ultrix cc workaround, see above */ | |
445 | } | |
446 | #endif | |
447 | Free(b->d); | |
448 | } | |
449 | ||
450 | b->d=a; | |
451 | b->max=words; | |
452 | ||
453 | /* Now need to zero any data between b->top and b->max */ | |
454 | ||
455 | A= &(b->d[b->top]); | |
456 | for (i=(b->max - b->top)>>3; i>0; i--,A+=8) | |
457 | { | |
458 | A[0]=0; A[1]=0; A[2]=0; A[3]=0; | |
459 | A[4]=0; A[5]=0; A[6]=0; A[7]=0; | |
460 | } | |
461 | for (i=(b->max - b->top)&7; i>0; i--,A++) | |
462 | A[0]=0; | |
463 | #else | |
464 | memset(A,0,sizeof(BN_ULONG)*(words+1)); | |
465 | memcpy(A,b->d,sizeof(b->d[0])*b->top); | |
466 | b->d=a; | |
467 | b->max=words; | |
468 | #endif | |
469 | ||
470 | /* memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG)); */ | |
471 | /* { int i; for (i=b->max; i<words+1; i++) p[i]=i;} */ | |
472 | ||
473 | } | |
474 | return(b); | |
475 | } | |
476 | ||
477 | BIGNUM *BN_dup(const BIGNUM *a) | |
478 | { | |
479 | BIGNUM *r; | |
480 | ||
481 | if (a == NULL) return NULL; | |
482 | ||
483 | bn_check_top(a); | |
484 | ||
485 | r=BN_new(); | |
486 | if (r == NULL) return(NULL); | |
487 | return((BIGNUM *)BN_copy(r,a)); | |
488 | } | |
489 | ||
490 | BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) | |
491 | { | |
492 | int i; | |
493 | BN_ULONG *A; | |
494 | const BN_ULONG *B; | |
495 | ||
496 | bn_check_top(b); | |
497 | ||
498 | if (a == b) return(a); | |
499 | if (bn_wexpand(a,b->top) == NULL) return(NULL); | |
500 | ||
501 | #if 1 | |
502 | A=a->d; | |
503 | B=b->d; | |
504 | for (i=b->top>>2; i>0; i--,A+=4,B+=4) | |
505 | { | |
506 | BN_ULONG a0,a1,a2,a3; | |
507 | a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3]; | |
508 | A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3; | |
509 | } | |
510 | switch (b->top&3) | |
511 | { | |
512 | case 3: A[2]=B[2]; | |
513 | case 2: A[1]=B[1]; | |
514 | case 1: A[0]=B[0]; | |
515 | case 0: ; /* ultrix cc workaround, see comments in bn_expand2 */ | |
516 | } | |
517 | #else | |
518 | memcpy(a->d,b->d,sizeof(b->d[0])*b->top); | |
519 | #endif | |
520 | ||
521 | /* memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/ | |
522 | a->top=b->top; | |
523 | if ((a->top == 0) && (a->d != NULL)) | |
524 | a->d[0]=0; | |
525 | a->neg=b->neg; | |
526 | return(a); | |
527 | } | |
528 | ||
529 | void BN_clear(BIGNUM *a) | |
530 | { | |
531 | if (a->d != NULL) | |
532 | memset(a->d,0,a->max*sizeof(a->d[0])); | |
533 | a->top=0; | |
534 | a->neg=0; | |
535 | } | |
536 | ||
537 | BN_ULONG BN_get_word(BIGNUM *a) | |
538 | { | |
539 | int i; | |
540 | unsigned n; | |
541 | BN_ULONG ret=0; | |
542 | ||
543 | n=BN_num_bytes(a); | |
544 | if (n > sizeof(BN_ULONG)) | |
545 | return(BN_MASK2); | |
546 | for (i=a->top-1; i>=0; i--) | |
547 | { | |
548 | #ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ | |
549 | ret<<=BN_BITS4; /* stops the compiler complaining */ | |
550 | ret<<=BN_BITS4; | |
551 | #else | |
552 | ret=0; | |
553 | #endif | |
554 | ret|=a->d[i]; | |
555 | } | |
556 | return(ret); | |
557 | } | |
558 | ||
559 | int BN_set_word(BIGNUM *a, BN_ULONG w) | |
560 | { | |
561 | int i,n; | |
562 | ||
563 | if (bn_expand(a,(int)(sizeof(BN_ULONG)*8)) == NULL) return(0); | |
564 | ||
565 | n=sizeof(BN_ULONG)/BN_BYTES; | |
566 | a->neg=0; | |
567 | a->top=0; | |
568 | a->d[0]=(BN_ULONG)w&BN_MASK2; | |
569 | if (a->d[0] != 0) a->top=1; | |
570 | for (i=1; i<n; i++) | |
571 | { | |
572 | /* the following is done instead of | |
573 | * w>>=BN_BITS2 so compilers don't complain | |
574 | * on builds where sizeof(long) == BN_TYPES */ | |
575 | #ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ | |
576 | w>>=BN_BITS4; | |
577 | w>>=BN_BITS4; | |
578 | #else | |
579 | w=0; | |
580 | #endif | |
581 | a->d[i]=(BN_ULONG)w&BN_MASK2; | |
582 | if (a->d[i] != 0) a->top=i+1; | |
583 | } | |
584 | return(1); | |
585 | } | |
586 | ||
587 | /* ignore negative */ | |
588 | BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) | |
589 | { | |
590 | unsigned int i,m; | |
591 | unsigned int n; | |
592 | BN_ULONG l; | |
593 | ||
594 | if (ret == NULL) ret=BN_new(); | |
595 | if (ret == NULL) return(NULL); | |
596 | l=0; | |
597 | n=len; | |
598 | if (n == 0) | |
599 | { | |
600 | ret->top=0; | |
601 | return(ret); | |
602 | } | |
603 | if (bn_expand(ret,(int)(n+2)*8) == NULL) | |
604 | return(NULL); | |
605 | i=((n-1)/BN_BYTES)+1; | |
606 | m=((n-1)%(BN_BYTES)); | |
607 | ret->top=i; | |
608 | while (n-- > 0) | |
609 | { | |
610 | l=(l<<8L)| *(s++); | |
611 | if (m-- == 0) | |
612 | { | |
613 | ret->d[--i]=l; | |
614 | l=0; | |
615 | m=BN_BYTES-1; | |
616 | } | |
617 | } | |
618 | /* need to call this due to clear byte at top if avoiding | |
619 | * having the top bit set (-ve number) */ | |
620 | bn_fix_top(ret); | |
621 | return(ret); | |
622 | } | |
623 | ||
624 | /* ignore negative */ | |
625 | int BN_bn2bin(const BIGNUM *a, unsigned char *to) | |
626 | { | |
627 | int n,i; | |
628 | BN_ULONG l; | |
629 | ||
630 | n=i=BN_num_bytes(a); | |
631 | while (i-- > 0) | |
632 | { | |
633 | l=a->d[i/BN_BYTES]; | |
634 | *(to++)=(unsigned char)(l>>(8*(i%BN_BYTES)))&0xff; | |
635 | } | |
636 | return(n); | |
637 | } | |
638 | ||
639 | int BN_ucmp(const BIGNUM *a, const BIGNUM *b) | |
640 | { | |
641 | int i; | |
642 | BN_ULONG t1,t2,*ap,*bp; | |
643 | ||
644 | bn_check_top(a); | |
645 | bn_check_top(b); | |
646 | ||
647 | i=a->top-b->top; | |
648 | if (i != 0) return(i); | |
649 | ap=a->d; | |
650 | bp=b->d; | |
651 | for (i=a->top-1; i>=0; i--) | |
652 | { | |
653 | t1= ap[i]; | |
654 | t2= bp[i]; | |
655 | if (t1 != t2) | |
656 | return(t1 > t2?1:-1); | |
657 | } | |
658 | return(0); | |
659 | } | |
660 | ||
661 | int BN_cmp(const BIGNUM *a, const BIGNUM *b) | |
662 | { | |
663 | int i; | |
664 | int gt,lt; | |
665 | BN_ULONG t1,t2; | |
666 | ||
667 | if ((a == NULL) || (b == NULL)) | |
668 | { | |
669 | if (a != NULL) | |
670 | return(-1); | |
671 | else if (b != NULL) | |
672 | return(1); | |
673 | else | |
674 | return(0); | |
675 | } | |
676 | ||
677 | bn_check_top(a); | |
678 | bn_check_top(b); | |
679 | ||
680 | if (a->neg != b->neg) | |
681 | { | |
682 | if (a->neg) | |
683 | return(-1); | |
684 | else return(1); | |
685 | } | |
686 | if (a->neg == 0) | |
687 | { gt=1; lt= -1; } | |
688 | else { gt= -1; lt=1; } | |
689 | ||
690 | if (a->top > b->top) return(gt); | |
691 | if (a->top < b->top) return(lt); | |
692 | for (i=a->top-1; i>=0; i--) | |
693 | { | |
694 | t1=a->d[i]; | |
695 | t2=b->d[i]; | |
696 | if (t1 > t2) return(gt); | |
697 | if (t1 < t2) return(lt); | |
698 | } | |
699 | return(0); | |
700 | } | |
701 | ||
702 | int BN_set_bit(BIGNUM *a, int n) | |
703 | { | |
704 | int i,j,k; | |
705 | ||
706 | i=n/BN_BITS2; | |
707 | j=n%BN_BITS2; | |
708 | if (a->top <= i) | |
709 | { | |
710 | if (bn_wexpand(a,i+1) == NULL) return(0); | |
711 | for(k=a->top; k<i+1; k++) | |
712 | a->d[k]=0; | |
713 | a->top=i+1; | |
714 | } | |
715 | ||
716 | a->d[i]|=(((BN_ULONG)1)<<j); | |
717 | return(1); | |
718 | } | |
719 | ||
720 | int BN_clear_bit(BIGNUM *a, int n) | |
721 | { | |
722 | int i,j; | |
723 | ||
724 | i=n/BN_BITS2; | |
725 | j=n%BN_BITS2; | |
726 | if (a->top <= i) return(0); | |
727 | ||
728 | a->d[i]&=(~(((BN_ULONG)1)<<j)); | |
729 | bn_fix_top(a); | |
730 | return(1); | |
731 | } | |
732 | ||
733 | int BN_is_bit_set(const BIGNUM *a, int n) | |
734 | { | |
735 | int i,j; | |
736 | ||
737 | if (n < 0) return(0); | |
738 | i=n/BN_BITS2; | |
739 | j=n%BN_BITS2; | |
740 | if (a->top <= i) return(0); | |
741 | return((a->d[i]&(((BN_ULONG)1)<<j))?1:0); | |
742 | } | |
743 | ||
744 | int BN_mask_bits(BIGNUM *a, int n) | |
745 | { | |
746 | int b,w; | |
747 | ||
748 | w=n/BN_BITS2; | |
749 | b=n%BN_BITS2; | |
750 | if (w >= a->top) return(0); | |
751 | if (b == 0) | |
752 | a->top=w; | |
753 | else | |
754 | { | |
755 | a->top=w+1; | |
756 | a->d[w]&= ~(BN_MASK2<<b); | |
757 | } | |
758 | bn_fix_top(a); | |
759 | return(1); | |
760 | } | |
761 | ||
762 | int bn_cmp_words(BN_ULONG *a, BN_ULONG *b, int n) | |
763 | { | |
764 | int i; | |
765 | BN_ULONG aa,bb; | |
766 | ||
767 | aa=a[n-1]; | |
768 | bb=b[n-1]; | |
769 | if (aa != bb) return((aa > bb)?1:-1); | |
770 | for (i=n-2; i>=0; i--) | |
771 | { | |
772 | aa=a[i]; | |
773 | bb=b[i]; | |
774 | if (aa != bb) return((aa > bb)?1:-1); | |
775 | } | |
776 | return(0); | |
777 | } | |
778 |