]>
Commit | Line | Data |
---|---|---|
0095f096 | 1 | /* |
2 | * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION | |
3 | * ALL RIGHTS RESERVED | |
4 | * | |
5 | * "Digital Equipment Corporation authorizes the reproduction, | |
6 | * distribution and modification of this software subject to the following | |
7 | * restrictions: | |
8 | * | |
9 | * 1. Any partial or whole copy of this software, or any modification | |
10 | * thereof, must include this copyright notice in its entirety. | |
11 | * | |
12 | * 2. This software is supplied "as is" with no warranty of any kind, | |
13 | * expressed or implied, for any purpose, including any warranty of fitness | |
14 | * or merchantibility. DIGITAL assumes no responsibility for the use or | |
15 | * reliability of this software, nor promises to provide any form of | |
16 | * support for it on any basis. | |
17 | * | |
18 | * 3. Distribution of this software is authorized only if no profit or | |
19 | * remuneration of any kind is received in exchange for such distribution. | |
20 | * | |
21 | * 4. This software produces public key authentication certificates | |
22 | * bearing an expiration date established by DIGITAL and RSA Data | |
23 | * Security, Inc. It may cease to generate certificates after the expiration | |
24 | * date. Any modification of this software that changes or defeats | |
25 | * the expiration date or its effect is unauthorized. | |
26 | * | |
27 | * 5. Software that will renew or extend the expiration date of | |
28 | * authentication certificates produced by this software may be obtained | |
29 | * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA | |
30 | * 94065, (415)595-8782, or from DIGITAL" | |
31 | * | |
32 | */ | |
33 | ||
34 | /* This code was derived from Mark Shand's PRL Montgomery code. */ | |
35 | ||
36 | #include <stdio.h> | |
37 | #include <time.h> | |
38 | #include <sys/types.h> | |
0095f096 | 39 | |
40 | #include "BigZ.h" | |
41 | #include "BigRSA.h" | |
42 | #include "bigrsacode.h" | |
43 | #include "bigkeygen.h" | |
44 | ||
45 | #ifdef mips | |
46 | #undef BnnSetToZero | |
47 | #endif | |
48 | ||
49 | #define KEY_LINE 64 | |
50 | #define KEY_RADIX 16 | |
51 | ||
52 | /* | |
53 | #define DEBUG_1 | |
54 | */ | |
55 | ||
56 | /* Global storage indicating whether to print prime progress reports */ | |
57 | ||
58 | int bigkeygenPrintStatistics = 0; | |
59 | ||
60 | #ifdef DEBUG | |
61 | #undef DEBUG | |
62 | #endif | |
63 | ||
64 | /* | |
65 | * One-half the difference between the lengths of p and q, in bits | |
66 | */ | |
67 | #define PRIME_BIT_DIFF 3 | |
68 | ||
69 | /* | |
70 | * Local modular product routines | |
71 | */ | |
72 | ||
73 | /* put in-line RSA routines here */ | |
74 | ||
75 | #include "RSAcrypto.h" | |
76 | ||
77 | static void BnnGCD_1(); | |
78 | static void modpwr2_1(); | |
79 | static BigNum muB_1(); | |
80 | static int bigprime(); | |
81 | ||
82 | /* | |
83 | * newRSAKey generates a new RSA key instance. | |
84 | * | |
85 | * bitlen length of primes, in bits. Modulus will be | |
86 | * approximately 2*bitlen | |
87 | * keys RSAKeyStorage structure for new key | |
88 | */ | |
89 | ||
90 | int newRSAKey ( bitlen , keys ) | |
91 | int bitlen ; | |
92 | RSAKeyStorage *keys ; | |
93 | { | |
94 | BigNum p = keys->p, q = keys->q ; | |
95 | unsigned lowbits = 1, confidence = 20, pl, ql; | |
96 | #ifdef DEBUG | |
97 | clock_t mark, tenths; | |
98 | struct timeb start_time , end_time ; | |
99 | #endif | |
100 | ||
101 | if ((bitlen<128)||(bitlen>MaxPrimeBits)) return (0); | |
102 | ||
103 | memset(keys,0,sizeof(RSAKeyStorage)); | |
104 | BnnInit(); | |
105 | ||
106 | #ifdef DEBUG | |
107 | mark = clock(); | |
108 | ftime (&start_time); | |
109 | #endif | |
110 | ||
111 | bigprime(p, &pl, bitlen+PRIME_BIT_DIFF, lowbits, confidence, 0); | |
112 | do { | |
113 | bigprime(q, &ql, bitlen-PRIME_BIT_DIFF, lowbits, confidence, 0); | |
114 | } while (BnnCompare(p, pl, q, ql) == 0); | |
115 | ||
116 | #ifdef DEBUG | |
117 | mark = clock() - mark ; | |
118 | ftime (&end_time); | |
119 | ||
120 | #ifdef ultrix | |
121 | #ifndef CLOCKS_PER_SEC | |
122 | #define CLOCKS_PER_SEC 1000000 | |
123 | #endif | |
124 | tenths = (100*(mark%CLOCKS_PER_SEC))/CLOCKS_PER_SEC ; | |
125 | mark /= CLOCKS_PER_SEC ; | |
126 | #else | |
127 | tenths = (100*(mark%CLK_TCK))/CLK_TCK ; | |
128 | mark /= CLK_TCK ; | |
129 | #endif | |
130 | ||
131 | printf ("\n/* Primes found in %d.%02d seconds of process time*/\n", mark, tenths ); | |
132 | mark = end_time.time - start_time.time ; | |
133 | { long xt = (unsigned long) end_time.millitm - (unsigned long) start_time.millitm ; | |
134 | if (xt<0) { mark--; xt = 1000 - xt;} | |
135 | printf ("\n/* Primes found in %d.%03d elapsed seconds */\n", | |
136 | end_time.time-start_time.time, xt ); | |
137 | } | |
138 | #endif | |
139 | ||
140 | if (BnnCompare(p, pl, q, ql) == -1) { | |
141 | unsigned tpl = pl; | |
142 | BigNumDigit tp[DigitLim]; | |
143 | BnnSetToZero(tp,DigitLim); | |
144 | BnnAssign(tp,p,pl); | |
145 | BnnSetToZero(p,pl); | |
146 | BnnAssign(p,q,ql); | |
147 | BnnAssign(q,tp,pl); | |
148 | pl = ql; | |
149 | ql = tpl; | |
150 | } | |
151 | ||
152 | keys->pl = pl; | |
153 | keys->ql = ql; | |
154 | ||
155 | /* | |
156 | * Set exponent to F16 and compute modulus. | |
157 | */ | |
158 | BnnSetDigit(keys->e, (BigNumDigit) ((1<<16)+1)); | |
159 | keys->el = 1; | |
160 | ||
161 | BnnMultiply(keys->n, pl+ql, p, pl, q, ql), | |
162 | keys->nl = pl+ql; | |
163 | ||
164 | if (FinishKey(keys)==0) return (0); | |
165 | ||
166 | if (TestRSAKeys(keys)!=1) { | |
167 | #ifdef DEBUG | |
168 | printf("\nFailed.\n"); | |
169 | #endif | |
170 | return(0); | |
171 | } | |
172 | ||
173 | BnnClose(); | |
174 | return(1); | |
175 | } | |
176 | ||
177 | ||
178 | /* | |
179 | * Prime-finding routines | |
180 | */ | |
181 | ||
182 | ||
183 | static BigNumDigit smallprime[]= | |
184 | {3,5,7,11,13,17,19,23,29,31,37,41,43,53,59, | |
185 | 61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157, | |
186 | 163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251, | |
187 | 257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353, | |
188 | 359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457, | |
189 | 461,463,467,479,487,491,499 }; | |
190 | ||
191 | ||
192 | /* | |
193 | * Test for primality. | |
194 | */ | |
195 | ||
196 | static int IsPrime(n,nl,confidence) | |
197 | BigNum n; | |
198 | int nl; | |
199 | { | |
200 | int i; | |
201 | static BigNumDigit x[DigitLim], | |
202 | y[2*DigitLim], | |
203 | beta2n[2*DigitLim+1], | |
204 | nINV [2*DigitLim] ; | |
205 | ||
206 | for(i=0;i<=(sizeof(smallprime)/sizeof(BigNumDigit));i++) | |
207 | if(BnnDivideDigit(y,n,nl+1,smallprime[i])==0) goto exit ; | |
208 | ||
209 | muB_1(nINV, n, nl*BN_DIGIT_SIZE); | |
210 | modpwr2_1(beta2n, 2, n, nl); | |
211 | BnnSetToZero (x, nl); | |
212 | ||
213 | for(i=0;i<=confidence;i++) { | |
214 | x[0]+= smallprime[i] ; | |
215 | BnnDyRaise_1(y, x, n, nl, n, beta2n, nINV, nl); | |
216 | BnnDyCanon_1(y, n, nl); | |
217 | if (BnnCompare(y, nl, x, nl)) goto exit; | |
218 | } | |
219 | return(1); | |
220 | ||
221 | exit: | |
222 | return(0); | |
223 | } | |
224 | ||
225 | /* | |
226 | * Generate a big prime. | |
227 | */ | |
228 | static bigprime (n,nlen,bitlen,lowbits,confidence,stats) | |
229 | BigNum n; | |
230 | unsigned *nlen; | |
231 | int bitlen; | |
232 | BigNumDigit lowbits; | |
233 | int confidence; | |
234 | unsigned *stats; | |
235 | { | |
236 | char * z ; | |
237 | static char sieve [1000]; | |
238 | int i,j; | |
239 | BigNumDigit r, s, q[DigitLim] ; | |
240 | unsigned nl =(bitlen+(BN_DIGIT_SIZE-1))/BN_DIGIT_SIZE ; | |
241 | unsigned ntop = nl; | |
242 | ||
243 | if((((bitlen-1)%BN_DIGIT_SIZE)+1)>=(BN_DIGIT_SIZE-1)) nl++; | |
244 | *nlen = nl; | |
245 | BnnSetToZero(n,nl+1); | |
246 | while(1) { | |
247 | random_BigNum(n,ntop); | |
248 | n[nl-1]&=(1<<((BN_DIGIT_SIZE)-(nl*(BN_DIGIT_SIZE)-bitlen))) -1 ; | |
249 | n[(bitlen-1)/BN_DIGIT_SIZE] |= 1<<((bitlen-1)%BN_DIGIT_SIZE); | |
250 | n[(bitlen-2)/BN_DIGIT_SIZE] |= 1<<((bitlen-2)%BN_DIGIT_SIZE); | |
251 | n[0]&=~1; | |
252 | ||
253 | if(bigkeygenPrintStatistics) | |
254 | printf("\nCandidate Random Number: %s\n",BzToString(BzFromBigNum(n,nl),16)); | |
255 | ||
256 | z = &sieve[0] ; | |
257 | for (i=0;i<1000;i=i+2){*z++=1;*z++=0;}; | |
258 | r = BnnDivideDigit(q,n,nl+1,(BigNumDigit)3); | |
259 | if (r==0) r = (BigNumDigit) 3; | |
260 | r--; | |
261 | z = &sieve[3-r] ; | |
262 | for (j=3-r;j<1000;j+=3) {*z=1;z+=3;} | |
263 | ||
264 | for (s=3;s<10000;s+=2) { | |
265 | for (j=0; j<5; j++)if ((s>smallprime[j])&&(0==(s%smallprime[j]))) goto nexts; | |
266 | r = BnnDivideDigit(q,n,nl+1,s); | |
267 | if (r==0) r = s; | |
268 | z = &sieve[s-r] ; | |
269 | for (j=s-r;j<1000;j+=s) {*z=1;z+=s;} | |
270 | nexts: ; | |
271 | } | |
272 | for(i=0;i<1000;i++) { | |
273 | if (!sieve[i]) { | |
274 | ||
275 | if(bigkeygenPrintStatistics) printf("|"),fflush(stdout); | |
276 | ||
277 | if (IsPrime(n,nl,5)) goto exit; | |
278 | } | |
279 | BnnAddCarry(n,nl,1); /* try next one */ | |
280 | } | |
281 | } | |
282 | exit: | |
283 | ||
284 | if(bigkeygenPrintStatistics) printf(""), fflush(stdout); | |
285 | ||
286 | } | |
287 | ||
288 | ||
289 | /* | |
290 | * This routine expects modulus n and exponent e to be initialized | |
291 | * in the RSAKeyStorage structure supplied. It computes the rest of | |
292 | * the key components based on what is provided. If p and q are there | |
293 | * it also makes sure a complete private key is initialized. | |
294 | */ | |
295 | int FinishKey (keys) | |
296 | RSAKeyStorage *keys; | |
297 | { | |
298 | static BigNumDigit g[4*DigitLim], wgcd[12*DigitLim], | |
299 | r[4*DigitLim], pq[4*DigitLim], d[4*DigitLim], z[4*DigitLim]; | |
300 | ||
301 | BigNum n = keys->n, dp = keys->dp, dq = keys->dq, cr = keys->cr, | |
302 | e = keys->e, p = keys->p, q = keys->q ; | |
303 | ||
304 | unsigned nl=keys->nl, pl=keys->pl, ql=keys->ql, tmp, | |
305 | dpl = keys->dpl, dql = keys->dql ; | |
306 | ||
307 | /* | |
308 | * If primes are supplied, generate dp, dq, and cr if needed. | |
309 | * Assume cr there if dp and dq are. | |
310 | */ | |
311 | ||
312 | if (pl && ql && ((dpl == 0)||(dql ==0)) ) { | |
313 | BnnAssign(pq, n, nl); | |
314 | BnnSubtract(pq, nl, p, pl, 1); | |
315 | BnnSubtract(pq, nl, q, ql, 1); | |
316 | BnnAddCarry(pq, nl, 1); | |
317 | BnnGCD_1(g, d, r, e, pq, wgcd, nl); | |
318 | if (BnnCompare(g,nl,one,nl)!=0) { | |
319 | #ifdef DEBUG | |
320 | printf("GCD failed to generate private key exponent.\n"); | |
321 | #endif | |
322 | return(0); | |
323 | } | |
324 | BnnAssign(z, d, nl); | |
325 | z[nl] = 0; | |
326 | BnnAssign(pq, p, pl); | |
327 | BnnSubtractBorrow(pq, pl, 0); | |
328 | BnnDivide(z, nl+1, pq, tmp=BnnNumDigits(pq, pl)); | |
329 | BnnSetToZero(z+tmp, nl+1-tmp); | |
330 | BnnAssign(dp, z, (keys->dpl)=BnnNumDigits(z,nl)); | |
331 | ||
332 | BnnAssign(z, d, nl); | |
333 | z[nl] = 0; | |
334 | BnnAssign(pq, q, ql); | |
335 | BnnSubtractBorrow(pq, ql, 0); | |
336 | BnnDivide(z, nl+1, pq, tmp=BnnNumDigits(pq, ql)); | |
337 | BnnSetToZero(z+tmp, nl+1-tmp); | |
338 | BnnAssign(dq, z, (keys->dql)=BnnNumDigits(z,nl)); | |
339 | ||
340 | BnnGCD_1(g,r,cr,p,q,wgcd,pl); | |
341 | if ((BnnGetDigit(cr+(pl-1))&TopBitInWord)!=0) BnnAdd(cr,pl,p,pl,0); | |
342 | } | |
343 | ||
344 | modpwr2_1(z, 2, n, nl); | |
345 | BnnAssign(keys->beta2n, z, nl); | |
346 | muB_1(keys->nINV, n, nl*BN_DIGIT_SIZE); | |
347 | ||
348 | if (pl&&ql) { | |
349 | modpwr2_1(z, 3, p, pl); | |
350 | BnnAssign(keys->beta3p, z, pl); | |
351 | modpwr2_1(z, 2, p, pl); | |
352 | BnnAssign(keys->beta2p, z, pl); | |
353 | modpwr2_1(z, 3, q, ql); | |
354 | BnnAssign(keys->beta3q, z, ql); | |
355 | muB_1(keys->pINV, p, pl*BN_DIGIT_SIZE); | |
356 | muB_1(keys->qINV, q, ql*BN_DIGIT_SIZE); | |
357 | } | |
358 | ||
359 | #ifdef DEBUG_1 | |
360 | printf("\n"); | |
361 | printf("p = %s\n", BzToString(BzFromBigNum(p, pl), 16)); | |
362 | printf("q = %s\n", BzToString(BzFromBigNum(q, ql), 16)); | |
363 | printf("n = %s\n", BzToString(BzFromBigNum(n, nl), 16)); | |
364 | printf("e = %s\n", BzToString(BzFromBigNum(e, nl), 16)); | |
365 | printf("d = %s\n", BzToString(BzFromBigNum(d, nl), 16)); | |
366 | printf("dp = %s\n", BzToString(BzFromBigNum(dp, dpl), 16)); | |
367 | printf("dq = %s\n", BzToString(BzFromBigNum(dq, dql), 16)); | |
368 | printf("cr = %s\n", BzToString(BzFromBigNum(cr, pl), 16)); | |
369 | fflush(stdout); | |
370 | #endif | |
371 | ||
372 | ||
373 | return(1); | |
374 | } | |
375 | ||
376 | ||
377 | static BigNum muB_1(res, zz, bits) | |
378 | BigNum res, zz; | |
379 | int bits; | |
380 | { | |
381 | /* Compute -z^-1 mod 2^bits */ | |
382 | #define muBLIM 40 | |
383 | BigNumDigit n[muBLIM]; | |
384 | BigNumDigit msk[muBLIM], z[muBLIM]; | |
385 | unsigned nl = (bits+BN_DIGIT_SIZE-1)/BN_DIGIT_SIZE; | |
386 | int i; | |
387 | ||
388 | if (nl > muBLIM) | |
389 | { | |
390 | fprintf(stderr, "Limit check in %s:muB_1 line %d\n", __FILE__, __LINE__); | |
391 | abort(); | |
392 | } | |
393 | ||
394 | BnnSetToZero(n, nl); | |
395 | BnnComplement(n,nl); | |
396 | BnnSetToZero(res, nl); | |
397 | BnnSetToZero(msk, nl); | |
398 | BnnSetDigit(msk, 1); | |
399 | BnnAssign(z, zz, nl); | |
400 | BnnShiftRight(z,nl,1); | |
401 | while (bits--) | |
402 | { | |
403 | if (BnnIsDigitOdd(*n)) | |
404 | { | |
405 | for (i = 0; i < nl; i++) | |
406 | BnnOrDigits(res+i, msk[i]); | |
407 | BnnShiftRight(n,nl,1); | |
408 | BnnSubtract(n, nl, z, nl, 1); | |
409 | } | |
410 | else | |
411 | BnnShiftRight(n,nl,1); | |
412 | BnnShiftLeft(msk,nl,1); | |
413 | } | |
414 | return res; | |
415 | } | |
416 | ||
417 | static void modpwr2_1(result, pwr, m, ml) | |
418 | BigNum result, m; | |
419 | unsigned pwr, ml; | |
420 | { unsigned tmp; | |
421 | BnnSetToZero(result, pwr*ml); | |
422 | BnnSetDigit(result+pwr*ml, (BigNumDigit) 1); | |
423 | BnnDivide(result, pwr*ml+1, m, tmp=BnnNumDigits(m, ml)); | |
424 | BnnSetToZero(result+tmp, pwr*ml+1-tmp); | |
425 | } | |
426 | ||
427 | ||
428 | static void BnnGCD_1(gcd, A, B, U, V, work, len) | |
429 | BigNum gcd, A, B, U, V, work; | |
430 | int len; | |
431 | { | |
432 | /* Extended binary GCD | |
433 | code based on Knuth Vol.2 Second Edition | |
434 | section 4.5.2 Answers to Exercises page 599 | |
435 | */ | |
436 | /* Note: len must be large enough to hold 2*U or 2*V */ | |
437 | /* "work" is a BigNum of length 3*len */ | |
438 | BigNumDigit k; | |
439 | BigNum u1,u2,u3, v1,v2,v3; | |
440 | BigNum t1,t2,t3; | |
441 | u1 = A; u2 = B; u3 = gcd; | |
442 | v1 = work; v2 = work + len; v3 = work + 2*len; | |
443 | ||
444 | k = 0; | |
445 | while (!BnnIsDigitOdd(*U) && !BnnIsDigitOdd(*V)) | |
446 | { | |
447 | BnnShiftRight(U, len, 1); | |
448 | BnnShiftRight(V, len, 1); | |
449 | k++; | |
450 | } | |
451 | BnnSetToZero(u1, len); BnnSetDigit(u1, (BigNumDigit) 1); | |
452 | BnnSetToZero(u2, len); | |
453 | BnnAssign(u3, U, len); | |
454 | if (BnnIsDigitOdd(*U)) | |
455 | { | |
456 | t1 = v1; t2 = v2; t3 = v3; | |
457 | BnnSetToZero(v1, len); | |
458 | BnnSetToZero(v2, len); BnnComplement(v2, len); | |
459 | BnnSetToZero(v3, len); BnnSubtract(v3, len, V, len, 1); | |
460 | } | |
461 | else | |
462 | { | |
463 | t1 = u1; t2 = u2; t3 = u3; | |
464 | BnnAssign(v1, V, len); | |
465 | BnnSetToZero(v2, len); BnnSetDigit(v2, (BigNumDigit) 1); | |
466 | BnnSubtract(v2, len, U, len, 1); | |
467 | BnnAssign(v3, V, len); | |
468 | } | |
469 | #ifdef PRINT_LEVEL2 | |
470 | printf("#[%d %d %d ] [ %d %d %d ]\n", *u1,*u2,*u3, *v1,*v2,*v3); | |
471 | #endif | |
472 | while (!BnnIsZero(t3, len)) | |
473 | { | |
474 | while (!BnnIsDigitOdd(*t3)) | |
475 | { | |
476 | BigNumDigit sign; | |
477 | if (!BnnIsDigitOdd(*t1) && !BnnIsDigitOdd(*t2)) | |
478 | { | |
479 | sign = BnnGetDigit(t1+(len-1)) & TopBitInWord; | |
480 | BnnShiftRight(t1, len, 1); | |
481 | BnnOrDigits(t1+(len-1), sign); | |
482 | sign = BnnGetDigit(t2+(len-1)) & TopBitInWord; | |
483 | BnnShiftRight(t2, len, 1); | |
484 | BnnOrDigits(t2+(len-1), sign); | |
485 | } | |
486 | else | |
487 | { | |
488 | BnnAdd(t1, len, V, len, 0); | |
489 | sign = BnnGetDigit(t1+(len-1)) & TopBitInWord; | |
490 | BnnShiftRight(t1, len, 1); | |
491 | BnnOrDigits(t1+(len-1), sign); | |
492 | BnnSubtract(t2, len, U, len, 1); | |
493 | sign = BnnGetDigit(t2+(len-1)) & TopBitInWord; | |
494 | BnnShiftRight(t2, len, 1); | |
495 | BnnOrDigits(t2+(len-1), sign); | |
496 | } | |
497 | sign = BnnGetDigit(t3+(len-1)) & TopBitInWord; | |
498 | BnnShiftRight(t3, len, 1); | |
499 | BnnOrDigits(t3+(len-1), sign); | |
500 | } | |
501 | if (t1 == v1) /* a cheap way to recall what state we are in */ | |
502 | { | |
503 | BnnComplement(v1, len); | |
504 | BnnAdd(v1, len, V, len, 1); | |
505 | BnnComplement(v2, len); | |
506 | BnnAddCarry(v2, len, 1); | |
507 | BnnSubtract(v2, len, U, len, 1); | |
508 | BnnComplement(v3, len); | |
509 | BnnAddCarry(v3, len, 1); | |
510 | } | |
511 | if (BnnCompare(u3, len, v3, len) > 0) | |
512 | { | |
513 | BnnSubtract(u1, len, v1, len, 1); | |
514 | BnnSubtract(u2, len, v2, len, 1); | |
515 | BnnSubtract(u3, len, v3, len, 1); | |
516 | t1 = u1; t2 = u2; t3 = u3; | |
517 | } | |
518 | else | |
519 | { | |
520 | BnnComplement(v1, len); | |
521 | BnnAdd(v1, len, u1, len, 1); | |
522 | BnnComplement(v2, len); | |
523 | BnnAdd(v2, len, u2, len, 1); | |
524 | BnnComplement(v3, len); | |
525 | BnnAdd(v3, len, u3, len, 1); | |
526 | t1 = v1; t2 = v2; t3 = v3; | |
527 | } | |
528 | ||
529 | if (BnnGetDigit(t1+(len-1)) & TopBitInWord) | |
530 | { | |
531 | BnnAdd(t1, len, V, len, 0); | |
532 | BnnSubtract(t2, len, U, len, 1); | |
533 | } | |
534 | #ifdef PRINT_LEVEL2 | |
535 | printf(">[%d %d %d ] [ %d %d %d ]\n", *u1,*u2,*u3, *v1,*v2,*v3); | |
536 | #endif | |
537 | } | |
538 | while (k-- > 0) | |
539 | BnnShiftLeft(u3, len, 1); | |
540 | } | |
541 | ||
542 | ||
543 | /**********************************************************************/ | |
544 | ||
545 | static char *TestData = "Now is the time for all good men to come to the aid of their" ; | |
546 | static BigNumDigit test_in [2*DigitLim], test1 [2*DigitLim], test2 [2*DigitLim] ; | |
547 | ||
548 | int TestRSAKeys(key) | |
549 | RSAKeyStorage *key ; | |
550 | { | |
551 | int nl=key->nl; | |
552 | int ll = BnnNumDigits(key->n,nl); | |
553 | ||
554 | memset(test_in,0,sizeof(test_in)); | |
555 | memset(test1,0,sizeof(test1)); | |
556 | memset(test2,0,sizeof(test2)); | |
557 | strcpy((char *)test_in,TestData); | |
558 | BnnSetToZero(test_in+ll-2,(nl-ll)+3); | |
559 | #ifdef DEBUG | |
560 | printf("\nPrivate Key Encrypt/Decrypt Test."); | |
561 | printf("\nInput(hex): %s", BzToString(BzFromBigNum(test_in, nl), 16)); | |
562 | printf("\nInput(string): %s", test_in); | |
563 | #endif | |
564 | rsaencrypt_1(test_in,test1,key); | |
565 | #ifdef DEBUG | |
566 | printf("\nEncrypted: %s", BzToString(BzFromBigNum(test1, nl), 16)); | |
567 | #endif | |
568 | rsadecrypt_1(test1,test2,key); | |
569 | #ifdef DEBUG | |
570 | printf("\nDecrypted: %s", BzToString(BzFromBigNum(test2, nl), 16)); | |
571 | printf("\n"); | |
572 | #endif | |
573 | if (BnnCompare(test_in,nl,test2,nl) != 0) { | |
574 | #ifdef DEBUG | |
575 | printf("\nKey Test Failed.\n"); | |
576 | #endif | |
577 | return(0); | |
578 | } | |
579 | #ifdef DEBUG | |
580 | printf("\nKey Test Passed.\n"); | |
581 | #endif | |
582 | return(1); | |
583 | } | |
584 | ||
585 | static int Test2RSAPrivate_1(key) | |
586 | RSAKeyStorage *key ; | |
587 | { | |
588 | int nl=key->nl; | |
589 | int ll = BnnNumDigits(key->n,nl); | |
590 | ||
591 | memset(test_in,0,sizeof(test_in)); | |
592 | memset(test1,0,sizeof(test1)); | |
593 | memset(test2,0,sizeof(test2)); | |
594 | strcpy((char *)test_in,TestData); | |
595 | BnnSetToZero(test_in+ll-2,(nl-ll)+3); | |
596 | #ifdef DEBUG | |
597 | printf("\nPrivate Key Decrypt/Encrypt Test."); | |
598 | printf("\nInput(hex): %s", BzToString(BzFromBigNum(test_in, nl), 16)); | |
599 | printf("\nInput(string): %s", test_in); | |
600 | #endif | |
601 | rsadecrypt_1(test_in,test1,key); | |
602 | #ifdef DEBUG | |
603 | printf("\nSigned: %s", BzToString(BzFromBigNum(test1, nl), 16)); | |
604 | #endif | |
605 | rsaencrypt_1(test1,test2,key); | |
606 | #ifdef DEBUG | |
607 | printf("\nVerified: %s", BzToString(BzFromBigNum(test2, nl), 16)); | |
608 | printf("\n"); | |
609 | #endif | |
610 | if (BnnCompare(test_in,nl,test2,nl) != 0) { | |
611 | #ifdef DEBUG | |
612 | printf("\nKey Test Failed.\n"); | |
613 | #endif | |
614 | return(0); | |
615 | } | |
616 | return(1); | |
617 | } | |
618 | ||
619 | ||
620 | PrintBigNum(n,nl,radix) | |
621 | BigNum n; | |
622 | int radix, nl; | |
623 | { | |
624 | static char oneline [KEY_LINE+1]; | |
625 | char *p = BzToString(BzFromBigNum(n,nl), radix); | |
626 | ||
627 | oneline[KEY_LINE]='\0'; | |
628 | while(*p != '\0'){ | |
629 | strncpy(oneline,p,KEY_LINE); | |
630 | printf("\n %s",oneline); | |
631 | p+=((strlen(p)>KEY_LINE)?KEY_LINE:strlen(p)); | |
632 | } | |
633 | } | |
634 | ||
635 | int PrintTestKey (Keys) | |
636 | RSAKeyStorage *Keys; | |
637 | { | |
638 | int i; | |
639 | ||
640 | printf("\ne: (%d BigNumDigit", Keys->el); | |
641 | if(Keys->el > 1) printf("s) "); else printf(")"); | |
642 | PrintBigNum(Keys->e,Keys->el,KEY_RADIX); | |
643 | printf("\nn: (%d BigNumDigits) ", Keys->nl); | |
644 | PrintBigNum(Keys->n,Keys->nl,KEY_RADIX); | |
645 | ||
646 | if (Keys->pl) { printf("\np: (%d BigNumDigits) ", Keys->pl); | |
647 | PrintBigNum(Keys->p,Keys->pl,KEY_RADIX); | |
648 | printf("\nq: (%d BigNumDigits) ", Keys->ql); | |
649 | PrintBigNum(Keys->q,Keys->ql,KEY_RADIX); | |
650 | printf("\ndp: (%d BigNumDigits) ", Keys->dpl); | |
651 | PrintBigNum(Keys->dp, Keys->dpl,KEY_RADIX); | |
652 | printf("\ndq: (%d BigNumDigits) ", Keys->dql); | |
653 | PrintBigNum(Keys->dq, Keys->dql,KEY_RADIX); | |
654 | printf("\ncr: "); | |
655 | PrintBigNum(Keys->cr, Keys->pl,KEY_RADIX); | |
656 | } | |
657 | ||
658 | i=BnnNumDigits(Keys->nINV,sizeof(*Keys->nINV)*sizeof(int)); | |
659 | printf("\nnINV: (%d BigNumDigits) ", i); | |
660 | PrintBigNum(Keys->nINV, i, KEY_RADIX); | |
661 | ||
662 | i=BnnNumDigits(Keys->beta2n,sizeof(*Keys->beta2n)*sizeof(int)); | |
663 | printf("\nbeta2n: (%d BigNumDigits) ", i); | |
664 | PrintBigNum(Keys->beta2n, i,KEY_RADIX); | |
665 | ||
666 | if(Keys->pl) { | |
667 | i=BnnNumDigits(Keys->pINV,sizeof(*Keys->pINV)*sizeof(int)); | |
668 | printf("\npINV: (%d BigNumDigits) ", i); | |
669 | PrintBigNum(Keys->pINV, i,KEY_RADIX); | |
670 | ||
671 | i=BnnNumDigits(Keys->qINV,sizeof(*Keys->qINV)*sizeof(int)); | |
672 | printf("\nqINV: (%d BigNumDigits) ", i); | |
673 | PrintBigNum(Keys->qINV, i,KEY_RADIX); | |
674 | ||
675 | ||
676 | i=BnnNumDigits(Keys->beta2p,sizeof(*Keys->beta2p)*sizeof(int)); | |
677 | printf("\nbeta2p: (%d BigNumDigits) ", i); | |
678 | PrintBigNum(Keys->beta2p, i,KEY_RADIX); | |
679 | ||
680 | i=BnnNumDigits(Keys->beta3p,sizeof(*Keys->beta3p)*sizeof(int)); | |
681 | printf("\nbeta3p: (%d BigNumDigits) ", i); | |
682 | PrintBigNum(Keys->beta3p, i,KEY_RADIX); | |
683 | ||
684 | i=BnnNumDigits(Keys->beta3q,sizeof(*Keys->beta3q)*sizeof(int)); | |
685 | printf("\nbeta3q: (%d BigNumDigits) ", i); | |
686 | PrintBigNum(Keys->beta3q, i,KEY_RADIX); | |
687 | } | |
688 | ||
689 | printf("\n"); | |
690 | fflush(stdout); | |
691 | } | |
692 | ||
693 | ||
694 | int PrintPubKey (Keys) | |
695 | RSAKeyStorage *Keys; | |
696 | { | |
697 | int i=BnnNumDigits(Keys->n,Keys->nl); | |
698 | i = i*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(Keys->n[i-1]); | |
699 | ||
700 | printf("\ne: (%d BigNumDigit", Keys->el); | |
701 | if(Keys->el > 1) printf("s) "); else printf(")"); | |
702 | PrintBigNum(Keys->e,Keys->el,KEY_RADIX); | |
703 | printf("\nn: (%d BigNumDigits, %d bits) ", Keys->nl, i); | |
704 | PrintBigNum(Keys->n,Keys->nl,KEY_RADIX); | |
705 | ||
706 | printf("\n"); | |
707 | fflush(stdout); | |
708 | } | |
709 | ||
710 | int PrintPrivKey (Keys) | |
711 | RSAKeyStorage *Keys; | |
712 | { | |
713 | int i=BnnNumDigits(Keys->n,Keys->nl); | |
714 | i = i*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(Keys->n[i-1]); | |
715 | ||
716 | printf("\ne: (%d BigNumDigit", Keys->el); | |
717 | if(Keys->el > 1) printf("s) "); else printf(")"); | |
718 | PrintBigNum(Keys->e,Keys->el,KEY_RADIX); | |
719 | printf("\nn: (%d BigNumDigits, %d bits) ", Keys->nl, i); | |
720 | PrintBigNum(Keys->n,Keys->nl,KEY_RADIX); | |
721 | ||
722 | if (Keys->pl) { printf("\np: (%d BigNumDigits) ", Keys->pl); | |
723 | PrintBigNum(Keys->p,Keys->pl,KEY_RADIX); | |
724 | printf("\nq: (%d BigNumDigits) ", Keys->ql); | |
725 | PrintBigNum(Keys->q,Keys->ql,KEY_RADIX); | |
726 | printf("\ndp: (%d BigNumDigits) ", Keys->dpl); | |
727 | PrintBigNum(Keys->dp, Keys->dpl,KEY_RADIX); | |
728 | printf("\ndq: (%d BigNumDigits) ", Keys->dql); | |
729 | PrintBigNum(Keys->dq, Keys->dql,KEY_RADIX); | |
730 | printf("\ncr: "); | |
731 | PrintBigNum(Keys->cr, Keys->pl,KEY_RADIX); | |
732 | } | |
733 | else printf("\n no private key parameters."); | |
734 | ||
735 | printf("\n"); | |
736 | fflush(stdout); | |
737 | } | |
738 | ||
739 | ||
740 | /*********************************************************************/ | |
741 | ||
742 | /* In-line DES routines here. */ | |
743 | ||
744 | #include "DEScrypto.h" | |
745 | ||
746 | static KEYschedule local_key_schedule; | |
747 | static RSAKeyStorage tempkey; | |
748 | ||
749 | /* | |
750 | * Decrypts an RSA private key. | |
751 | */ | |
752 | int recover_private(deskey, encrypted_key, encrypted_key_len, key) | |
753 | DESblock *deskey; /* derived from password */ | |
754 | char *encrypted_key; /* input to be decrypted */ | |
755 | unsigned encrypted_key_len; /* must be multiple of 8 bytes */ | |
756 | RSAKeyStorage *key; /* output with new key in it */ | |
757 | { | |
758 | unsigned char *outbuf; | |
759 | int rt=0; | |
760 | ||
761 | if((outbuf=(unsigned char *)calloc(encrypted_key_len,1))==0)return(0); | |
762 | ||
763 | DES_load_key_local( deskey, &local_key_schedule); | |
764 | if (DES_CBC_decrypt_local(0, encrypted_key, encrypted_key_len, | |
765 | outbuf, &local_key_schedule)==0) | |
766 | goto clean; | |
767 | memset(&tempkey,0,sizeof(tempkey)); | |
768 | if (key->nl) tempkey.nl=key->nl, BnnAssign(tempkey.n,key->n,key->nl); | |
769 | #ifdef DEBUG | |
770 | printf("\nDecrypted private key:\n"); | |
771 | dumphex(outbuf,encrypted_key_len-sizeof(long)); | |
772 | #endif | |
773 | if (DecodePrivate(outbuf, &tempkey) != NULL) { | |
774 | #ifdef DEBUG | |
775 | printf("\nRecovered Key:\n"); | |
776 | PrintTestKey(&tempkey); | |
777 | #endif | |
778 | if (rt=TestRSAKeys(&tempkey)) memcpy(key,&tempkey,sizeof(RSAKeyStorage)); | |
779 | } | |
780 | #ifdef DEBUG | |
781 | else printf("\nDecode Failed.\n"); | |
782 | #endif | |
783 | ||
784 | memset(outbuf,0,encrypted_key_len); | |
785 | memset(&tempkey,0,sizeof(tempkey)); | |
786 | clean: | |
787 | free(outbuf); | |
788 | return(rt); | |
789 | } | |
790 | ||
791 | /* | |
792 | * Decrypts an RSA private key. | |
793 | */ | |
794 | int recover_privateP(deskey, encrypted_key, encrypted_key_len, key) | |
795 | DESblock *deskey; /* derived from password */ | |
796 | char *encrypted_key; /* input to be decrypted */ | |
797 | unsigned encrypted_key_len; /* must be multiple of 8 bytes */ | |
798 | RSAKeyStorage *key; /* output with new key in it */ | |
799 | { | |
800 | unsigned char *outbuf; | |
801 | int rt=0; | |
802 | ||
803 | if((outbuf=(unsigned char *)calloc(encrypted_key_len,1))==0)return(0); | |
804 | ||
805 | DES_load_key_local( deskey, &local_key_schedule); | |
806 | if (DES_CBC_decrypt_local(0, encrypted_key, encrypted_key_len, | |
807 | outbuf, &local_key_schedule)==0) | |
808 | goto clean; | |
809 | memset(&tempkey,0,sizeof(tempkey)); | |
810 | if (key->nl) tempkey.nl=key->nl, BnnAssign(tempkey.n,key->n,key->nl); | |
811 | #ifdef DEBUG | |
812 | printf("\nDecrypted private key:\n"); | |
813 | dumphex(outbuf,encrypted_key_len-sizeof(long)); | |
814 | #endif | |
815 | /* make sure that we decode the private key with only the prime p */ | |
816 | if (DecodePrivateP(outbuf, &tempkey) != NULL) { | |
817 | #ifdef DEBUG | |
818 | printf("\nRecovered Key:\n"); | |
819 | PrintTestKey(&tempkey); | |
820 | #endif | |
821 | if (rt=TestRSAKeys(&tempkey)) memcpy(key,&tempkey,sizeof(RSAKeyStorage)); | |
822 | } | |
823 | #ifdef DEBUG | |
824 | else printf("\nDecode Failed.\n"); | |
825 | #endif | |
826 | ||
827 | memset(outbuf,0,encrypted_key_len); | |
828 | memset(&tempkey,0,sizeof(tempkey)); | |
829 | clean: | |
830 | free(outbuf); | |
831 | return(rt); | |
832 | } | |
833 | ||
834 | /* | |
835 | * Encrypts an RSA private key. | |
836 | * | |
837 | * NOTE: Contains components to foil use as a general encrypt/decrypt | |
838 | * facility. | |
839 | * | |
840 | */ | |
841 | int hide_private(deskey, encrypted_key, encrypted_key_len, key) | |
842 | DESblock *deskey; /* derived from password */ | |
843 | char **encrypted_key; /* storage will be allocated */ | |
844 | unsigned *encrypted_key_len; /* will be written */ | |
845 | RSAKeyStorage *key; /* input must be a valid private key */ | |
846 | { | |
847 | unsigned char *outbuf, *encoded_key; | |
848 | int len, klen; | |
849 | ||
850 | if (TestRSAKeys(key)!=1) return(0); | |
851 | if ((encoded_key=EncodePrivate(key))==0) return(0) ; | |
852 | len = (((klen=DecodeTotalLength(encoded_key))+7)/8)*8; /* pad */ | |
853 | if ((outbuf = (unsigned char *)calloc(len,1)) ==0) | |
854 | {FreePrivate(encoded_key); return(0);}; | |
855 | memcpy(outbuf,encoded_key,klen); | |
856 | FreePrivate(encoded_key); | |
857 | DES_load_key_local(deskey, &local_key_schedule); | |
858 | DES_CBC_encrypt_local (0, outbuf, len, outbuf, &local_key_schedule); | |
859 | *encrypted_key = (char *)outbuf; | |
860 | *encrypted_key_len = len; | |
861 | return(1); | |
862 | } | |
863 | ||
864 | ||
865 | /* | |
866 | * Same as above, but only encrypts prime P | |
867 | */ | |
868 | int hide_privateP(deskey, encrypted_key, encrypted_key_len, key) | |
869 | DESblock *deskey; /* derived from password */ | |
870 | char **encrypted_key; /* storage will be allocated */ | |
871 | unsigned *encrypted_key_len; /* will be written */ | |
872 | RSAKeyStorage *key; /* input must be a valid private key */ | |
873 | { | |
874 | unsigned char *outbuf, *encoded_key; | |
875 | int len, klen; | |
876 | ||
877 | if (TestRSAKeys(key)!=1) return(0); | |
878 | if ((encoded_key=EncodePrivateP(key))==0) return(0) ; | |
879 | len = (((klen=DecodeTotalLength(encoded_key))+7)/8)*8; | |
880 | if ((outbuf = (unsigned char *)calloc(len,1)) ==0) | |
881 | {FreePrivate(encoded_key); return(0);}; | |
882 | memcpy(outbuf,encoded_key,klen); | |
883 | FreePrivate(encoded_key); | |
884 | DES_load_key_local(deskey, &local_key_schedule); | |
885 | DES_CBC_encrypt_local (0, outbuf, len, outbuf, &local_key_schedule); | |
886 | *encrypted_key = (char *)outbuf; | |
887 | *encrypted_key_len = len; | |
888 | return(1); | |
889 | } |