summaryrefslogtreecommitdiffstats
path: root/crypto/cms
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2008-03-19 18:39:51 +0000
committerDr. Stephen Henson <steve@openssl.org>2008-03-19 18:39:51 +0000
commiteeb9cdfc945783753c1de319a76608422df878aa (patch)
tree67642f619f65efa6cf0e093aa2c8f7a11f31a4d9 /crypto/cms
parent16fe5f8b506e92d8d23f76d07baf5bb298edf85a (diff)
Add support for KEK decrypt in cms utility.
Diffstat (limited to 'crypto/cms')
-rw-r--r--crypto/cms/cms.h19
-rw-r--r--crypto/cms/cms_env.c37
-rw-r--r--crypto/cms/cms_err.c10
-rw-r--r--crypto/cms/cms_smime.c111
4 files changed, 132 insertions, 45 deletions
diff --git a/crypto/cms/cms.h b/crypto/cms/cms.h
index 5a74c4bb21..49fdcf539c 100644
--- a/crypto/cms/cms.h
+++ b/crypto/cms/cms.h
@@ -166,6 +166,11 @@ CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
BIO *data, BIO *dcont,
unsigned int flags);
+
+int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
+int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
+ unsigned char *key, size_t keylen,
+ unsigned char *id, size_t idlen);
STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
@@ -187,7 +192,13 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
ASN1_GENERALIZEDTIME *date,
ASN1_OBJECT *otherTypeId,
ASN1_TYPE *otherType);
-
+
+int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
+ unsigned char *key, size_t keylen);
+
+int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
+ const unsigned char *id, size_t idlen);
+
int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
@@ -297,6 +308,8 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_DECRYPT 152
#define CMS_F_CMS_DECRYPTEDCONTENT_DECRYPT_BIO 145
#define CMS_F_CMS_DECRYPTEDCONTENT_ENCRYPT_BIO 143
+#define CMS_F_CMS_DECRYPT_SET1_KEY 167
+#define CMS_F_CMS_DECRYPT_SET1_PKEY 168
#define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 110
#define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 111
#define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 112
@@ -322,9 +335,12 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_GET0_REVOCATION_CHOICES 120
#define CMS_F_CMS_GET0_SIGNED 121
#define CMS_F_CMS_RECIPIENTINFO_DECRYPT 150
+#define CMS_F_CMS_RECIPIENTINFO_KEKI_KEY_CMP 164
#define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT 161
#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 162
#define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 158
+#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP 166
+#define CMS_F_CMS_RECIPIENTINFO_KEKRI_KEY_CMP 165
#define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 122
#define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 160
#define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 155
@@ -359,6 +375,7 @@ void ERR_load_CMS_strings(void);
#define CMS_R_CONTENT_VERIFY_ERROR 106
#define CMS_R_CTRL_ERROR 107
#define CMS_R_CTRL_FAILURE 108
+#define CMS_R_DECRYPT_ERROR 159
#define CMS_R_ERROR_GETTING_PUBLIC_KEY 109
#define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 110
#define CMS_R_ERROR_SETTING_KEY 155
diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c
index 1bea558216..d9487541c1 100644
--- a/crypto/cms/cms_env.c
+++ b/crypto/cms/cms_env.c
@@ -431,6 +431,24 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
/* Key Encrypted Key (KEK) RecipientInfo routines */
+int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
+ const unsigned char *id, size_t idlen)
+ {
+ ASN1_OCTET_STRING tmp_os;
+ CMS_KEKRecipientInfo *kekri;
+ if (ri->type != CMS_RECIPINFO_KEK)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK);
+ return -2;
+ }
+ kekri = ri->d.kekri;
+ tmp_os.type = V_ASN1_OCTET_STRING;
+ tmp_os.flags = 0;
+ tmp_os.data = (unsigned char *)id;
+ tmp_os.length = (int)idlen;
+ return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
+ }
+
/* For now hard code AES key wrap info */
static size_t aes_wrap_keylen(int nid)
@@ -605,20 +623,13 @@ int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
unsigned char *key, size_t keylen)
{
CMS_KEKRecipientInfo *kekri;
- int wrap_nid;
if (ri->type != CMS_RECIPINFO_KEK)
{
CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);
return 0;
}
+
kekri = ri->d.kekri;
- wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
- if (aes_wrap_keylen(wrap_nid) != keylen)
- {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY,
- CMS_R_INVALID_KEY_LENGTH);
- return 0;
- }
kekri->key = key;
kekri->keylen = keylen;
return 1;
@@ -695,7 +706,7 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
AES_KEY actx;
unsigned char *ukey = NULL;
int ukeylen;
- int r = 0;
+ int r = 0, wrap_nid;
ec = cms->d.envelopedData->encryptedContentInfo;
@@ -707,6 +718,14 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
return 0;
}
+ wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
+ if (aes_wrap_keylen(wrap_nid) != kekri->keylen)
+ {
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
+ CMS_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+
/* If encrypted key length is invalid don't bother */
if (kekri->encryptedKey->length < 16)
diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c
index f7df77ba90..6fbab4da12 100644
--- a/crypto/cms/cms_err.c
+++ b/crypto/cms/cms_err.c
@@ -71,7 +71,7 @@
static ERR_STRING_DATA CMS_str_functs[]=
{
{ERR_FUNC(CMS_F_CHECK_CONTENT), "CHECK_CONTENT"},
-{ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_KEY), "CMS_ADD0_RECIPIENT_KEY"},
+{ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_KEY), "CMS_add0_recipient_key"},
{ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT), "CMS_add1_recipient_cert"},
{ERR_FUNC(CMS_F_CMS_ADD1_SIGNER), "CMS_add1_signer"},
{ERR_FUNC(CMS_F_CMS_ADD1_SIGNINGTIME), "CMS_ADD1_SIGNINGTIME"},
@@ -88,6 +88,8 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_DECRYPT), "CMS_decrypt"},
{ERR_FUNC(CMS_F_CMS_DECRYPTEDCONTENT_DECRYPT_BIO), "CMS_DECRYPTEDCONTENT_DECRYPT_BIO"},
{ERR_FUNC(CMS_F_CMS_DECRYPTEDCONTENT_ENCRYPT_BIO), "CMS_DECRYPTEDCONTENT_ENCRYPT_BIO"},
+{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_KEY), "CMS_DECRYPT_SET1_KEY"},
+{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_PKEY), "CMS_DECRYPT_SET1_PKEY"},
{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX), "CMS_DIGESTALGORITHM_FIND_CTX"},
{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO), "CMS_DIGESTALGORITHM_INIT_BIO"},
{ERR_FUNC(CMS_F_CMS_DIGESTEDDATA_DO_FINAL), "CMS_DIGESTEDDATA_DO_FINAL"},
@@ -113,15 +115,18 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES), "CMS_GET0_REVOCATION_CHOICES"},
{ERR_FUNC(CMS_F_CMS_GET0_SIGNED), "CMS_GET0_SIGNED"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_DECRYPT), "CMS_RecipientInfo_decrypt"},
+{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKI_KEY_CMP), "CMS_RECIPIENTINFO_KEKI_KEY_CMP"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT), "CMS_RECIPIENTINFO_KEKRI_DECRYPT"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT), "CMS_RECIPIENTINFO_KEKRI_ENCRYPT"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID), "CMS_RECIPIENTINFO_KEKRI_GET0_ID"},
+{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP), "CMS_RecipientInfo_kekri_id_cmp"},
+{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_KEY_CMP), "CMS_RECIPIENTINFO_KEKRI_KEY_CMP"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP), "CMS_RecipientInfo_ktri_cert_cmp"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT), "CMS_RECIPIENTINFO_KTRI_DECRYPT"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT), "CMS_RECIPIENTINFO_KTRI_ENCRYPT"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS), "CMS_RecipientInfo_ktri_get0_algs"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID), "CMS_RecipientInfo_ktri_get0_signer_id"},
-{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY), "CMS_RECIPIENTINFO_SET0_KEY"},
+{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY), "CMS_RecipientInfo_set0_key"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY), "CMS_RecipientInfo_set0_pkey"},
{ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER), "CMS_SET1_SIGNERIDENTIFIER"},
{ERR_FUNC(CMS_F_CMS_SET_DETACHED), "CMS_set_detached"},
@@ -153,6 +158,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_CONTENT_VERIFY_ERROR) ,"content verify error"},
{ERR_REASON(CMS_R_CTRL_ERROR) ,"ctrl error"},
{ERR_REASON(CMS_R_CTRL_FAILURE) ,"ctrl failure"},
+{ERR_REASON(CMS_R_DECRYPT_ERROR) ,"decrypt error"},
{ERR_REASON(CMS_R_ERROR_GETTING_PUBLIC_KEY),"error getting public key"},
{ERR_REASON(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),"error reading messagedigest attribute"},
{ERR_REASON(CMS_R_ERROR_SETTING_KEY) ,"error setting key"},
diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c
index c9be5a03e5..6388df89d1 100644
--- a/crypto/cms/cms_smime.c
+++ b/crypto/cms/cms_smime.c
@@ -493,12 +493,87 @@ CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
CMS_ContentInfo_free(cms);
return NULL;
}
+
+int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
+ {
+ STACK_OF(CMS_RecipientInfo) *ris;
+ CMS_RecipientInfo *ri;
+ int i, r;
+ ris = CMS_get0_RecipientInfos(cms);
+ for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
+ {
+ ri = sk_CMS_RecipientInfo_value(ris, i);
+ if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
+ continue;
+ /* If we have a cert try matching RecipientInfo
+ * otherwise try them all.
+ */
+ if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
+ {
+ CMS_RecipientInfo_set0_pkey(ri, pk);
+ r = CMS_RecipientInfo_decrypt(cms, ri);
+ CMS_RecipientInfo_set0_pkey(ri, NULL);
+ if (r > 0)
+ return 1;
+ if (cert)
+ {
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
+ CMS_R_DECRYPT_ERROR);
+ return 0;
+ }
+ ERR_clear_error();
+ }
+ }
+
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
+ return 0;
+
+ }
+
+int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
+ unsigned char *key, size_t keylen,
+ unsigned char *id, size_t idlen)
+ {
+ STACK_OF(CMS_RecipientInfo) *ris;
+ CMS_RecipientInfo *ri;
+ int i, r;
+ ris = CMS_get0_RecipientInfos(cms);
+ for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
+ {
+ ri = sk_CMS_RecipientInfo_value(ris, i);
+ if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
+ continue;
+
+ /* If we have an id try matching RecipientInfo
+ * otherwise try them all.
+ */
+ if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0))
+ {
+ CMS_RecipientInfo_set0_key(ri, key, keylen);
+ r = CMS_RecipientInfo_decrypt(cms, ri);
+ CMS_RecipientInfo_set0_key(ri, NULL, 0);
+ if (r > 0)
+ return 1;
+ if (id)
+ {
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY,
+ CMS_R_DECRYPT_ERROR);
+ return 0;
+ }
+ ERR_clear_error();
+ }
+ }
+
+ CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
+ return 0;
+
+ }
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
BIO *dcont, BIO *out,
unsigned int flags)
{
- int i, r;
+ int r;
BIO *cont;
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
{
@@ -507,39 +582,9 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
}
if (!dcont && !check_content(cms))
return 0;
- if (pk)
- {
- STACK_OF(CMS_RecipientInfo) *ris;
- CMS_RecipientInfo *ri;
- ris = CMS_get0_RecipientInfos(cms);
- for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
- {
- ri = sk_CMS_RecipientInfo_value(ris, i);
- if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS)
- continue;
- /* If we have a cert try matching RecipientInfo
- * otherwise try them all.
- */
- if (!cert ||
- (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
- {
- CMS_RecipientInfo_set0_pkey(ri, pk);
- r = CMS_RecipientInfo_decrypt(cms, ri);
- CMS_RecipientInfo_set0_pkey(ri, NULL);
- if (r > 0)
- break;
- if (cert)
- return 0;
- ERR_clear_error();
- }
- }
+ if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
+ return 0;
- if (i == sk_CMS_RecipientInfo_num(ris))
- {
- CMSerr(CMS_F_CMS_DECRYPT, CMS_R_NO_MATCHING_RECIPIENT);
- return 0;
- }
- }
cont = CMS_dataInit(cms, dcont);
if (!cont)
return 0;