mirror of
https://github.com/openssl/openssl.git
synced 2025-01-30 14:01:55 +08:00
Add support for KEK decrypt in cms utility.
This commit is contained in:
parent
16fe5f8b50
commit
eeb9cdfc94
27
apps/cms.c
27
apps/cms.c
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user