Fix for `ProcessBuffer` with PEM private keys, where `PemToDer` call was only setting `eccKey`. Cleanup to use "keyFormat" OID sum.

pull/2739/head
David Garske 2020-01-15 11:02:09 -08:00
parent de8e5ffd6e
commit 0489cc97a8
3 changed files with 74 additions and 55 deletions

View File

@ -5232,8 +5232,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
} }
static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der, static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der,
int* keySz, word32* idx, int* resetSuites, int *rsaKey, int *eccKey, int* keySz, word32* idx, int* resetSuites, int* keyFormat, void* heap, int devId)
int *ed25519Key, void* heap, int devId)
{ {
int ret = 0; int ret = 0;
@ -5242,11 +5241,11 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
if (ctx == NULL && ssl == NULL) if (ctx == NULL && ssl == NULL)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
if (!der || !keySz || !idx || !resetSuites || !rsaKey || !eccKey || !ed25519Key) if (!der || !keySz || !idx || !resetSuites || !keyFormat)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
#ifndef NO_RSA #ifndef NO_RSA
if (ret == 0 && !*eccKey && !*ed25519Key) { if (ret == 0 && (*keyFormat == 0 || *keyFormat == RSAk)) {
/* make sure RSA key can be used */ /* make sure RSA key can be used */
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
RsaKey* key = NULL; RsaKey* key = NULL;
@ -5265,13 +5264,8 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
*idx = 0; *idx = 0;
if (wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length) if (wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length)
!= 0) { != 0) {
#ifdef HAVE_ECC #if !defined(HAVE_ECC) && !defined(HAVE_ED25519)
/* could have DER ECC (or pkcs8 ecc), no easy way to tell */ WOLFSSL_MSG("RSA decode failed and ECC/ED25519 not enabled to try");
*eccKey = 1; /* try it next */
#elif defined(HAVE_ED25519)
*ed25519Key = 1; /* try it next */
#else
WOLFSSL_MSG("RSA decode failed and ECC not enabled to try");
ret = WOLFSSL_BAD_FILE; ret = WOLFSSL_BAD_FILE;
#endif #endif
} }
@ -5294,8 +5288,7 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
ctx->privateKeySz = *keySz; ctx->privateKeySz = *keySz;
} }
*rsaKey = 1; *keyFormat = RSAk;
(void)rsaKey; /* for no ecc builds */
if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
ssl->options.haveStaticECC = 0; ssl->options.haveStaticECC = 0;
@ -5312,7 +5305,7 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
} }
#endif #endif
#ifdef HAVE_ECC #ifdef HAVE_ECC
if (ret == 0 && !*rsaKey && !*ed25519Key) { if (ret == 0 && (*keyFormat == 0 || *keyFormat == ECDSAk)) {
/* make sure ECC key can be used */ /* make sure ECC key can be used */
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
ecc_key* key = NULL; ecc_key* key = NULL;
@ -5339,7 +5332,7 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
ret = ECC_KEY_SIZE_E; ret = ECC_KEY_SIZE_E;
} }
*eccKey = 1; *keyFormat = ECDSAk;
if (ssl) { if (ssl) {
ssl->options.haveStaticECC = 1; ssl->options.haveStaticECC = 1;
ssl->buffers.keyType = ecc_dsa_sa_algo; ssl->buffers.keyType = ecc_dsa_sa_algo;
@ -5355,8 +5348,6 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
*resetSuites = 1; *resetSuites = 1;
} }
} }
else
*eccKey = 0;
wc_ecc_free(key); wc_ecc_free(key);
} }
@ -5367,7 +5358,7 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
} }
#endif /* HAVE_ECC */ #endif /* HAVE_ECC */
#ifdef HAVE_ED25519 #ifdef HAVE_ED25519
if (ret == 0 && !*rsaKey && !*eccKey) { if (ret == 0 && (*keyFormat == 0 || *keyFormat == ED25519k)) {
/* make sure Ed25519 key can be used */ /* make sure Ed25519 key can be used */
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
ed25519_key* key = NULL; ed25519_key* key = NULL;
@ -5410,7 +5401,7 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
ctx->privateKeySz = *keySz; ctx->privateKeySz = *keySz;
} }
*ed25519Key = 1; *keyFormat = ED25519k;
if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
*resetSuites = 1; *resetSuites = 1;
} }
@ -5437,9 +5428,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */ DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */
int ret = 0; int ret = 0;
int done = 0; int done = 0;
int eccKey = 0; int keyFormat = 0;
int ed25519Key = 0;
int rsaKey = 0;
int resetSuites = 0; int resetSuites = 0;
void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
int devId = wolfSSL_CTX_GetDevId(ctx, ssl); int devId = wolfSSL_CTX_GetDevId(ctx, ssl);
@ -5455,7 +5444,6 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
EncryptedInfo info[1]; EncryptedInfo info[1];
#endif #endif
(void)rsaKey;
(void)devId; (void)devId;
(void)idx; (void)idx;
(void)keySz; (void)keySz;
@ -5488,7 +5476,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
if (format == WOLFSSL_FILETYPE_PEM) { if (format == WOLFSSL_FILETYPE_PEM) {
#ifdef WOLFSSL_PEM_TO_DER #ifdef WOLFSSL_PEM_TO_DER
ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey); ret = PemToDer(buff, sz, type, &der, heap, info, &keyFormat);
#else #else
ret = NOT_COMPILED_IN; ret = NOT_COMPILED_IN;
#endif #endif
@ -5647,22 +5635,31 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
} }
else if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) { else if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) {
#if defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8) #if defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8)
/* attempt to detect key type */ #ifndef NO_DSA
if (algId == RSAk) if (algId == DSAk)
rsaKey = 1; keyFormat = DSAk;
else if (algId == ECDSAk) #endif
eccKey = 1; #ifdef HAVE_ECC
else if (algId == ED25519k) if (algId == ECDSAk)
ed25519Key = 1; keyFormat = ECDSAk;
#endif
#ifndef NO_DH
if (algId == DHk)
keyFormat = DHk;
#endif
#ifdef HAVE_ED25519
if (algId == ED25519k)
keyFormat = ED25519k;
#endif
#endif #endif
ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, &resetSuites, ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, &resetSuites,
&rsaKey, &eccKey, &ed25519Key, heap, devId); &keyFormat, heap, devId);
#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
/* for WOLFSSL_FILETYPE_PEM, PemToDer manages the decryption */ /* for WOLFSSL_FILETYPE_PEM, PemToDer manages the decryption */
/* If private key type PKCS8 header wasn't already removed (algoId == 0) */ /* If private key type PKCS8 header wasn't already removed (algoId == 0) */
if ((ret != 0 || (!rsaKey && !eccKey && !ed25519Key)) if ((ret != 0 || keyFormat == 0)
&& format != WOLFSSL_FILETYPE_PEM && info->passwd_cb && algId == 0) && format != WOLFSSL_FILETYPE_PEM && info->passwd_cb && algId == 0)
{ {
int passwordSz = NAME_SZ; int passwordSz = NAME_SZ;
@ -5699,7 +5696,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
XFREE(password, heap, DYNAMIC_TYPE_STRING); XFREE(password, heap, DYNAMIC_TYPE_STRING);
#endif #endif
ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx,
&resetSuites, &rsaKey, &eccKey, &ed25519Key, heap, devId); &resetSuites, &keyFormat, heap, devId);
} }
#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
@ -5709,9 +5706,9 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
if (ret != 0) if (ret != 0)
return ret; return ret;
if (!rsaKey && !eccKey && !ed25519Key) if (keyFormat == 0)
return WOLFSSL_BAD_FILE; return WOLFSSL_BAD_FILE;
(void)ed25519Key;
(void)devId; (void)devId;
} }
else if (type == CERT_TYPE) { else if (type == CERT_TYPE) {
@ -35265,14 +35262,14 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
if (keyFormat) { if (keyFormat) {
/* keyFormat is Key_Sum enum */ /* keyFormat is Key_Sum enum */
if (keyFormat == ECDSAk) if (keyFormat == RSAk)
type = EVP_PKEY_RSA;
else if (keyFormat == ECDSAk)
type = EVP_PKEY_EC; type = EVP_PKEY_EC;
else if (keyFormat == DSAk) else if (keyFormat == DSAk)
type = EVP_PKEY_DSA; type = EVP_PKEY_DSA;
#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
else if (keyFormat == DHk) else if (keyFormat == DHk)
type = EVP_PKEY_DH; type = EVP_PKEY_DH;
#endif
} }
else { else {
/* Default to RSA if format is not set */ /* Default to RSA if format is not set */

View File

@ -4895,7 +4895,7 @@ static void test_wolfSSL_PKCS8(void)
flag = 0; /* used by password callback as return code */ flag = 0; /* used by password callback as return code */
AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes,
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
#endif /* !NO_RSA */ #endif /* !NO_RSA && !NO_SHA */
#if defined(HAVE_ECC) && !defined(NO_SHA) #if defined(HAVE_ECC) && !defined(NO_SHA)
/* test loading PEM PKCS8 encrypted ECC Key file */ /* test loading PEM PKCS8 encrypted ECC Key file */
@ -4936,7 +4936,7 @@ static void test_wolfSSL_PKCS8(void)
/* leave flag as "okay" */ /* leave flag as "okay" */
flag = 1; flag = 1;
#endif /* HAVE_ECC */ #endif /* HAVE_ECC && !NO_SHA */
#endif /* TEST_PKCS8_ENC */ #endif /* TEST_PKCS8_ENC */

View File

@ -10330,7 +10330,8 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
/* pkcs8 key, convert and adjust length */ /* pkcs8 key, convert and adjust length */
if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) { if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) {
der->length = ret; der->length = ret;
#if !defined(NO_DSA) if (keyFormat) {
#ifndef NO_DSA
if (algId == DSAk) if (algId == DSAk)
*keyFormat = DSAk; *keyFormat = DSAk;
#endif #endif
@ -10338,10 +10339,15 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
if (algId == ECDSAk) if (algId == ECDSAk)
*keyFormat = ECDSAk; *keyFormat = ECDSAk;
#endif #endif
#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) #ifndef NO_DH
if (algId == DHk) if (algId == DHk)
*keyFormat = DHk; *keyFormat = DHk;
#endif #endif
#ifdef HAVE_ED25519
if (algId == ED25519k)
*keyFormat = ED25519k;
#endif
}
} }
else { else {
/* ignore failure here and assume key is not pkcs8 wrapped */ /* ignore failure here and assume key is not pkcs8 wrapped */
@ -10385,8 +10391,24 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
if (ret >= 0) { if (ret >= 0) {
der->length = ret; der->length = ret;
if (keyFormat) if (keyFormat) {
*keyFormat = algId; #ifndef NO_DSA
if (algId == DSAk)
*keyFormat = DSAk;
#endif
#ifdef HAVE_ECC
if (algId == ECDSAk)
*keyFormat = ECDSAk;
#endif
#ifndef NO_DH
if (algId == DHk)
*keyFormat = DHk;
#endif
#ifdef HAVE_ED25519
if (algId == ED25519k)
*keyFormat = ED25519k;
#endif
}
ret = 0; ret = 0;
} }
#else #else