diff --git a/src/ssl.c b/src/ssl.c index 911966588..96deacdd2 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -5685,6 +5685,42 @@ int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format) #ifdef OPENSSL_EXTRA /* put SSL type in extra for now, not very common */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz) +{ + WOLFSSL_EVP_PKEY* local; + + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); + + if (in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + local = wolfSSL_PKEY_new(); + if (local == NULL) { + return NULL; + } + + local->type = type; + local->pkey_sz = inSz; + local->pkey.ptr = (char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (local->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(local); + local = NULL; + } + else { + XMEMCPY(local->pkey.ptr, *in, inSz); + } + + if (out != NULL) { + *out = local; + } + + return local; +} + + long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt) { WOLFSSL_STUB("wolfSSL_ctrl"); @@ -13803,6 +13839,20 @@ void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj) } +WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new() +{ + WOLFSSL_EVP_PKEY* pkey; + + pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey != NULL) { + XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY)); + } + + return pkey; +} + + void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) { if (key != NULL) { @@ -17417,26 +17467,72 @@ int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa, } #endif /* NO_FILESYSTEM */ -/*** TBD ***/ -WOLFSSL_API -int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, RSA* rsa, - const EVP_CIPHER* cipher, +int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, + const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int len, pem_password_cb cb, void* arg) { - (void)bio; - (void)rsa; + byte* keyDer; + int pemSz; + int type; + int ret; + (void)cipher; (void)passwd; (void)len; (void)cb; (void)arg; - WOLFSSL_MSG("wolfSSL_PEM_write_bio_PrivateKey not implemented"); + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); - return SSL_FAILURE; + if (bio == NULL || key == NULL) { + return SSL_FAILURE; + } + + keyDer = (byte*)key->pkey.ptr; + + switch (key->type) { + case EVP_PKEY_RSA: + type = PRIVATEKEY_TYPE; + break; + +#ifndef NO_DSA + case EVP_PKEY_DSA: + type = DSA_PRIVATEKEY_TYPE; + break; +#endif + + case EVP_PKEY_EC: + type = ECC_PRIVATEKEY_TYPE; + break; + + default: + WOLFSSL_MSG("Unknown Key type!"); + type = PRIVATEKEY_TYPE; + } + + pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz); + return SSL_FAILURE; + } + if (bio->mem != NULL) { + XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL); + } + bio->mem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_OPENSSL); + bio->memLen = pemSz; + + ret = wc_DerToPemEx(keyDer, key->pkey_sz, bio->mem, bio->memLen, + NULL, type); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret); + return SSL_FAILURE; + } + + return SSL_SUCCESS; } + int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, RSA* rsa, const EVP_CIPHER* cipher, unsigned char* passwd, int len, diff --git a/tests/api.c b/tests/api.c index 6173a7a92..6068aad91 100644 --- a/tests/api.c +++ b/tests/api.c @@ -48,6 +48,7 @@ #include #include #include + #include #ifndef NO_DES3 #include #endif @@ -2435,6 +2436,9 @@ static void test_wolfSSL_private_keys(void) AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); #ifdef USE_CERT_BUFFERS_2048 + { + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + AssertIntEQ(SSL_use_RSAPrivateKey_ASN1(ssl, (unsigned char*)client_key_der_2048, sizeof_client_key_der_2048), SSL_SUCCESS); @@ -2444,15 +2448,23 @@ static void test_wolfSSL_private_keys(void) #endif AssertIntEQ(SSL_use_PrivateKey_ASN1(0, ssl, - (unsigned char*)server_key_der_2048, + (unsigned char*)server_key, sizeof_server_key_der_2048), SSL_SUCCESS); /* After loading back in DER format of original key, should match */ AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); -#endif /* pkey not set yet, expecting to fail */ AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), SSL_FAILURE); + /* set PKEY and test again */ + AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, + &server_key, (long)sizeof_server_key_der_2048)); + AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), SSL_SUCCESS); + } +#endif + + + EVP_PKEY_free(pkey); SSL_free(ssl); /* frees x509 also since loaded into ssl */ SSL_CTX_free(ctx); @@ -2466,6 +2478,34 @@ static void test_wolfSSL_private_keys(void) } +static void test_wolfSSL_PEM_PrivateKey(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ + (defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) && \ + defined(USE_CERT_BUFFERS_2048) + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + EVP_PKEY* pkey = NULL; + BIO* bio; + + printf(testingFmt, "wolfSSL_PEM_PrivateKey()"); + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + AssertNotNull(bio); + + 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), + SSL_SUCCESS); + + BIO_free(bio); + EVP_PKEY_free(pkey); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + + static void test_wolfSSL_tmp_dh(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ @@ -2576,6 +2616,7 @@ void ApiTest(void) test_wolfSSL_DES(); test_wolfSSL_certs(); test_wolfSSL_private_keys(); + test_wolfSSL_PEM_PrivateKey(); test_wolfSSL_tmp_dh(); test_wolfSSL_ctrl(); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 5cf74ef93..765f42c73 100755 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -5908,6 +5908,20 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, headerLen = (int)XSTRLEN(header); footerLen = (int)XSTRLEN(footer); + /* if null output and 0 size passed in then return size needed */ + if (!output && outSz == 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + outLen = 0; + if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen)) + != LENGTH_ONLY_E) { + return err; + } + return headerLen + footerLen + outLen; + } + if (!der || !output) { #ifdef WOLFSSL_SMALL_STACK XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index d41d1e9c4..86ac26ab6 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -150,6 +150,8 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, return 0; } (void)in; + (void)inl; + (void)out; return 1; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index c0d79b45a..ae1754240 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -6980,6 +6980,7 @@ int openssl_test(void) #define OPENSSL_TEST_ERROR (-10000) +#ifndef NO_AES #ifdef WOLFSSL_AES_DIRECT /* enable HAVE_AES_DECRYPT for AES_encrypt/decrypt */ { @@ -7320,6 +7321,7 @@ int openssl_test(void) return -3428; } +#endif /* ifndef NO_AES */ return 0; } diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index 282a49b81..3148d63b5 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -145,7 +145,7 @@ enum { NULL_CIPHER_TYPE = 15, EVP_PKEY_RSA = 16, EVP_PKEY_DSA = 17, - EVP_PKEY_EC = 18, + EVP_PKEY_EC = 18, IDEA_CBC_TYPE = 19, NID_sha1 = 64, NID_md2 = 3, diff --git a/wolfssl/openssl/pem.h b/wolfssl/openssl/pem.h index 043854342..9f0ec25bb 100644 --- a/wolfssl/openssl/pem.h +++ b/wolfssl/openssl/pem.h @@ -13,6 +13,7 @@ extern "C" { #endif +#define PEM_write_bio_PrivateKey wolfSSL_PEM_write_bio_PrivateKey /* RSA */ WOLFSSL_API @@ -90,8 +91,8 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, pem_password_cb cb, void* arg); WOLFSSL_API -int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, RSA* rsa, - const EVP_CIPHER* cipher, +int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, + const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int len, pem_password_cb cb, void* arg); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 1b759da67..0fcdb4828 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -124,7 +124,7 @@ typedef struct WOLFSSL_EVP_PKEY { int save_type; /* openssh dereference */ int pkey_sz; union { - char* ptr; + char* ptr; /* der format of key / or raw for NTRU */ } pkey; #ifdef HAVE_ECC int pkey_curve; @@ -631,6 +631,9 @@ WOLFSSL_API int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL*, WOLFSSL_EVP_PKE WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX*, int); WOLFSSL_API void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT*); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, + WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(void); WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY*); WOLFSSL_API int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*); WOLFSSL_API int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*);