From d1c05c1883c02b4bc8f39951dda7aca1a076c76f Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 4 Apr 2017 09:58:13 -0600 Subject: [PATCH] fix DER to internal private key function --- src/ssl.c | 70 ++++++++++++++++++++++++++++++++--------- tests/api.c | 77 +++++++++++++++++++++++++++++++++++++++++++-- wolfcrypt/src/asn.c | 5 +++ wolfssl/test.h | 10 ++++-- 4 files changed, 142 insertions(+), 20 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 173152352..ba6cf4412 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -7110,33 +7110,48 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, XMEMCPY(local->pkey.ptr, *in + idx, inSz - idx); } - if (out != NULL) { - *out = local; - } - #ifndef NO_RSA if (type == EVP_PKEY_RSA && local != NULL){ local->ownRsa = 1; local->rsa = wolfSSL_RSA_new(); if (local->rsa == NULL) { - XFREE(local, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + wolfSSL_EVP_PKEY_free(local); return NULL; } if (wolfSSL_RSA_LoadDer_ex(local->rsa, (const unsigned char*)local->pkey.ptr, local->pkey_sz, WOLFSSL_RSA_LOAD_PRIVATE) != SSL_SUCCESS) { - XFREE(local, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - wolfSSL_RSA_free(local->rsa); + wolfSSL_EVP_PKEY_free(local); return NULL; } } #endif /* NO_RSA */ +#ifdef HAVE_ECC + if (type == EVP_PKEY_EC && local != NULL){ + local->ownEcc = 1; + local->ecc = wolfSSL_EC_KEY_new(); + if (local->ecc == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wolfSSL_EC_KEY_LoadDer(local->ecc, + (const unsigned char*)local->pkey.ptr, local->pkey_sz) + != SSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + } +#endif /* HAVE_ECC */ /* advance pointer with success */ if (local != NULL) { if ((idx + local->pkey_sz) <= (word32)inSz) { *in = *in + idx + local->pkey_sz; } + + if (out != NULL) { + *out = local; + } } return local; @@ -26022,7 +26037,8 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, const unsigned char* ptr = der->buffer; /* write left over data back to bio */ - if ((memSz - (int)info->consumed) > 0) { + if ((memSz - (int)info->consumed) > 0 && + bio->type != WOLFSSL_BIO_FILE) { if (wolfSSL_BIO_write(bio, mem + (int)info->consumed, memSz - (int)info->consumed) <= 0) { WOLFSSL_MSG("Unable to advance bio read pointer"); @@ -26030,10 +26046,10 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, } if (eccFlag) { - type = ECDSAk; + type = EVP_PKEY_EC; } else { - type = RSAk; + type = EVP_PKEY_RSA; } /* handle case where reuse is attempted */ @@ -26062,13 +26078,31 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, } +/* return of pkey->type which will be EVP_PKEY_RSA for example. + * + * type type of EVP_PKEY + * + * returns type or if type is not found then NID_undef + */ int wolfSSL_EVP_PKEY_type(int type) { - (void) type; - WOLFSSL_MSG("wolfSSL_EVP_PKEY_type always returns EVP_PKEY_RSA"); - return EVP_PKEY_RSA; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_type"); + + switch (type) { + #ifdef OPENSSL_EXTRA + case EVP_PKEY_RSA: + return EVP_PKEY_RSA; + case EVP_PKEY_DSA: + return EVP_PKEY_DSA; + case EVP_PKEY_EC: + return EVP_PKEY_EC; + #endif + default: + return NID_undef; + } } + int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey) { return EVP_PKEY_type(pkey->type); @@ -28084,9 +28118,15 @@ int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) return WOLFSSL_FAILURE; } - return wolfSSL_CTX_use_PrivateKey_buffer(ctx, + if (pkey->pkey.ptr != NULL) { + /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */ + return wolfSSL_CTX_use_PrivateKey_buffer(ctx, (const unsigned char*)pkey->pkey.ptr, - pkey->pkey_sz, PRIVATEKEY_TYPE); + pkey->pkey_sz, SSL_FILETYPE_ASN1); + } + + WOLFSSL_MSG("wolfSSL private key not set"); + return BAD_FUNC_ARG; } #endif /* !NO_CERTS */ diff --git a/tests/api.c b/tests/api.c index f63a1d72e..f28d0b87f 100644 --- a/tests/api.c +++ b/tests/api.c @@ -13872,6 +13872,10 @@ static void test_wolfSSL_PEM_PrivateKey(void) AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); AssertIntEQ(BIO_set_write_buf_size(bio, 4096), SSL_FAILURE); + AssertNull(d2i_PrivateKey(EVP_PKEY_EC, &pkey, + &server_key, (long)sizeof_server_key_der_2048)); + AssertNull(pkey); + AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, (long)sizeof_server_key_der_2048)); AssertIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), @@ -13900,6 +13904,68 @@ static void test_wolfSSL_PEM_PrivateKey(void) EVP_PKEY_free(pkey); EVP_PKEY_free(pkey2); + #if !defined(NO_DES3) /* key is DES encrypted */ + { + pem_password_cb* passwd_cb; + void* passwd_cb_userdata; + SSL_CTX* ctx; + char passwd[] = "bad password"; + + AssertNotNull(ctx = SSL_CTX_new(TLSv1_2_server_method())); + + AssertNotNull(bio = BIO_new_file("./certs/server-keyEnc.pem", "rb")); + SSL_CTX_set_default_passwd_cb(ctx, &PasswordCallBack); + AssertNotNull(passwd_cb = SSL_CTX_get_default_passwd_cb(ctx)); + AssertNull(passwd_cb_userdata = + SSL_CTX_get_default_passwd_cb_userdata(ctx)); + + /* fail case with password call back */ + AssertNull(pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, + (void*)passwd)); + BIO_free(bio); + AssertNotNull(bio = BIO_new_file("./certs/server-keyEnc.pem", "rb")); + AssertNull(pkey = PEM_read_bio_PrivateKey(bio, NULL, passwd_cb, + (void*)passwd)); + BIO_free(bio); + AssertNotNull(bio = BIO_new_file("./certs/server-keyEnc.pem", "rb")); + + /* use callback that works */ + AssertNotNull(pkey = PEM_read_bio_PrivateKey(bio, NULL, passwd_cb, + (void*)"yassl123")); + + AssertIntEQ(SSL_CTX_use_PrivateKey(ctx, pkey), SSL_SUCCESS); + + EVP_PKEY_free(pkey); + BIO_free(bio); + SSL_CTX_free(ctx); + } + #endif /* !defined(NO_DES3) */ + + #ifdef HAVE_ECC + { + unsigned char buf[2048]; + int bytes; + XFILE f; + SSL_CTX* ctx; + + AssertNotNull(ctx = SSL_CTX_new(TLSv1_2_server_method())); + + AssertNotNull(f = XFOPEN("./certs/ecc-key.der", "rb")); + bytes = XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + server_key = buf; + pkey = NULL; + AssertNull(d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, bytes)); + AssertNull(pkey); + AssertNotNull(d2i_PrivateKey(EVP_PKEY_EC, &pkey, &server_key, bytes)); + AssertIntEQ(SSL_CTX_use_PrivateKey(ctx, pkey), SSL_SUCCESS); + + EVP_PKEY_free(pkey); + SSL_CTX_free(ctx); + } + #endif + printf(resultFmt, passed); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ } @@ -14109,7 +14175,7 @@ static void test_wolfSSL_CTX_add_extra_chain_cert(void) * allowed with user RSA */ { EVP_PKEY* pkey; - #if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + #if defined(HAVE_ECC) X509* ecX509; #endif /* HAVE_ECC */ @@ -14119,10 +14185,15 @@ static void test_wolfSSL_CTX_add_extra_chain_cert(void) EVP_PKEY_free(pkey); - #if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + #if defined(HAVE_ECC) + #if defined(USE_CERT_BUFFERS_256) AssertNotNull(ecX509 = wolfSSL_X509_load_certificate_buffer( cliecc_cert_der_256, sizeof_cliecc_cert_der_256, SSL_FILETYPE_ASN1)); + #else + AssertNotNull(ecX509 = wolfSSL_X509_load_certificate_file(cliEccCertFile, + SSL_FILETYPE_PEM)); + #endif AssertNotNull(pkey = X509_get_pubkey(ecX509)); /* current ECC key is 256 bit (32 bytes) */ AssertIntEQ(EVP_PKEY_size(pkey), 32); @@ -15555,7 +15626,7 @@ static void test_wolfSSL_BIO_write(void) char out[40]; char expected[] = "Y29udmVyc2lvbiB0ZXN0AA==\n"; - printf(testingFmt, "BIO_write()"); + printf(testingFmt, "wolfSSL_BIO_write()"); AssertNotNull(bio64 = BIO_new(BIO_f_base64())); AssertNotNull(bio = BIO_push(bio64, BIO_new(BIO_s_mem()))); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 40f39f49c..f58d40030 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2572,6 +2572,11 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) byte cbcIv[MAX_IV_SIZE]; #endif + if (passwordSz < 0) { + WOLFSSL_MSG("Bad password size"); + return BAD_FUNC_ARG; + } + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { ERROR_OUT(ASN_PARSE_E, exit_tte); } diff --git a/wolfssl/test.h b/wolfssl/test.h index 784aee03d..ad1d8d355 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -472,8 +472,14 @@ static INLINE int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) { (void)rw; (void)userdata; - strncpy(passwd, "yassl123", sz); - return 8; + if (userdata != NULL) { + strncpy(passwd, (char*)userdata, sz); + return (int)XSTRLEN((char*)userdata); + } + else { + strncpy(passwd, "yassl123", sz); + return 8; + } } #endif