From 88370285cc95835c8e37e8100e783a0ec8611c03 Mon Sep 17 00:00:00 2001 From: Hayden Roche Date: Wed, 26 May 2021 10:26:39 -0700 Subject: [PATCH] Add an API function wc_DecryptPKCS8Key to handle decrypting a DER, PKCS#8 encrypted key. --- wolfcrypt/src/asn.c | 61 ++++++++++++++++++++++++++-------- wolfssl/wolfcrypt/asn_public.h | 1 + 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index fe20f4bc1..e322a5999 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -3921,6 +3921,48 @@ int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32 outSz, return ret; } +/* PKCS#8 decryption from RFC 5208 + * + * NOTE: input buffer is overwritten with decrypted data! + * + * This function takes an encrypted PKCS#8 DER key and decrypts it to PKCS#8 + * unencrypted DER. Undoes the encryption done by wc_EncryptPKCS8Key. Returns + * the length of the decrypted buffer or a negative value if there was an error. + */ +int wc_DecryptPKCS8Key(byte* input, word32 sz, const char* password, + int passwordSz) +{ + int ret; + int 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); + } + } + + if (ret > 0) { + /* DecryptContent will decrypt the data, but it will leave any padding + * bytes intact. This code calculates the length without the padding + * and we return that to the user. */ + inOutIdx = 0; + if (GetSequence(input, &inOutIdx, &length, ret) < 0) { + ret = ASN_PARSE_E; + } + else { + ret = inOutIdx + length; + } + } + + return ret; +} + /* Takes an unencrypted, traditional DER-encoded key and converts it to a PKCS#8 * encrypted key. */ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, @@ -4146,25 +4188,16 @@ exit_dc: return ret; } - /* Remove Encrypted PKCS8 header, move beginning of traditional to beginning of input */ -int ToTraditionalEnc(byte* input, word32 sz,const char* password, +int ToTraditionalEnc(byte* input, word32 sz, const char* password, int passwordSz, word32* algId) { - int ret, length; - word32 inOutIdx = 0; + int ret; - 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); - } + ret = wc_DecryptPKCS8Key(input, sz, password, passwordSz); + if (ret > 0) { + ret = ToTraditional_ex(input, ret, algId); } return ret; diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 2e539c358..289f3620e 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -585,6 +585,7 @@ WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz); WOLFSSL_API int wc_EncryptPKCS8Key(byte*, word32, byte*, word32, const char*, int, int, int, int, byte*, word32, int, WC_RNG*, void*); +WOLFSSL_API int wc_DecryptPKCS8Key(byte*, word32, const char*, int); #ifndef NO_ASN_TIME /* Time */