From 1d0fc83d4039c606c76fffa384a884689b83f86e Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 29 Nov 2016 10:32:25 -0700 Subject: [PATCH] function to add X509 to cert chain --- src/ssl.c | 193 ++++++++++++++++++++++++++++++++------------------ tests/api.c | 29 ++++++++ wolfssl/ssl.h | 2 +- 3 files changed, 153 insertions(+), 71 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 5071055a3..46fdfca67 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -14274,13 +14274,64 @@ long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) return 0; } -/*** TBC ***/ -WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx) + +long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) { - (void)ctx; - return 0; + byte* chain; + long chainSz = 0; + int derSz; + const byte* der; + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert"); + + if (ctx == NULL || x509 == NULL) { + WOLFSSL_MSG("Bad Argument"); + return SSL_FAILURE; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL || derSz <= 0) { + WOLFSSL_MSG("Error getting X509 DER"); + return SSL_FAILURE; + } + + /* adding cert to existing chain */ + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + chainSz += ctx->certChain->length; + } + chainSz += derSz; + + chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (chain == NULL) { + WOLFSSL_MSG("Memory Error"); + return SSL_FAILURE; + } + + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); + XMEMCPY(chain + ctx->certChain->length, der, derSz); + } + else { + XMEMCPY(chain, der, derSz); + } + + ret = ProcessBuffer(ctx, chain, chainSz, SSL_FILETYPE_ASN1, CERT_TYPE, + NULL, NULL, 1); + if (ret != SSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + XFREE(chain, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + + /* on success WOLFSSL_X509 memory is responsibility of ctx */ + wolfSSL_X509_free(x509); + XFREE(chain, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return SSL_SUCCESS; } + /*** TBC ***/ WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx) { @@ -17319,6 +17370,74 @@ static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, } #endif /* defined(WOLFSSL_KEY_GEN) */ +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) + +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) +{ + byte* keyDer; + int pemSz; + int type; + int ret; + + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); + + 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; +} +#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */ + #if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) /* return code compliant with OpenSSL : @@ -17467,72 +17586,6 @@ int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa, } #endif /* NO_FILESYSTEM */ -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) -{ - byte* keyDer; - int pemSz; - int type; - int ret; - - (void)cipher; - (void)passwd; - (void)len; - (void)cb; - (void)arg; - - WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); - - 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 51e797ab9..f8ffe1dba 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2568,6 +2568,34 @@ static void test_wolfSSL_ctrl(void) #endif /* defined(OPENSSL_EXTRA) */ } + +static void test_wolfSSL_CTX_add_extra_chain_cert(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) + char caFile[] = "./certs/client-ca.pem"; + char clientFile[] = "./certs/client-cert.pem"; + SSL_CTX* ctx; + X509* x509; + + printf(testingFmt, "wolfSSL_CTX_add_extra_chain_cert()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + + x509 = wolfSSL_X509_load_certificate_file(caFile, SSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ((int)wolfSSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); + + x509 = wolfSSL_X509_load_certificate_file(clientFile, SSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ((int)wolfSSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); + + SSL_CTX_free(ctx); + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) */ +} + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -2619,6 +2647,7 @@ void ApiTest(void) test_wolfSSL_PEM_PrivateKey(); test_wolfSSL_tmp_dh(); test_wolfSSL_ctrl(); + test_wolfSSL_CTX_add_extra_chain_cert(); AssertIntEQ(test_wolfSSL_Cleanup(), SSL_SUCCESS); printf(" End API Tests\n"); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 0fcdb4828..ecfda40b3 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -696,7 +696,7 @@ WOLFSSL_API long wolfSSL_CTX_sess_misses(WOLFSSL_CTX*); WOLFSSL_API long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX*); WOLFSSL_API long wolfSSL_CTX_sess_number(WOLFSSL_CTX*); -WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*); WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long); WOLFSSL_API long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX*);