Skip to content

Commit 388eea3

Browse files
Merge pull request #8976 from holtrop/decode-encrypted-key-package
Add wc_PKCS7_DecodeEncryptedKeyPackage()
2 parents 046e46a + 3ce8c6e commit 388eea3

File tree

8 files changed

+358
-16
lines changed

8 files changed

+358
-16
lines changed

certs/renewcerts.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,8 @@ run_renewcerts(){
792792
cd ./test || { echo "Failed to switch to dir ./test"; exit 1; }
793793
echo "test" | openssl cms -encrypt -binary -keyid -out ktri-keyid-cms.msg -outform der -recip ../client-cert.pem -nocerts
794794
check_result $? "generate ktri-keyid-cms.msg"
795+
echo "testencrypt" | openssl cms -EncryptedData_encrypt -binary -keyid -aes-128-cbc -secretkey 0123456789ABCDEF0011223344556677 -out encrypteddata.msg -outform der -recip ../client-cert.pem -nocerts
796+
check_result $? "generate encrypteddata.msg"
795797
cd ../ || exit 1
796798
echo "End of section"
797799
echo "---------------------------------------------------------------------"

certs/test/encrypteddata.msg

82 Bytes
Binary file not shown.

certs/test/include.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ EXTRA_DIST += \
6969
certs/test/server-localhost.pem \
7070
certs/test/ossl-trusted-cert.pem \
7171
certs/test/ktri-keyid-cms.msg \
72+
certs/test/encrypteddata.msg \
7273
certs/test/smime-test.p7s \
7374
certs/test/smime-test-canon.p7s \
7475
certs/test/smime-test-multipart.p7s \

doc/dox_comments/header_files/pkcs7.h

Lines changed: 114 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,7 @@ int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf,
312312
\return 0 Returned on successfully extracting the information
313313
from the message
314314
\return BAD_FUNC_ARG Returned if one of the input parameters is invalid
315-
\return ASN_PARSE_E Returned if there is an error parsing from the
316-
given pkiMsg
315+
\return ASN_PARSE_E Returned if there is an error parsing the given pkiMsg
317316
\return PKCS7_OID_E Returned if the given pkiMsg is not a signed data type
318317
\return ASN_VERSION_E Returned if the PKCS7 signer info is not version 1
319318
\return MEMORY_E Returned if there is an error allocating memory
@@ -390,8 +389,7 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7,
390389
\return 0 Returned on successfully extracting the information
391390
from the message
392391
\return BAD_FUNC_ARG Returned if one of the input parameters is invalid
393-
\return ASN_PARSE_E Returned if there is an error parsing from the
394-
given pkiMsg
392+
\return ASN_PARSE_E Returned if there is an error parsing the given pkiMsg
395393
\return PKCS7_OID_E Returned if the given pkiMsg is not a signed data type
396394
\return ASN_VERSION_E Returned if the PKCS7 signer info is not version 1
397395
\return MEMORY_E Returned if there is an error allocating memory
@@ -522,7 +520,7 @@ int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf,
522520
... etc.
523521
524522
ret = wc_PKCS7_EncodeEnvelopedData(&pkcs7, pkcs7Buff, sizeof(pkcs7Buff));
525-
if ( ret != 0 ) {
523+
if ( ret < 0 ) {
526524
// error encoding into output buffer
527525
}
528526
\endcode
@@ -543,8 +541,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7,
543541
\return On successfully extracting the information from the message,
544542
returns the bytes written to output
545543
\return BAD_FUNC_ARG Returned if one of the input parameters is invalid
546-
\return ASN_PARSE_E Returned if there is an error parsing from the
547-
given pkiMsg
544+
\return ASN_PARSE_E Returned if there is an error parsing the given pkiMsg
548545
\return PKCS7_OID_E Returned if the given pkiMsg is not an enveloped
549546
data type
550547
\return ASN_VERSION_E Returned if the PKCS7 signer info is not version 0
@@ -599,15 +596,119 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7,
599596
pkcs7.privateKeySz = keySz;
600597
601598
decodedSz = wc_PKCS7_DecodeEnvelopedData(&pkcs7, received,
602-
sizeof(received),decoded, sizeof(decoded));
603-
if ( decodedSz != 0 ) {
604-
// error decoding message
599+
sizeof(received),decoded, sizeof(decoded));
600+
if ( decodedSz < 0 ) {
601+
// error decoding message
605602
}
606603
\endcode
607604
608605
\sa wc_PKCS7_InitWithCert
609606
\sa wc_PKCS7_EncodeEnvelopedData
610607
*/
611-
int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
612-
word32 pkiMsgSz, byte* output,
613-
word32 outputSz);
608+
int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
609+
word32 pkiMsgSz, byte* output, word32 outputSz);
610+
611+
/*!
612+
\ingroup PKCS7
613+
614+
\brief This function unwraps and decrypts a PKCS7 encrypted data content
615+
type, decoding the message into output. It uses the encryption key of the
616+
PKCS7 object passed in via pkcs7->encryptionKey and
617+
pkcs7->encryptionKeySz to decrypt the message.
618+
619+
\return On successfully extracting the information from the message,
620+
returns the bytes written to output
621+
\return BAD_FUNC_ARG Returned if one of the input parameters is invalid
622+
\return ASN_PARSE_E Returned if there is an error parsing the given pkiMsg
623+
\return PKCS7_OID_E Returned if the given pkiMsg is not an encrypted
624+
data type
625+
\return ASN_VERSION_E Returned if the PKCS7 signer info is not version 0
626+
\return MEMORY_E Returned if there is an error allocating memory
627+
\return BUFFER_E Returned if the encrypted content size is invalid
628+
629+
\param pkcs7 pointer to the PKCS7 structure containing the encryption key with
630+
which to decode the encrypted data package
631+
\param pkiMsg pointer to the buffer containing the encrypted data package
632+
\param pkiMsgSz size of the encrypted data package
633+
\param output pointer to the buffer in which to store the decoded message
634+
\param outputSz size available in the output buffer
635+
636+
_Example_
637+
\code
638+
PKCS7 pkcs7;
639+
byte received[] = { }; // initialize with received encrypted data message
640+
byte decoded[FOURK_BUF];
641+
int decodedSz;
642+
643+
// initialize pkcs7 with certificate
644+
// update key
645+
pkcs7.encryptionKey = key;
646+
pkcs7.encryptionKeySz = keySz;
647+
648+
decodedSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, received,
649+
sizeof(received), decoded, sizeof(decoded));
650+
if ( decodedSz < 0 ) {
651+
// error decoding message
652+
}
653+
\endcode
654+
655+
\sa wc_PKCS7_InitWithCert
656+
*/
657+
int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg,
658+
word32 pkiMsgSz, byte* output, word32 outputSz);
659+
660+
/*!
661+
\ingroup PKCS7
662+
663+
\brief This function unwraps and decrypts a PKCS7 encrypted key package
664+
content type, decoding the message into output. If the wrapped content
665+
type is EncryptedData, the encryption key must be set in the pkcs7 input
666+
structure (via pkcs7->encryptionKey and pkcs7->encryptionKeySz). If the
667+
wrapped content type is EnvelopedData, the private key must be set in the
668+
pkcs7 input structure (via pkcs7->privateKey and pkcs7->privateKeySz).
669+
A wrapped content type of AuthEnvelopedData is not currently supported.
670+
671+
This function will automatically call either wc_PKCS7_DecodeEnvelopedData()
672+
or wc_PKCS7_DecodeEncryptedData() depending on the wrapped content type.
673+
This function could also return any error code from either of those
674+
functions in addition to the error codes listed here.
675+
676+
\return On successfully extracting the information from the message,
677+
returns the bytes written to output
678+
\return BAD_FUNC_ARG Returned if one of the input parameters is invalid
679+
\return ASN_PARSE_E Returned if there is an error parsing the given pkiMsg
680+
or if the wrapped content type is EncryptedData and support for
681+
EncryptedData is not compiled in (e.g. NO_PKCS7_ENCRYPTED_DATA is set)
682+
\return PKCS7_OID_E Returned if the given pkiMsg is not an encrypted
683+
key package data type
684+
685+
\param pkcs7 pointer to the PKCS7 structure containing the private key or
686+
encryption key with which to decode the encrypted key package
687+
\param pkiMsg pointer to the buffer containing the encrypted key package message
688+
\param pkiMsgSz size of the encrypted key package message
689+
\param output pointer to the buffer in which to store the decoded output
690+
\param outputSz size available in the output buffer
691+
692+
_Example_
693+
\code
694+
PKCS7 pkcs7;
695+
byte received[] = { }; // initialize with received encrypted data message
696+
byte decoded[FOURK_BUF];
697+
int decodedSz;
698+
699+
// initialize pkcs7 with certificate
700+
// update key for expected EnvelopedData (example)
701+
pkcs7.privateKey = key;
702+
pkcs7.privateKeySz = keySz;
703+
704+
decodedSz = wc_PKCS7_DecodeEncryptedKeyPackage(&pkcs7, received,
705+
sizeof(received), decoded, sizeof(decoded));
706+
if ( decodedSz < 0 ) {
707+
// error decoding message
708+
}
709+
\endcode
710+
711+
\sa wc_PKCS7_InitWithCert
712+
*/
713+
int wc_PKCS7_DecodeEncryptedKeyPackage(wc_PKCS7 * pkcs7,
714+
byte * pkiMsg, word32 pkiMsgSz, byte * output, word32 outputSz);

tests/api.c

Lines changed: 175 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17494,7 +17494,7 @@ static int test_wc_PKCS7_DecodeEnvelopedData_stream(void)
1749417494
} /* END test_wc_PKCS7_DecodeEnvelopedData_stream() */
1749517495

1749617496
/*
17497-
* Testing wc_PKCS7_EncodeEnvelopedData()
17497+
* Testing wc_PKCS7_EncodeEnvelopedData(), wc_PKCS7_DecodeEnvelopedData()
1749817498
*/
1749917499
static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void)
1750017500
{
@@ -18185,6 +18185,179 @@ static int test_wc_PKCS7_EncodeEncryptedData(void)
1818518185
return EXPECT_RESULT();
1818618186
} /* END test_wc_PKCS7_EncodeEncryptedData() */
1818718187

18188+
18189+
#if defined(HAVE_PKCS7) && defined(USE_CERT_BUFFERS_2048) && !defined(NO_DES3) && !defined(NO_RSA) && !defined(NO_SHA)
18190+
static void build_test_EncryptedKeyPackage(byte * out, word32 * out_size, byte * in_data, word32 in_size, size_t in_content_type, size_t test_vector)
18191+
{
18192+
/* EncryptedKeyPackage ContentType TLV DER */
18193+
static const byte ekp_oid_tlv[] = {0x06U, 10U,
18194+
0X60U, 0X86U, 0X48U, 0X01U, 0X65U, 0X02U, 0X01U, 0X02U, 0X4EU, 0X02U};
18195+
if (in_content_type == ENCRYPTED_DATA) {
18196+
/* EncryptedData subtype */
18197+
size_t ekp_content_der_size = 2U + in_size;
18198+
size_t ekp_content_info_size = sizeof(ekp_oid_tlv) + ekp_content_der_size;
18199+
/* EncryptedKeyPackage ContentType */
18200+
out[0] = 0x30U;
18201+
out[1] = ekp_content_info_size & 0x7FU;
18202+
/* EncryptedKeyPackage ContentInfo */
18203+
XMEMCPY(&out[2], ekp_oid_tlv, sizeof(ekp_oid_tlv));
18204+
/* EncryptedKeyPackage content [0] */
18205+
out[14] = 0xA0U;
18206+
out[15] = in_size & 0x7FU;
18207+
XMEMCPY(&out[16], in_data, in_size);
18208+
*out_size = 16U + in_size;
18209+
switch (test_vector)
18210+
{
18211+
case 1: out[0] = 0x20U; break;
18212+
case 2: out[2] = 0x01U; break;
18213+
case 3: out[7] = 0x42U; break;
18214+
case 4: out[14] = 0xA2U; break;
18215+
}
18216+
}
18217+
else if (in_content_type == ENVELOPED_DATA) {
18218+
/* EnvelopedData subtype */
18219+
size_t ekp_choice_der_size = 4U + in_size;
18220+
size_t ekp_content_der_size = 4U + ekp_choice_der_size;
18221+
size_t ekp_content_info_size = sizeof(ekp_oid_tlv) + ekp_content_der_size;
18222+
/* EncryptedKeyPackage ContentType */
18223+
out[0] = 0x30U;
18224+
out[1] = 0x82U;
18225+
out[2] = ekp_content_info_size >> 8U;
18226+
out[3] = ekp_content_info_size & 0xFFU;
18227+
/* EncryptedKeyPackage ContentInfo */
18228+
XMEMCPY(&out[4], ekp_oid_tlv, sizeof(ekp_oid_tlv));
18229+
/* EncryptedKeyPackage content [0] */
18230+
out[16] = 0xA0U;
18231+
out[17] = 0x82U;
18232+
out[18] = ekp_choice_der_size >> 8U;
18233+
out[19] = ekp_choice_der_size & 0xFFU;
18234+
/* EncryptedKeyPackage CHOICE [0] EnvelopedData */
18235+
out[20] = 0xA0U;
18236+
out[21] = 0x82U;
18237+
out[22] = in_size >> 8U;
18238+
out[23] = in_size & 0xFFU;
18239+
XMEMCPY(&out[24], in_data, in_size);
18240+
*out_size = 24U + in_size;
18241+
switch (test_vector)
18242+
{
18243+
case 1: out[0] = 0x20U; break;
18244+
case 2: out[4] = 0x01U; break;
18245+
case 3: out[9] = 0x42U; break;
18246+
case 4: out[16] = 0xA2U; break;
18247+
}
18248+
}
18249+
}
18250+
#endif /* HAVE_PKCS7 && USE_CERT_BUFFERS_2048 && !NO_DES3 && !NO_RSA && !NO_SHA */
18251+
18252+
/*
18253+
* Test wc_PKCS7_DecodeEncryptedKeyPackage().
18254+
*/
18255+
static int test_wc_PKCS7_DecodeEncryptedKeyPackage(void)
18256+
{
18257+
EXPECT_DECLS;
18258+
#if defined(HAVE_PKCS7) && defined(USE_CERT_BUFFERS_2048) && !defined(NO_DES3) && !defined(NO_RSA) && !defined(NO_SHA)
18259+
static const struct {
18260+
const char * msg_file_name;
18261+
word32 msg_content_type;
18262+
} test_messages[] = {
18263+
{"./certs/test/ktri-keyid-cms.msg", ENVELOPED_DATA},
18264+
{"./certs/test/encrypteddata.msg", ENCRYPTED_DATA},
18265+
};
18266+
static const int test_vectors[] = {
18267+
0,
18268+
WC_NO_ERR_TRACE(ASN_PARSE_E),
18269+
WC_NO_ERR_TRACE(ASN_PARSE_E),
18270+
WC_NO_ERR_TRACE(PKCS7_OID_E),
18271+
WC_NO_ERR_TRACE(ASN_PARSE_E),
18272+
};
18273+
static const byte key[] = {
18274+
0x01U, 0x23U, 0x45U, 0x67U, 0x89U, 0xABU, 0xCDU, 0xEFU,
18275+
0x00U, 0x11U, 0x22U, 0x33U, 0x44U, 0x55U, 0x66U, 0x77U,
18276+
};
18277+
size_t test_msg = 0U;
18278+
size_t test_vector = 0U;
18279+
18280+
for (test_msg = 0U; test_msg < (sizeof(test_messages)/sizeof(test_messages[0])); test_msg++)
18281+
{
18282+
for (test_vector = 0U; test_vector < (sizeof(test_vectors)/sizeof(test_vectors[0])); test_vector++)
18283+
{
18284+
byte * ekp_cms_der = NULL;
18285+
word32 ekp_cms_der_size = 0U;
18286+
byte * inner_cms_der = NULL;
18287+
word32 inner_cms_der_size = (word32)FOURK_BUF;
18288+
XFILE inner_cms_file = XBADFILE;
18289+
PKCS7 * pkcs7 = NULL;
18290+
byte out[15] = {0};
18291+
int result = 0;
18292+
18293+
ExpectNotNull(ekp_cms_der = (byte *)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER));
18294+
/* Check for possible previous test failure. */
18295+
if (ekp_cms_der == NULL) {
18296+
break;
18297+
}
18298+
18299+
ExpectNotNull(inner_cms_der = (byte *)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER));
18300+
ExpectTrue((inner_cms_file = XFOPEN(test_messages[test_msg].msg_file_name, "rb")) != XBADFILE);
18301+
ExpectTrue((inner_cms_der_size = (word32)XFREAD(inner_cms_der, 1, inner_cms_der_size, inner_cms_file)) > 0);
18302+
if (inner_cms_file != XBADFILE) {
18303+
XFCLOSE(inner_cms_file);
18304+
}
18305+
if (test_messages[test_msg].msg_content_type == ENVELOPED_DATA) {
18306+
/* Verify that the build_test_EncryptedKeyPackage can format as expected. */
18307+
ExpectIntGT(inner_cms_der_size, 127);
18308+
}
18309+
if (test_messages[test_msg].msg_content_type == ENCRYPTED_DATA) {
18310+
/* Verify that the build_test_EncryptedKeyPackage can format as expected. */
18311+
ExpectIntLT(inner_cms_der_size, 124);
18312+
}
18313+
build_test_EncryptedKeyPackage(ekp_cms_der, &ekp_cms_der_size, inner_cms_der, inner_cms_der_size, test_messages[test_msg].msg_content_type, test_vector);
18314+
XFREE(inner_cms_der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
18315+
18316+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
18317+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte *)client_cert_der_2048, sizeof_client_cert_der_2048), 0);
18318+
if (pkcs7 != NULL) {
18319+
if (test_messages[test_msg].msg_content_type == ENVELOPED_DATA) {
18320+
/* To test EnvelopedData, set private key. */
18321+
pkcs7->privateKey = (byte *)client_key_der_2048;
18322+
pkcs7->privateKeySz = sizeof_client_key_der_2048;
18323+
}
18324+
if (test_messages[test_msg].msg_content_type == ENCRYPTED_DATA) {
18325+
/* To test EncryptedData, set symmetric encryption key. */
18326+
pkcs7->encryptionKey = (byte *)key;
18327+
pkcs7->encryptionKeySz = sizeof(key);
18328+
}
18329+
}
18330+
ExpectIntEQ(wc_PKCS7_DecodeEncryptedKeyPackage(pkcs7, NULL, ekp_cms_der_size, out, sizeof(out)), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
18331+
result = wc_PKCS7_DecodeEncryptedKeyPackage(pkcs7, ekp_cms_der, ekp_cms_der_size, out, sizeof(out));
18332+
if (result == WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
18333+
result = wc_PKCS7_DecodeEncryptedKeyPackage(pkcs7, ekp_cms_der, ekp_cms_der_size, out, sizeof(out));
18334+
}
18335+
if (test_vectors[test_vector] == 0U) {
18336+
if (test_messages[test_msg].msg_content_type == ENVELOPED_DATA) {
18337+
ExpectIntGT(result, 0);
18338+
ExpectIntEQ(XMEMCMP(out, "test", 4), 0);
18339+
}
18340+
if (test_messages[test_msg].msg_content_type == ENCRYPTED_DATA) {
18341+
#ifndef NO_PKCS7_ENCRYPTED_DATA
18342+
ExpectIntGT(result, 0);
18343+
ExpectIntEQ(XMEMCMP(out, "testencrypt", 11), 0);
18344+
#else
18345+
ExpectIntEQ(result, WC_NO_ERR_TRACE(ASN_PARSE_E));
18346+
#endif
18347+
}
18348+
}
18349+
else {
18350+
ExpectIntEQ(result, test_vectors[test_vector]);
18351+
}
18352+
XFREE(ekp_cms_der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
18353+
wc_PKCS7_Free(pkcs7);
18354+
}
18355+
}
18356+
#endif /* HAVE_PKCS7 && USE_CERT_BUFFERS_2048 && !NO_DES3 && !NO_RSA && !NO_SHA */
18357+
return EXPECT_RESULT();
18358+
} /* END test_wc_PKCS7_DecodeEncryptedKeyPackage() */
18359+
18360+
1818818361
/*
1818918362
* Testing wc_PKCS7_Degenerate()
1819018363
*/
@@ -67609,6 +67782,7 @@ TEST_CASE testCases[] = {
6760967782
TEST_DECL(test_wc_PKCS7_DecodeEnvelopedData_stream),
6761067783
TEST_DECL(test_wc_PKCS7_EncodeDecodeEnvelopedData),
6761167784
TEST_DECL(test_wc_PKCS7_EncodeEncryptedData),
67785+
TEST_DECL(test_wc_PKCS7_DecodeEncryptedKeyPackage),
6761267786
TEST_DECL(test_wc_PKCS7_Degenerate),
6761367787
TEST_DECL(test_wc_PKCS7_BER),
6761467788
TEST_DECL(test_wc_PKCS7_signed_enveloped),

0 commit comments

Comments
 (0)