@@ -10205,6 +10205,214 @@ int ToTraditionalEnc(byte* input, word32 sz, const char* password,
1020510205
1020610206#ifdef HAVE_PKCS12
1020710207
10208+ #ifdef WOLFSSL_ASN_TEMPLATE
10209+ /* ASN.1 template for PKCS #8 encrypted key with PBES2 parameters.
10210+ * PKCS #8: RFC 5958, 3 - EncryptedPrivateKeyInfo
10211+ * PKCS #5: RFC 8018, A.4 - PBES2
10212+ */
10213+ static const ASNItem p8EncPbes2ASN[] = {
10214+ /* SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
10215+ /* ALGO_SEQ */ { 1, ASN_SEQUENCE, 1, 1, 0 },
10216+ /* PBE algorithm */
10217+ /* ALGO_OID */ { 2, ASN_OBJECT_ID, 0, 0, 0 },
10218+ /* ALGO_PARAMS_SEQ */ { 2, ASN_SEQUENCE, 1, 1, 0 },
10219+ /* ALGO_PARAMS_KDF_SEQ */ { 3, ASN_SEQUENCE, 1, 1, 0 },
10220+ /* PBKDF2 */
10221+ /* ALGO_PARAMS_KDF_OID */ { 4, ASN_OBJECT_ID, 0, 0, 0 },
10222+ /* ALGO_PARAMS_PBKDF2_SEQ */ { 4, ASN_SEQUENCE, 1, 1, 0 },
10223+ /* Salt */
10224+ /* ALGO_PARAMS_PBKDF2_SALT */ { 5, ASN_OCTET_STRING, 0, 0, 0 },
10225+ /* Iteration count */
10226+ /* ALGO_PARAMS_PBKDF2_ITER */ { 5, ASN_INTEGER, 0, 0, 0 },
10227+ /* Key length */
10228+ /* ALGO_PARAMS_PBKDF2_KEYLEN */ { 5, ASN_INTEGER, 0, 0, 1 },
10229+ /* PRF - default is HMAC-SHA1 */
10230+ /* ALGO_PARAMS_PBKDF2_PRF */ { 5, ASN_SEQUENCE, 1, 1, 1 },
10231+ /* ALGO_PARAMS_PBKDF2_PRF_OID */ { 6, ASN_OBJECT_ID, 0, 0, 0 },
10232+ /* ALGO_PARAMS_PBKDF2_PRF_NULL */ { 6, ASN_TAG_NULL, 0, 0, 1 },
10233+ /* ALGO_ENCS_SEQ */ { 3, ASN_SEQUENCE, 1, 1, 0 },
10234+ /* Encryption algorithm */
10235+ /* ALGO_ENCS_OID */ { 4, ASN_OBJECT_ID, 0, 0, 0 },
10236+ /* IV for CBC */
10237+ /* ALGO_ENCS_PARAMS */ { 4, ASN_OCTET_STRING, 0, 0, 0 },
10238+ /* ENCDATA */ { 1, (ASN_CONTEXT_SPECIFIC | 0), 0, 0, 0 },
10239+ };
10240+ enum {
10241+ P8ENCPBES2ASN_IDX_SEQ = 0,
10242+ P8ENCPBES2ASN_IDX_ALGO_SEQ,
10243+ P8ENCPBES2ASN_IDX_ALGO_OID,
10244+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_SEQ,
10245+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_KDF_SEQ,
10246+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_KDF_OID,
10247+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_SEQ,
10248+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_SALT,
10249+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_ITER,
10250+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_KEYLEN,
10251+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_PRF,
10252+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_PRF_OID,
10253+ P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_PRF_NULL,
10254+ P8ENCPBES2ASN_IDX_ALGO_ENCS_SEQ,
10255+ P8ENCPBES2ASN_IDX_ALGO_ENCS_OID,
10256+ P8ENCPBES2ASN_IDX_ALGO_ENCS_PARAMS,
10257+ P8ENCPBES2ASN_IDX_ENCDATA
10258+ };
10259+
10260+ #define p8EncPbes2ASN_Length (sizeof(p8EncPbes2ASN) / sizeof(ASNItem))
10261+ #endif /* WOLFSSL_ASN_TEMPLATE */
10262+
10263+ static int EncryptContentPBES2(byte* input, word32 inputSz, byte* out,
10264+ word32* outSz, const char* password, int passwordSz, int encAlgId,
10265+ byte* salt, word32 saltSz, int itt, int hmacOid, WC_RNG* rng,
10266+ void* heap)
10267+ {
10268+ int ret = 0;
10269+ #ifndef WOLFSSL_ASN_TEMPLATE
10270+ (void)input;
10271+ (void)inputSz;
10272+ (void)out;
10273+ (void)outSz;
10274+ (void)password;
10275+ (void)passwordSz;
10276+ (void)encAlgId;
10277+ (void)salt;
10278+ (void)saltSz;
10279+ (void)itt;
10280+ (void)hmacOid;
10281+ (void)rng;
10282+ (void)heap;
10283+ ret = ASN_VERSION_E;
10284+ #else /* WOLFSSL_ASN_TEMPLATE */
10285+ /* PBES2 is only supported when enabling the ASN template */
10286+
10287+ DECL_ASNSETDATA(dataASN, p8EncPbes2ASN_Length);
10288+ const byte* blkOidBuf = NULL;
10289+ int blkOidSz = 0;
10290+ int pbesId = -1;
10291+ int blockSz = 0;
10292+ int asnSz = 0;
10293+ word32 pkcs8Sz = 0;
10294+ byte* cbcIv = NULL;
10295+ byte* saltEnc = NULL;
10296+ int genSalt = (salt == NULL || saltSz == 0);
10297+
10298+ WOLFSSL_ENTER("EncryptContentPBES2");
10299+
10300+ /* Must have a output size to return or check. */
10301+ if (outSz == NULL) {
10302+ ret = BAD_FUNC_ARG;
10303+ }
10304+ if ((ret == 0) && genSalt) {
10305+ salt = NULL;
10306+ saltSz = PKCS5V2_SALT_SZ;
10307+ /* Salt generated into encoding below. */
10308+ }
10309+ /* Check salt size is valid. */
10310+ if ((ret == 0) && (saltSz > MAX_SALT_SIZE)) {
10311+ ret = ASN_PARSE_E;
10312+ }
10313+ if ((ret == 0) && GetAlgoV2(encAlgId, &blkOidBuf, &blkOidSz, &pbesId,
10314+ &blockSz) < 0) {
10315+ ret = ASN_INPUT_E;
10316+ }
10317+ CALLOC_ASNSETDATA(dataASN, p8EncPbes2ASN_Length, ret, heap);
10318+
10319+ if (ret == 0) {
10320+ /* Setup data to go into encoding including PBE algorithm, salt,
10321+ * iteration count, and padded key length. */
10322+ SetASN_OID(&dataASN[P8ENCPBES2ASN_IDX_ALGO_OID], (word32)PBES2,
10323+ oidPBEType);
10324+ SetASN_Buffer(&dataASN[P8ENCPBES2ASN_IDX_ALGO_PARAMS_KDF_OID],
10325+ pbkdf2Oid, sizeof(pbkdf2Oid));
10326+ SetASN_Buffer(&dataASN[P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_SALT], NULL,
10327+ saltSz);
10328+ SetASN_Int16Bit(&dataASN[P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_ITER],
10329+ (word16)itt);
10330+ dataASN[P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_KEYLEN].noOut = 1;
10331+ if (hmacOid > 0) {
10332+ const byte* hmacOidBuf = NULL;
10333+ word32 hmacOidSz = 0;
10334+ hmacOidBuf = OidFromId((word32)hmacOid, oidHmacType, &hmacOidSz);
10335+ if (hmacOidBuf == NULL) {
10336+ ret = ASN_PARSE_E;
10337+ }
10338+ if (ret == 0) {
10339+ SetASN_Buffer(
10340+ &dataASN[P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_PRF_OID],
10341+ hmacOidBuf, hmacOidSz);
10342+ }
10343+ }
10344+ else {
10345+ /* SHA1 will be used as default without PRF parameters */
10346+ dataASN[P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_PRF].noOut = 1;
10347+ dataASN[P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_PRF_OID].noOut = 1;
10348+ dataASN[P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_PRF_NULL].noOut = 1;
10349+ }
10350+ SetASN_Buffer(&dataASN[P8ENCPBES2ASN_IDX_ALGO_ENCS_OID], blkOidBuf,
10351+ blkOidSz);
10352+ SetASN_Buffer(&dataASN[P8ENCPBES2ASN_IDX_ALGO_ENCS_PARAMS], NULL,
10353+ blockSz);
10354+ pkcs8Sz = wc_PkcsPad(NULL, inputSz, (word32)blockSz);
10355+ SetASN_Buffer(&dataASN[P8ENCPBES2ASN_IDX_ENCDATA], NULL, pkcs8Sz);
10356+
10357+ /* Calculate size of encoding. */
10358+ ret = SizeASN_Items(p8EncPbes2ASN + P8ENCPBES2ASN_IDX_ALGO_SEQ,
10359+ dataASN + P8ENCPBES2ASN_IDX_ALGO_SEQ,
10360+ (int)(p8EncPbes2ASN_Length - P8ENCPBES2ASN_IDX_ALGO_SEQ),
10361+ &asnSz);
10362+ }
10363+ /* Return size when no output buffer. */
10364+ if ((ret == 0) && (out == NULL)) {
10365+ *outSz = (word32)asnSz;
10366+ ret = WC_NO_ERR_TRACE(LENGTH_ONLY_E);
10367+ }
10368+ /* Check output buffer is big enough for encoded data. */
10369+ if ((ret == 0) && (asnSz > (int)*outSz)) {
10370+ ret = BAD_FUNC_ARG;
10371+ }
10372+ if (ret == 0) {
10373+ /* Encode PKCS#8 key. */
10374+ SetASN_Items(p8EncPbes2ASN + P8ENCPBES2ASN_IDX_ALGO_SEQ,
10375+ dataASN + P8ENCPBES2ASN_IDX_ALGO_SEQ,
10376+ (int)(p8EncPbes2ASN_Length - P8ENCPBES2ASN_IDX_ALGO_SEQ),
10377+ out);
10378+
10379+ saltEnc = (byte*)
10380+ dataASN[P8ENCPBES2ASN_IDX_ALGO_PARAMS_PBKDF2_SALT].data.buffer.data;
10381+ if (genSalt) {
10382+ /* Generate salt into encoding. */
10383+ ret = wc_RNG_GenerateBlock(rng, saltEnc, saltSz);
10384+ }
10385+ else {
10386+ XMEMCPY(saltEnc, salt, saltSz);
10387+ }
10388+ }
10389+ if (ret == 0) {
10390+ cbcIv = (byte*)
10391+ dataASN[P8ENCPBES2ASN_IDX_ALGO_ENCS_PARAMS].data.buffer.data;
10392+ ret = wc_RNG_GenerateBlock(rng, cbcIv, (word32)blockSz);
10393+ }
10394+ if (ret == 0) {
10395+ /* Store PKCS#8 key in output buffer. */
10396+ byte* pkcs8 = (byte*)
10397+ dataASN[P8ENCPBES2ASN_IDX_ENCDATA].data.buffer.data;
10398+ XMEMCPY(pkcs8, input, inputSz);
10399+ (void)wc_PkcsPad(pkcs8, inputSz, (word32)blockSz);
10400+
10401+ /* Encrypt PKCS#8 key inline. */
10402+ ret = wc_CryptKey(password, passwordSz, saltEnc, (int)saltSz, itt,
10403+ pbesId, pkcs8, (int)pkcs8Sz, PKCS5v2, cbcIv, 1, hmacOid);
10404+ }
10405+ if (ret == 0) {
10406+ /* Returning size on success. */
10407+ ret = asnSz;
10408+ }
10409+
10410+ FREE_ASNSETDATA(dataASN, heap);
10411+ (void)heap;
10412+ #endif /* WOLFSSL_ASN_TEMPLATE */
10413+ return ret;
10414+ }
10415+
1020810416#ifdef WOLFSSL_ASN_TEMPLATE
1020910417/* ASN.1 template for PKCS #8 encrypted key with PBES1 parameters.
1021010418 * PKCS #8: RFC 5958, 3 - EncryptedPrivateKeyInfo
@@ -10233,7 +10441,7 @@ enum {
1023310441};
1023410442
1023510443#define p8EncPbes1ASN_Length (sizeof(p8EncPbes1ASN) / sizeof(ASNItem))
10236- #endif
10444+ #endif /* WOLFSSL_ASN_TEMPLATE */
1023710445
1023810446/* Wrap a private key in PKCS#8 and encrypt.
1023910447 *
@@ -10254,9 +10462,11 @@ enum {
1025410462 * @param [in] passwordSz Length of password in bytes.
1025510463 * @param [in] vPKCS First byte used to determine PBE algorithm.
1025610464 * @param [in] vAlgo Second byte used to determine PBE algorithm.
10465+ * @param [in] encAlgId Encryption Algorithm for PBES2.
1025710466 * @param [in] salt Salt to use with KDF.
1025810467 * @param [in] saltSz Length of salt in bytes.
1025910468 * @param [in] itt Number of iterations to use in KDF.
10469+ * @param [in] hmacOid HMAC Algorithm for PBES2.
1026010470 * @param [in] rng Random number generator to use to generate salt.
1026110471 * @param [in] heap Dynamic memory allocator hint.
1026210472 * @return The size of encrypted data on success
@@ -10269,7 +10479,8 @@ enum {
1026910479 */
1027010480int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
1027110481 const char* password, int passwordSz, int vPKCS, int vAlgo,
10272- byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
10482+ int encAlgId, byte* salt, word32 saltSz, int itt, int hmacOid,
10483+ WC_RNG* rng, void* heap)
1027310484{
1027410485#ifndef WOLFSSL_ASN_TEMPLATE
1027510486 word32 sz;
@@ -10293,8 +10504,12 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
1029310504 word32 algoSz;
1029410505 const byte* algoName;
1029510506
10507+ (void)encAlgId;
10508+ (void)hmacOid;
1029610509 (void)heap;
1029710510
10511+ (void)EncryptContentPBES2;
10512+
1029810513 WOLFSSL_ENTER("EncryptContent");
1029910514
1030010515 if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0)
@@ -10449,7 +10664,9 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
1044910664 (void)rng;
1045010665
1045110666 return (int)(inOutIdx + sz);
10452- #else
10667+ #else /* WOLFSSL_ASN_TEMPLATE */
10668+ /* PBES2 is only supported when enabling the ASN template */
10669+
1045310670 DECL_ASNSETDATA(dataASN, p8EncPbes1ASN_Length);
1045410671 int ret = 0;
1045510672 int sz = 0;
@@ -10476,7 +10693,8 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
1047610693 }
1047710694 /* Check PKCS #5 version - only PBSE1 parameters supported. */
1047810695 if ((ret == 0) && (version == PKCS5v2)) {
10479- ret = BAD_FUNC_ARG;
10696+ return EncryptContentPBES2(input, inputSz, out, outSz, password,
10697+ passwordSz, encAlgId, salt, saltSz, itt, hmacOid, rng, heap);
1048010698 }
1048110699
1048210700 CALLOC_ASNSETDATA(dataASN, p8EncPbes1ASN_Length, ret, heap);
0 commit comments