Merge pull request #9029 from holtrop/extract-kari-rid

Add wc_PKCS7_GetEnvelopedDataKariRid()
This commit is contained in:
David Garske
2025-07-25 09:04:11 -07:00
committed by GitHub
8 changed files with 222 additions and 1 deletions

View File

@@ -523,6 +523,11 @@ run_renewcerts(){
openssl x509 -in client-ecc-cert.pem -text > tmp.pem
check_result $? "Step 3"
mv tmp.pem client-ecc-cert.pem
# Extract the Subject Key Identifier from the generated certificate
# for unit test use.
openssl x509 -in client-ecc-cert.pem -noout -text | grep -A1 'Subject Key Identifier' | tail -n +2 | sed -e 's/[ :]//g' > test/client-ecc-cert-ski.hex
check_result $? "Step 4"
echo "End of section"
echo "---------------------------------------------------------------------"
############################################################
@@ -792,6 +797,9 @@ run_renewcerts(){
cd ./test || { echo "Failed to switch to dir ./test"; exit 1; }
echo "test" | openssl cms -encrypt -binary -keyid -out ktri-keyid-cms.msg -outform der -recip ../client-cert.pem -nocerts
check_result $? "generate ktri-keyid-cms.msg"
# Generate an EnvelopedData with KARI recipient for testing.
echo "testkari" | openssl cms -encrypt -binary -keyid -out kari-keyid-cms.msg -outform der -recip ../client-ecc-cert.pem -nocerts
check_result $? "generate kari-keyid-cms.msg"
echo "testencrypt" | openssl cms -EncryptedData_encrypt -binary -keyid -aes-128-cbc -secretkey 0123456789ABCDEF0011223344556677 -out encrypteddata.msg -outform der -recip ../client-cert.pem -nocerts
check_result $? "generate encrypteddata.msg"
cd ../ || exit 1

View File

@@ -0,0 +1 @@
EBD44B596B95613F5157B6044D894188445CABF2

View File

@@ -36,7 +36,8 @@ EXTRA_DIST += \
certs/test/cert-over-max-altnames.cfg \
certs/test/cert-over-max-altnames.pem \
certs/test/cert-over-max-nc.cfg \
certs/test/cert-over-max-nc.pem
certs/test/cert-over-max-nc.pem \
certs/test/client-ecc-cert-ski.hex
# The certs/server-cert with the last byte (signature byte) changed
EXTRA_DIST += \
@@ -69,6 +70,7 @@ EXTRA_DIST += \
certs/test/server-localhost.pem \
certs/test/ossl-trusted-cert.pem \
certs/test/ktri-keyid-cms.msg \
certs/test/kari-keyid-cms.msg \
certs/test/encrypteddata.msg \
certs/test/smime-test.p7s \
certs/test/smime-test-canon.p7s \

Binary file not shown.

View File

@@ -643,6 +643,31 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7,
int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
word32 pkiMsgSz, byte* output, word32 outputSz);
/*!
\ingroup PKCS7
\brief This function extracts the KeyAgreeRecipientIdentifier object from
an EnvelopedData package containing a KeyAgreeRecipientInfo RecipientInfo
object. Only the first KeyAgreeRecipientIdentifer found in the first
RecipientInfo is copied. This function does not support multiple
RecipientInfo objects or multiple RecipientEncryptedKey objects within an
KeyAgreeRecipientInfo.
\return Returns 0 on success.
\return BAD_FUNC_ARG Returned if one of the input parameters is invalid.
\return ASN_PARSE_E Returned if there is an error parsing the input message.
\return PKCS7_OID_E Returned if the input message is not an enveloped
data type.
\return BUFFER_E Returned if there is not enough room in the output buffer.
\param[in] in Input buffer containing the EnvelopedData ContentInfo message.
\param[in] inSz Size of the input buffer.
\param[out] out Output buffer.
\param[in,out] outSz Output buffer size on input, Size written on output.
*/
int wc_PKCS7_GetEnvelopedDataKariRid(const byte * in, word32 inSz,
byte * out, word32 * outSz);
/*!
\ingroup PKCS7

View File

@@ -18304,6 +18304,78 @@ static int test_wc_PKCS7_SetAESKeyWrapUnwrapCb(void)
return EXPECT_RESULT();
}
/*
* Testing wc_PKCS7_GetEnvelopedDataKariRid().
*/
static int test_wc_PKCS7_GetEnvelopedDataKariRid(void)
{
EXPECT_DECLS;
#if defined(HAVE_PKCS7)
#if defined(HAVE_ECC) && (!defined(NO_AES) || (!defined(NO_SHA) || \
!defined(NO_SHA256) || defined(WOLFSSL_SHA512)))
/* The kari-keyid-cms.msg generated by openssl has a 68 byte RID structure.
* Reserve a bit more than that in case it might grow. */
byte rid[256];
byte cms[1024];
XFILE cmsFile = XBADFILE;
int ret;
word32 ridSz = sizeof(rid);
XFILE skiHexFile = XBADFILE;
byte skiHex[256];
word32 cmsSz = 0;
word32 skiHexSz = 0;
size_t i = 0;
const word32 ridKeyIdentifierOffset = 4;
ExpectTrue((cmsFile = XFOPEN("./certs/test/kari-keyid-cms.msg", "rb"))
!= XBADFILE);
ExpectTrue((cmsSz = (word32)XFREAD(cms, 1, sizeof(cms), cmsFile)) > 0);
if (cmsFile != XBADFILE)
XFCLOSE(cmsFile);
ExpectTrue((skiHexFile = XFOPEN("./certs/test/client-ecc-cert-ski.hex",
"rb")) != XBADFILE);
ExpectTrue((skiHexSz = (word32)XFREAD(skiHex, 1, sizeof(skiHex),
skiHexFile)) > 0);
if (skiHexFile != XBADFILE)
XFCLOSE(skiHexFile);
if (EXPECT_SUCCESS()) {
ret = wc_PKCS7_GetEnvelopedDataKariRid(cms, cmsSz, rid, &ridSz);
}
ExpectIntEQ(ret, 0);
ExpectIntLT(ridSz, sizeof(rid));
ExpectIntGT(ridSz, ridKeyIdentifierOffset);
/* The Subject Key Identifier hex file should have 2 hex characters for each
* byte of the key identifier in the returned recipient ID (rid), plus a
* terminating new line character. */
ExpectIntGE(skiHexSz, ((ridSz - ridKeyIdentifierOffset) * 2) + 1);
if (EXPECT_SUCCESS()) {
for (i = 0; i < (ridSz - ridKeyIdentifierOffset); i++)
{
size_t j;
byte ridKeyIdByte = rid[ridKeyIdentifierOffset + i];
byte skiByte = 0;
for (j = 0; j <= 1; j++)
{
byte hexChar = skiHex[i * 2 + j];
skiByte = skiByte << 4;
if ('0' <= hexChar && hexChar <= '9')
skiByte |= (hexChar - '0');
else if ('A' <= hexChar && hexChar <= 'F')
skiByte |= (hexChar - 'A' + 10);
else
ExpectTrue(0);
}
ExpectIntEQ(ridKeyIdByte, skiByte);
}
}
#endif
#endif /* HAVE_PKCS7 */
return EXPECT_RESULT();
} /* END test_wc_PKCS7_GetEnvelopedDataKariRid() */
/*
* Testing wc_PKCS7_EncodeEncryptedData()
*/
@@ -68404,6 +68476,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wc_PKCS7_DecodeEnvelopedData_stream),
TEST_DECL(test_wc_PKCS7_EncodeDecodeEnvelopedData),
TEST_DECL(test_wc_PKCS7_SetAESKeyWrapUnwrapCb),
TEST_DECL(test_wc_PKCS7_GetEnvelopedDataKariRid),
TEST_DECL(test_wc_PKCS7_EncodeEncryptedData),
TEST_DECL(test_wc_PKCS7_DecodeEncryptedKeyPackage),
TEST_DECL(test_wc_PKCS7_DecodeSymmetricKeyPackage),

View File

@@ -12957,6 +12957,116 @@ int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
}
int wc_PKCS7_GetEnvelopedDataKariRid(const byte * in, word32 inSz,
byte * out, word32 * outSz)
{
int ret = 0;
word32 idx = 0;
int length = 0;
word32 contentType = 0;
word32 ridIdx = 0;
byte ridTag = 0;
if (in == NULL || inSz == 0 || out == NULL || outSz == NULL) {
ret = BAD_FUNC_ARG;
}
/* Consume ContentInfo SEQUENCE header. */
else if (GetSequence(in, &idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Validate the EnvelopedData OBJECT IDENTIFIER. */
else if (wc_GetContentType(in, &idx, &contentType, inSz) < 0) {
ret = ASN_PARSE_E;
}
else if (contentType != ENVELOPED_DATA) {
WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData");
ret = PKCS7_OID_E;
}
/* Consume EXPLICIT content [0] header. */
else if (GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED, &idx,
&length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Consume EnvelopedData SEQUENCE header. */
else if (GetSequence(in, &idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Consume version. */
else if (GetMyVersion(in, &idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Consume originatorInfo if present. */
else if (GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED, &idx,
&length, inSz) >= 0) {
idx += (word32)length;
}
/* Consume recipientInfos SET OF header. */
if (ret == 0 && GetSet(in, &idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Consume kari [1] header. */
if (ret == 0 && GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
&idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Consume KARI version. */
if (ret == 0 && GetMyVersion(in, &idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Consume KARI originator [0] header. */
if (ret == 0 && GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED,
&idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Skip originator [0] content. */
if (ret == 0)
idx += (word32)length;
/* Consume KARI ukm [1] if present. */
if (ret == 0 && GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
&idx, &length, inSz) >= 0) {
idx += (word32) length;
}
/* Consume KARI keyEncryptionAlgorithm. */
if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Skip keyEncryptionAlgorithm content. */
if (ret == 0)
idx += (word32)length;
/* Consume RecipientEncryptedKeys SEQUENCE OF header. */
if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Consume RecipientEncryptedKey SEQUENCE header. */
if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
if (ret == 0)
ridIdx = idx;
/* Consume KeyAgreeRecipientIdentifier tag. */
if (ret == 0 && GetASNTag(in, &idx, &ridTag, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Consume KeyAgreeRecipientIdentifier length. */
if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) {
ret = ASN_PARSE_E;
}
if (ret == 0) {
word32 ridSz = (idx + (word32)length) - ridIdx;
if (ridSz > *outSz) {
/* Not enough room in output buffer. */
ret = BUFFER_E;
}
else {
/* Copy KeyAgreeRecipientIdentifier to output buffer. */
XMEMCPY(out, &in[ridIdx], ridSz);
*outSz = ridSz;
}
}
return ret;
}
/* build PKCS#7 authEnvelopedData content type, return enveloped size */
int wc_PKCS7_EncodeAuthEnvelopedData(wc_PKCS7* pkcs7, byte* output,
word32 outputSz)

View File

@@ -516,6 +516,8 @@ WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(wc_PKCS7* pkcs7,
WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* pkiMsg,
word32 pkiMsgSz, byte* output,
word32 outputSz);
WOLFSSL_API int wc_PKCS7_GetEnvelopedDataKariRid(const byte * in, word32 inSz,
byte * out, word32 * outSz);
/* CMS/PKCS#7 AuthEnvelopedData */
WOLFSSL_API int wc_PKCS7_EncodeAuthEnvelopedData(wc_PKCS7* pkcs7,