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"
35 #include <sys/types.h>
44 * These routines convert ASN.1 to RSAKeyStorage and vice-versa.
48 #define BITSTRING_TAG 3
49 #define SEQUENCE_TAG 48
50 #define CONTEXT_0_TAG 160
51 #define CONTEXT_1_TAG 161
52 #define CONTEXT_2_TAG 162
53 #define CONTEXT_3_TAG 163
54 #define CONTEXT_4_TAG 164
55 #define CONTEXT_5_TAG 165
58 * Routines for encoding keys.
62 * Compute total size of length field assuming minimal (X.509) encoding.
65 int NumEncodeLengthOctets (size)
69 if (size<128) i=1; else if (size>256) i=3 ;
74 * Write out length, advance pointer to next thing to be written.
76 unsigned char *EncodeLength (input, size)
80 int i = NumEncodeLengthOctets(size);
82 if (i==1) (*input++)=(unsigned char)size ;
85 for (i--;i>=0;i--) (*input++)=(size>>(i*8));
91 * Compute the value of the INTEGER encoded length field for a BigNum
94 int NumEncodeValueOctets(n,nl)
100 if (n==0) return (0);
102 i = BnnNumDigits(n,nl);
103 j = BnnNumLeadingZeroBitsInDigit(BnnGetDigit(n+i-1));
111 * Write out BigNum as encoded INTEGER, most to least significant octet, and
112 * return pointer to next octet in stream. Expects to be supplied with
113 * a sufficiently large buffer. Always expects the BigNum to be positive.
115 unsigned char *EncodeBigIntegerValue (stream, input, size)
116 unsigned char *stream;
120 int nl = BnnNumDigits(input, size);
121 BigNumDigit d = BnnGetDigit(input+nl-1);
122 int i = BnnNumLeadingZeroBitsInDigit(d);
124 if ((i%8)==0) *stream++ = 0; /* want positive number, after all */
125 for(i=sizeof(int)-(i/8)-1;i>=0;i--) *stream++ = (unsigned char) (d>>(i*8))&0xff;
127 d = BnnGetDigit(input+nl-1);
128 for(i=sizeof(int)-1;i>=0;i--) *stream++ = (d>>(i*8))&0xff;
134 * Make an encoded public key from RSAKeyStorage. This includes allocating
135 * the stream storage.
137 * A public key is defined as SEQUENCE { INTEGER, INTEGER }
139 unsigned char *EncodePublic(keys)
142 int mod_len,exp_len,sequence_len,public_key_len ;
143 unsigned char *buffer, *start;
145 if ((keys->nl)==0) return(0);
147 mod_len = NumEncodeValueOctets(keys->n,keys->nl);
148 exp_len = NumEncodeValueOctets(keys->e,keys->el);
149 sequence_len = exp_len + mod_len + NumEncodeLengthOctets(exp_len)+
150 NumEncodeLengthOctets(mod_len)+2;
151 public_key_len = NumEncodeLengthOctets(sequence_len)+sequence_len+1;
153 if (start = buffer = (unsigned char *) calloc(public_key_len,1)) {
154 *buffer++ = SEQUENCE_TAG;
155 buffer = EncodeLength (buffer,sequence_len);
156 *buffer++= INTEGER_TAG;
157 buffer=EncodeLength (buffer,mod_len);
158 buffer=EncodeBigIntegerValue(buffer,keys->n,keys->nl);
159 *buffer++= INTEGER_TAG;
160 buffer=EncodeLength (buffer,exp_len);
161 buffer=EncodeBigIntegerValue (buffer,keys->e,keys->el);
166 void FreePublic(buffer)
171 * Make an encoded private key from RSAKeyStorage. This includes allocating
172 * the stream storage.
174 * A private key is defined as
176 * primep INTEGER, -- always there
177 * primeq [0] INTEGER OPTIONAL,
178 * mod [1] INTEGER OPTIONAL, -- never there
179 * exp [2] INTEGER OPTIONAL,
180 * dp [3] INTEGER OPTIONAL,
181 * dq [4] INTEGER OPTIONAL,
182 * cr [5] INTEGER OPTIONAL }
184 unsigned char *EncodePrivate(keys)
187 int p_len, q_len, exp_len, dp_len, dq_len, cr_len, sequence_len ;
188 unsigned char *buffer, *start;
190 /* must have two primes to be a private key */
191 if ((keys->pl ==0)||(keys->ql ==0)) return(0);
194 (p_len = NumEncodeValueOctets(keys->p,keys->pl)) +
195 NumEncodeLengthOctets(p_len) +
196 (q_len = NumEncodeValueOctets(keys->q,keys->ql)) +
197 NumEncodeLengthOctets(q_len) +
198 (exp_len = NumEncodeValueOctets(keys->e,keys->el)) +
199 NumEncodeLengthOctets(exp_len) +
200 (dp_len = NumEncodeValueOctets(keys->dp,keys->dpl)) +
201 NumEncodeLengthOctets(dp_len) +
202 (dq_len = NumEncodeValueOctets(keys->dq,keys->dql)) +
203 NumEncodeLengthOctets(dq_len) +
204 (cr_len = NumEncodeValueOctets(keys->cr,keys->pl)) +
205 NumEncodeLengthOctets(cr_len);
208 (unsigned char *)calloc(1+NumEncodeLengthOctets(sequence_len)+sequence_len,1)) {
209 *buffer++ = SEQUENCE_TAG;
210 buffer=EncodeLength (buffer,sequence_len);
211 *buffer++= INTEGER_TAG;
212 buffer=EncodeLength (buffer,p_len);
213 buffer=EncodeBigIntegerValue (buffer,keys->p,keys->pl);
214 *buffer++= CONTEXT_0_TAG;
215 buffer=EncodeLength (buffer,q_len);
216 buffer=EncodeBigIntegerValue (buffer,keys->q,keys->ql);
218 * No optional modulus.
220 *buffer++= CONTEXT_2_TAG;
221 buffer=EncodeLength (buffer,exp_len);
222 buffer=EncodeBigIntegerValue (buffer,keys->e,keys->el);
223 *buffer++= CONTEXT_3_TAG;
224 buffer=EncodeLength (buffer,dp_len);
225 buffer=EncodeBigIntegerValue (buffer,keys->dp,keys->dpl);
226 *buffer++= CONTEXT_4_TAG;
227 buffer=EncodeLength (buffer,dq_len);
228 buffer=EncodeBigIntegerValue (buffer,keys->dq,keys->dql);
229 *buffer++= CONTEXT_5_TAG;
230 buffer=EncodeLength (buffer,cr_len);
231 buffer=EncodeBigIntegerValue (buffer,keys->cr,keys->pl);
237 * The following routine is similar to the above but just puts prime p in
238 * the encoded private key.
240 unsigned char *EncodePrivateP(keys)
243 int p_len = NumEncodeValueOctets(keys->p,keys->pl);
244 int sequence_len = p_len + 1 + NumEncodeLengthOctets(p_len) ;
245 unsigned char *start, *buffer ;
247 if (start=buffer= (unsigned char *)
248 calloc(1+NumEncodeLengthOctets(sequence_len)+sequence_len, 1)) {
249 *buffer++ = SEQUENCE_TAG;
250 buffer=EncodeLength (buffer,sequence_len);
251 *buffer++= INTEGER_TAG;
252 buffer=EncodeLength (buffer,p_len);
253 buffer=EncodeBigIntegerValue (buffer,keys->p,keys->pl);
258 void FreePrivate(buffer)
268 * Input is an encoded value field, tells how many octets in the value.
269 * Does not handle indefinite length forms.
271 int DecodeValueLength (input) /* handles non-minimal size case */
272 unsigned char *input ;
276 if ((*input&0x80)==0) return(*input);
277 if (*input==0x80) return(0);
278 for (i=(*input++ & 0x7f),len=0;i>0;i--) len=(len << 8)+(unsigned int)*input++;
284 * Input is undecoded string. Returns offset to start of value field.
286 int DecodeHeaderLength (input)
287 unsigned char *input ;
289 int tlen = DecodeTypeLength(input);
292 if (*input&0x80) tlen += (*input&0x7f);
297 * Compute number of type bytes.
299 int DecodeTypeLength (input)
300 unsigned char *input;
302 if ((*input&31)==31) do {input++;temp++;} while (*input&0x80) ;
307 * Compute offset to next element to decode.
308 * Assumes definite length encoding.
310 int DecodeTotalLength (input)
311 unsigned char *input ;
313 return (DecodeHeaderLength(input)+DecodeValueLength(input+DecodeTypeLength(input)));
317 * DecodeBigInteger Returns pointer to one byte beyond end of encoded value.
318 * Reads in least to most significant.
320 unsigned char *DecodeBigInteger (stream, value, size)
321 unsigned char *stream;
325 int nl = (size+sizeof(int)-1)/sizeof(int);
329 for(i=0;i<(nl-1);i++){
331 for(j=0;j<sizeof(int);j++)
332 d |= (BigNumDigit)(stream[k-j]&0xff)<<(j*8);
333 BnnSetDigit(value+i,d);
336 /* assert: i = nl-1 */
338 BnnSetToZero(value+i,1);
339 nl=(size+sizeof(int)-1)%sizeof(int);
341 d |= (BigNumDigit)(stream[k-j]&0xff)<<(j*8);
342 BnnSetDigit(value+i,d);
348 * DecodePublic. Initializes RSAKeyStorage.
349 * Returns pointer to next element if no syntax problems, else zero.
351 unsigned char *DecodePublic (input, keys)
352 unsigned char *input;
356 unsigned char *next=input;
358 memset(keys,0,sizeof(RSAKeyStorage));
360 if ((*input != SEQUENCE_TAG)|| /* must be definite form */
361 (DecodeValueLength(input+1)<=0)) goto syntax_error;
362 input += DecodeHeaderLength(input);
364 if (*input != INTEGER_TAG) goto syntax_error;
365 len = DecodeValueLength(input+1);
366 if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
367 input+= DecodeHeaderLength(input);
368 input = DecodeBigInteger (input, keys->n, len);
369 keys->nl = 1 + BnnNumDigits(keys->n, (len+sizeof(int)-1)/sizeof(int));
371 if (*input != INTEGER_TAG) goto syntax_error;
372 len = DecodeValueLength(input+1);
373 if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
374 input+= DecodeHeaderLength(input);
375 input = DecodeBigInteger (input, keys->e, len);
376 keys->el = BnnNumDigits(keys->e, (len+sizeof(int)-1)/sizeof(int));
379 * should be at the end of the encoded substring
381 if (input != next+DecodeTotalLength(next)) goto syntax_error ;
389 printf("\nDecodePublic: Syntax Error.\n");
395 * DecodePrivate. Returns pointer to next element if good, else zero.
397 * Fills in RSAKeyStorage with key parameters if succesful,
398 * assuming there is enough to go on. The modulus can be supplied in the structure
399 * already, but other values are assumed cleared as necessary. The idea
400 * in this case is to call with the same structure as the public key is in to
401 * make it into a private key structure based on decoding the prime p.
403 unsigned char *DecodePrivate (input, keys)
404 unsigned char *input;
408 unsigned char *next=input;
411 if ((*input != SEQUENCE_TAG)|| /* must be definite form */
412 (DecodeValueLength(input+1)<=0)) goto syntax_error;
413 input += DecodeHeaderLength(input);
415 if (*input == INTEGER_TAG) { /* must have a p */
416 len = DecodeValueLength(input+1);
417 if ((len<=0)||(len >= sizeof(BigNumDigit)*PrimeSize)) goto syntax_error;
418 input+= DecodeHeaderLength(input);
419 input = DecodeBigInteger (input, keys->p, len);
420 len = keys->pl = BnnNumDigits(x=keys->p, (len+sizeof(int)-1)/sizeof(int));
421 if ((x[len-1]&(3<<BN_DIGIT_SIZE-2))!=0)
422 if (len<PrimeSize) keys->pl = len+1;
423 else goto syntax_error ;
424 } else goto syntax_error ;
426 if (*input == CONTEXT_0_TAG) { /* may have a q */
427 len = DecodeValueLength(input+1);
428 if ((len<=0)||(len >= sizeof(BigNumDigit)*PrimeSize)) goto syntax_error;
429 input+= DecodeHeaderLength(input);
430 input = DecodeBigInteger (input, keys->q, len);
431 len= keys->ql = BnnNumDigits(x=keys->q, (len+sizeof(int)-1)/sizeof(int));
432 if ((x[len-1]&(3<<BN_DIGIT_SIZE-2))!=0)
433 if (len<PrimeSize) keys->ql = len+1;
434 else goto syntax_error ;
438 if (*input == CONTEXT_1_TAG) { /* may have a modulus */
439 memset(keys->n,0,sizeof(*keys->n));
440 len = DecodeValueLength(input+1);
441 if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
442 input+= DecodeHeaderLength(input);
443 input = DecodeBigInteger (input, keys->n, len);
444 keys->nl = 1 + BnnNumDigits(keys->n, (len+sizeof(int)-1)/sizeof(int));
447 memset(keys->e,0,sizeof(*keys->e));
448 if (*input == CONTEXT_2_TAG) { /* may have an exponent */
449 len = DecodeValueLength(input+1);
450 if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
451 input+= DecodeHeaderLength(input);
452 input = DecodeBigInteger (input, keys->e, len);
454 else /* use default exponent */
455 BnnSetDigit(keys->e, (BigNumDigit) ((1<<16)+1) ); /* 32 bits */
456 keys->el = BnnNumDigits(keys->e, (len+sizeof(int)-1)/sizeof(int));
458 memset(keys->dp,0,sizeof(*keys->dp));
459 if (*input == CONTEXT_3_TAG) { /* may have a dp */
460 len = DecodeValueLength(input+1);
461 if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
462 input+= DecodeHeaderLength(input);
463 input = DecodeBigInteger (input, keys->dp, len);
464 keys->dpl = BnnNumDigits(keys->dp, (len+sizeof(int)-1)/sizeof(int));
468 memset(keys->dq,0,sizeof(*keys->dq));
469 if (*input == CONTEXT_4_TAG) { /* may have a dq */
470 len = DecodeValueLength(input+1);
471 if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
472 input+= DecodeHeaderLength(input);
473 input = DecodeBigInteger (input, keys->dq, len);
474 keys->dql = BnnNumDigits(keys->dq, (len+sizeof(int)-1)/sizeof(int));
478 memset(keys->cr,0,sizeof(*keys->cr));
479 if (*input == CONTEXT_5_TAG) { /* may have a cr */
480 len = DecodeValueLength(input+1);
481 if ((len<=0)||(len >= sizeof(int)*2*DigitLim)) goto syntax_error;
482 input+= DecodeHeaderLength(input);
483 input = DecodeBigInteger (input, keys->cr, len);
489 * should be at the end of the encoded substring
491 if (input != next+DecodeTotalLength(next)) goto syntax_error ;
493 if (keys->ql == 0) /* need to regenerate q */
494 if (keys->nl == 0) goto syntax_error; /* must know n */
496 BigNumDigit xx[4*DigitLim];
499 memset(xx,0,sizeof(xx));
500 BnnAssign(xx,keys->n,nl=keys->nl);
501 BnnDivide(xx,nl,keys->p,pl=keys->pl);
502 /* check that p evenly divided n */
503 for(i=0;i<pl;i++) if(xx[i]) goto syntax_error;
504 ql = keys->ql = BnnNumDigits(xx,nl) - pl;
505 BnnAssign(keys->q,xx+pl,ql);
506 if ((x[ql-1]&(3<<BN_DIGIT_SIZE-2))!=0)
507 if (ql<PrimeSize) keys->ql = ql+1;
508 else goto syntax_error ;
511 if (keys->nl == 0){ /* need to regenerate n */
512 int nl = keys->pl + keys->ql;
513 memset(keys->n,0,sizeof(*keys->n));
514 BnnMultiply(keys->n,nl,keys->p,keys->pl,keys->q,keys->ql);
518 if(FinishKey(keys) == 0) goto syntax_error ;
523 printf("\nDecodePrivate: Syntax Error.\n");
526 memset(keys->p,0,sizeof(*keys->p));
527 memset(keys->q,0,sizeof(*keys->q));
528 memset(keys->dp,0,sizeof(*keys->dp));
529 memset(keys->dq,0,sizeof(*keys->dq));
530 memset(keys->cr,0,sizeof(*keys->cr));
531 keys->pl=keys->ql=keys->dpl=keys->dql=0;
537 * DecodePrivateP. Returns pointer to next element if good, else zero.
539 * Fills in RSAKeyStorage with key parameters if succesful,
540 * assuming there is enough to go on. The modulus can be supplied in the structure
541 * already, but other values are assumed cleared as necessary. The idea
542 * in this case is to call with the same structure as the public key is in to
543 * make it into a private key structure based on decoding the prime p.
544 * Only the prime p must be passed in.
546 unsigned char *DecodePrivateP (input, keys)
547 unsigned char *input;
551 unsigned char *next=input;
554 if ((*input != SEQUENCE_TAG)|| /* must be definite form */
555 (DecodeValueLength(input+1)<=0)) goto syntax_error;
556 input += DecodeHeaderLength(input);
558 if (*input == INTEGER_TAG) { /* must have a p */
559 len = DecodeValueLength(input+1);
560 if ((len<=0)||(len >= sizeof(BigNumDigit)*PrimeSize)) goto syntax_error;
561 input+= DecodeHeaderLength(input);
562 input = DecodeBigInteger (input, keys->p, len);
563 len = keys->pl = BnnNumDigits(x=keys->p, (len+sizeof(int)-1)/sizeof(int));
564 if ((x[len-1]&(3<<BN_DIGIT_SIZE-2))!=0)
565 if (len<PrimeSize) keys->pl = len+1;
566 else goto syntax_error ;
567 } else goto syntax_error ;
569 if (*input == CONTEXT_0_TAG) goto syntax_error ;
572 if (*input == CONTEXT_1_TAG) goto syntax_error ;
574 memset(keys->e,0,sizeof(*keys->e));
575 if (*input == CONTEXT_2_TAG) goto syntax_error ;
576 else /* use default exponent */
577 BnnSetDigit(keys->e, (BigNumDigit) ((1<<16)+1) ); /* 32 bits */
578 keys->el = BnnNumDigits(keys->e, (len+sizeof(int)-1)/sizeof(int));
580 memset(keys->dp,0,sizeof(*keys->dp));
581 if (*input == CONTEXT_3_TAG) goto syntax_error ;
584 memset(keys->dq,0,sizeof(*keys->dq));
585 if (*input == CONTEXT_4_TAG) goto syntax_error ;
588 memset(keys->cr,0,sizeof(*keys->cr));
589 if (*input == CONTEXT_5_TAG) goto syntax_error ;
593 * should be at the end of the encoded substring
595 if (input != next+DecodeTotalLength(next)) goto syntax_error ;
597 if (keys->ql == 0) /* need to regenerate q */
598 if (keys->nl == 0) goto syntax_error; /* must know n */
600 BigNumDigit xx[4*DigitLim];
603 memset(xx,0,sizeof(xx));
604 BnnAssign(xx,keys->n,nl=keys->nl);
605 BnnDivide(xx,nl,keys->p,pl=keys->pl);
606 /* check that p evenly divided n */
607 for(i=0;i<pl;i++) if(xx[i]) goto syntax_error;
608 ql = keys->ql = BnnNumDigits(xx,nl) - pl;
609 BnnAssign(keys->q,xx+pl,ql);
610 if ((x[ql-1]&(3<<BN_DIGIT_SIZE-2))!=0)
611 if (ql<PrimeSize) keys->ql = ql+1;
612 else goto syntax_error ;
615 if (keys->nl == 0){ /* need to regenerate n */
616 int nl = keys->pl + keys->ql;
617 memset(keys->n,0,sizeof(*keys->n));
618 BnnMultiply(keys->n,nl,keys->p,keys->pl,keys->q,keys->ql);
622 if(FinishKey(keys) == 0) goto syntax_error ;
627 printf("\nDecodePrivateP: Syntax Error.\n");
630 memset(keys->p,0,sizeof(*keys->p));
631 memset(keys->q,0,sizeof(*keys->q));
632 memset(keys->dp,0,sizeof(*keys->dp));
633 memset(keys->dq,0,sizeof(*keys->dq));
634 memset(keys->cr,0,sizeof(*keys->cr));
635 keys->pl=keys->ql=keys->dpl=keys->dql=0;