2 * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
5 * "Digital Equipment Corporation authorizes the reproduction,
6 * distribution and modification of this software subject to the following
9 * 1. Any partial or whole copy of this software, or any modification
10 * thereof, must include this copyright notice in its entirety.
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.
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.
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.
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"
34 /* This code was derived from Mark Shand's PRL Montgomery code. */
38 #include <sys/types.h>
40 #include <sys/timeb.h>
45 #include "bigrsacode.h"
46 #include "bigkeygen.h"
59 /* Global storage indicating whether to print prime progress reports */
61 int bigkeygenPrintStatistics = 0;
68 * One-half the difference between the lengths of p and q, in bits
70 #define PRIME_BIT_DIFF 3
73 * Local modular product routines
76 /* put in-line RSA routines here */
78 #include "RSAcrypto.h"
80 static void BnnGCD_1();
81 static void modpwr2_1();
82 static BigNum muB_1();
83 static int bigprime();
86 * newRSAKey generates a new RSA key instance.
88 * bitlen length of primes, in bits. Modulus will be
89 * approximately 2*bitlen
90 * keys RSAKeyStorage structure for new key
93 int newRSAKey ( bitlen , keys )
97 BigNum p = keys->p, q = keys->q ;
98 unsigned lowbits = 1, confidence = 20, pl, ql;
100 clock_t mark, tenths;
101 struct timeb start_time , end_time ;
104 if ((bitlen<128)||(bitlen>MaxPrimeBits)) return (0);
106 memset(keys,0,sizeof(RSAKeyStorage));
114 bigprime(p, &pl, bitlen+PRIME_BIT_DIFF, lowbits, confidence, 0);
116 bigprime(q, &ql, bitlen-PRIME_BIT_DIFF, lowbits, confidence, 0);
117 } while (BnnCompare(p, pl, q, ql) == 0);
120 mark = clock() - mark ;
124 #ifndef CLOCKS_PER_SEC
125 #define CLOCKS_PER_SEC 1000000
127 tenths = (100*(mark%CLOCKS_PER_SEC))/CLOCKS_PER_SEC ;
128 mark /= CLOCKS_PER_SEC ;
130 tenths = (100*(mark%CLK_TCK))/CLK_TCK ;
134 printf ("\n/* Primes found in %d.%02d seconds of process time*/\n", mark, tenths );
135 mark = end_time.time - start_time.time ;
136 { long xt = (unsigned long) end_time.millitm - (unsigned long) start_time.millitm ;
137 if (xt<0) { mark--; xt = 1000 - xt;}
138 printf ("\n/* Primes found in %d.%03d elapsed seconds */\n",
139 end_time.time-start_time.time, xt );
143 if (BnnCompare(p, pl, q, ql) == -1) {
145 BigNumDigit tp[DigitLim];
146 BnnSetToZero(tp,DigitLim);
159 * Set exponent to F16 and compute modulus.
161 BnnSetDigit(keys->e, (BigNumDigit) ((1<<16)+1));
164 BnnMultiply(keys->n, pl+ql, p, pl, q, ql),
167 if (FinishKey(keys)==0) return (0);
169 if (TestRSAKeys(keys)!=1) {
171 printf("\nFailed.\n");
182 * Prime-finding routines
186 static BigNumDigit smallprime[]=
187 {3,5,7,11,13,17,19,23,29,31,37,41,43,53,59,
188 61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,
189 163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,
190 257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,
191 359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,
192 461,463,467,479,487,491,499 };
196 * Test for primality.
199 static int IsPrime(n,nl,confidence)
204 static BigNumDigit x[DigitLim],
206 beta2n[2*DigitLim+1],
209 for(i=0;i<=(sizeof(smallprime)/sizeof(BigNumDigit));i++)
210 if(BnnDivideDigit(y,n,nl+1,smallprime[i])==0) goto exit ;
212 muB_1(nINV, n, nl*BN_DIGIT_SIZE);
213 modpwr2_1(beta2n, 2, n, nl);
214 BnnSetToZero (x, nl);
216 for(i=0;i<=confidence;i++) {
217 x[0]+= smallprime[i] ;
218 BnnDyRaise_1(y, x, n, nl, n, beta2n, nINV, nl);
219 BnnDyCanon_1(y, n, nl);
220 if (BnnCompare(y, nl, x, nl)) goto exit;
229 * Generate a big prime.
231 static bigprime (n,nlen,bitlen,lowbits,confidence,stats)
240 static char sieve [1000];
242 BigNumDigit r, s, q[DigitLim] ;
243 unsigned nl =(bitlen+(BN_DIGIT_SIZE-1))/BN_DIGIT_SIZE ;
246 if((((bitlen-1)%BN_DIGIT_SIZE)+1)>=(BN_DIGIT_SIZE-1)) nl++;
248 BnnSetToZero(n,nl+1);
250 random_BigNum(n,ntop);
251 n[nl-1]&=(1<<((BN_DIGIT_SIZE)-(nl*(BN_DIGIT_SIZE)-bitlen))) -1 ;
252 n[(bitlen-1)/BN_DIGIT_SIZE] |= 1<<((bitlen-1)%BN_DIGIT_SIZE);
253 n[(bitlen-2)/BN_DIGIT_SIZE] |= 1<<((bitlen-2)%BN_DIGIT_SIZE);
256 if(bigkeygenPrintStatistics)
257 printf("\nCandidate Random Number: %s\n",BzToString(BzFromBigNum(n,nl),16));
260 for (i=0;i<1000;i=i+2){*z++=1;*z++=0;};
261 r = BnnDivideDigit(q,n,nl+1,(BigNumDigit)3);
262 if (r==0) r = (BigNumDigit) 3;
265 for (j=3-r;j<1000;j+=3) {*z=1;z+=3;}
267 for (s=3;s<10000;s+=2) {
268 for (j=0; j<5; j++)if ((s>smallprime[j])&&(0==(s%smallprime[j]))) goto nexts;
269 r = BnnDivideDigit(q,n,nl+1,s);
272 for (j=s-r;j<1000;j+=s) {*z=1;z+=s;}
275 for(i=0;i<1000;i++) {
278 if(bigkeygenPrintStatistics) printf("|"),fflush(stdout);
280 if (IsPrime(n,nl,5)) goto exit;
282 BnnAddCarry(n,nl,1); /* try next one */
287 if(bigkeygenPrintStatistics) printf(""), fflush(stdout);
293 * This routine expects modulus n and exponent e to be initialized
294 * in the RSAKeyStorage structure supplied. It computes the rest of
295 * the key components based on what is provided. If p and q are there
296 * it also makes sure a complete private key is initialized.
301 static BigNumDigit g[4*DigitLim], wgcd[12*DigitLim],
302 r[4*DigitLim], pq[4*DigitLim], d[4*DigitLim], z[4*DigitLim];
304 BigNum n = keys->n, dp = keys->dp, dq = keys->dq, cr = keys->cr,
305 e = keys->e, p = keys->p, q = keys->q ;
307 unsigned nl=keys->nl, pl=keys->pl, ql=keys->ql, tmp,
308 dpl = keys->dpl, dql = keys->dql ;
311 * If primes are supplied, generate dp, dq, and cr if needed.
312 * Assume cr there if dp and dq are.
315 if (pl && ql && ((dpl == 0)||(dql ==0)) ) {
316 BnnAssign(pq, n, nl);
317 BnnSubtract(pq, nl, p, pl, 1);
318 BnnSubtract(pq, nl, q, ql, 1);
319 BnnAddCarry(pq, nl, 1);
320 BnnGCD_1(g, d, r, e, pq, wgcd, nl);
321 if (BnnCompare(g,nl,one,nl)!=0) {
323 printf("GCD failed to generate private key exponent.\n");
329 BnnAssign(pq, p, pl);
330 BnnSubtractBorrow(pq, pl, 0);
331 BnnDivide(z, nl+1, pq, tmp=BnnNumDigits(pq, pl));
332 BnnSetToZero(z+tmp, nl+1-tmp);
333 BnnAssign(dp, z, (keys->dpl)=BnnNumDigits(z,nl));
337 BnnAssign(pq, q, ql);
338 BnnSubtractBorrow(pq, ql, 0);
339 BnnDivide(z, nl+1, pq, tmp=BnnNumDigits(pq, ql));
340 BnnSetToZero(z+tmp, nl+1-tmp);
341 BnnAssign(dq, z, (keys->dql)=BnnNumDigits(z,nl));
343 BnnGCD_1(g,r,cr,p,q,wgcd,pl);
344 if ((BnnGetDigit(cr+(pl-1))&TopBitInWord)!=0) BnnAdd(cr,pl,p,pl,0);
347 modpwr2_1(z, 2, n, nl);
348 BnnAssign(keys->beta2n, z, nl);
349 muB_1(keys->nINV, n, nl*BN_DIGIT_SIZE);
352 modpwr2_1(z, 3, p, pl);
353 BnnAssign(keys->beta3p, z, pl);
354 modpwr2_1(z, 2, p, pl);
355 BnnAssign(keys->beta2p, z, pl);
356 modpwr2_1(z, 3, q, ql);
357 BnnAssign(keys->beta3q, z, ql);
358 muB_1(keys->pINV, p, pl*BN_DIGIT_SIZE);
359 muB_1(keys->qINV, q, ql*BN_DIGIT_SIZE);
364 printf("p = %s\n", BzToString(BzFromBigNum(p, pl), 16));
365 printf("q = %s\n", BzToString(BzFromBigNum(q, ql), 16));
366 printf("n = %s\n", BzToString(BzFromBigNum(n, nl), 16));
367 printf("e = %s\n", BzToString(BzFromBigNum(e, nl), 16));
368 printf("d = %s\n", BzToString(BzFromBigNum(d, nl), 16));
369 printf("dp = %s\n", BzToString(BzFromBigNum(dp, dpl), 16));
370 printf("dq = %s\n", BzToString(BzFromBigNum(dq, dql), 16));
371 printf("cr = %s\n", BzToString(BzFromBigNum(cr, pl), 16));
380 static BigNum muB_1(res, zz, bits)
384 /* Compute -z^-1 mod 2^bits */
386 BigNumDigit n[muBLIM];
387 BigNumDigit msk[muBLIM], z[muBLIM];
388 unsigned nl = (bits+BN_DIGIT_SIZE-1)/BN_DIGIT_SIZE;
393 fprintf(stderr, "Limit check in %s:muB_1 line %d\n", __FILE__, __LINE__);
399 BnnSetToZero(res, nl);
400 BnnSetToZero(msk, nl);
402 BnnAssign(z, zz, nl);
403 BnnShiftRight(z,nl,1);
406 if (BnnIsDigitOdd(*n))
408 for (i = 0; i < nl; i++)
409 BnnOrDigits(res+i, msk[i]);
410 BnnShiftRight(n,nl,1);
411 BnnSubtract(n, nl, z, nl, 1);
414 BnnShiftRight(n,nl,1);
415 BnnShiftLeft(msk,nl,1);
420 static void modpwr2_1(result, pwr, m, ml)
424 BnnSetToZero(result, pwr*ml);
425 BnnSetDigit(result+pwr*ml, (BigNumDigit) 1);
426 BnnDivide(result, pwr*ml+1, m, tmp=BnnNumDigits(m, ml));
427 BnnSetToZero(result+tmp, pwr*ml+1-tmp);
431 static void BnnGCD_1(gcd, A, B, U, V, work, len)
432 BigNum gcd, A, B, U, V, work;
435 /* Extended binary GCD
436 code based on Knuth Vol.2 Second Edition
437 section 4.5.2 Answers to Exercises page 599
439 /* Note: len must be large enough to hold 2*U or 2*V */
440 /* "work" is a BigNum of length 3*len */
442 BigNum u1,u2,u3, v1,v2,v3;
444 u1 = A; u2 = B; u3 = gcd;
445 v1 = work; v2 = work + len; v3 = work + 2*len;
448 while (!BnnIsDigitOdd(*U) && !BnnIsDigitOdd(*V))
450 BnnShiftRight(U, len, 1);
451 BnnShiftRight(V, len, 1);
454 BnnSetToZero(u1, len); BnnSetDigit(u1, (BigNumDigit) 1);
455 BnnSetToZero(u2, len);
456 BnnAssign(u3, U, len);
457 if (BnnIsDigitOdd(*U))
459 t1 = v1; t2 = v2; t3 = v3;
460 BnnSetToZero(v1, len);
461 BnnSetToZero(v2, len); BnnComplement(v2, len);
462 BnnSetToZero(v3, len); BnnSubtract(v3, len, V, len, 1);
466 t1 = u1; t2 = u2; t3 = u3;
467 BnnAssign(v1, V, len);
468 BnnSetToZero(v2, len); BnnSetDigit(v2, (BigNumDigit) 1);
469 BnnSubtract(v2, len, U, len, 1);
470 BnnAssign(v3, V, len);
473 printf("#[%d %d %d ] [ %d %d %d ]\n", *u1,*u2,*u3, *v1,*v2,*v3);
475 while (!BnnIsZero(t3, len))
477 while (!BnnIsDigitOdd(*t3))
480 if (!BnnIsDigitOdd(*t1) && !BnnIsDigitOdd(*t2))
482 sign = BnnGetDigit(t1+(len-1)) & TopBitInWord;
483 BnnShiftRight(t1, len, 1);
484 BnnOrDigits(t1+(len-1), sign);
485 sign = BnnGetDigit(t2+(len-1)) & TopBitInWord;
486 BnnShiftRight(t2, len, 1);
487 BnnOrDigits(t2+(len-1), sign);
491 BnnAdd(t1, len, V, len, 0);
492 sign = BnnGetDigit(t1+(len-1)) & TopBitInWord;
493 BnnShiftRight(t1, len, 1);
494 BnnOrDigits(t1+(len-1), sign);
495 BnnSubtract(t2, len, U, len, 1);
496 sign = BnnGetDigit(t2+(len-1)) & TopBitInWord;
497 BnnShiftRight(t2, len, 1);
498 BnnOrDigits(t2+(len-1), sign);
500 sign = BnnGetDigit(t3+(len-1)) & TopBitInWord;
501 BnnShiftRight(t3, len, 1);
502 BnnOrDigits(t3+(len-1), sign);
504 if (t1 == v1) /* a cheap way to recall what state we are in */
506 BnnComplement(v1, len);
507 BnnAdd(v1, len, V, len, 1);
508 BnnComplement(v2, len);
509 BnnAddCarry(v2, len, 1);
510 BnnSubtract(v2, len, U, len, 1);
511 BnnComplement(v3, len);
512 BnnAddCarry(v3, len, 1);
514 if (BnnCompare(u3, len, v3, len) > 0)
516 BnnSubtract(u1, len, v1, len, 1);
517 BnnSubtract(u2, len, v2, len, 1);
518 BnnSubtract(u3, len, v3, len, 1);
519 t1 = u1; t2 = u2; t3 = u3;
523 BnnComplement(v1, len);
524 BnnAdd(v1, len, u1, len, 1);
525 BnnComplement(v2, len);
526 BnnAdd(v2, len, u2, len, 1);
527 BnnComplement(v3, len);
528 BnnAdd(v3, len, u3, len, 1);
529 t1 = v1; t2 = v2; t3 = v3;
532 if (BnnGetDigit(t1+(len-1)) & TopBitInWord)
534 BnnAdd(t1, len, V, len, 0);
535 BnnSubtract(t2, len, U, len, 1);
538 printf(">[%d %d %d ] [ %d %d %d ]\n", *u1,*u2,*u3, *v1,*v2,*v3);
542 BnnShiftLeft(u3, len, 1);
546 /**********************************************************************/
548 static char *TestData = "Now is the time for all good men to come to the aid of their" ;
549 static BigNumDigit test_in [2*DigitLim], test1 [2*DigitLim], test2 [2*DigitLim] ;
555 int ll = BnnNumDigits(key->n,nl);
557 memset(test_in,0,sizeof(test_in));
558 memset(test1,0,sizeof(test1));
559 memset(test2,0,sizeof(test2));
560 strcpy((char *)test_in,TestData);
561 BnnSetToZero(test_in+ll-2,(nl-ll)+3);
563 printf("\nPrivate Key Encrypt/Decrypt Test.");
564 printf("\nInput(hex): %s", BzToString(BzFromBigNum(test_in, nl), 16));
565 printf("\nInput(string): %s", test_in);
567 rsaencrypt_1(test_in,test1,key);
569 printf("\nEncrypted: %s", BzToString(BzFromBigNum(test1, nl), 16));
571 rsadecrypt_1(test1,test2,key);
573 printf("\nDecrypted: %s", BzToString(BzFromBigNum(test2, nl), 16));
576 if (BnnCompare(test_in,nl,test2,nl) != 0) {
578 printf("\nKey Test Failed.\n");
583 printf("\nKey Test Passed.\n");
588 static int Test2RSAPrivate_1(key)
592 int ll = BnnNumDigits(key->n,nl);
594 memset(test_in,0,sizeof(test_in));
595 memset(test1,0,sizeof(test1));
596 memset(test2,0,sizeof(test2));
597 strcpy((char *)test_in,TestData);
598 BnnSetToZero(test_in+ll-2,(nl-ll)+3);
600 printf("\nPrivate Key Decrypt/Encrypt Test.");
601 printf("\nInput(hex): %s", BzToString(BzFromBigNum(test_in, nl), 16));
602 printf("\nInput(string): %s", test_in);
604 rsadecrypt_1(test_in,test1,key);
606 printf("\nSigned: %s", BzToString(BzFromBigNum(test1, nl), 16));
608 rsaencrypt_1(test1,test2,key);
610 printf("\nVerified: %s", BzToString(BzFromBigNum(test2, nl), 16));
613 if (BnnCompare(test_in,nl,test2,nl) != 0) {
615 printf("\nKey Test Failed.\n");
623 PrintBigNum(n,nl,radix)
627 static char oneline [KEY_LINE+1];
628 char *p = BzToString(BzFromBigNum(n,nl), radix);
630 oneline[KEY_LINE]='\0';
632 strncpy(oneline,p,KEY_LINE);
633 printf("\n %s",oneline);
634 p+=((strlen(p)>KEY_LINE)?KEY_LINE:strlen(p));
638 int PrintTestKey (Keys)
643 printf("\ne: (%d BigNumDigit", Keys->el);
644 if(Keys->el > 1) printf("s) "); else printf(")");
645 PrintBigNum(Keys->e,Keys->el,KEY_RADIX);
646 printf("\nn: (%d BigNumDigits) ", Keys->nl);
647 PrintBigNum(Keys->n,Keys->nl,KEY_RADIX);
649 if (Keys->pl) { printf("\np: (%d BigNumDigits) ", Keys->pl);
650 PrintBigNum(Keys->p,Keys->pl,KEY_RADIX);
651 printf("\nq: (%d BigNumDigits) ", Keys->ql);
652 PrintBigNum(Keys->q,Keys->ql,KEY_RADIX);
653 printf("\ndp: (%d BigNumDigits) ", Keys->dpl);
654 PrintBigNum(Keys->dp, Keys->dpl,KEY_RADIX);
655 printf("\ndq: (%d BigNumDigits) ", Keys->dql);
656 PrintBigNum(Keys->dq, Keys->dql,KEY_RADIX);
658 PrintBigNum(Keys->cr, Keys->pl,KEY_RADIX);
661 i=BnnNumDigits(Keys->nINV,sizeof(*Keys->nINV)*sizeof(int));
662 printf("\nnINV: (%d BigNumDigits) ", i);
663 PrintBigNum(Keys->nINV, i, KEY_RADIX);
665 i=BnnNumDigits(Keys->beta2n,sizeof(*Keys->beta2n)*sizeof(int));
666 printf("\nbeta2n: (%d BigNumDigits) ", i);
667 PrintBigNum(Keys->beta2n, i,KEY_RADIX);
670 i=BnnNumDigits(Keys->pINV,sizeof(*Keys->pINV)*sizeof(int));
671 printf("\npINV: (%d BigNumDigits) ", i);
672 PrintBigNum(Keys->pINV, i,KEY_RADIX);
674 i=BnnNumDigits(Keys->qINV,sizeof(*Keys->qINV)*sizeof(int));
675 printf("\nqINV: (%d BigNumDigits) ", i);
676 PrintBigNum(Keys->qINV, i,KEY_RADIX);
679 i=BnnNumDigits(Keys->beta2p,sizeof(*Keys->beta2p)*sizeof(int));
680 printf("\nbeta2p: (%d BigNumDigits) ", i);
681 PrintBigNum(Keys->beta2p, i,KEY_RADIX);
683 i=BnnNumDigits(Keys->beta3p,sizeof(*Keys->beta3p)*sizeof(int));
684 printf("\nbeta3p: (%d BigNumDigits) ", i);
685 PrintBigNum(Keys->beta3p, i,KEY_RADIX);
687 i=BnnNumDigits(Keys->beta3q,sizeof(*Keys->beta3q)*sizeof(int));
688 printf("\nbeta3q: (%d BigNumDigits) ", i);
689 PrintBigNum(Keys->beta3q, i,KEY_RADIX);
697 int PrintPubKey (Keys)
700 int i=BnnNumDigits(Keys->n,Keys->nl);
701 i = i*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(Keys->n[i-1]);
703 printf("\ne: (%d BigNumDigit", Keys->el);
704 if(Keys->el > 1) printf("s) "); else printf(")");
705 PrintBigNum(Keys->e,Keys->el,KEY_RADIX);
706 printf("\nn: (%d BigNumDigits, %d bits) ", Keys->nl, i);
707 PrintBigNum(Keys->n,Keys->nl,KEY_RADIX);
713 int PrintPrivKey (Keys)
716 int i=BnnNumDigits(Keys->n,Keys->nl);
717 i = i*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(Keys->n[i-1]);
719 printf("\ne: (%d BigNumDigit", Keys->el);
720 if(Keys->el > 1) printf("s) "); else printf(")");
721 PrintBigNum(Keys->e,Keys->el,KEY_RADIX);
722 printf("\nn: (%d BigNumDigits, %d bits) ", Keys->nl, i);
723 PrintBigNum(Keys->n,Keys->nl,KEY_RADIX);
725 if (Keys->pl) { printf("\np: (%d BigNumDigits) ", Keys->pl);
726 PrintBigNum(Keys->p,Keys->pl,KEY_RADIX);
727 printf("\nq: (%d BigNumDigits) ", Keys->ql);
728 PrintBigNum(Keys->q,Keys->ql,KEY_RADIX);
729 printf("\ndp: (%d BigNumDigits) ", Keys->dpl);
730 PrintBigNum(Keys->dp, Keys->dpl,KEY_RADIX);
731 printf("\ndq: (%d BigNumDigits) ", Keys->dql);
732 PrintBigNum(Keys->dq, Keys->dql,KEY_RADIX);
734 PrintBigNum(Keys->cr, Keys->pl,KEY_RADIX);
736 else printf("\n no private key parameters.");
743 /*********************************************************************/
745 /* In-line DES routines here. */
747 #include "DEScrypto.h"
749 static KEYschedule local_key_schedule;
750 static RSAKeyStorage tempkey;
753 * Decrypts an RSA private key.
755 int recover_private(deskey, encrypted_key, encrypted_key_len, key)
756 DESblock *deskey; /* derived from password */
757 char *encrypted_key; /* input to be decrypted */
758 unsigned encrypted_key_len; /* must be multiple of 8 bytes */
759 RSAKeyStorage *key; /* output with new key in it */
761 unsigned char *outbuf;
764 if((outbuf=(unsigned char *)calloc(encrypted_key_len,1))==0)return(0);
766 DES_load_key_local( deskey, &local_key_schedule);
767 if (DES_CBC_decrypt_local(0, encrypted_key, encrypted_key_len,
768 outbuf, &local_key_schedule)==0)
770 memset(&tempkey,0,sizeof(tempkey));
771 if (key->nl) tempkey.nl=key->nl, BnnAssign(tempkey.n,key->n,key->nl);
773 printf("\nDecrypted private key:\n");
774 dumphex(outbuf,encrypted_key_len-sizeof(long));
776 if (DecodePrivate(outbuf, &tempkey) != NULL) {
778 printf("\nRecovered Key:\n");
779 PrintTestKey(&tempkey);
781 if (rt=TestRSAKeys(&tempkey)) memcpy(key,&tempkey,sizeof(RSAKeyStorage));
784 else printf("\nDecode Failed.\n");
787 memset(outbuf,0,encrypted_key_len);
788 memset(&tempkey,0,sizeof(tempkey));
795 * Decrypts an RSA private key.
797 int recover_privateP(deskey, encrypted_key, encrypted_key_len, key)
798 DESblock *deskey; /* derived from password */
799 char *encrypted_key; /* input to be decrypted */
800 unsigned encrypted_key_len; /* must be multiple of 8 bytes */
801 RSAKeyStorage *key; /* output with new key in it */
803 unsigned char *outbuf;
806 if((outbuf=(unsigned char *)calloc(encrypted_key_len,1))==0)return(0);
808 DES_load_key_local( deskey, &local_key_schedule);
809 if (DES_CBC_decrypt_local(0, encrypted_key, encrypted_key_len,
810 outbuf, &local_key_schedule)==0)
812 memset(&tempkey,0,sizeof(tempkey));
813 if (key->nl) tempkey.nl=key->nl, BnnAssign(tempkey.n,key->n,key->nl);
815 printf("\nDecrypted private key:\n");
816 dumphex(outbuf,encrypted_key_len-sizeof(long));
818 /* make sure that we decode the private key with only the prime p */
819 if (DecodePrivateP(outbuf, &tempkey) != NULL) {
821 printf("\nRecovered Key:\n");
822 PrintTestKey(&tempkey);
824 if (rt=TestRSAKeys(&tempkey)) memcpy(key,&tempkey,sizeof(RSAKeyStorage));
827 else printf("\nDecode Failed.\n");
830 memset(outbuf,0,encrypted_key_len);
831 memset(&tempkey,0,sizeof(tempkey));
838 * Encrypts an RSA private key.
840 * NOTE: Contains components to foil use as a general encrypt/decrypt
844 int hide_private(deskey, encrypted_key, encrypted_key_len, key)
845 DESblock *deskey; /* derived from password */
846 char **encrypted_key; /* storage will be allocated */
847 unsigned *encrypted_key_len; /* will be written */
848 RSAKeyStorage *key; /* input must be a valid private key */
850 unsigned char *outbuf, *encoded_key;
853 if (TestRSAKeys(key)!=1) return(0);
854 if ((encoded_key=EncodePrivate(key))==0) return(0) ;
855 len = (((klen=DecodeTotalLength(encoded_key))+7)/8)*8; /* pad */
856 if ((outbuf = (unsigned char *)calloc(len,1)) ==0)
857 {FreePrivate(encoded_key); return(0);};
858 memcpy(outbuf,encoded_key,klen);
859 FreePrivate(encoded_key);
860 DES_load_key_local(deskey, &local_key_schedule);
861 DES_CBC_encrypt_local (0, outbuf, len, outbuf, &local_key_schedule);
862 *encrypted_key = (char *)outbuf;
863 *encrypted_key_len = len;
869 * Same as above, but only encrypts prime P
871 int hide_privateP(deskey, encrypted_key, encrypted_key_len, key)
872 DESblock *deskey; /* derived from password */
873 char **encrypted_key; /* storage will be allocated */
874 unsigned *encrypted_key_len; /* will be written */
875 RSAKeyStorage *key; /* input must be a valid private key */
877 unsigned char *outbuf, *encoded_key;
880 if (TestRSAKeys(key)!=1) return(0);
881 if ((encoded_key=EncodePrivateP(key))==0) return(0) ;
882 len = (((klen=DecodeTotalLength(encoded_key))+7)/8)*8;
883 if ((outbuf = (unsigned char *)calloc(len,1)) ==0)
884 {FreePrivate(encoded_key); return(0);};
885 memcpy(outbuf,encoded_key,klen);
886 FreePrivate(encoded_key);
887 DES_load_key_local(deskey, &local_key_schedule);
888 DES_CBC_encrypt_local (0, outbuf, len, outbuf, &local_key_schedule);
889 *encrypted_key = (char *)outbuf;
890 *encrypted_key_len = len;