Skip to content

Commit 9e5c064

Browse files
authored
Merge pull request #8679 from kojiws/keep_header_on_pkcs12_parse
Add wc_PKCS12_parse_ex() to keep PKCS8 header
2 parents 543ba26 + 2e02274 commit 9e5c064

5 files changed

Lines changed: 221 additions & 11 deletions

File tree

tests/api/test_mldsa.c

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16788,3 +16788,165 @@ int test_mldsa_pkcs8(void)
1678816788
#endif
1678916789
return EXPECT_RESULT();
1679016790
}
16791+
16792+
int test_mldsa_pkcs12(void)
16793+
{
16794+
EXPECT_DECLS;
16795+
#if !defined(NO_ASN) && defined(HAVE_PKCS12) && \
16796+
defined(HAVE_DILITHIUM) && !defined(NO_TLS) && \
16797+
!defined(NO_PWDBASED) && !defined(NO_HMAC) && \
16798+
!defined(NO_CERTS) && !defined(NO_DES3) && \
16799+
(!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \
16800+
defined(WOLFSSL_CERT_GEN)
16801+
16802+
WOLFSSL_CTX* ctx = NULL;
16803+
word32 i;
16804+
byte* inKey = NULL;
16805+
byte* inCert = NULL;
16806+
const word32 inKeyHeaderSz = 4;
16807+
const word32 inKeyMaxSz = inKeyHeaderSz + DILITHIUM_MAX_PRV_KEY_SIZE;
16808+
const word32 certConstSz = 412;
16809+
const word32 inCertMaxSz =
16810+
certConstSz + DILITHIUM_MAX_SIG_SIZE + DILITHIUM_MAX_PUB_KEY_SIZE;
16811+
const word32 pkcs8HeaderSz = 24;
16812+
WC_RNG rng;
16813+
dilithium_key mldsa_key;
16814+
char pkcs12Passwd[] = "mldsa";
16815+
16816+
struct {
16817+
int enc;
16818+
int wcId;
16819+
int oidSum;
16820+
int keySz;
16821+
int sigType;
16822+
int keyType;
16823+
} test_variant[] = {
16824+
{PBE_SHA1_DES3, WC_ML_DSA_44, ML_DSA_LEVEL2k,
16825+
ML_DSA_LEVEL2_PRV_KEY_SIZE, CTC_ML_DSA_LEVEL2, ML_DSA_LEVEL2_TYPE},
16826+
{PBE_SHA1_DES3, WC_ML_DSA_65, ML_DSA_LEVEL3k,
16827+
ML_DSA_LEVEL3_PRV_KEY_SIZE, CTC_ML_DSA_LEVEL3, ML_DSA_LEVEL3_TYPE},
16828+
{PBE_SHA1_DES3, WC_ML_DSA_87, ML_DSA_LEVEL5k,
16829+
ML_DSA_LEVEL5_PRV_KEY_SIZE, CTC_ML_DSA_LEVEL5, ML_DSA_LEVEL5_TYPE},
16830+
{-1, WC_ML_DSA_44, ML_DSA_LEVEL2k,
16831+
ML_DSA_LEVEL2_PRV_KEY_SIZE, CTC_ML_DSA_LEVEL2, ML_DSA_LEVEL2_TYPE},
16832+
{-1, WC_ML_DSA_65, ML_DSA_LEVEL3k,
16833+
ML_DSA_LEVEL3_PRV_KEY_SIZE, CTC_ML_DSA_LEVEL3, ML_DSA_LEVEL3_TYPE},
16834+
{-1, WC_ML_DSA_87, ML_DSA_LEVEL5k,
16835+
ML_DSA_LEVEL5_PRV_KEY_SIZE, CTC_ML_DSA_LEVEL5, ML_DSA_LEVEL5_TYPE},
16836+
};
16837+
16838+
ExpectNotNull(inKey = (byte*) XMALLOC(inKeyMaxSz, NULL,
16839+
DYNAMIC_TYPE_TMP_BUFFER));
16840+
ExpectNotNull(inCert = (byte*) XMALLOC(inCertMaxSz, NULL,
16841+
DYNAMIC_TYPE_TMP_BUFFER));
16842+
16843+
#ifndef NO_WOLFSSL_SERVER
16844+
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
16845+
#else
16846+
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
16847+
#endif /* NO_WOLFSSL_SERVER */
16848+
16849+
ExpectIntEQ(wc_InitRng(&rng), 0);
16850+
ExpectIntEQ(wc_dilithium_init(&mldsa_key), 0);
16851+
16852+
for (i = 0; i < sizeof(test_variant) / sizeof(test_variant[0]); ++i) {
16853+
WC_PKCS12* pkcs12Export = NULL;
16854+
WC_PKCS12* pkcs12Import = NULL;
16855+
byte* pkcs12Der = NULL;
16856+
byte* outKey = NULL;
16857+
byte* outCert = NULL;
16858+
word32 inKeySz = 0;
16859+
word32 inCertSz = 0;
16860+
word32 pkcs12DerSz = 0;
16861+
word32 outKeySz = 0;
16862+
word32 outCertSz = 0;
16863+
Cert cert;
16864+
word32 size;
16865+
16866+
if (EXPECT_FAIL())
16867+
break;
16868+
16869+
/* Create a key for wc_PKCS12_create() */
16870+
inKeySz = 0;
16871+
inKey[0] = 0x04; /* ASN.1 OCTET STRING */
16872+
inKey[1] = 0x82; /* 2 bytes length field */
16873+
inKey[2] = (test_variant[i].keySz >> 8) & 0xff; /* MSB of the length */
16874+
inKey[3] = test_variant[i].keySz & 0xff; /* LSB of the length */
16875+
inKeySz += inKeyHeaderSz;
16876+
ExpectIntEQ(wc_dilithium_set_level(&mldsa_key, test_variant[i].wcId),
16877+
0);
16878+
ExpectIntEQ(wc_dilithium_make_key(&mldsa_key, &rng), 0);
16879+
size = inKeyMaxSz - inKeySz;
16880+
ExpectIntEQ(wc_dilithium_export_private(&mldsa_key, inKey + inKeySz,
16881+
&size), 0);
16882+
inKeySz += size;
16883+
size = inKeyMaxSz - inKeySz;
16884+
ExpectIntEQ(wc_dilithium_export_public(&mldsa_key, inKey + inKeySz,
16885+
&size), 0);
16886+
inKeySz += size;
16887+
16888+
/* Create a certificate for wc_PKCS12_create() */
16889+
ExpectIntEQ(wc_InitCert(&cert), 0);
16890+
XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE);
16891+
XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE);
16892+
XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE);
16893+
XSTRNCPY(cert.subject.org, "wolfSSL", CTC_NAME_SIZE);
16894+
XSTRNCPY(cert.subject.unit, "Engineering", CTC_NAME_SIZE);
16895+
XSTRNCPY(cert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE);
16896+
XSTRNCPY(cert.subject.email, "root@wolfssl.com", CTC_NAME_SIZE);
16897+
XSTRNCPY((char*)cert.beforeDate, "\x18\x0f""20250101000000Z",
16898+
CTC_DATE_SIZE);
16899+
cert.beforeDateSz = 17;
16900+
XSTRNCPY((char*)cert.afterDate, "\x18\x0f""20493112115959Z",
16901+
CTC_DATE_SIZE);
16902+
cert.afterDateSz = 17;
16903+
cert.selfSigned = 1;
16904+
cert.sigType = test_variant[i].sigType;
16905+
cert.isCA = 0;
16906+
ExpectIntGE(inCertSz = wc_MakeCert_ex(&cert, inCert, inCertMaxSz,
16907+
test_variant[i].keyType, &mldsa_key, &rng), 0);
16908+
ExpectIntGE(inCertSz = wc_SignCert_ex(cert.bodySz, cert.sigType, inCert,
16909+
inCertMaxSz, test_variant[i].keyType, &mldsa_key, &rng), 0);
16910+
16911+
ExpectNotNull(pkcs12Export = wc_PKCS12_create(pkcs12Passwd,
16912+
sizeof(pkcs12Passwd) - 1,
16913+
(char*) "friendlyName" /* not used currently */,
16914+
(byte*) inKey, inKeySz, (byte*) inCert, inCertSz,
16915+
NULL, test_variant[i].enc, test_variant[i].enc, 100, 100,
16916+
0 /* not used currently */, NULL));
16917+
pkcs12Der = NULL;
16918+
ExpectIntGE((pkcs12DerSz = wc_i2d_PKCS12(pkcs12Export, &pkcs12Der,
16919+
NULL)), 0);
16920+
16921+
ExpectNotNull(pkcs12Import = wc_PKCS12_new_ex(NULL));
16922+
ExpectIntGE(wc_d2i_PKCS12(pkcs12Der, pkcs12DerSz, pkcs12Import), 0);
16923+
ExpectIntEQ(wc_PKCS12_parse_ex(pkcs12Import, pkcs12Passwd, &outKey,
16924+
&outKeySz,
16925+
&outCert, &outCertSz, NULL, 1), 0);
16926+
ExpectIntGT(outKeySz, 0);
16927+
ExpectIntGT(outCertSz, 0);
16928+
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, outKey, outKeySz,
16929+
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
16930+
ExpectIntEQ(wolfSSL_CTX_use_certificate_buffer(ctx, outCert, outCertSz,
16931+
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
16932+
16933+
ExpectIntEQ(inKeySz, outKeySz - pkcs8HeaderSz);
16934+
ExpectIntEQ(XMEMCMP(inKey, outKey + pkcs8HeaderSz, inKeySz), 0);
16935+
ExpectIntEQ(inCertSz, outCertSz);
16936+
ExpectIntEQ(XMEMCMP(inCert, outCert, inCertSz), 0);
16937+
16938+
XFREE(outKey, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
16939+
XFREE(outCert, NULL, DYNAMIC_TYPE_PKCS);
16940+
wc_PKCS12_free(pkcs12Import);
16941+
XFREE(pkcs12Der, NULL, DYNAMIC_TYPE_PKCS);
16942+
wc_PKCS12_free(pkcs12Export);
16943+
}
16944+
16945+
wc_dilithium_free(&mldsa_key);
16946+
ExpectIntEQ(wc_FreeRng(&rng), 0);
16947+
wolfSSL_CTX_free(ctx);
16948+
XFREE(inCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
16949+
XFREE(inKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
16950+
#endif
16951+
return EXPECT_RESULT();
16952+
}

tests/api/test_mldsa.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ int test_wc_dilithium_make_key_from_seed(void);
3636
int test_wc_dilithium_sig_kats(void);
3737
int test_wc_dilithium_verify_kats(void);
3838
int test_mldsa_pkcs8(void);
39+
int test_mldsa_pkcs12(void);
3940

4041
#define TEST_MLDSA_DECLS \
4142
TEST_DECL_GROUP("mldsa", test_wc_dilithium), \
@@ -49,6 +50,7 @@ int test_mldsa_pkcs8(void);
4950
TEST_DECL_GROUP("mldsa", test_wc_dilithium_make_key_from_seed), \
5051
TEST_DECL_GROUP("mldsa", test_wc_dilithium_sig_kats), \
5152
TEST_DECL_GROUP("mldsa", test_wc_dilithium_verify_kats), \
52-
TEST_DECL_GROUP("mldsa", test_mldsa_pkcs8)
53+
TEST_DECL_GROUP("mldsa", test_mldsa_pkcs8), \
54+
TEST_DECL_GROUP("mldsa", test_mldsa_pkcs12)
5355

5456
#endif /* WOLFCRYPT_TEST_MLDSA_H */

wolfcrypt/src/asn.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9234,9 +9234,12 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
92349234
if (dilithium == NULL)
92359235
return MEMORY_E;
92369236

9237-
if (wc_dilithium_init(dilithium) != 0) {
9238-
tmpIdx = 0;
9239-
if (wc_dilithium_set_level(dilithium, WC_ML_DSA_44) == 0) {
9237+
/* wc_dilithium_init() returns 0 on success and a non-zero value on
9238+
* failure. */
9239+
if (wc_dilithium_init(dilithium) == 0) {
9240+
if ((*algoID == 0) &&
9241+
(wc_dilithium_set_level(dilithium, WC_ML_DSA_44) == 0)) {
9242+
tmpIdx = 0;
92409243
if (wc_Dilithium_PrivateKeyDecode(key, &tmpIdx, dilithium,
92419244
keySz) == 0) {
92429245
*algoID = ML_DSA_LEVEL2k;
@@ -9245,7 +9248,9 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
92459248
WOLFSSL_MSG("Not Dilithium Level 2 DER key");
92469249
}
92479250
}
9248-
else if (wc_dilithium_set_level(dilithium, WC_ML_DSA_65) == 0) {
9251+
if ((*algoID == 0) &&
9252+
(wc_dilithium_set_level(dilithium, WC_ML_DSA_65) == 0)) {
9253+
tmpIdx = 0;
92499254
if (wc_Dilithium_PrivateKeyDecode(key, &tmpIdx, dilithium,
92509255
keySz) == 0) {
92519256
*algoID = ML_DSA_LEVEL3k;
@@ -9254,7 +9259,9 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
92549259
WOLFSSL_MSG("Not Dilithium Level 3 DER key");
92559260
}
92569261
}
9257-
else if (wc_dilithium_set_level(dilithium, WC_ML_DSA_87) == 0) {
9262+
if ((*algoID == 0) &&
9263+
(wc_dilithium_set_level(dilithium, WC_ML_DSA_87) == 0)) {
9264+
tmpIdx = 0;
92589265
if (wc_Dilithium_PrivateKeyDecode(key, &tmpIdx, dilithium,
92599266
keySz) == 0) {
92609267
*algoID = ML_DSA_LEVEL5k;

wolfcrypt/src/pkcs12.c

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,27 @@ static int PKCS12_CoalesceOctetStrings(WC_PKCS12* pkcs12, byte* data,
12971297
int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
12981298
byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
12991299
WC_DerCertList** ca)
1300+
{
1301+
return wc_PKCS12_parse_ex(pkcs12, psw, pkey, pkeySz, cert, certSz, ca, 0);
1302+
}
1303+
1304+
/* return 0 on success and negative on failure.
1305+
* By side effect returns private key, cert, and optionally ca.
1306+
* Parses and decodes the parts of PKCS12
1307+
*
1308+
* NOTE: can parse with USER RSA enabled but may return cert that is not the
1309+
* pair for the key when using RSA key pairs.
1310+
*
1311+
* pkcs12 : non-null WC_PKCS12 struct
1312+
* psw : password to use for PKCS12 decode
1313+
* pkey : Private key returned
1314+
* cert : x509 cert returned
1315+
* ca : optional ca returned
1316+
* keepKeyHeader : 0 removes PKCS8 header, other than 0 keeps PKCS8 header
1317+
*/
1318+
int wc_PKCS12_parse_ex(WC_PKCS12* pkcs12, const char* psw,
1319+
byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
1320+
WC_DerCertList** ca, int keepKeyHeader)
13001321
{
13011322
ContentInfo* ci = NULL;
13021323
WC_DerCertList* certList = NULL;
@@ -1492,7 +1513,13 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
14921513
ERROR_OUT(MEMORY_E, exit_pk12par);
14931514
}
14941515
XMEMCPY(*pkey, data + idx, (size_t)size);
1495-
*pkeySz = (word32)ToTraditional_ex(*pkey, (word32)size, &algId);
1516+
if (keepKeyHeader) {
1517+
*pkeySz = (word32)size;
1518+
}
1519+
else {
1520+
*pkeySz = (word32)ToTraditional_ex(*pkey,
1521+
(word32)size, &algId);
1522+
}
14961523
}
14971524

14981525
#ifdef WOLFSSL_DEBUG_PKCS12
@@ -1531,10 +1558,19 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
15311558
XMEMCPY(k, data + idx, (size_t)size);
15321559

15331560
/* overwrites input, be warned */
1534-
if ((ret = ToTraditionalEnc(k, (word32)size, psw, pswSz,
1535-
&algId)) < 0) {
1536-
XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1537-
goto exit_pk12par;
1561+
if (keepKeyHeader) {
1562+
if ((ret = wc_DecryptPKCS8Key(k, (word32)size, psw,
1563+
pswSz)) < 0) {
1564+
XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1565+
goto exit_pk12par;
1566+
}
1567+
}
1568+
else {
1569+
if ((ret = ToTraditionalEnc(k, (word32)size, psw,
1570+
pswSz, &algId)) < 0) {
1571+
XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1572+
goto exit_pk12par;
1573+
}
15381574
}
15391575

15401576
if (ret < size) {

wolfssl/wolfcrypt/pkcs12.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ WOLFSSL_API int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz);
5555
WOLFSSL_API int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
5656
byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
5757
WC_DerCertList** ca);
58+
WOLFSSL_API int wc_PKCS12_parse_ex(WC_PKCS12* pkcs12, const char* psw,
59+
byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
60+
WC_DerCertList** ca, int keepKeyHeader);
5861
WOLFSSL_LOCAL int wc_PKCS12_verify_ex(WC_PKCS12* pkcs12,
5962
const byte* psw, word32 pswSz);
6063
WOLFSSL_API WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz,

0 commit comments

Comments
 (0)