提交 eeb9cdfc 编写于 作者: D Dr. Stephen Henson

Add support for KEK decrypt in cms utility.

上级 16fe5f8b
......@@ -465,7 +465,7 @@ int MAIN(int argc, char **argv)
}
else if (operation == SMIME_DECRYPT)
{
if (!recipfile && !keyfile)
if (!recipfile && !keyfile && !secret_key)
{
BIO_printf(bio_err, "No recipient certificate or key specified\n");
badarg = 1;
......@@ -838,7 +838,30 @@ int MAIN(int argc, char **argv)
ret = 4;
if (operation == SMIME_DECRYPT)
{
if (!CMS_decrypt(cms, key, recip, indata, out, flags))
if (secret_key)
{
if (!CMS_decrypt_set1_key(cms,
secret_key, secret_keylen,
secret_keyid, secret_keyidlen))
{
BIO_puts(bio_err,
"Error decrypting CMS using secret key\n");
goto end;
}
}
if (key)
{
if (!CMS_decrypt_set1_pkey(cms, key, recip))
{
BIO_puts(bio_err,
"Error decrypting CMS using private key\n");
goto end;
}
}
if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags))
{
BIO_printf(bio_err, "Error decrypting CMS structure\n");
goto end;
......
......@@ -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
......
......@@ -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)
......
......@@ -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"},
......
......@@ -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;
......
......@@ -235,6 +235,27 @@ my @smime_cms_tests = (
"-decrypt -recip $smdir/smrsa1.pem -in test.cms -out smtst.txt"
],
[
"enveloped content test streaming PEM format, KEK",
"-encrypt -in smcont.txt -outform PEM -aes128"
. " -stream -out test.cms "
. " -secretkey 000102030405060708090A0B0C0D0E0F "
. " -secretkeyid C0FEE0",
"-decrypt -in test.cms -out smtst.txt -inform PEM"
. " -secretkey 000102030405060708090A0B0C0D0E0F "
. " -secretkeyid C0FEE0"
],
[
"enveloped content test streaming PEM format, KEK, key only",
"-encrypt -in smcont.txt -outform PEM -aes128"
. " -stream -out test.cms "
. " -secretkey 000102030405060708090A0B0C0D0E0F "
. " -secretkeyid C0FEE0",
"-decrypt -in test.cms -out smtst.txt -inform PEM"
. " -secretkey 000102030405060708090A0B0C0D0E0F "
],
[
"data content test streaming PEM format",
"-data_create -in smcont.txt -outform PEM -nodetach"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册