1 /* R_ENHANC.C - cryptographic enhancements for RSAREF
4 /* Copyright (C) RSA Laboratories, a division of RSA Data Security,
5 Inc., created 1991. All rights reserved.
13 /* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 (for MD2/MD5),
14 then DIGEST_INFO_B, then 16-byte message digest.
17 static unsigned char DIGEST_INFO_A[] = {
18 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7,
21 #define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A)
23 static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 };
24 #define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B)
26 #define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16)
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"
37 #define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN
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 *,
44 static int DecryptPEMUpdateFinal PROTO_LIST
45 ((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
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 *));
53 int R_DigestInit (context, digestAlgorithm)
54 R_DIGEST_CTX *context; /* new context */
55 int digestAlgorithm; /* message-digest algorithm */
57 context->digestAlgorithm = digestAlgorithm;
59 switch (digestAlgorithm) {
61 MD2Init (&context->context.md2);
65 MD5Init (&context->context.md5);
69 return (RE_DIGEST_ALGORITHM);
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 */
80 if (context->digestAlgorithm == DA_MD2)
81 MD2Update (&context->context.md2, partIn, partInLen);
83 MD5Update (&context->context.md5, partIn, partInLen);
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 */
93 if (context->digestAlgorithm == DA_MD2)
94 MD2Final (digest, &context->context.md2);
96 MD5Final (digest, &context->context.md5);
101 int R_SignInit (context, digestAlgorithm)
102 R_SIGNATURE_CTX *context; /* new context */
103 int digestAlgorithm; /* message-digest algorithm */
105 return (R_DigestInit (&context->digestContext, digestAlgorithm));
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 */
113 return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
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 */
123 unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN];
124 unsigned int digestLen;
127 if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen))
132 (digestInfo, context->digestContext.digestAlgorithm, digest);
134 if (RSAPrivateEncrypt
135 (signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey)
137 status = RE_PRIVATE_KEY;
141 /* Reset for another verification. Assume Init won't fail */
143 (&context->digestContext, context->digestContext.digestAlgorithm);
146 /* Zeroize potentially sensitive information.
148 R_memset ((POINTER)digest, 0, sizeof (digest));
149 R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
154 int R_VerifyInit (context, digestAlgorithm)
155 R_SIGNATURE_CTX *context; /* new context */
156 int digestAlgorithm; /* message-digest algorithm */
158 return (R_DigestInit (&context->digestContext, digestAlgorithm));
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 */
166 return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
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 */
176 unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN],
177 originalDigestInfo[MAX_SIGNATURE_LEN];
178 unsigned int originalDigestInfoLen, digestLen;
180 if (signatureLen > MAX_SIGNATURE_LEN)
185 if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen))
190 (digestInfo, context->digestContext.digestAlgorithm, digest);
193 (originalDigestInfo, &originalDigestInfoLen, signature, signatureLen,
195 status = RE_PUBLIC_KEY;
199 if ((originalDigestInfoLen != DIGEST_INFO_LEN) ||
201 ((POINTER)originalDigestInfo, (POINTER)digestInfo,
203 status = RE_SIGNATURE;
207 /* Reset for another verification. Assume Init won't fail */
209 (&context->digestContext, context->digestContext.digestAlgorithm);
212 /* Zeroize potentially sensitive information.
214 R_memset ((POINTER)digest, 0, sizeof (digest));
215 R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
216 R_memset ((POINTER)originalDigestInfo, 0, sizeof (originalDigestInfo));
221 /* Caller must ASCII recode the encrypted keys if desired.
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 */
236 unsigned char key[24];
237 unsigned int keyLen, i;
240 context->encryptionAlgorithm = encryptionAlgorithm;
242 keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24;
243 if ((status = R_GenerateBytes (key, keyLen, randomStruct)) != 0)
245 if ((status = R_GenerateBytes (iv, 8, randomStruct)) != 0)
248 if (encryptionAlgorithm == EA_DES_EDE2_CBC)
249 /* Make both E keys the same */
250 R_memcpy ((POINTER)(key + 16), (POINTER)key, 8);
252 if ((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) != 0)
255 for (i = 0; i < publicKeyCount; ++i) {
257 (encryptedKeys[i], &encryptedKeyLens[i], key, keyLen,
258 publicKeys[i], randomStruct)) {
259 status = RE_PUBLIC_KEY;
266 context->bufferLen = 0;
269 /* Zeroize sensitive information.
271 R_memset ((POINTER)key, 0, sizeof (key));
276 /* Assume partOut buffer is at least partInLen + 7, since this may flush
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 */
286 unsigned int tempLen;
288 tempLen = 8 - context->bufferLen;
289 if (partInLen < tempLen) {
290 /* Just accumulate into buffer.
293 ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
295 context->bufferLen += partInLen;
300 /* Fill the buffer and encrypt.
303 ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
305 CipherUpdate (context, partOut, context->buffer, 8);
307 partInLen -= tempLen;
311 /* Encrypt as many 8-byte blocks as possible.
313 tempLen = 8 * (partInLen / 8);
314 CipherUpdate (context, partOut, partIn, tempLen);
316 partInLen -= tempLen;
317 *partOutLen += tempLen;
319 /* Length is now less than 8, so copy remainder to buffer.
322 ((POINTER)context->buffer, (POINTER)partIn,
323 context->bufferLen = partInLen);
328 /* Assume partOut buffer is at least 8 bytes.
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 */
337 /* Pad and encrypt final block.
339 padLen = 8 - context->bufferLen;
341 ((POINTER)(context->buffer + context->bufferLen), (int)padLen, padLen);
342 CipherUpdate (context, partOut, context->buffer, 8);
345 /* Restart the context.
347 CipherRestart (context);
348 context->bufferLen = 0;
353 /* Assume caller has already ASCII decoded the encryptedKey if necessary.
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 */
365 unsigned char key[MAX_ENCRYPTED_KEY_LEN];
368 if (encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN)
372 context->encryptionAlgorithm = encryptionAlgorithm;
374 if (RSAPrivateDecrypt
375 (key, &keyLen, encryptedKey, encryptedKeyLen, privateKey)) {
376 status = RE_PRIVATE_KEY;
380 if (encryptionAlgorithm == EA_DES_CBC) {
382 status = RE_PRIVATE_KEY;
388 status = RE_PRIVATE_KEY;
393 if ((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) != 0)
396 context->bufferLen = 0;
399 /* Zeroize sensitive information.
401 R_memset ((POINTER)key, 0, sizeof (key));
406 /* Assume partOut buffer is at least partInLen + 7, since this may flush
407 buffered input. Always leaves at least one byte in buffer.
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 */
416 unsigned int tempLen;
418 tempLen = 8 - context->bufferLen;
419 if (partInLen <= tempLen) {
420 /* Just accumulate into buffer.
423 ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
425 context->bufferLen += partInLen;
430 /* Fill the buffer and decrypt. We know that there will be more left
431 in partIn after decrypting the buffer.
434 ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
436 CipherUpdate (context, partOut, context->buffer, 8);
438 partInLen -= tempLen;
442 /* Decrypt as many 8 byte blocks as possible, leaving at least one byte
445 tempLen = 8 * ((partInLen - 1) / 8);
446 CipherUpdate (context, partOut, partIn, tempLen);
448 partInLen -= tempLen;
449 *partOutLen += tempLen;
451 /* Length is between 1 and 8, so copy into buffer.
454 ((POINTER)context->buffer, (POINTER)partIn,
455 context->bufferLen = partInLen);
460 /* Assume partOut buffer is at least 7 bytes.
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 */
468 unsigned char lastPart[8];
473 if (context->bufferLen == 0)
474 /* There was no input data to decrypt */
477 if (context->bufferLen != 8) {
482 /* Decrypt and strip padding from final block which is in buffer.
484 CipherUpdate (context, lastPart, context->buffer, 8);
486 padLen = lastPart[7];
487 if (padLen == 0 || padLen > 8) {
492 ((POINTER)&lastPart[8 - padLen], PADDING[padLen], padLen) != 0) {
497 R_memcpy ((POINTER)partOut, (POINTER)lastPart, *partOutLen = 8 - padLen);
500 /* Restart the context.
502 CipherRestart (context);
503 context->bufferLen = 0;
506 /* Zeroize sensitive information.
508 R_memset ((POINTER)lastPart, 0, sizeof (lastPart));
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 */
527 unsigned char signature[MAX_SIGNATURE_LEN];
528 unsigned int signatureLen;
530 if ((status = R_SignBlock
531 (signature, &signatureLen, content, contentLen, digestAlgorithm,
536 (encodedSignature, encodedSignatureLen, signature, signatureLen);
540 (encodedContent, encodedContentLen, content, contentLen);
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 */
554 R_SIGNATURE_CTX context;
558 if ((status = R_SignInit (&context, digestAlgorithm)) != 0)
560 if ((status = R_SignUpdate (&context, block, blockLen)) != 0)
562 if ((status = R_SignFinal (&context, signature, signatureLen, privateKey))
567 /* Zeroize sensitive information. */
568 R_memset ((POINTER)&context, 0, sizeof (context));
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 */
586 unsigned char signature[MAX_SIGNATURE_LEN];
587 unsigned int signatureLen;
589 if (encodedSignatureLen > MAX_PEM_SIGNATURE_LEN)
590 return (RE_SIGNATURE_ENCODING);
594 (content, contentLen, encodedContent, encodedContentLen))
595 return (RE_CONTENT_ENCODING);
598 content = encodedContent;
599 *contentLen = encodedContentLen;
603 (signature, &signatureLen, encodedSignature, encodedSignatureLen))
604 return (RE_SIGNATURE_ENCODING);
606 return (R_VerifyBlockSignature
607 (content, *contentLen, signature, signatureLen, digestAlgorithm,
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 */
620 R_SIGNATURE_CTX context;
624 if ((status = R_VerifyInit (&context, digestAlgorithm)) != 0)
626 if ((status = R_VerifyUpdate (&context, block, blockLen)) != 0)
628 if ((status = R_VerifyFinal (&context, signature, signatureLen, publicKey))
633 /* Zeroize sensitive information. */
634 R_memset ((POINTER)&context, 0, sizeof (context));
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 */
657 R_ENVELOPE_CTX context;
658 R_RSA_PUBLIC_KEY *publicKeys[1];
660 unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
661 signature[MAX_SIGNATURE_LEN], *encryptedKeys[1];
662 unsigned int signatureLen, encryptedKeyBlockLen;
665 if ((status = R_SignBlock
666 (signature, &signatureLen, content, contentLen, digestAlgorithm,
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)
678 (encryptedKey, encryptedKeyLen, encryptedKeyBlock,
679 encryptedKeyBlockLen);
681 EncryptPEMUpdateFinal
682 (&context, encryptedContent, encryptedContentLen, content,
685 EncryptPEMUpdateFinal
686 (&context, encryptedSignature, encryptedSignatureLen, signature,
690 /* Zeroize sensitive information.
692 R_memset ((POINTER)&context, 0, sizeof (context));
693 R_memset ((POINTER)signature, 0, sizeof (signature));
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 */
715 R_ENVELOPE_CTX context;
717 unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
718 signature[MAX_SIGNATURE_LEN];
719 unsigned int encryptedKeyBlockLen, signatureLen;
721 if (encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN)
722 return (RE_KEY_ENCODING);
724 if (encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN)
725 return (RE_SIGNATURE_ENCODING);
729 (encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey,
730 encryptedKeyLen) != 0) {
731 status = RE_KEY_ENCODING;
735 if ((status = R_OpenInit
736 (&context, EA_DES_CBC, encryptedKeyBlock, encryptedKeyBlockLen,
737 iv, privateKey)) != 0)
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;
750 if (status = DecryptPEMUpdateFinal
751 (&context, signature, &signatureLen, encryptedSignature,
752 encryptedSignatureLen)) {
753 if ((status == RE_LEN || status == RE_ENCODING))
754 status = RE_SIGNATURE_ENCODING;
760 if ((status = R_VerifyBlockSignature
761 (content, *contentLen, signature, signatureLen, digestAlgorithm,
766 /* Zeroize sensitive information.
768 R_memset ((POINTER)&context, 0, sizeof (context));
769 R_memset ((POINTER)signature, 0, sizeof (signature));
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 */
781 R_DIGEST_CTX context;
785 if ((status = R_DigestInit (&context, digestAlgorithm)) != 0)
787 if ((status = R_DigestUpdate (&context, block, blockLen)) != 0)
789 if ((status = R_DigestFinal (&context, digest, digestLen)) != 0)
793 /* Zeroize sensitive information. */
794 R_memset ((POINTER)&context, 0, sizeof (context));
799 /* Assumes digestAlgorithm is DA_MD2 or DA_MD5 and digest length is 16.
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 */
807 ((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN);
809 digestInfo[DIGEST_INFO_A_LEN] =
810 (digestAlgorithm == DA_MD2) ? (unsigned char)2 : (unsigned char)5;
813 ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B,
817 ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN],
818 (POINTER)digest, 16);
821 /* Call SealUpdate and SealFinal on the input and ASCII recode.
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 */
831 unsigned char encryptedPart[24];
832 unsigned int i, lastPartLen, tempLen, len;
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.
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);
843 /* len is always 32 */
844 R_EncodePEMBlock (&output[32*i], &tempLen, encryptedPart, 24);
847 /* Encrypt the last part into encryptedPart.
850 (context, encryptedPart, &lastPartLen, &input[24*i], inputLen - 24*i);
851 R_SealFinal (context, encryptedPart + lastPartLen, &len);
854 R_EncodePEMBlock (&output[32*i], &len, encryptedPart, lastPartLen);
855 *outputLen = 32*i + len;
857 /* Zeroize sensitive information.
859 R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
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 */
870 unsigned char encryptedPart[24];
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.
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)
885 /* Excpect no error return */
886 R_OpenUpdate (context, output, &len, encryptedPart, 24);
893 /* Decode the last part */
894 if ((status = R_DecodePEMBlock
895 (encryptedPart, &len, &input[32*i], inputLen - 32*i)) != 0)
898 /* Decrypt the last part.
900 R_OpenUpdate (context, output, &len, encryptedPart, len);
903 if ((status = R_OpenFinal (context, output, &len)) != 0)
908 /* Zeroize sensitive information.
910 R_memset ((POINTER)&context, 0, sizeof (context));
911 R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
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) */
923 switch (encryptionAlgorithm) {
925 DES_CBCInit (&context->cipherContext.des, key, iv, encrypt);
928 DESX_CBCInit (&context->cipherContext.desx, key, iv, encrypt);
930 case EA_DES_EDE2_CBC:
931 case EA_DES_EDE3_CBC:
932 DES3_CBCInit (&context->cipherContext.des3, key, iv, encrypt);
936 return (RE_ENCRYPTION_ALGORITHM);
940 /* Assume len is a multiple of 8.
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 */
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);
953 DES3_CBCUpdate (&context->cipherContext.des3, output, input, len);
956 static void CipherRestart (context)
957 R_ENVELOPE_CTX *context;
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);
964 DES3_CBCRestart (&context->cipherContext.des3);