Skip to content

Commit 85a4e34

Browse files
authored
Merge pull request wolfSSL#8782 from kojiws/support_aes_cbc_pkcs12_export
Support PBE_AES(256|128)_CBC key encryptions on wc_PKCS12_create()
2 parents 2398a94 + 3666851 commit 85a4e34

6 files changed

Lines changed: 177 additions & 19 deletions

File tree

tests/api.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18873,6 +18873,89 @@ static int test_wc_i2d_PKCS12(void)
1887318873
return EXPECT_RESULT();
1887418874
}
1887518875

18876+
static int test_wc_PKCS12_create_once(int keyEncType, int certEncType)
18877+
{
18878+
EXPECT_DECLS;
18879+
#if !defined(NO_ASN) && defined(HAVE_PKCS12) && !defined(NO_PWDBASED) \
18880+
&& !defined(NO_HMAC) && !defined(NO_CERTS) && defined(USE_CERT_BUFFERS_2048)
18881+
18882+
byte* inKey = (byte*) server_key_der_2048;
18883+
const word32 inKeySz= sizeof_server_key_der_2048;
18884+
byte* inCert = (byte*) server_cert_der_2048;
18885+
const word32 inCertSz = sizeof_server_cert_der_2048;
18886+
WC_DerCertList inCa = {
18887+
(byte*)ca_cert_der_2048, sizeof_ca_cert_der_2048, NULL
18888+
};
18889+
char pkcs12Passwd[] = "test_wc_PKCS12_create";
18890+
18891+
WC_PKCS12* pkcs12Export = NULL;
18892+
WC_PKCS12* pkcs12Import = NULL;
18893+
byte* pkcs12Der = NULL;
18894+
byte* outKey = NULL;
18895+
byte* outCert = NULL;
18896+
WC_DerCertList* outCaList = NULL;
18897+
word32 pkcs12DerSz = 0;
18898+
word32 outKeySz = 0;
18899+
word32 outCertSz = 0;
18900+
18901+
ExpectNotNull(pkcs12Export = wc_PKCS12_create(pkcs12Passwd,
18902+
sizeof(pkcs12Passwd) - 1,
18903+
(char*) "friendlyName" /* not used currently */,
18904+
inKey, inKeySz, inCert, inCertSz, &inCa, keyEncType, certEncType,
18905+
2048, 2048, 0 /* not used currently */, NULL));
18906+
pkcs12Der = NULL;
18907+
ExpectIntGE((pkcs12DerSz = wc_i2d_PKCS12(pkcs12Export, &pkcs12Der, NULL)),
18908+
0);
18909+
18910+
ExpectNotNull(pkcs12Import = wc_PKCS12_new_ex(NULL));
18911+
ExpectIntGE(wc_d2i_PKCS12(pkcs12Der, pkcs12DerSz, pkcs12Import), 0);
18912+
ExpectIntEQ(wc_PKCS12_parse(pkcs12Import, pkcs12Passwd, &outKey, &outKeySz,
18913+
&outCert, &outCertSz, &outCaList), 0);
18914+
18915+
ExpectIntEQ(outKeySz, inKeySz);
18916+
ExpectIntEQ(outCertSz, outCertSz);
18917+
ExpectNotNull(outCaList);
18918+
ExpectNotNull(outCaList->buffer);
18919+
ExpectIntEQ(outCaList->bufferSz, inCa.bufferSz);
18920+
ExpectNull(outCaList->next);
18921+
18922+
ExpectIntEQ(XMEMCMP(inKey, outKey, outKeySz), 0);
18923+
ExpectIntEQ(XMEMCMP(inCert, outCert, outCertSz), 0);
18924+
ExpectIntEQ(XMEMCMP(inCa.buffer, outCaList->buffer, outCaList->bufferSz),
18925+
0);
18926+
18927+
XFREE(outKey, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
18928+
XFREE(outCert, NULL, DYNAMIC_TYPE_PKCS);
18929+
wc_FreeCertList(outCaList, NULL);
18930+
wc_PKCS12_free(pkcs12Import);
18931+
XFREE(pkcs12Der, NULL, DYNAMIC_TYPE_PKCS);
18932+
wc_PKCS12_free(pkcs12Export);
18933+
#endif
18934+
(void) keyEncType;
18935+
(void) certEncType;
18936+
18937+
return EXPECT_RESULT();
18938+
}
18939+
18940+
static int test_wc_PKCS12_create(void)
18941+
{
18942+
EXPECT_DECLS;
18943+
#if !defined(NO_DES3)
18944+
ExpectIntEQ(test_wc_PKCS12_create_once(PBE_SHA1_DES3, PBE_SHA1_DES3),
18945+
TEST_SUCCESS);
18946+
#endif
18947+
#if defined(HAVE_AES_CBC) && !defined(NO_AES_256) && !defined(NO_DES3)
18948+
ExpectIntEQ(test_wc_PKCS12_create_once(PBE_AES256_CBC, PBE_SHA1_DES3),
18949+
TEST_SUCCESS);
18950+
#endif
18951+
#if defined(HAVE_AES_CBC) && !defined(NO_AES_128) && !defined(NO_DES3)
18952+
ExpectIntEQ(test_wc_PKCS12_create_once(PBE_AES128_CBC, PBE_SHA1_DES3),
18953+
TEST_SUCCESS);
18954+
#endif
18955+
(void) test_wc_PKCS12_create_once;
18956+
18957+
return EXPECT_RESULT();
18958+
}
1887618959

1887718960
/*----------------------------------------------------------------------------*
1887818961
| ASN.1 Tests
@@ -67045,6 +67128,7 @@ TEST_CASE testCases[] = {
6704567128

6704667129
/* wolfCrypt PKCS#12 */
6704767130
TEST_DECL(test_wc_i2d_PKCS12),
67131+
TEST_DECL(test_wc_PKCS12_create),
6704867132

6704967133
/*
6705067134
* test_wolfCrypt_Cleanup needs to come after the above wolfCrypt tests to

wolfcrypt/src/asn.c

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9536,10 +9536,10 @@ static int GetAlgoV2(int encAlgId, const byte** oid, int *len, int* id,
95369536
return ret;
95379537
}
95389538

9539-
int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
9539+
int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz,
95409540
const char* password, int passwordSz, int vPKCS, int pbeOid,
9541-
int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
9542-
void* heap)
9541+
int encAlgId, byte* salt, word32 saltSz, int itt, int hmacOid,
9542+
WC_RNG* rng, void* heap)
95439543
{
95449544
#ifdef WOLFSSL_SMALL_STACK
95459545
byte* saltTmp = NULL;
@@ -9563,10 +9563,12 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
95639563
byte cbcIv[MAX_IV_SIZE];
95649564
word32 idx = 0;
95659565
word32 encIdx = 0;
9566+
const byte* hmacOidBuf = NULL;
9567+
word32 hmacOidBufSz = 0;
95669568

95679569
(void)heap;
95689570

9569-
WOLFSSL_ENTER("wc_EncryptPKCS8Key");
9571+
WOLFSSL_ENTER("wc_EncryptPKCS8Key_ex");
95709572

95719573
if (key == NULL || outSz == NULL || password == NULL) {
95729574
ret = BAD_FUNC_ARG;
@@ -9594,6 +9596,11 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
95949596
pbeLen = 2 + pbeOidBufSz + 2 + innerLen;
95959597
}
95969598
else {
9599+
if (hmacOid > 0) {
9600+
hmacOidBuf = OidFromId((word32)hmacOid, oidHmacType,
9601+
&hmacOidBufSz);
9602+
innerLen += 2 + 2 + hmacOidBufSz;
9603+
}
95979604
pbeOidBuf = pbes2;
95989605
pbeOidBufSz = sizeof(pbes2);
95999606
/* kdf = OBJ pbkdf2 [ SEQ innerLen ] */
@@ -9650,7 +9657,7 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
96509657
}
96519658
if (ret == 0) {
96529659
ret = wc_CryptKey(password, passwordSz, salt, (int)saltSz, itt, pbeId,
9653-
out + encIdx, (int)keySz, version, cbcIv, 1, 0);
9660+
out + encIdx, (int)keySz, version, cbcIv, 1, hmacOid);
96549661
}
96559662
if (ret == 0) {
96569663
if (version != PKCS5v2) {
@@ -9680,6 +9687,14 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
96809687
ret = SetShortInt(out, &idx, (word32)itt, *outSz);
96819688
if (ret > 0)
96829689
ret = 0;
9690+
if (version == PKCS5v2) {
9691+
if (hmacOid > 0) {
9692+
idx += SetSequence(2+hmacOidBufSz, out + idx);
9693+
idx += (word32)SetObjectId((int)hmacOidBufSz, out + idx);
9694+
XMEMCPY(out + idx, hmacOidBuf, hmacOidBufSz);
9695+
idx += (word32)hmacOidBufSz;
9696+
}
9697+
}
96839698
}
96849699
if (ret == 0) {
96859700
if (version == PKCS5v2) {
@@ -9704,11 +9719,20 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
97049719
XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
97059720
#endif
97069721

9707-
WOLFSSL_LEAVE("wc_EncryptPKCS8Key", ret);
9722+
WOLFSSL_LEAVE("wc_EncryptPKCS8Key_ex", ret);
97089723

97099724
return ret;
97109725
}
97119726

9727+
int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
9728+
const char* password, int passwordSz, int vPKCS, int pbeOid,
9729+
int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
9730+
void* heap)
9731+
{
9732+
return wc_EncryptPKCS8Key_ex(key, keySz, out, outSz, password, passwordSz,
9733+
vPKCS, pbeOid, encAlgId, salt, saltSz, itt, 0, rng, heap);
9734+
}
9735+
97129736
int wc_DecryptPKCS8Key(byte* input, word32 sz, const char* password,
97139737
int passwordSz)
97149738
{
@@ -9751,10 +9775,10 @@ int wc_DecryptPKCS8Key(byte* input, word32 sz, const char* password,
97519775
* encrypted key. If out is not NULL, it will hold the encrypted key. If it's
97529776
* NULL, LENGTH_ONLY_E will be returned and outSz will have the required out
97539777
* buffer size. */
9754-
int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
9778+
int TraditionalEnc_ex(byte* key, word32 keySz, byte* out, word32* outSz,
97559779
const char* password, int passwordSz, int vPKCS, int vAlgo,
9756-
int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
9757-
void* heap)
9780+
int encAlgId, byte* salt, word32 saltSz, int itt, int hmacOid,
9781+
WC_RNG* rng, void* heap)
97589782
{
97599783
int ret = 0;
97609784
byte *pkcs8Key = NULL;
@@ -9794,8 +9818,9 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
97949818
}
97959819
#endif
97969820
if (ret == 0) {
9797-
ret = wc_EncryptPKCS8Key(pkcs8Key, pkcs8KeySz, out, outSz, password,
9798-
passwordSz, vPKCS, vAlgo, encAlgId, salt, saltSz, itt, rng, heap);
9821+
ret = wc_EncryptPKCS8Key_ex(pkcs8Key, pkcs8KeySz, out, outSz, password,
9822+
passwordSz, vPKCS, vAlgo, encAlgId, salt, saltSz, itt, hmacOid, rng,
9823+
heap);
97999824
}
98009825

98019826
if (pkcs8Key != NULL) {
@@ -9808,6 +9833,20 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
98089833
return ret;
98099834
}
98109835

9836+
/* Takes an unencrypted, traditional DER-encoded key and converts it to a PKCS#8
9837+
* encrypted key. If out is not NULL, it will hold the encrypted key. If it's
9838+
* NULL, LENGTH_ONLY_E will be returned and outSz will have the required out
9839+
* buffer size. */
9840+
int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
9841+
const char* password, int passwordSz, int vPKCS, int vAlgo,
9842+
int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
9843+
void* heap)
9844+
{
9845+
return TraditionalEnc_ex(key, keySz, out, outSz, password, passwordSz,
9846+
vPKCS, vAlgo, encAlgId, salt, saltSz, itt, 0, rng, heap);
9847+
9848+
}
9849+
98119850
/* Same as TraditionalEnc, but in the public API. */
98129851
int wc_CreateEncryptedPKCS8Key(byte* key, word32 keySz, byte* out,
98139852
word32* outSz, const char* password, int passwordSz, int vPKCS,

wolfcrypt/src/pkcs12.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,6 +1787,10 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng,
17871787
int ret;
17881788
byte* pkcs8Key = NULL;
17891789

1790+
/* The blkOid and hmacOid are only valid for PKCS#5v2 (PBES2) */
1791+
int blkOid = 0;
1792+
int hmacOid = 0; /* If 0, use the default HMAC algorithm */
1793+
17901794
if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL ||
17911795
pass == NULL) {
17921796
return BAD_FUNC_ARG;
@@ -1822,13 +1826,25 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng,
18221826
else {
18231827
WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag");
18241828

1829+
/* Need to handle PKCS#5v1/v2 (=non-PKCS#12v1) encryptions */
18251830
if (vAlgo == PBE_SHA1_DES) {
18261831
vPKCS = PKCS5;
18271832
vAlgo = 10;
18281833
}
1829-
1830-
ret = UnTraditionalEnc(key, keySz, pkcs8Key, &sz, pass, passSz,
1831-
vPKCS, vAlgo, NULL, 0, itt, rng, heap);
1834+
else if (vAlgo == PBE_AES256_CBC) {
1835+
vPKCS = PKCS5;
1836+
vAlgo = PBES2;
1837+
blkOid = AES256CBCb;
1838+
hmacOid = HMAC_SHA256_OID;
1839+
}
1840+
else if (vAlgo == PBE_AES128_CBC) {
1841+
vPKCS = PKCS5;
1842+
vAlgo = PBES2;
1843+
blkOid = AES128CBCb;
1844+
hmacOid = HMAC_SHA256_OID;
1845+
}
1846+
ret = TraditionalEnc_ex(key, keySz, pkcs8Key, &sz, pass, passSz,
1847+
vPKCS, vAlgo, blkOid, NULL, 0, itt, hmacOid, rng, heap);
18321848
}
18331849
if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
18341850
*outSz = sz + MAX_LENGTH_SZ + 1;
@@ -2261,6 +2277,7 @@ static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey,
22612277
heap = wc_PKCS12_GetHeap(pkcs12);
22622278
*keyCiSz = 0;
22632279
switch (nidKey) {
2280+
/* supported key encryptions */
22642281
case PBE_SHA1_RC4_128:
22652282
algo = 1;
22662283
break;
@@ -2273,8 +2290,15 @@ static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey,
22732290
algo = 3;
22742291
break;
22752292

2276-
/* no encryption */
2277-
case -1:
2293+
case PBE_AES256_CBC:
2294+
algo = PBE_AES256_CBC;
2295+
break;
2296+
2297+
case PBE_AES128_CBC:
2298+
algo = PBE_AES128_CBC;
2299+
break;
2300+
2301+
case -1: /* no encryption */
22782302
algo = -1;
22792303
break;
22802304

wolfcrypt/src/wc_encrypt.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -636,10 +636,14 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt,
636636
break;
637637
}
638638
#endif
639-
#if !defined(NO_AES) && defined(HAVE_AES_CBC)
639+
#if !defined(NO_AES) && defined(HAVE_AES_CBC) && \
640+
(defined(WOLFSSL_AES_256) || defined(WOLFSSL_AES_128))
640641
#ifdef WOLFSSL_AES_256
641642
case PBE_AES256_CBC:
643+
#endif /* WOLFSSL_AES_256 */
644+
#ifdef WOLFSSL_AES_128
642645
case PBE_AES128_CBC:
646+
#endif /* WOLFSSL_AES_128 */
643647
{
644648
int free_aes;
645649

@@ -686,8 +690,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt,
686690
#endif
687691
break;
688692
}
689-
#endif /* WOLFSSL_AES_256 */
690-
#endif /* !NO_AES && HAVE_AES_CBC */
693+
#endif /* !NO_AES && HAVE_AES_CBC && (WOLFSSL_AES_256 || WOLFSSL_AES_128) */
691694
#ifdef WC_RC2
692695
case PBE_SHA1_40RC2_CBC:
693696
{

wolfssl/wolfcrypt/asn.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,6 +2224,10 @@ WOLFSSL_LOCAL int ToTraditionalEnc(byte* input, word32 sz, const char* password,
22242224
WOLFSSL_ASN_API int UnTraditionalEnc(byte* key, word32 keySz, byte* out,
22252225
word32* outSz, const char* password, int passwordSz, int vPKCS,
22262226
int vAlgo, byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap);
2227+
WOLFSSL_ASN_API int TraditionalEnc_ex(byte* key, word32 keySz, byte* out,
2228+
word32* outSz, const char* password, int passwordSz, int vPKCS,
2229+
int vAlgo, int encAlgId, byte* salt, word32 saltSz, int itt,
2230+
int hmacOid, WC_RNG* rng, void* heap);
22272231
WOLFSSL_ASN_API int TraditionalEnc(byte* key, word32 keySz, byte* out,
22282232
word32* outSz, const char* password, int passwordSz, int vPKCS,
22292233
int vAlgo, int encAlgId, byte* salt, word32 saltSz, int itt,

wolfssl/wolfcrypt/asn_public.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,10 @@ WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input,
798798
WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz,
799799
byte* key, word32 keySz, int algoID, const byte* curveOID,
800800
word32 oidSz);
801+
WOLFSSL_API int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out,
802+
word32* outSz, const char* password, int passwordSz, int vPKCS,
803+
int pbeOid, int encAlgId, byte* salt, word32 saltSz, int itt,
804+
int hmacOid, WC_RNG* rng, void* heap);
801805
WOLFSSL_API int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
802806
const char* password, int passwordSz, int vPKCS, int pbeOid,
803807
int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,

0 commit comments

Comments
 (0)