Merge pull request #8782 from kojiws/support_aes_cbc_pkcs12_export

Support PBE_AES(256|128)_CBC key encryptions on wc_PKCS12_create()
This commit is contained in:
Sean Parkinson
2025-05-22 08:39:11 +10:00
committed by GitHub
6 changed files with 177 additions and 19 deletions

View File

@@ -9536,10 +9536,10 @@ static int GetAlgoV2(int encAlgId, const byte** oid, int *len, int* id,
return ret;
}
int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz,
const char* password, int passwordSz, int vPKCS, int pbeOid,
int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
void* heap)
int encAlgId, byte* salt, word32 saltSz, int itt, int hmacOid,
WC_RNG* rng, void* heap)
{
#ifdef WOLFSSL_SMALL_STACK
byte* saltTmp = NULL;
@@ -9563,10 +9563,12 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
byte cbcIv[MAX_IV_SIZE];
word32 idx = 0;
word32 encIdx = 0;
const byte* hmacOidBuf = NULL;
word32 hmacOidBufSz = 0;
(void)heap;
WOLFSSL_ENTER("wc_EncryptPKCS8Key");
WOLFSSL_ENTER("wc_EncryptPKCS8Key_ex");
if (key == NULL || outSz == NULL || password == NULL) {
ret = BAD_FUNC_ARG;
@@ -9594,6 +9596,11 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
pbeLen = 2 + pbeOidBufSz + 2 + innerLen;
}
else {
if (hmacOid > 0) {
hmacOidBuf = OidFromId((word32)hmacOid, oidHmacType,
&hmacOidBufSz);
innerLen += 2 + 2 + hmacOidBufSz;
}
pbeOidBuf = pbes2;
pbeOidBufSz = sizeof(pbes2);
/* kdf = OBJ pbkdf2 [ SEQ innerLen ] */
@@ -9650,7 +9657,7 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
}
if (ret == 0) {
ret = wc_CryptKey(password, passwordSz, salt, (int)saltSz, itt, pbeId,
out + encIdx, (int)keySz, version, cbcIv, 1, 0);
out + encIdx, (int)keySz, version, cbcIv, 1, hmacOid);
}
if (ret == 0) {
if (version != PKCS5v2) {
@@ -9680,6 +9687,14 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
ret = SetShortInt(out, &idx, (word32)itt, *outSz);
if (ret > 0)
ret = 0;
if (version == PKCS5v2) {
if (hmacOid > 0) {
idx += SetSequence(2+hmacOidBufSz, out + idx);
idx += (word32)SetObjectId((int)hmacOidBufSz, out + idx);
XMEMCPY(out + idx, hmacOidBuf, hmacOidBufSz);
idx += (word32)hmacOidBufSz;
}
}
}
if (ret == 0) {
if (version == PKCS5v2) {
@@ -9704,11 +9719,20 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
WOLFSSL_LEAVE("wc_EncryptPKCS8Key", ret);
WOLFSSL_LEAVE("wc_EncryptPKCS8Key_ex", ret);
return ret;
}
int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz,
const char* password, int passwordSz, int vPKCS, int pbeOid,
int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
void* heap)
{
return wc_EncryptPKCS8Key_ex(key, keySz, out, outSz, password, passwordSz,
vPKCS, pbeOid, encAlgId, salt, saltSz, itt, 0, rng, heap);
}
int wc_DecryptPKCS8Key(byte* input, word32 sz, const char* password,
int passwordSz)
{
@@ -9751,10 +9775,10 @@ int wc_DecryptPKCS8Key(byte* input, word32 sz, const char* password,
* encrypted key. If out is not NULL, it will hold the encrypted key. If it's
* NULL, LENGTH_ONLY_E will be returned and outSz will have the required out
* buffer size. */
int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
int TraditionalEnc_ex(byte* key, word32 keySz, byte* out, word32* outSz,
const char* password, int passwordSz, int vPKCS, int vAlgo,
int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
void* heap)
int encAlgId, byte* salt, word32 saltSz, int itt, int hmacOid,
WC_RNG* rng, void* heap)
{
int ret = 0;
byte *pkcs8Key = NULL;
@@ -9794,8 +9818,9 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
}
#endif
if (ret == 0) {
ret = wc_EncryptPKCS8Key(pkcs8Key, pkcs8KeySz, out, outSz, password,
passwordSz, vPKCS, vAlgo, encAlgId, salt, saltSz, itt, rng, heap);
ret = wc_EncryptPKCS8Key_ex(pkcs8Key, pkcs8KeySz, out, outSz, password,
passwordSz, vPKCS, vAlgo, encAlgId, salt, saltSz, itt, hmacOid, rng,
heap);
}
if (pkcs8Key != NULL) {
@@ -9808,6 +9833,20 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
return ret;
}
/* Takes an unencrypted, traditional DER-encoded key and converts it to a PKCS#8
* encrypted key. If out is not NULL, it will hold the encrypted key. If it's
* NULL, LENGTH_ONLY_E will be returned and outSz will have the required out
* buffer size. */
int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
const char* password, int passwordSz, int vPKCS, int vAlgo,
int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
void* heap)
{
return TraditionalEnc_ex(key, keySz, out, outSz, password, passwordSz,
vPKCS, vAlgo, encAlgId, salt, saltSz, itt, 0, rng, heap);
}
/* Same as TraditionalEnc, but in the public API. */
int wc_CreateEncryptedPKCS8Key(byte* key, word32 keySz, byte* out,
word32* outSz, const char* password, int passwordSz, int vPKCS,

View File

@@ -1787,6 +1787,10 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng,
int ret;
byte* pkcs8Key = NULL;
/* The blkOid and hmacOid are only valid for PKCS#5v2 (PBES2) */
int blkOid = 0;
int hmacOid = 0; /* If 0, use the default HMAC algorithm */
if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL ||
pass == NULL) {
return BAD_FUNC_ARG;
@@ -1822,13 +1826,25 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng,
else {
WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag");
/* Need to handle PKCS#5v1/v2 (=non-PKCS#12v1) encryptions */
if (vAlgo == PBE_SHA1_DES) {
vPKCS = PKCS5;
vAlgo = 10;
}
ret = UnTraditionalEnc(key, keySz, pkcs8Key, &sz, pass, passSz,
vPKCS, vAlgo, NULL, 0, itt, rng, heap);
else if (vAlgo == PBE_AES256_CBC) {
vPKCS = PKCS5;
vAlgo = PBES2;
blkOid = AES256CBCb;
hmacOid = HMAC_SHA256_OID;
}
else if (vAlgo == PBE_AES128_CBC) {
vPKCS = PKCS5;
vAlgo = PBES2;
blkOid = AES128CBCb;
hmacOid = HMAC_SHA256_OID;
}
ret = TraditionalEnc_ex(key, keySz, pkcs8Key, &sz, pass, passSz,
vPKCS, vAlgo, blkOid, NULL, 0, itt, hmacOid, rng, heap);
}
if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
*outSz = sz + MAX_LENGTH_SZ + 1;
@@ -2261,6 +2277,7 @@ static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey,
heap = wc_PKCS12_GetHeap(pkcs12);
*keyCiSz = 0;
switch (nidKey) {
/* supported key encryptions */
case PBE_SHA1_RC4_128:
algo = 1;
break;
@@ -2273,8 +2290,15 @@ static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey,
algo = 3;
break;
/* no encryption */
case -1:
case PBE_AES256_CBC:
algo = PBE_AES256_CBC;
break;
case PBE_AES128_CBC:
algo = PBE_AES128_CBC;
break;
case -1: /* no encryption */
algo = -1;
break;

View File

@@ -636,10 +636,14 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt,
break;
}
#endif
#if !defined(NO_AES) && defined(HAVE_AES_CBC)
#if !defined(NO_AES) && defined(HAVE_AES_CBC) && \
(defined(WOLFSSL_AES_256) || defined(WOLFSSL_AES_128))
#ifdef WOLFSSL_AES_256
case PBE_AES256_CBC:
#endif /* WOLFSSL_AES_256 */
#ifdef WOLFSSL_AES_128
case PBE_AES128_CBC:
#endif /* WOLFSSL_AES_128 */
{
int free_aes;
@@ -686,8 +690,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt,
#endif
break;
}
#endif /* WOLFSSL_AES_256 */
#endif /* !NO_AES && HAVE_AES_CBC */
#endif /* !NO_AES && HAVE_AES_CBC && (WOLFSSL_AES_256 || WOLFSSL_AES_128) */
#ifdef WC_RC2
case PBE_SHA1_40RC2_CBC:
{