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>
42 #include "bigrsacode.h"
43 #include "bigkeygen.h"
56 /* Global storage indicating whether to print prime progress reports */
58 int bigkeygenPrintStatistics = 0;
65 * One-half the difference between the lengths of p and q, in bits
67 #define PRIME_BIT_DIFF 3
70 * Local modular product routines
73 /* put in-line RSA routines here */
75 #include "RSAcrypto.h"
77 static void BnnGCD_1();
78 static void modpwr2_1();
79 static BigNum muB_1();
80 static int bigprime();
83 * newRSAKey generates a new RSA key instance.
85 * bitlen length of primes, in bits. Modulus will be
86 * approximately 2*bitlen
87 * keys RSAKeyStorage structure for new key
90 int newRSAKey ( bitlen , keys )
94 BigNum p = keys->p, q = keys->q ;
95 unsigned lowbits = 1, confidence = 20, pl, ql;
98 struct timeb start_time , end_time ;
101 if ((bitlen<128)||(bitlen>MaxPrimeBits)) return (0);
103 memset(keys,0,sizeof(RSAKeyStorage));
111 bigprime(p, &pl, bitlen+PRIME_BIT_DIFF, lowbits, confidence, 0);
113 bigprime(q, &ql, bitlen-PRIME_BIT_DIFF, lowbits, confidence, 0);
114 } while (BnnCompare(p, pl, q, ql) == 0);
117 mark = clock() - mark ;
121 #ifndef CLOCKS_PER_SEC
122 #define CLOCKS_PER_SEC 1000000
124 tenths = (100*(mark%CLOCKS_PER_SEC))/CLOCKS_PER_SEC ;
125 mark /= CLOCKS_PER_SEC ;
127 tenths = (100*(mark%CLK_TCK))/CLK_TCK ;
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 );
140 if (BnnCompare(p, pl, q, ql) == -1) {
142 BigNumDigit tp[DigitLim];
143 BnnSetToZero(tp,DigitLim);
156 * Set exponent to F16 and compute modulus.
158 BnnSetDigit(keys->e, (BigNumDigit) ((1<<16)+1));
161 BnnMultiply(keys->n, pl+ql, p, pl, q, ql),
164 if (FinishKey(keys)==0) return (0);
166 if (TestRSAKeys(keys)!=1) {
168 printf("\nFailed.\n");
179 * Prime-finding routines
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 };
193 * Test for primality.
196 static int IsPrime(n,nl,confidence)
201 static BigNumDigit x[DigitLim],
203 beta2n[2*DigitLim+1],
206 for(i=0;i<=(sizeof(smallprime)/sizeof(BigNumDigit));i++)
207 if(BnnDivideDigit(y,n,nl+1,smallprime[i])==0) goto exit ;
209 muB_1(nINV, n, nl*BN_DIGIT_SIZE);
210 modpwr2_1(beta2n, 2, n, nl);
211 BnnSetToZero (x, nl);
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;
226 * Generate a big prime.
228 static bigprime (n,nlen,bitlen,lowbits,confidence,stats)
237 static char sieve [1000];
239 BigNumDigit r, s, q[DigitLim] ;
240 unsigned nl =(bitlen+(BN_DIGIT_SIZE-1))/BN_DIGIT_SIZE ;
243 if((((bitlen-1)%BN_DIGIT_SIZE)+1)>=(BN_DIGIT_SIZE-1)) nl++;
245 BnnSetToZero(n,nl+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);
253 if(bigkeygenPrintStatistics)
254 printf("\nCandidate Random Number: %s\n",BzToString(BzFromBigNum(n,nl),16));
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;
262 for (j=3-r;j<1000;j+=3) {*z=1;z+=3;}
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);
269 for (j=s-r;j<1000;j+=s) {*z=1;z+=s;}
272 for(i=0;i<1000;i++) {
275 if(bigkeygenPrintStatistics) printf("|"),fflush(stdout);
277 if (IsPrime(n,nl,5)) goto exit;
279 BnnAddCarry(n,nl,1); /* try next one */
284 if(bigkeygenPrintStatistics) printf(""), fflush(stdout);
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.
298 static BigNumDigit g[4*DigitLim], wgcd[12*DigitLim],
299 r[4*DigitLim], pq[4*DigitLim], d[4*DigitLim], z[4*DigitLim];
301 BigNum n = keys->n, dp = keys->dp, dq = keys->dq, cr = keys->cr,
302 e = keys->e, p = keys->p, q = keys->q ;
304 unsigned nl=keys->nl, pl=keys->pl, ql=keys->ql, tmp,
305 dpl = keys->dpl, dql = keys->dql ;
308 * If primes are supplied, generate dp, dq, and cr if needed.
309 * Assume cr there if dp and dq are.
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) {
320 printf("GCD failed to generate private key exponent.\n");
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));
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));
340 BnnGCD_1(g,r,cr,p,q,wgcd,pl);
341 if ((BnnGetDigit(cr+(pl-1))&TopBitInWord)!=0) BnnAdd(cr,pl,p,pl,0);
344 modpwr2_1(z, 2, n, nl);
345 BnnAssign(keys->beta2n, z, nl);
346 muB_1(keys->nINV, n, nl*BN_DIGIT_SIZE);
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);
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));
377 static BigNum muB_1(res, zz, bits)
381 /* Compute -z^-1 mod 2^bits */
383 BigNumDigit n[muBLIM];
384 BigNumDigit msk[muBLIM], z[muBLIM];
385 unsigned nl = (bits+BN_DIGIT_SIZE-1)/BN_DIGIT_SIZE;
390 fprintf(stderr, "Limit check in %s:muB_1 line %d\n", __FILE__, __LINE__);
396 BnnSetToZero(res, nl);
397 BnnSetToZero(msk, nl);
399 BnnAssign(z, zz, nl);
400 BnnShiftRight(z,nl,1);
403 if (BnnIsDigitOdd(*n))
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);
411 BnnShiftRight(n,nl,1);
412 BnnShiftLeft(msk,nl,1);
417 static void modpwr2_1(result, pwr, m, ml)
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);
428 static void BnnGCD_1(gcd, A, B, U, V, work, len)
429 BigNum gcd, A, B, U, V, work;
432 /* Extended binary GCD
433 code based on Knuth Vol.2 Second Edition
434 section 4.5.2 Answers to Exercises page 599
436 /* Note: len must be large enough to hold 2*U or 2*V */
437 /* "work" is a BigNum of length 3*len */
439 BigNum u1,u2,u3, v1,v2,v3;
441 u1 = A; u2 = B; u3 = gcd;
442 v1 = work; v2 = work + len; v3 = work + 2*len;
445 while (!BnnIsDigitOdd(*U) && !BnnIsDigitOdd(*V))
447 BnnShiftRight(U, len, 1);
448 BnnShiftRight(V, len, 1);
451 BnnSetToZero(u1, len); BnnSetDigit(u1, (BigNumDigit) 1);
452 BnnSetToZero(u2, len);
453 BnnAssign(u3, U, len);
454 if (BnnIsDigitOdd(*U))
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);
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);
470 printf("#[%d %d %d ] [ %d %d %d ]\n", *u1,*u2,*u3, *v1,*v2,*v3);
472 while (!BnnIsZero(t3, len))
474 while (!BnnIsDigitOdd(*t3))
477 if (!BnnIsDigitOdd(*t1) && !BnnIsDigitOdd(*t2))
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);
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);
497 sign = BnnGetDigit(t3+(len-1)) & TopBitInWord;
498 BnnShiftRight(t3, len, 1);
499 BnnOrDigits(t3+(len-1), sign);
501 if (t1 == v1) /* a cheap way to recall what state we are in */
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);
511 if (BnnCompare(u3, len, v3, len) > 0)
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;
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;
529 if (BnnGetDigit(t1+(len-1)) & TopBitInWord)
531 BnnAdd(t1, len, V, len, 0);
532 BnnSubtract(t2, len, U, len, 1);
535 printf(">[%d %d %d ] [ %d %d %d ]\n", *u1,*u2,*u3, *v1,*v2,*v3);
539 BnnShiftLeft(u3, len, 1);
543 /**********************************************************************/
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] ;
552 int ll = BnnNumDigits(key->n,nl);
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);
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);
564 rsaencrypt_1(test_in,test1,key);
566 printf("\nEncrypted: %s", BzToString(BzFromBigNum(test1, nl), 16));
568 rsadecrypt_1(test1,test2,key);
570 printf("\nDecrypted: %s", BzToString(BzFromBigNum(test2, nl), 16));
573 if (BnnCompare(test_in,nl,test2,nl) != 0) {
575 printf("\nKey Test Failed.\n");
580 printf("\nKey Test Passed.\n");
585 static int Test2RSAPrivate_1(key)
589 int ll = BnnNumDigits(key->n,nl);
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);
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);
601 rsadecrypt_1(test_in,test1,key);
603 printf("\nSigned: %s", BzToString(BzFromBigNum(test1, nl), 16));
605 rsaencrypt_1(test1,test2,key);
607 printf("\nVerified: %s", BzToString(BzFromBigNum(test2, nl), 16));
610 if (BnnCompare(test_in,nl,test2,nl) != 0) {
612 printf("\nKey Test Failed.\n");
620 PrintBigNum(n,nl,radix)
624 static char oneline [KEY_LINE+1];
625 char *p = BzToString(BzFromBigNum(n,nl), radix);
627 oneline[KEY_LINE]='\0';
629 strncpy(oneline,p,KEY_LINE);
630 printf("\n %s",oneline);
631 p+=((strlen(p)>KEY_LINE)?KEY_LINE:strlen(p));
635 int PrintTestKey (Keys)
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);
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);
655 PrintBigNum(Keys->cr, Keys->pl,KEY_RADIX);
658 i=BnnNumDigits(Keys->nINV,sizeof(*Keys->nINV)*sizeof(int));
659 printf("\nnINV: (%d BigNumDigits) ", i);
660 PrintBigNum(Keys->nINV, i, KEY_RADIX);
662 i=BnnNumDigits(Keys->beta2n,sizeof(*Keys->beta2n)*sizeof(int));
663 printf("\nbeta2n: (%d BigNumDigits) ", i);
664 PrintBigNum(Keys->beta2n, i,KEY_RADIX);
667 i=BnnNumDigits(Keys->pINV,sizeof(*Keys->pINV)*sizeof(int));
668 printf("\npINV: (%d BigNumDigits) ", i);
669 PrintBigNum(Keys->pINV, i,KEY_RADIX);
671 i=BnnNumDigits(Keys->qINV,sizeof(*Keys->qINV)*sizeof(int));
672 printf("\nqINV: (%d BigNumDigits) ", i);
673 PrintBigNum(Keys->qINV, i,KEY_RADIX);
676 i=BnnNumDigits(Keys->beta2p,sizeof(*Keys->beta2p)*sizeof(int));
677 printf("\nbeta2p: (%d BigNumDigits) ", i);
678 PrintBigNum(Keys->beta2p, i,KEY_RADIX);
680 i=BnnNumDigits(Keys->beta3p,sizeof(*Keys->beta3p)*sizeof(int));
681 printf("\nbeta3p: (%d BigNumDigits) ", i);
682 PrintBigNum(Keys->beta3p, i,KEY_RADIX);
684 i=BnnNumDigits(Keys->beta3q,sizeof(*Keys->beta3q)*sizeof(int));
685 printf("\nbeta3q: (%d BigNumDigits) ", i);
686 PrintBigNum(Keys->beta3q, i,KEY_RADIX);
694 int PrintPubKey (Keys)
697 int i=BnnNumDigits(Keys->n,Keys->nl);
698 i = i*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(Keys->n[i-1]);
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);
710 int PrintPrivKey (Keys)
713 int i=BnnNumDigits(Keys->n,Keys->nl);
714 i = i*BN_DIGIT_SIZE - BnnNumLeadingZeroBitsInDigit(Keys->n[i-1]);
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);
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);
731 PrintBigNum(Keys->cr, Keys->pl,KEY_RADIX);
733 else printf("\n no private key parameters.");
740 /*********************************************************************/
742 /* In-line DES routines here. */
744 #include "DEScrypto.h"
746 static KEYschedule local_key_schedule;
747 static RSAKeyStorage tempkey;
750 * Decrypts an RSA private key.
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 */
758 unsigned char *outbuf;
761 if((outbuf=(unsigned char *)calloc(encrypted_key_len,1))==0)return(0);
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)
767 memset(&tempkey,0,sizeof(tempkey));
768 if (key->nl) tempkey.nl=key->nl, BnnAssign(tempkey.n,key->n,key->nl);
770 printf("\nDecrypted private key:\n");
771 dumphex(outbuf,encrypted_key_len-sizeof(long));
773 if (DecodePrivate(outbuf, &tempkey) != NULL) {
775 printf("\nRecovered Key:\n");
776 PrintTestKey(&tempkey);
778 if (rt=TestRSAKeys(&tempkey)) memcpy(key,&tempkey,sizeof(RSAKeyStorage));
781 else printf("\nDecode Failed.\n");
784 memset(outbuf,0,encrypted_key_len);
785 memset(&tempkey,0,sizeof(tempkey));
792 * Decrypts an RSA private key.
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 */
800 unsigned char *outbuf;
803 if((outbuf=(unsigned char *)calloc(encrypted_key_len,1))==0)return(0);
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)
809 memset(&tempkey,0,sizeof(tempkey));
810 if (key->nl) tempkey.nl=key->nl, BnnAssign(tempkey.n,key->n,key->nl);
812 printf("\nDecrypted private key:\n");
813 dumphex(outbuf,encrypted_key_len-sizeof(long));
815 /* make sure that we decode the private key with only the prime p */
816 if (DecodePrivateP(outbuf, &tempkey) != NULL) {
818 printf("\nRecovered Key:\n");
819 PrintTestKey(&tempkey);
821 if (rt=TestRSAKeys(&tempkey)) memcpy(key,&tempkey,sizeof(RSAKeyStorage));
824 else printf("\nDecode Failed.\n");
827 memset(outbuf,0,encrypted_key_len);
828 memset(&tempkey,0,sizeof(tempkey));
835 * Encrypts an RSA private key.
837 * NOTE: Contains components to foil use as a general encrypt/decrypt
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 */
847 unsigned char *outbuf, *encoded_key;
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;
866 * Same as above, but only encrypts prime P
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 */
874 unsigned char *outbuf, *encoded_key;
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;