From 45eddc68e2f67d71b5f16a7aac90ccbb205358b7 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 3 Aug 2021 14:45:45 -0700 Subject: [PATCH] Fix to always support parsing of the PKCS8 header. Improved macro logic for PKCS8 and PKCS12. Added `--disable-pkcs8` option. Fix to enable PWDBASED and PKCS8 if PKCS12 is enabled. --- configure.ac | 34 +++++++++++---- src/ssl.c | 5 +-- wolfcrypt/src/asn.c | 81 +++++++++++++++--------------------- wolfcrypt/src/pkcs12.c | 1 + wolfssl/wolfcrypt/settings.h | 7 ++-- 5 files changed, 64 insertions(+), 64 deletions(-) diff --git a/configure.ac b/configure.ac index 710998c5e..76d669648 100644 --- a/configure.ac +++ b/configure.ac @@ -4836,6 +4836,18 @@ then fi +# PKCS#12 +AC_ARG_ENABLE([pkcs12], + [AS_HELP_STRING([--enable-pkcs12],[Enable pkcs12 (default: enabled)])], + [ ENABLED_PKCS12=$enableval ], + [ ENABLED_PKCS12=yes ] + ) + +if test "x$ENABLED_PKCS12" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_PKCS12" +fi + # PWDBASED has to come after certservice since we want it on w/o explicit on # PWDBASED AC_ARG_ENABLE([pwdbased], @@ -4846,9 +4858,11 @@ AC_ARG_ENABLE([pwdbased], if test "$ENABLED_PWDBASED" = "no" then - if test "$ENABLED_OPENSSLEXTRA" = "yes" || test "$ENABLED_OPENSSLALL" = "yes" || test "$ENABLED_WEBSERVER" = "yes" || test "$ENABLED_ENCKEYS" = "yes" + if test "$ENABLED_OPENSSLEXTRA" = "yes" || test "$ENABLED_OPENSSLALL" = "yes" || \ + test "$ENABLED_WEBSERVER" = "yes" || test "$ENABLED_ENCKEYS" = "yes" || \ + test "$ENABLED_PKCS12" = "yes" then - # opensslextra, opensslall, webserver, and enckeys needs pwdbased + # opensslextra, opensslall, webserver, enckeys and pkcs12 need pwdbased ENABLED_PWDBASED=yes else AM_CFLAGS="$AM_CFLAGS -DNO_PWDBASED" @@ -5068,16 +5082,16 @@ then fi -# PKCS#12 -AC_ARG_ENABLE([pkcs12], - [AS_HELP_STRING([--enable-pkcs12],[Enable pkcs12 (default: enabled)])], - [ ENABLED_PKCS12=$enableval ], - [ ENABLED_PKCS12=yes ] +# PKCS#8 +AC_ARG_ENABLE([pkcs8], + [AS_HELP_STRING([--enable-pkcs8],[Enable PKCS #8 key packages (default: enabled)])], + [ ENABLED_PKCS8=$enableval ], + [ ENABLED_PKCS8=yes ] ) -if test "x$ENABLED_PKCS12" = "xno" +if test "x$ENABLED_PKCS8" = "xno" then - AM_CFLAGS="$AM_CFLAGS -DNO_PKCS12" + AM_CFLAGS="$AM_CFLAGS -DNO_PKCS8" fi @@ -6631,6 +6645,7 @@ AM_CONDITIONAL([BUILD_WOLFCRYPT_TESTS],[test "x$ENABLED_CRYPT_TESTS" = "xyes"]) AM_CONDITIONAL([BUILD_LIBZ],[test "x$ENABLED_LIBZ" = "xyes"]) AM_CONDITIONAL([BUILD_PKCS11],[test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_PKCS12],[test "x$ENABLED_PKCS12" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_PKCS8],[test "x$ENABLED_PKCS8" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_CAVIUM],[test "x$ENABLED_CAVIUM" = "xyes"]) AM_CONDITIONAL([BUILD_CAVIUM_V],[test "x$ENABLED_CAVIUM_V" = "xyes"]) AM_CONDITIONAL([BUILD_OCTEON_SYNC],[test "x$ENABLED_OCTEON_SYNC" = "xyes"]) @@ -7012,6 +7027,7 @@ else fi echo " * SP math implementation: $ENABLED_SP_MATH_DESC" echo " * Async Crypto: $ENABLED_ASYNCCRYPT" +echo " * PKCS#8: $ENABLED_PKCS8" echo " * PKCS#11: $ENABLED_PKCS11" echo " * PKCS#12: $ENABLED_PKCS12" echo " * Cavium Nitrox: $ENABLED_CAVIUM" diff --git a/src/ssl.c b/src/ssl.c index e0875ef87..ee7c8cead 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -37830,7 +37830,6 @@ int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf, } rsa->pkcs8HeaderSz = 0; -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) /* Check if input buffer has PKCS8 header. In the case that it does not * have a PKCS8 header then do not error out. */ if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx, (word32)derSz, @@ -37844,7 +37843,6 @@ int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf, return WOLFSSL_FATAL_ERROR; } } -#endif if (opt == WOLFSSL_RSA_LOAD_PRIVATE) { ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); @@ -38390,7 +38388,7 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, } key->pkcs8HeaderSz = 0; -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + /* Check if input buffer has PKCS8 header. In the case that it does not * have a PKCS8 header then do not error out. */ if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx, (word32)derSz, @@ -38404,7 +38402,6 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, return WOLFSSL_FATAL_ERROR; } } -#endif if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index bcdf3737c..762767789 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2866,20 +2866,16 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { int version, length; -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) word32 algId = 0; -#endif if (inOutIdx == NULL || input == NULL || key == NULL) { return BAD_FUNC_ARG; } -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) /* if has pkcs8 header skip it */ if (ToTraditionalInline_ex(input, inOutIdx, inSz, &algId) < 0) { /* ignore error, did not have pkcs8 header */ } -#endif if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -2924,10 +2920,9 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, #endif /* HAVE_USER_RSA */ #endif /* NO_RSA */ -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) - /* Remove PKCS8 header, place inOutIdx at beginning of traditional, - * return traditional length on success, negative on error */ + * return traditional length on success, negative on error. + * Keeping this function for all builds */ int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz, word32* algId) { @@ -2979,6 +2974,8 @@ int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz) return ToTraditionalInline_ex(input, inOutIdx, sz, &oid); } +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + /* Remove PKCS8 header, move beginning of traditional to beginning of input */ int ToTraditional_ex(byte* input, word32 sz, word32* algId) { @@ -3388,6 +3385,7 @@ int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der) #ifndef NO_PWDBASED #if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + /* Check To see if PKCS version algo is supported, set id if it is return 0 < 0 on error */ static int CheckAlgo(int first, int second, int* id, int* version, int* blockSz) @@ -3459,6 +3457,10 @@ static int CheckAlgo(int first, int second, int* id, int* version, int* blockSz) } } +#endif /* HAVE_PKCS8 || HAVE_PKCS12 */ + +#ifdef HAVE_PKCS8 + /* Check To see if PKCS v2 algo is supported, set id if it is return 0 < 0 on error */ static int CheckAlgoV2(int oid, int* id, int* blockSz) @@ -3495,9 +3497,9 @@ static int CheckAlgoV2(int oid, int* id, int* blockSz) } } -#endif /* HAVE_PKCS8 || HAVE_PKCS12 */ +#endif /* HAVE_PKCS8 */ -#ifdef HAVE_PKCS8 +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, int* algoID, void* heap) @@ -3613,29 +3615,6 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, return 1; } -#endif /* HAVE_PKCS8 */ - -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) - -#define PKCS8_MIN_BLOCK_SIZE 8 -static int Pkcs8Pad(byte* buf, int sz, int blockSz) -{ - int i, padSz; - - /* calculate pad size */ - padSz = blockSz - (sz & (blockSz - 1)); - - /* pad with padSz value */ - if (buf) { - for (i = 0; i < padSz; i++) { - buf[sz+i] = (byte)(padSz & 0xFF); - } - } - - /* return adjusted length */ - return sz + padSz; -} - #endif /* HAVE_PKCS8 || HAVE_PKCS12 */ #ifdef HAVE_PKCS8 @@ -3970,10 +3949,6 @@ int wc_CreateEncryptedPKCS8Key(byte* key, word32 keySz, byte* out, pbeOid, encAlgId, salt, saltSz, itt, rng, heap); } - -#endif /* HAVE_PKCS8 */ - -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) /* decrypt PKCS * * NOTE: input buffer is overwritten with decrypted data! @@ -4157,10 +4132,29 @@ int ToTraditionalEnc(byte* input, word32 sz, const char* password, return ret; } -#endif /* HAVE_PKCS8 || HAVE_PKCS12 */ +#endif /* HAVE_PKCS8 */ #ifdef HAVE_PKCS12 +#define PKCS8_MIN_BLOCK_SIZE 8 +static int Pkcs8Pad(byte* buf, int sz, int blockSz) +{ + int i, padSz; + + /* calculate pad size */ + padSz = blockSz - (sz & (blockSz - 1)); + + /* pad with padSz value */ + if (buf) { + for (i = 0; i < padSz; i++) { + buf[sz+i] = (byte)(padSz & 0xFF); + } + } + + /* return adjusted length */ + return sz + padSz; +} + /* encrypt PKCS 12 content * * NOTE: if out is NULL then outSz is set with the total buffer size needed and @@ -5029,21 +5023,17 @@ int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, word32 inSz) { int length, version, ret = 0, temp = 0; -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) word32 algId = 0; -#endif /* Sanity checks on input */ if (input == NULL || inOutIdx == NULL || key == NULL) { return BAD_FUNC_ARG; } -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) /* if has pkcs8 header skip it */ if (ToTraditionalInline_ex(input, inOutIdx, inSz, &algId) < 0) { /* ignore error, did not have pkcs8 header */ } -#endif if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -11306,9 +11296,9 @@ int PemToDer(const unsigned char* buff, long longSz, int type, int sz = (int)longSz; int encrypted_key = 0; DerBuffer* der; -#if defined(HAVE_PKCS8) || defined(WOLFSSL_ENCRYPTED_KEYS) word32 algId = 0; word32 idx; +#if defined(WOLFSSL_ENCRYPTED_KEYS) #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_WOLFSSL_SKIP_TRAILING_PAD) int padVal = 0; #endif @@ -11519,7 +11509,6 @@ int PemToDer(const unsigned char* buff, long longSz, int type, #endif ) && !encrypted_key) { - #ifdef HAVE_PKCS8 /* detect pkcs8 key and get alg type */ /* keep PKCS8 header */ idx = 0; @@ -11531,9 +11520,9 @@ int PemToDer(const unsigned char* buff, long longSz, int type, else { /* ignore failure here and assume key is not pkcs8 wrapped */ } - #endif return 0; } + #ifdef WOLFSSL_ENCRYPTED_KEYS if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) { @@ -16358,20 +16347,16 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, byte priv[ECC_MAXSIZE+1]; byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */ #endif -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) word32 algId = 0; -#endif byte* pubData = NULL; if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; -#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) /* if has pkcs8 header skip it */ if (ToTraditionalInline_ex(input, inOutIdx, inSz, &algId) < 0) { /* ignore error, did not have pkcs8 header */ } -#endif if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index 7c3eb8994..5ea4dec78 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/* PKCS#12 allows storage of key and certificates into containers */ #ifdef HAVE_CONFIG_H #include diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 314388518..609b8efec 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -2147,17 +2147,18 @@ extern void uITRON4_free(void *p) ; #endif #endif -#if !defined(NO_PKCS12) && !defined(NO_PKCS8) +#ifndef NO_PKCS12 #undef HAVE_PKCS12 #define HAVE_PKCS12 #endif -#ifndef NO_PKCS8 +#if !defined(NO_PKCS8) || defined(HAVE_PKCS12) #undef HAVE_PKCS8 #define HAVE_PKCS8 #endif -#if !defined(NO_PBKDF1) || defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8) || defined(HAVE_PKCS12) +#if !defined(NO_PBKDF1) || defined(WOLFSSL_ENCRYPTED_KEYS) || \ + defined(HAVE_PKCS8) || defined(HAVE_PKCS12) #undef HAVE_PBKDF1 #define HAVE_PBKDF1 #endif