]> andersk Git - moira.git/blob - util/rsaref/r_enhanc.c
Fixes from dtanner. Correct some typos and before/after confusion.
[moira.git] / util / rsaref / r_enhanc.c
1 /* R_ENHANC.C - cryptographic enhancements for RSAREF
2  */
3
4 /* Copyright (C) RSA Laboratories, a division of RSA Data Security,
5      Inc., created 1991. All rights reserved.
6  */
7
8 #include "global.h"
9 #include "rsaref.h"
10 #include "r_random.h"
11 #include "rsa.h"
12
13 /* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 (for MD2/MD5),
14    then DIGEST_INFO_B, then 16-byte message digest.
15  */
16
17 static unsigned char DIGEST_INFO_A[] = {
18   0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7,
19   0x0d, 0x02
20 };
21 #define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A)
22
23 static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 };
24 #define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B)
25
26 #define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16)
27
28 static unsigned char *PADDING[] = {
29   (unsigned char *)"", (unsigned char *)"\001", (unsigned char *)"\002\002",
30   (unsigned char *)"\003\003\003", (unsigned char *)"\004\004\004\004",
31   (unsigned char *)"\005\005\005\005\005",
32   (unsigned char *)"\006\006\006\006\006\006", 
33   (unsigned char *)"\007\007\007\007\007\007\007",
34   (unsigned char *)"\010\010\010\010\010\010\010\010"
35 };
36
37 #define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN
38
39 static void R_EncodeDigestInfo PROTO_LIST
40   ((unsigned char *, int, unsigned char *));
41 static void EncryptPEMUpdateFinal PROTO_LIST
42   ((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
43     unsigned int));
44 static int DecryptPEMUpdateFinal PROTO_LIST
45   ((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
46     unsigned int));
47 static int CipherInit PROTO_LIST
48   ((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int));
49 static void CipherUpdate PROTO_LIST
50   ((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int));
51 static void CipherRestart PROTO_LIST ((R_ENVELOPE_CTX *));
52
53 int R_DigestInit (context, digestAlgorithm)
54 R_DIGEST_CTX *context;                                       /* new context */
55 int digestAlgorithm;                            /* message-digest algorithm */
56 {
57   context->digestAlgorithm = digestAlgorithm;
58
59   switch (digestAlgorithm) {
60   case DA_MD2:
61     MD2Init (&context->context.md2);
62     break;
63
64   case DA_MD5:
65     MD5Init (&context->context.md5);
66     break;
67   
68   default:
69     return (RE_DIGEST_ALGORITHM);
70   }
71
72   return (0);
73 }
74
75 int R_DigestUpdate (context, partIn, partInLen)
76 R_DIGEST_CTX *context;                                           /* context */
77 unsigned char *partIn;                                    /* next data part */
78 unsigned int partInLen;                         /* length of next data part */
79 {
80   if (context->digestAlgorithm == DA_MD2)
81     MD2Update (&context->context.md2, partIn, partInLen);
82   else
83     MD5Update (&context->context.md5, partIn, partInLen);
84   return (0);
85 }
86
87 int R_DigestFinal (context, digest, digestLen)
88 R_DIGEST_CTX *context;                                           /* context */
89 unsigned char *digest;                                    /* message digest */
90 unsigned int *digestLen;                        /* length of message digest */
91 {
92   *digestLen = 16;
93   if (context->digestAlgorithm == DA_MD2)
94     MD2Final (digest, &context->context.md2);
95   else
96     MD5Final (digest, &context->context.md5);
97
98   return (0);
99 }
100
101 int R_SignInit (context, digestAlgorithm)
102 R_SIGNATURE_CTX *context;                                    /* new context */
103 int digestAlgorithm;                            /* message-digest algorithm */
104 {
105   return (R_DigestInit (&context->digestContext, digestAlgorithm));
106 }
107
108 int R_SignUpdate (context, partIn, partInLen)
109 R_SIGNATURE_CTX *context;                                        /* context */
110 unsigned char *partIn;                                    /* next data part */
111 unsigned int partInLen;                         /* length of next data part */
112 {
113   return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
114 }
115
116 int R_SignFinal (context, signature, signatureLen, privateKey)
117 R_SIGNATURE_CTX *context;                                        /* context */
118 unsigned char *signature;                                      /* signature */
119 unsigned int *signatureLen;                          /* length of signature */
120 R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
121 {
122   int status;
123   unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN];
124   unsigned int digestLen;
125
126   do {
127     if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen))
128         != 0)
129       break;
130
131     R_EncodeDigestInfo
132       (digestInfo, context->digestContext.digestAlgorithm, digest);
133     
134     if (RSAPrivateEncrypt
135         (signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey)
136         != 0) {
137       status = RE_PRIVATE_KEY;
138       break;
139     }
140
141     /* Reset for another verification. Assume Init won't fail */
142     R_DigestInit
143       (&context->digestContext, context->digestContext.digestAlgorithm);
144   } while (0);
145   
146   /* Zeroize potentially sensitive information.
147    */
148   R_memset ((POINTER)digest, 0, sizeof (digest));
149   R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
150
151   return (status);
152 }
153
154 int R_VerifyInit (context, digestAlgorithm)
155 R_SIGNATURE_CTX *context;                                    /* new context */
156 int digestAlgorithm;                            /* message-digest algorithm */
157 {
158   return (R_DigestInit (&context->digestContext, digestAlgorithm));
159 }
160
161 int R_VerifyUpdate (context, partIn, partInLen)
162 R_SIGNATURE_CTX *context;                                        /* context */
163 unsigned char *partIn;                                    /* next data part */
164 unsigned int partInLen;                         /* length of next data part */
165 {
166   return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
167 }
168
169 int R_VerifyFinal (context, signature, signatureLen, publicKey)
170 R_SIGNATURE_CTX *context;                                        /* context */
171 unsigned char *signature;                                      /* signature */
172 unsigned int signatureLen;                           /* length of signature */
173 R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
174 {
175   int status;
176   unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN],
177     originalDigestInfo[MAX_SIGNATURE_LEN];
178   unsigned int originalDigestInfoLen, digestLen;
179   
180   if (signatureLen > MAX_SIGNATURE_LEN)
181     return (RE_LEN);
182
183   status = 0;
184   do {
185     if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen))
186         != 0)
187       break;
188
189     R_EncodeDigestInfo
190       (digestInfo, context->digestContext.digestAlgorithm, digest);
191     
192     if (RSAPublicDecrypt
193         (originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, 
194          publicKey) != 0) {
195       status = RE_PUBLIC_KEY;
196       break;
197     }
198     
199     if ((originalDigestInfoLen != DIGEST_INFO_LEN) ||
200         (R_memcmp 
201          ((POINTER)originalDigestInfo, (POINTER)digestInfo,
202           DIGEST_INFO_LEN))) {
203       status = RE_SIGNATURE;
204       break;
205     }
206
207     /* Reset for another verification. Assume Init won't fail */
208     R_DigestInit
209       (&context->digestContext, context->digestContext.digestAlgorithm);
210   } while (0);
211   
212   /* Zeroize potentially sensitive information.
213    */
214   R_memset ((POINTER)digest, 0, sizeof (digest));
215   R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
216   R_memset ((POINTER)originalDigestInfo, 0, sizeof (originalDigestInfo));
217
218   return (status);
219 }
220
221 /* Caller must ASCII recode the encrypted keys if desired.
222  */
223 int R_SealInit
224   (context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys,
225    encryptionAlgorithm, randomStruct)
226 R_ENVELOPE_CTX *context;                                     /* new context */
227 unsigned char **encryptedKeys;                            /* encrypted keys */
228 unsigned int *encryptedKeyLens;                /* lengths of encrypted keys */
229 unsigned char iv[8];                               /* initialization vector */
230 unsigned int publicKeyCount;                       /* number of public keys */
231 R_RSA_PUBLIC_KEY **publicKeys;                               /* public keys */
232 int encryptionAlgorithm;                       /* data encryption algorithm */
233 R_RANDOM_STRUCT *randomStruct;                          /* random structure */
234 {
235   int status;
236   unsigned char key[24];
237   unsigned int keyLen, i;
238   
239   do {
240     context->encryptionAlgorithm = encryptionAlgorithm;
241     
242     keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24;
243     if ((status = R_GenerateBytes (key, keyLen, randomStruct)) != 0)
244       break;
245     if ((status = R_GenerateBytes (iv, 8, randomStruct)) != 0)
246       break;
247
248     if (encryptionAlgorithm == EA_DES_EDE2_CBC)
249       /* Make both E keys the same */
250       R_memcpy ((POINTER)(key + 16), (POINTER)key, 8);
251
252     if ((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) != 0)
253       break;
254
255     for (i = 0; i < publicKeyCount; ++i) {
256       if (RSAPublicEncrypt
257           (encryptedKeys[i], &encryptedKeyLens[i], key, keyLen,
258            publicKeys[i], randomStruct)) {
259         status = RE_PUBLIC_KEY;
260         break;
261       }
262     }
263     if (status != 0)
264       break;
265
266     context->bufferLen = 0;
267   } while (0);
268   
269   /* Zeroize sensitive information.
270    */
271   R_memset ((POINTER)key, 0, sizeof (key));
272
273   return (status);
274 }
275
276 /* Assume partOut buffer is at least partInLen + 7, since this may flush
277      buffered input.
278  */
279 int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen)
280 R_ENVELOPE_CTX *context;                                         /* context */
281 unsigned char *partOut;                         /* next encrypted data part */
282 unsigned int *partOutLen;             /* length of next encrypted data part */
283 unsigned char *partIn;                                    /* next data part */
284 unsigned int partInLen;                         /* length of next data part */
285 {
286   unsigned int tempLen;
287
288   tempLen = 8 - context->bufferLen;
289   if (partInLen < tempLen) {
290     /* Just accumulate into buffer.
291      */
292     R_memcpy
293       ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
294        partInLen);
295     context->bufferLen += partInLen;
296     *partOutLen = 0;
297     return (0);
298   }
299
300   /* Fill the buffer and encrypt.
301    */
302   R_memcpy
303     ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
304      tempLen);
305   CipherUpdate (context, partOut, context->buffer, 8);
306   partIn += tempLen;
307   partInLen -= tempLen;
308   partOut += 8;
309   *partOutLen = 8;
310
311   /* Encrypt as many 8-byte blocks as possible.
312    */
313   tempLen = 8 * (partInLen / 8);
314   CipherUpdate (context, partOut, partIn, tempLen);
315   partIn += tempLen;
316   partInLen -= tempLen;
317   *partOutLen += tempLen;
318
319   /* Length is now less than 8, so copy remainder to buffer.
320    */
321   R_memcpy
322     ((POINTER)context->buffer, (POINTER)partIn,
323      context->bufferLen = partInLen);
324
325   return (0);
326 }
327
328 /* Assume partOut buffer is at least 8 bytes.
329  */
330 int R_SealFinal (context, partOut, partOutLen)
331 R_ENVELOPE_CTX *context;                                         /* context */
332 unsigned char *partOut;                         /* last encrypted data part */
333 unsigned int *partOutLen;             /* length of last encrypted data part */
334 {
335   unsigned int padLen;
336
337   /* Pad and encrypt final block.
338    */
339   padLen = 8 - context->bufferLen;
340   R_memset
341     ((POINTER)(context->buffer + context->bufferLen), (int)padLen, padLen);
342   CipherUpdate (context, partOut, context->buffer, 8);
343   *partOutLen = 8;
344
345   /* Restart the context.
346    */
347   CipherRestart (context);
348   context->bufferLen = 0;
349
350   return (0);
351 }
352
353 /* Assume caller has already ASCII decoded the encryptedKey if necessary.
354  */
355 int R_OpenInit
356   (context, encryptionAlgorithm, encryptedKey, encryptedKeyLen, iv, privateKey)
357 R_ENVELOPE_CTX *context;                                     /* new context */
358 int encryptionAlgorithm;                       /* data encryption algorithm */
359 unsigned char *encryptedKey;               /* encrypted data encryption key */
360 unsigned int encryptedKeyLen;                    /* length of encrypted key */
361 unsigned char iv[8];                               /* initialization vector */
362 R_RSA_PRIVATE_KEY *privateKey;               /* recipient's RSA private key */
363 {
364   int status;
365   unsigned char key[MAX_ENCRYPTED_KEY_LEN];
366   unsigned int keyLen;
367   
368   if (encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN)
369     return (RE_LEN);
370   
371   do {
372     context->encryptionAlgorithm = encryptionAlgorithm;
373
374     if (RSAPrivateDecrypt
375         (key, &keyLen, encryptedKey, encryptedKeyLen, privateKey)) {
376       status = RE_PRIVATE_KEY;
377       break;
378     }
379
380     if (encryptionAlgorithm == EA_DES_CBC) {    
381       if (keyLen != 8) {
382         status = RE_PRIVATE_KEY;
383         break;
384       }
385     }
386     else {
387       if (keyLen != 24) {
388         status = RE_PRIVATE_KEY;
389         break;
390       }
391     }
392     
393     if ((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) != 0)
394       break;
395
396     context->bufferLen = 0;
397   } while (0);
398   
399   /* Zeroize sensitive information.
400    */
401   R_memset ((POINTER)key, 0, sizeof (key));
402
403   return (status);
404 }
405
406 /* Assume partOut buffer is at least partInLen + 7, since this may flush
407      buffered input. Always leaves at least one byte in buffer.
408  */
409 int R_OpenUpdate (context, partOut, partOutLen, partIn, partInLen)
410 R_ENVELOPE_CTX *context;                                         /* context */
411 unsigned char *partOut;                         /* next recovered data part */
412 unsigned int *partOutLen;             /* length of next recovered data part */
413 unsigned char *partIn;                          /* next encrypted data part */
414 unsigned int partInLen;               /* length of next encrypted data part */
415 {
416   unsigned int tempLen;
417
418   tempLen = 8 - context->bufferLen;
419   if (partInLen <= tempLen) {
420     /* Just accumulate into buffer.
421      */
422     R_memcpy
423       ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
424        partInLen);
425     context->bufferLen += partInLen;
426     *partOutLen = 0;
427     return (0);
428   }
429
430   /* Fill the buffer and decrypt.  We know that there will be more left
431        in partIn after decrypting the buffer.
432    */
433   R_memcpy
434     ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
435      tempLen);
436   CipherUpdate (context, partOut, context->buffer, 8);
437   partIn += tempLen;
438   partInLen -= tempLen;
439   partOut += 8;
440   *partOutLen = 8;
441
442   /* Decrypt as many 8 byte blocks as possible, leaving at least one byte
443        in partIn.
444    */
445   tempLen = 8 * ((partInLen - 1) / 8);
446   CipherUpdate (context, partOut, partIn, tempLen);
447   partIn += tempLen;
448   partInLen -= tempLen;
449   *partOutLen += tempLen;
450
451   /* Length is between 1 and 8, so copy into buffer.
452    */
453   R_memcpy
454     ((POINTER)context->buffer, (POINTER)partIn,
455      context->bufferLen = partInLen);
456
457   return (0);
458 }
459
460 /* Assume partOut buffer is at least 7 bytes.
461  */
462 int R_OpenFinal (context, partOut, partOutLen)
463 R_ENVELOPE_CTX *context;                                         /* context */
464 unsigned char *partOut;                         /* last recovered data part */
465 unsigned int *partOutLen;             /* length of last recovered data part */
466 {
467   int status;
468   unsigned char lastPart[8];
469   unsigned int padLen;
470
471   status = 0;
472   do {
473     if (context->bufferLen == 0)
474       /* There was no input data to decrypt */
475       *partOutLen = 0;
476     else {
477       if (context->bufferLen != 8) {
478         status = RE_KEY;
479         break;
480       }
481
482       /* Decrypt and strip padding from final block which is in buffer.
483        */
484       CipherUpdate (context, lastPart, context->buffer, 8);
485     
486       padLen = lastPart[7];
487       if (padLen == 0 || padLen > 8) {
488         status = RE_KEY;
489         break;
490       }
491       if (R_memcmp 
492           ((POINTER)&lastPart[8 - padLen], PADDING[padLen], padLen) != 0) {
493         status = RE_KEY;
494         break;
495       }
496       
497       R_memcpy ((POINTER)partOut, (POINTER)lastPart, *partOutLen = 8 - padLen);
498     }
499
500     /* Restart the context.
501      */
502     CipherRestart (context);
503     context->bufferLen = 0;
504   } while (0);
505
506   /* Zeroize sensitive information.
507    */
508   R_memset ((POINTER)lastPart, 0, sizeof (lastPart));
509
510   return (status);
511 }
512
513 int R_SignPEMBlock 
514   (encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen,
515    content, contentLen, recode, digestAlgorithm, privateKey)
516 unsigned char *encodedContent;                           /* encoded content */
517 unsigned int *encodedContentLen;               /* length of encoded content */
518 unsigned char *encodedSignature;                       /* encoded signature */
519 unsigned int *encodedSignatureLen;           /* length of encoded signature */
520 unsigned char *content;                                          /* content */
521 unsigned int contentLen;                               /* length of content */
522 int recode;                                                /* recoding flag */
523 int digestAlgorithm;                            /* message-digest algorithm */
524 R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
525 {
526   int status;
527   unsigned char signature[MAX_SIGNATURE_LEN];
528   unsigned int signatureLen;
529   
530   if ((status = R_SignBlock
531        (signature, &signatureLen, content, contentLen, digestAlgorithm,
532         privateKey)) != 0)
533     return (status);
534
535   R_EncodePEMBlock 
536     (encodedSignature, encodedSignatureLen, signature, signatureLen);
537
538   if (recode)
539     R_EncodePEMBlock
540     (encodedContent, encodedContentLen, content, contentLen);
541
542   return (0);
543 }
544
545 int R_SignBlock
546   (signature, signatureLen, block, blockLen, digestAlgorithm, privateKey)
547 unsigned char *signature;                                      /* signature */
548 unsigned int *signatureLen;                          /* length of signature */
549 unsigned char *block;                                              /* block */
550 unsigned int blockLen;                                   /* length of block */
551 int digestAlgorithm;                            /* message-digest algorithm */
552 R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
553 {
554   R_SIGNATURE_CTX context;
555   int status;
556
557   do {
558     if ((status = R_SignInit (&context, digestAlgorithm)) != 0)
559       break;
560     if ((status = R_SignUpdate (&context, block, blockLen)) != 0)
561       break;
562     if ((status = R_SignFinal (&context, signature, signatureLen, privateKey))
563         != 0)
564       break;
565   } while (0);
566
567   /* Zeroize sensitive information. */
568   R_memset ((POINTER)&context, 0, sizeof (context));
569
570   return (status);
571 }
572
573 int R_VerifyPEMSignature 
574   (content, contentLen, encodedContent, encodedContentLen, encodedSignature,
575    encodedSignatureLen, recode, digestAlgorithm, publicKey)
576 unsigned char *content;                                          /* content */
577 unsigned int *contentLen;                              /* length of content */
578 unsigned char *encodedContent;                /* (possibly) encoded content */
579 unsigned int encodedContentLen;                /* length of encoded content */
580 unsigned char *encodedSignature;                       /* encoded signature */
581 unsigned int encodedSignatureLen;            /* length of encoded signature */
582 int recode;                                                /* recoding flag */
583 int digestAlgorithm;                            /* message-digest algorithm */
584 R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
585 {
586   unsigned char signature[MAX_SIGNATURE_LEN];
587   unsigned int signatureLen;
588   
589   if (encodedSignatureLen > MAX_PEM_SIGNATURE_LEN)
590     return (RE_SIGNATURE_ENCODING);
591   
592   if (recode) {
593     if (R_DecodePEMBlock
594         (content, contentLen, encodedContent, encodedContentLen))
595       return (RE_CONTENT_ENCODING);
596   }
597   else {
598     content = encodedContent;
599     *contentLen = encodedContentLen;
600   }
601     
602   if (R_DecodePEMBlock
603       (signature, &signatureLen, encodedSignature, encodedSignatureLen))
604     return (RE_SIGNATURE_ENCODING);
605   
606   return (R_VerifyBlockSignature 
607           (content, *contentLen, signature, signatureLen, digestAlgorithm,
608            publicKey));
609 }
610
611 int R_VerifyBlockSignature 
612   (block, blockLen, signature, signatureLen, digestAlgorithm, publicKey)
613 unsigned char *block;                                              /* block */
614 unsigned int blockLen;                                   /* length of block */
615 unsigned char *signature;                                      /* signature */
616 unsigned int signatureLen;                           /* length of signature */
617 int digestAlgorithm;                            /* message-digest algorithm */
618 R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
619 {
620   R_SIGNATURE_CTX context;
621   int status;
622
623   do {
624     if ((status = R_VerifyInit (&context, digestAlgorithm)) != 0)
625       break;
626     if ((status = R_VerifyUpdate (&context, block, blockLen)) != 0)
627       break;
628     if ((status = R_VerifyFinal (&context, signature, signatureLen, publicKey))
629         != 0)
630       break;
631   } while (0);
632
633   /* Zeroize sensitive information. */
634   R_memset ((POINTER)&context, 0, sizeof (context));
635
636   return (status);
637 }
638
639 int R_SealPEMBlock 
640   (encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen,
641    encryptedSignature, encryptedSignatureLen, iv, content, contentLen,
642    digestAlgorithm, publicKey, privateKey, randomStruct)
643 unsigned char *encryptedContent;              /* encoded, encrypted content */
644 unsigned int *encryptedContentLen;                                /* length */
645 unsigned char *encryptedKey;                      /* encoded, encrypted key */
646 unsigned int *encryptedKeyLen;                                    /* length */
647 unsigned char *encryptedSignature;          /* encoded, encrypted signature */
648 unsigned int *encryptedSignatureLen;                              /* length */
649 unsigned char iv[8];                           /* DES initialization vector */
650 unsigned char *content;                                          /* content */
651 unsigned int contentLen;                               /* length of content */
652 int digestAlgorithm;                           /* message-digest algorithms */
653 R_RSA_PUBLIC_KEY *publicKey;                  /* recipient's RSA public key */
654 R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
655 R_RANDOM_STRUCT *randomStruct;                          /* random structure */
656 {
657   R_ENVELOPE_CTX context;
658   R_RSA_PUBLIC_KEY *publicKeys[1];
659   int status;
660   unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
661     signature[MAX_SIGNATURE_LEN], *encryptedKeys[1];
662   unsigned int signatureLen, encryptedKeyBlockLen;
663   
664   do {
665     if ((status = R_SignBlock
666          (signature, &signatureLen, content, contentLen, digestAlgorithm,
667           privateKey)) != 0)
668       break;
669
670     publicKeys[0] = publicKey;
671     encryptedKeys[0] = encryptedKeyBlock;
672     if ((status = R_SealInit
673          (&context, encryptedKeys, &encryptedKeyBlockLen, iv, 1, publicKeys,
674           EA_DES_CBC, randomStruct)) != 0)
675       break;
676
677     R_EncodePEMBlock 
678       (encryptedKey, encryptedKeyLen, encryptedKeyBlock,
679        encryptedKeyBlockLen);
680
681     EncryptPEMUpdateFinal
682       (&context, encryptedContent, encryptedContentLen, content,
683        contentLen);
684     
685     EncryptPEMUpdateFinal
686       (&context, encryptedSignature, encryptedSignatureLen, signature,
687        signatureLen);
688   } while (0);
689   
690   /* Zeroize sensitive information.
691    */
692   R_memset ((POINTER)&context, 0, sizeof (context));
693   R_memset ((POINTER)signature, 0, sizeof (signature));
694
695   return (status);
696 }
697
698 int R_OpenPEMBlock
699   (content, contentLen, encryptedContent, encryptedContentLen, encryptedKey,
700    encryptedKeyLen, encryptedSignature, encryptedSignatureLen,
701    iv, digestAlgorithm, privateKey, publicKey)
702 unsigned char *content;                                          /* content */
703 unsigned int *contentLen;                              /* length of content */
704 unsigned char *encryptedContent;              /* encoded, encrypted content */
705 unsigned int encryptedContentLen;                                 /* length */
706 unsigned char *encryptedKey;                      /* encoded, encrypted key */
707 unsigned int encryptedKeyLen;                                     /* length */
708 unsigned char *encryptedSignature;          /* encoded, encrypted signature */
709 unsigned int encryptedSignatureLen;                               /* length */
710 unsigned char iv[8];                           /* DES initialization vector */
711 int digestAlgorithm;                           /* message-digest algorithms */
712 R_RSA_PRIVATE_KEY *privateKey;               /* recipient's RSA private key */
713 R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
714 {
715   R_ENVELOPE_CTX context;
716   int status;
717   unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
718     signature[MAX_SIGNATURE_LEN];
719   unsigned int encryptedKeyBlockLen, signatureLen;
720   
721   if (encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN)
722     return (RE_KEY_ENCODING);
723   
724   if (encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN)
725     return (RE_SIGNATURE_ENCODING);
726   
727   do {
728     if (R_DecodePEMBlock 
729         (encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey,
730          encryptedKeyLen) != 0) {
731       status = RE_KEY_ENCODING;
732       break;
733     }
734
735     if ((status = R_OpenInit
736          (&context, EA_DES_CBC, encryptedKeyBlock, encryptedKeyBlockLen,
737           iv, privateKey)) != 0)
738       break;
739
740     if ((status = DecryptPEMUpdateFinal
741          (&context, content, contentLen, encryptedContent,
742           encryptedContentLen)) != 0) {
743       if ((status == RE_LEN || status == RE_ENCODING))
744         status = RE_CONTENT_ENCODING;
745       else
746         status = RE_KEY;
747       break;
748     }
749     
750     if (status = DecryptPEMUpdateFinal
751         (&context, signature, &signatureLen, encryptedSignature,
752          encryptedSignatureLen)) {
753       if ((status == RE_LEN || status == RE_ENCODING))
754         status = RE_SIGNATURE_ENCODING;
755       else
756         status = RE_KEY;
757       break;
758     }
759
760     if ((status = R_VerifyBlockSignature
761          (content, *contentLen, signature, signatureLen, digestAlgorithm,
762           publicKey)) != 0)
763       break;
764   } while (0);
765   
766   /* Zeroize sensitive information.
767    */
768   R_memset ((POINTER)&context, 0, sizeof (context));
769   R_memset ((POINTER)signature, 0, sizeof (signature));
770
771   return (status);
772 }
773
774 int R_DigestBlock (digest, digestLen, block, blockLen, digestAlgorithm)
775 unsigned char *digest;                                    /* message digest */
776 unsigned int *digestLen;                        /* length of message digest */
777 unsigned char *block;                                              /* block */
778 unsigned int blockLen;                                   /* length of block */
779 int digestAlgorithm;                            /* message-digest algorithm */
780 {
781   R_DIGEST_CTX context;
782   int status;
783
784   do {
785     if ((status = R_DigestInit (&context, digestAlgorithm)) != 0)
786       break;
787     if ((status = R_DigestUpdate (&context, block, blockLen)) != 0)
788       break;
789     if ((status = R_DigestFinal (&context, digest, digestLen)) != 0)
790       break;
791   } while (0);
792
793   /* Zeroize sensitive information. */
794   R_memset ((POINTER)&context, 0, sizeof (context));
795
796   return (status);
797 }
798
799 /* Assumes digestAlgorithm is DA_MD2 or DA_MD5 and digest length is 16.
800  */
801 static void R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest)
802 unsigned char *digestInfo;                           /* DigestInfo encoding */
803 int digestAlgorithm;                            /* message-digest algorithm */
804 unsigned char *digest;                                    /* message digest */
805 {
806   R_memcpy 
807     ((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN);
808   
809   digestInfo[DIGEST_INFO_A_LEN] =
810     (digestAlgorithm == DA_MD2) ? (unsigned char)2 : (unsigned char)5;
811
812   R_memcpy 
813     ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B,
814      DIGEST_INFO_B_LEN);
815   
816   R_memcpy 
817     ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN],
818      (POINTER)digest, 16);
819 }
820
821 /* Call SealUpdate and SealFinal on the input and ASCII recode.
822  */
823 static void EncryptPEMUpdateFinal
824   (context, output, outputLen, input, inputLen)
825 R_ENVELOPE_CTX *context;
826 unsigned char *output;                          /* encrypted, encoded block */
827 unsigned int *outputLen;                                /* length of output */
828 unsigned char *input;                                   /* block to encrypt */
829 unsigned int inputLen;                                            /* length */
830 {
831   unsigned char encryptedPart[24];
832   unsigned int i, lastPartLen, tempLen, len;
833
834   /* Choose a buffer size of 24 bytes to hold the temporary encrypted output
835        which will be encoded.
836      Encrypt and encode as many 24-byte blocks as possible.
837    */
838   for (i = 0; i < inputLen / 24; ++i) {
839     /* Assume part out length will equal part in length since it is
840          a multiple of 8.  Also assume no error output. */
841     R_SealUpdate (context, encryptedPart, &tempLen, &input[24*i], 24);
842
843     /* len is always 32 */
844     R_EncodePEMBlock (&output[32*i], &tempLen, encryptedPart, 24);
845   }
846   
847   /* Encrypt the last part into encryptedPart.
848    */  
849   R_SealUpdate
850     (context, encryptedPart, &lastPartLen, &input[24*i], inputLen - 24*i);
851   R_SealFinal (context, encryptedPart + lastPartLen, &len);
852   lastPartLen += len;
853
854   R_EncodePEMBlock (&output[32*i], &len, encryptedPart, lastPartLen);
855   *outputLen = 32*i + len;
856
857   /* Zeroize sensitive information.
858    */
859   R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
860 }
861
862 static int DecryptPEMUpdateFinal (context, output, outputLen, input, inputLen)
863 R_ENVELOPE_CTX *context;
864 unsigned char *output;                          /* decoded, decrypted block */
865 unsigned int *outputLen;                                /* length of output */
866 unsigned char *input;                           /* encrypted, encoded block */
867 unsigned int inputLen;                                            /* length */
868 {
869   int status;
870   unsigned char encryptedPart[24];
871   unsigned int i, len;
872   
873   do {
874     /* Choose a buffer size of 24 bytes to hold the temporary decoded output
875          which will be decrypted.
876        Decode and decrypt as many 32-byte input blocks as possible.
877      */
878     *outputLen = 0;
879     for (i = 0; i < inputLen/32; i++) {
880       /* len is always 24 */
881       if ((status = R_DecodePEMBlock
882            (encryptedPart, &len, &input[32*i], 32)) != 0)
883         break;
884
885       /* Excpect no error return */
886       R_OpenUpdate (context, output, &len, encryptedPart, 24);
887       output += len;
888       *outputLen += len;
889     }
890     if (status)
891       break;
892
893     /* Decode the last part */  
894     if ((status = R_DecodePEMBlock
895          (encryptedPart, &len, &input[32*i], inputLen - 32*i)) != 0)
896       break;
897
898     /* Decrypt the last part.
899      */
900     R_OpenUpdate (context, output, &len, encryptedPart, len);
901     output += len;
902     *outputLen += len;
903     if ((status = R_OpenFinal (context, output, &len)) != 0)
904       break;
905     *outputLen += len;
906   } while (0);
907
908   /* Zeroize sensitive information.
909    */
910   R_memset ((POINTER)&context, 0, sizeof (context));
911   R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
912
913   return (status);
914 }
915
916 static int CipherInit (context, encryptionAlgorithm, key, iv, encrypt)
917 R_ENVELOPE_CTX *context;
918 int encryptionAlgorithm;
919 unsigned char *key;                                              /* DES key */
920 unsigned char *iv;                             /* DES initialization vector */
921 int encrypt;                     /* encrypt flag (1 = encrypt, 0 = decrypt) */
922 {
923   switch (encryptionAlgorithm) {
924   case EA_DES_CBC:
925     DES_CBCInit (&context->cipherContext.des, key, iv, encrypt);
926     return (0);
927   case EA_DESX_CBC:
928     DESX_CBCInit (&context->cipherContext.desx, key, iv, encrypt);
929     return (0);
930   case EA_DES_EDE2_CBC:
931   case EA_DES_EDE3_CBC:
932     DES3_CBCInit (&context->cipherContext.des3, key, iv, encrypt);
933     return (0);
934
935   default:
936     return (RE_ENCRYPTION_ALGORITHM);
937   }
938 }
939
940 /* Assume len is a multiple of 8.
941  */
942 static void CipherUpdate (context, output, input, len)
943 R_ENVELOPE_CTX *context;
944 unsigned char *output;                                      /* output block */
945 unsigned char *input;                                        /* input block */
946 unsigned int len;                      /* length of input and output blocks */
947 {
948   if (context->encryptionAlgorithm == EA_DES_CBC)
949     DES_CBCUpdate (&context->cipherContext.des, output, input, len);
950   else if (context->encryptionAlgorithm == EA_DESX_CBC)
951     DESX_CBCUpdate (&context->cipherContext.desx, output, input, len);
952   else
953     DES3_CBCUpdate (&context->cipherContext.des3, output, input, len);
954 }
955
956 static void CipherRestart (context)
957 R_ENVELOPE_CTX *context;
958 {
959   if (context->encryptionAlgorithm == EA_DES_CBC)
960     DES_CBCRestart (&context->cipherContext.des);
961   else if (context->encryptionAlgorithm == EA_DESX_CBC)
962     DESX_CBCRestart (&context->cipherContext.desx);
963   else
964     DES3_CBCRestart (&context->cipherContext.des3);
965 }
This page took 0.117209 seconds and 5 git commands to generate.