refactor decrypt content with PKCS12 and fix for AES-256 + HMAC SHA256 case

This commit is contained in:
Jacob Barthelmeh
2020-03-24 22:23:44 -06:00
parent 26f539400a
commit 59ab600d76

View File

@@ -3756,11 +3756,18 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
#endif /* HAVE_PKCS8 */ #endif /* HAVE_PKCS8 */
#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) #if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
/* decrypt PKCS
/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning *
of input */ * NOTE: input buffer is overwritten with decrypted data!
int ToTraditionalEnc(byte* input, word32 sz,const char* password, *
int passwordSz, word32* algId) * input[in/out] data to decrypt and results are written to
* sz size of input buffer
* password password if used. Can be NULL for no password
* passwordSz size of password buffer
*
* returns the total size of decrypted content on success.
*/
int DecryptContent(byte* input, word32 sz, const char* password, int passwordSz)
{ {
word32 inOutIdx = 0, seqEnd, oid, shaOid = 0; word32 inOutIdx = 0, seqEnd, oid, shaOid = 0;
int ret = 0, first, second, length = 0, version, saltSz, id; int ret = 0, first, second, length = 0, version, saltSz, id;
@@ -3772,43 +3779,40 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,
byte salt[MAX_SALT_SIZE]; byte salt[MAX_SALT_SIZE];
byte cbcIv[MAX_IV_SIZE]; byte cbcIv[MAX_IV_SIZE];
#endif #endif
byte tag;
if (passwordSz < 0) { if (passwordSz < 0) {
WOLFSSL_MSG("Bad password size"); WOLFSSL_MSG("Bad password size");
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte);
}
if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) { if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */ first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */
second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ second = input[inOutIdx - 1]; /* version.algo, algo id last byte */
if (CheckAlgo(first, second, &id, &version, NULL) < 0) { if (CheckAlgo(first, second, &id, &version, NULL) < 0) {
ERROR_OUT(ASN_INPUT_E, exit_tte); /* Algo ID error */ ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */
} }
if (version == PKCS5v2) { if (version == PKCS5v2) {
if (GetSequence(input, &inOutIdx, &length, sz) < 0) { if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) { if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
if (oid != PBKDF2_OID) { if (oid != PBKDF2_OID) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
} }
if (GetSequence(input, &inOutIdx, &length, sz) <= 0) { if (GetSequence(input, &inOutIdx, &length, sz) <= 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
/* Find the end of this SEQUENCE so we can check for the OPTIONAL and /* Find the end of this SEQUENCE so we can check for the OPTIONAL and
* DEFAULT items. */ * DEFAULT items. */
@@ -3816,16 +3820,16 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,
ret = GetOctetString(input, &inOutIdx, &saltSz, sz); ret = GetOctetString(input, &inOutIdx, &saltSz, sz);
if (ret < 0) if (ret < 0)
goto exit_tte; goto exit_dc;
if (saltSz > MAX_SALT_SIZE) { if (saltSz > MAX_SALT_SIZE) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (salt == NULL) { if (salt == NULL) {
ERROR_OUT(MEMORY_E, exit_tte); ERROR_OUT(MEMORY_E, exit_dc);
} }
#endif #endif
@@ -3833,28 +3837,27 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,
inOutIdx += saltSz; inOutIdx += saltSz;
if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) { if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
/* OPTIONAL key length */ /* OPTIONAL key length */
if (seqEnd > inOutIdx) { if (seqEnd > inOutIdx) {
word32 localIdx = inOutIdx; word32 localIdx = inOutIdx;
byte tag;
if (GetASNTag(input, &localIdx, &tag, sz) < 0) { if (GetASNTag(input, &localIdx, &tag, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
if (tag == ASN_INTEGER && if (tag == ASN_INTEGER &&
GetShortInt(input, &inOutIdx, &keySz, sz) < 0) { GetShortInt(input, &inOutIdx, &keySz, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
} }
/* DEFAULT HMAC is SHA-1 */ /* DEFAULT HMAC is SHA-1 */
if (seqEnd > inOutIdx) { if (seqEnd > inOutIdx) {
if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) { if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
shaOid = oid; shaOid = oid;
@@ -3863,18 +3866,18 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (cbcIv == NULL) { if (cbcIv == NULL) {
ERROR_OUT(MEMORY_E, exit_tte); ERROR_OUT(MEMORY_E, exit_dc);
} }
#endif #endif
if (version == PKCS5v2) { if (version == PKCS5v2) {
/* get encryption algo */ /* get encryption algo */
if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
if (CheckAlgoV2(oid, &id, NULL) < 0) { if (CheckAlgoV2(oid, &id, NULL) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_tte); /* PKCS v2 algo id error */ ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */
} }
if (shaOid == 0) if (shaOid == 0)
@@ -3882,24 +3885,32 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,
ret = GetOctetString(input, &inOutIdx, &length, sz); ret = GetOctetString(input, &inOutIdx, &length, sz);
if (ret < 0) if (ret < 0)
goto exit_tte; goto exit_dc;
if (length > MAX_IV_SIZE) { if (length > MAX_IV_SIZE) {
ERROR_OUT(ASN_PARSE_E, exit_tte); ERROR_OUT(ASN_PARSE_E, exit_dc);
} }
XMEMCPY(cbcIv, &input[inOutIdx], length); XMEMCPY(cbcIv, &input[inOutIdx], length);
inOutIdx += length; inOutIdx += length;
} }
ret = GetOctetString(input, &inOutIdx, &length, sz); if (GetASNTag(input, &inOutIdx, &tag, sz) < 0) {
if (ret < 0) ERROR_OUT(ASN_PARSE_E, exit_dc);
goto exit_tte; }
if (tag != (ASN_CONTEXT_SPECIFIC | 0) && tag != ASN_OCTET_STRING) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
if (GetLength(input, &inOutIdx, &length, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id, ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id,
input + inOutIdx, length, version, cbcIv, 0, shaOid); input + inOutIdx, length, version, cbcIv, 0, shaOid);
exit_tte: exit_dc:
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -3907,7 +3918,31 @@ exit_tte:
if (ret == 0) { if (ret == 0) {
XMEMMOVE(input, input + inOutIdx, length); XMEMMOVE(input, input + inOutIdx, length);
ret = ToTraditional_ex(input, length, algId); ret = length;
}
return ret;
}
/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning
of input */
int ToTraditionalEnc(byte* input, word32 sz,const char* password,
int passwordSz, word32* algId)
{
int ret, length;
word32 inOutIdx = 0;
if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
ret = ASN_PARSE_E;
}
else {
ret = DecryptContent(input + inOutIdx, sz - inOutIdx, password,
passwordSz);
if (ret > 0) {
XMEMMOVE(input, input + inOutIdx, ret);
ret = ToTraditional_ex(input, ret, algId);
}
} }
return ret; return ret;
@@ -4124,165 +4159,6 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
} }
/* decrypt PKCS
*
* NOTE: input buffer is overwritten with decrypted data!
*
* input[in/out] data to decrypt and results are written to
* sz size of input buffer
* password password if used. Can be NULL for no password
* passwordSz size of password buffer
*
* returns the total size of decrypted content on success.
*/
int DecryptContent(byte* input, word32 sz,const char* password, int passwordSz)
{
word32 inOutIdx = 0, seqEnd, oid;
int ret = 0;
int first, second, length = 0, version, saltSz, id;
int iterations = 0, keySz = 0;
#ifdef WOLFSSL_SMALL_STACK
byte* salt = NULL;
byte* cbcIv = NULL;
#else
byte salt[MAX_SALT_SIZE];
byte cbcIv[MAX_IV_SIZE];
#endif
byte tag;
if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */
second = input[inOutIdx - 1]; /* version.algo, algo id last byte */
if (CheckAlgo(first, second, &id, &version, NULL) < 0) {
ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */
}
if (version == PKCS5v2) {
if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
if (oid != PBKDF2_OID) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
}
if (GetSequence(input, &inOutIdx, &length, sz) <= 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
/* Find the end of this SEQUENCE so we can check for the OPTIONAL and
* DEFAULT items. */
seqEnd = inOutIdx + length;
ret = GetOctetString(input, &inOutIdx, &saltSz, sz);
if (ret < 0)
goto exit_dc;
if (saltSz > MAX_SALT_SIZE) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
#ifdef WOLFSSL_SMALL_STACK
salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (salt == NULL) {
ERROR_OUT(MEMORY_E, exit_dc);
}
#endif
XMEMCPY(salt, &input[inOutIdx], saltSz);
inOutIdx += saltSz;
if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
/* OPTIONAL key length */
if (seqEnd > inOutIdx) {
word32 localIdx = inOutIdx;
if (GetASNTag(input, &localIdx, &tag, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
if (tag == ASN_INTEGER &&
GetShortInt(input, &inOutIdx, &keySz, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
}
/* DEFAULT HMAC is SHA-1 */
if (seqEnd > inOutIdx) {
if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
}
#ifdef WOLFSSL_SMALL_STACK
cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (cbcIv == NULL) {
ERROR_OUT(MEMORY_E, exit_dc);
}
#endif
if (version == PKCS5v2) {
/* get encryption algo */
if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
if (CheckAlgoV2(oid, &id, NULL) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */
}
ret = GetOctetString(input, &inOutIdx, &length, sz);
if (ret < 0)
goto exit_dc;
if (length > MAX_IV_SIZE) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
XMEMCPY(cbcIv, &input[inOutIdx], length);
inOutIdx += length;
}
if (GetASNTag(input, &inOutIdx, &tag, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
if (tag != (ASN_CONTEXT_SPECIFIC | 0)) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
if (GetLength(input, &inOutIdx, &length, sz) < 0) {
ERROR_OUT(ASN_PARSE_E, exit_dc);
}
ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id,
input + inOutIdx, length, version, cbcIv, 0, 0);
exit_dc:
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
if (ret == 0) {
XMEMMOVE(input, input + inOutIdx, length);
ret = length;
}
return ret;
}
#endif /* HAVE_PKCS12 */ #endif /* HAVE_PKCS12 */
#endif /* NO_PWDBASED */ #endif /* NO_PWDBASED */