source: trunk/third/moira/util/rsaref/r_enhanc.c @ 23095

Revision 23095, 32.1 KB checked in by ghudson, 16 years ago (diff)
Import the moira package from SIPB Debathena.
Line 
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
17static 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
23static 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
28static 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
39static void R_EncodeDigestInfo PROTO_LIST
40  ((unsigned char *, int, unsigned char *));
41static void EncryptPEMUpdateFinal PROTO_LIST
42  ((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
43    unsigned int));
44static int DecryptPEMUpdateFinal PROTO_LIST
45  ((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
46    unsigned int));
47static int CipherInit PROTO_LIST
48  ((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int));
49static void CipherUpdate PROTO_LIST
50  ((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int));
51static void CipherRestart PROTO_LIST ((R_ENVELOPE_CTX *));
52
53int R_DigestInit (context, digestAlgorithm)
54R_DIGEST_CTX *context;                                       /* new context */
55int 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
75int R_DigestUpdate (context, partIn, partInLen)
76R_DIGEST_CTX *context;                                           /* context */
77unsigned char *partIn;                                    /* next data part */
78unsigned 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
87int R_DigestFinal (context, digest, digestLen)
88R_DIGEST_CTX *context;                                           /* context */
89unsigned char *digest;                                    /* message digest */
90unsigned 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
101int R_SignInit (context, digestAlgorithm)
102R_SIGNATURE_CTX *context;                                    /* new context */
103int digestAlgorithm;                            /* message-digest algorithm */
104{
105  return (R_DigestInit (&context->digestContext, digestAlgorithm));
106}
107
108int R_SignUpdate (context, partIn, partInLen)
109R_SIGNATURE_CTX *context;                                        /* context */
110unsigned char *partIn;                                    /* next data part */
111unsigned int partInLen;                         /* length of next data part */
112{
113  return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
114}
115
116int R_SignFinal (context, signature, signatureLen, privateKey)
117R_SIGNATURE_CTX *context;                                        /* context */
118unsigned char *signature;                                      /* signature */
119unsigned int *signatureLen;                          /* length of signature */
120R_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
154int R_VerifyInit (context, digestAlgorithm)
155R_SIGNATURE_CTX *context;                                    /* new context */
156int digestAlgorithm;                            /* message-digest algorithm */
157{
158  return (R_DigestInit (&context->digestContext, digestAlgorithm));
159}
160
161int R_VerifyUpdate (context, partIn, partInLen)
162R_SIGNATURE_CTX *context;                                        /* context */
163unsigned char *partIn;                                    /* next data part */
164unsigned int partInLen;                         /* length of next data part */
165{
166  return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
167}
168
169int R_VerifyFinal (context, signature, signatureLen, publicKey)
170R_SIGNATURE_CTX *context;                                        /* context */
171unsigned char *signature;                                      /* signature */
172unsigned int signatureLen;                           /* length of signature */
173R_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 */
223int R_SealInit
224  (context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys,
225   encryptionAlgorithm, randomStruct)
226R_ENVELOPE_CTX *context;                                     /* new context */
227unsigned char **encryptedKeys;                            /* encrypted keys */
228unsigned int *encryptedKeyLens;                /* lengths of encrypted keys */
229unsigned char iv[8];                               /* initialization vector */
230unsigned int publicKeyCount;                       /* number of public keys */
231R_RSA_PUBLIC_KEY **publicKeys;                               /* public keys */
232int encryptionAlgorithm;                       /* data encryption algorithm */
233R_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 */
279int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen)
280R_ENVELOPE_CTX *context;                                         /* context */
281unsigned char *partOut;                         /* next encrypted data part */
282unsigned int *partOutLen;             /* length of next encrypted data part */
283unsigned char *partIn;                                    /* next data part */
284unsigned 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 */
330int R_SealFinal (context, partOut, partOutLen)
331R_ENVELOPE_CTX *context;                                         /* context */
332unsigned char *partOut;                         /* last encrypted data part */
333unsigned 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 */
355int R_OpenInit
356  (context, encryptionAlgorithm, encryptedKey, encryptedKeyLen, iv, privateKey)
357R_ENVELOPE_CTX *context;                                     /* new context */
358int encryptionAlgorithm;                       /* data encryption algorithm */
359unsigned char *encryptedKey;               /* encrypted data encryption key */
360unsigned int encryptedKeyLen;                    /* length of encrypted key */
361unsigned char iv[8];                               /* initialization vector */
362R_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 */
409int R_OpenUpdate (context, partOut, partOutLen, partIn, partInLen)
410R_ENVELOPE_CTX *context;                                         /* context */
411unsigned char *partOut;                         /* next recovered data part */
412unsigned int *partOutLen;             /* length of next recovered data part */
413unsigned char *partIn;                          /* next encrypted data part */
414unsigned 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 */
462int R_OpenFinal (context, partOut, partOutLen)
463R_ENVELOPE_CTX *context;                                         /* context */
464unsigned char *partOut;                         /* last recovered data part */
465unsigned 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
513int R_SignPEMBlock
514  (encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen,
515   content, contentLen, recode, digestAlgorithm, privateKey)
516unsigned char *encodedContent;                           /* encoded content */
517unsigned int *encodedContentLen;               /* length of encoded content */
518unsigned char *encodedSignature;                       /* encoded signature */
519unsigned int *encodedSignatureLen;           /* length of encoded signature */
520unsigned char *content;                                          /* content */
521unsigned int contentLen;                               /* length of content */
522int recode;                                                /* recoding flag */
523int digestAlgorithm;                            /* message-digest algorithm */
524R_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
545int R_SignBlock
546  (signature, signatureLen, block, blockLen, digestAlgorithm, privateKey)
547unsigned char *signature;                                      /* signature */
548unsigned int *signatureLen;                          /* length of signature */
549unsigned char *block;                                              /* block */
550unsigned int blockLen;                                   /* length of block */
551int digestAlgorithm;                            /* message-digest algorithm */
552R_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
573int R_VerifyPEMSignature
574  (content, contentLen, encodedContent, encodedContentLen, encodedSignature,
575   encodedSignatureLen, recode, digestAlgorithm, publicKey)
576unsigned char *content;                                          /* content */
577unsigned int *contentLen;                              /* length of content */
578unsigned char *encodedContent;                /* (possibly) encoded content */
579unsigned int encodedContentLen;                /* length of encoded content */
580unsigned char *encodedSignature;                       /* encoded signature */
581unsigned int encodedSignatureLen;            /* length of encoded signature */
582int recode;                                                /* recoding flag */
583int digestAlgorithm;                            /* message-digest algorithm */
584R_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
611int R_VerifyBlockSignature
612  (block, blockLen, signature, signatureLen, digestAlgorithm, publicKey)
613unsigned char *block;                                              /* block */
614unsigned int blockLen;                                   /* length of block */
615unsigned char *signature;                                      /* signature */
616unsigned int signatureLen;                           /* length of signature */
617int digestAlgorithm;                            /* message-digest algorithm */
618R_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
639int R_SealPEMBlock
640  (encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen,
641   encryptedSignature, encryptedSignatureLen, iv, content, contentLen,
642   digestAlgorithm, publicKey, privateKey, randomStruct)
643unsigned char *encryptedContent;              /* encoded, encrypted content */
644unsigned int *encryptedContentLen;                                /* length */
645unsigned char *encryptedKey;                      /* encoded, encrypted key */
646unsigned int *encryptedKeyLen;                                    /* length */
647unsigned char *encryptedSignature;          /* encoded, encrypted signature */
648unsigned int *encryptedSignatureLen;                              /* length */
649unsigned char iv[8];                           /* DES initialization vector */
650unsigned char *content;                                          /* content */
651unsigned int contentLen;                               /* length of content */
652int digestAlgorithm;                           /* message-digest algorithms */
653R_RSA_PUBLIC_KEY *publicKey;                  /* recipient's RSA public key */
654R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
655R_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
698int R_OpenPEMBlock
699  (content, contentLen, encryptedContent, encryptedContentLen, encryptedKey,
700   encryptedKeyLen, encryptedSignature, encryptedSignatureLen,
701   iv, digestAlgorithm, privateKey, publicKey)
702unsigned char *content;                                          /* content */
703unsigned int *contentLen;                              /* length of content */
704unsigned char *encryptedContent;              /* encoded, encrypted content */
705unsigned int encryptedContentLen;                                 /* length */
706unsigned char *encryptedKey;                      /* encoded, encrypted key */
707unsigned int encryptedKeyLen;                                     /* length */
708unsigned char *encryptedSignature;          /* encoded, encrypted signature */
709unsigned int encryptedSignatureLen;                               /* length */
710unsigned char iv[8];                           /* DES initialization vector */
711int digestAlgorithm;                           /* message-digest algorithms */
712R_RSA_PRIVATE_KEY *privateKey;               /* recipient's RSA private key */
713R_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
774int R_DigestBlock (digest, digestLen, block, blockLen, digestAlgorithm)
775unsigned char *digest;                                    /* message digest */
776unsigned int *digestLen;                        /* length of message digest */
777unsigned char *block;                                              /* block */
778unsigned int blockLen;                                   /* length of block */
779int 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 */
801static void R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest)
802unsigned char *digestInfo;                           /* DigestInfo encoding */
803int digestAlgorithm;                            /* message-digest algorithm */
804unsigned 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 */
823static void EncryptPEMUpdateFinal
824  (context, output, outputLen, input, inputLen)
825R_ENVELOPE_CTX *context;
826unsigned char *output;                          /* encrypted, encoded block */
827unsigned int *outputLen;                                /* length of output */
828unsigned char *input;                                   /* block to encrypt */
829unsigned 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
862static int DecryptPEMUpdateFinal (context, output, outputLen, input, inputLen)
863R_ENVELOPE_CTX *context;
864unsigned char *output;                          /* decoded, decrypted block */
865unsigned int *outputLen;                                /* length of output */
866unsigned char *input;                           /* encrypted, encoded block */
867unsigned 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
916static int CipherInit (context, encryptionAlgorithm, key, iv, encrypt)
917R_ENVELOPE_CTX *context;
918int encryptionAlgorithm;
919unsigned char *key;                                              /* DES key */
920unsigned char *iv;                             /* DES initialization vector */
921int 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 */
942static void CipherUpdate (context, output, input, len)
943R_ENVELOPE_CTX *context;
944unsigned char *output;                                      /* output block */
945unsigned char *input;                                        /* input block */
946unsigned 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
956static void CipherRestart (context)
957R_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}
Note: See TracBrowser for help on using the repository browser.