diff options
Diffstat (limited to 'src/ssl/ssl_rsa.c')
-rw-r--r-- | src/ssl/ssl_rsa.c | 470 |
1 files changed, 369 insertions, 101 deletions
diff --git a/src/ssl/ssl_rsa.c b/src/ssl/ssl_rsa.c index ccd3858..87f4c1c 100644 --- a/src/ssl/ssl_rsa.c +++ b/src/ssl/ssl_rsa.c @@ -54,38 +54,79 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ -#include <openssl/ssl.h> +#include <stdio.h> +#include <openssl/bio.h> #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/mem.h> +#include <openssl/obj.h> +#include <openssl/pem.h> #include <openssl/x509.h> #include "internal.h" - static int ssl_set_cert(CERT *c, X509 *x509); static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); -static int is_key_type_supported(int key_type) { - return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC; -} - int SSL_use_certificate(SSL *ssl, X509 *x) { if (x == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate, ERR_R_PASSED_NULL_PARAMETER); return 0; } return ssl_set_cert(ssl->cert, x); } +int SSL_use_certificate_file(SSL *ssl, const char *file, int type) { + int reason_code; + BIO *in; + int ret = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, reason_code); + goto end; + } + + ret = SSL_use_certificate(ssl, x); + +end: + X509_free(x); + BIO_free(in); + + return ret; +} + int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *d, int len) { X509 *x; int ret; x = d2i_X509(NULL, &d, (long)len); if (x == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_ASN1, ERR_R_ASN1_LIB); return 0; } @@ -99,13 +140,13 @@ int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) { int ret; if (rsa == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_PASSED_NULL_PARAMETER); return 0; } pkey = EVP_PKEY_new(); if (pkey == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_EVP_LIB); return 0; } @@ -119,36 +160,86 @@ int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) { } static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { - if (!is_key_type_supported(pkey->type)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + int i; + + i = ssl_cert_type(pkey); + if (i < 0) { + OPENSSL_PUT_ERROR(SSL, ssl_set_pkey, SSL_R_UNKNOWN_CERTIFICATE_TYPE); return 0; } - if (c->x509 != NULL) { + if (c->pkeys[i].x509 != NULL) { /* Sanity-check that the private key and the certificate match, unless the * key is opaque (in case of, say, a smartcard). */ if (!EVP_PKEY_is_opaque(pkey) && - !X509_check_private_key(c->x509, pkey)) { - X509_free(c->x509); - c->x509 = NULL; + !X509_check_private_key(c->pkeys[i].x509, pkey)) { + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509 = NULL; return 0; } } - EVP_PKEY_free(c->privatekey); - c->privatekey = EVP_PKEY_up_ref(pkey); + EVP_PKEY_free(c->pkeys[i].privatekey); + c->pkeys[i].privatekey = EVP_PKEY_up_ref(pkey); + c->key = &(c->pkeys[i]); return 1; } -int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) { - RSA *rsa = RSA_private_key_from_bytes(der, der_len); +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + rsa = + PEM_read_bio_RSAPrivateKey(in, NULL, ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, reason_code); + goto end; + } + ret = SSL_use_RSAPrivateKey(ssl, rsa); + RSA_free(rsa); + +end: + BIO_free(in); + return ret; +} + +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, uint8_t *d, long len) { + int ret; + const uint8_t *p; + RSA *rsa; + + p = d; + rsa = d2i_RSAPrivateKey(NULL, &p, (long)len); if (rsa == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB); return 0; } - int ret = SSL_use_RSAPrivateKey(ssl, rsa); + ret = SSL_use_RSAPrivateKey(ssl, rsa); RSA_free(rsa); return ret; } @@ -157,7 +248,7 @@ int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) { int ret; if (pkey == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -165,6 +256,46 @@ int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) { return ret; } +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, reason_code); + goto end; + } + ret = SSL_use_PrivateKey(ssl, pkey); + EVP_PKEY_free(pkey); + +end: + BIO_free(in); + return ret; +} + int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *d, long len) { int ret; const uint8_t *p; @@ -173,7 +304,7 @@ int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *d, long len) { p = d; pkey = d2i_PrivateKey(type, NULL, &p, (long)len); if (pkey == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_ASN1, ERR_R_ASN1_LIB); return 0; } @@ -184,7 +315,8 @@ int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *d, long len) { int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) { if (x == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate, + ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -192,28 +324,32 @@ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) { } static int ssl_set_cert(CERT *c, X509 *x) { - EVP_PKEY *pkey = X509_get_pubkey(x); + EVP_PKEY *pkey; + int i; + + pkey = X509_get_pubkey(x); if (pkey == NULL) { - OPENSSL_PUT_ERROR(SSL, SSL_R_X509_LIB); + OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_X509_LIB); return 0; } - if (!is_key_type_supported(pkey->type)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + i = ssl_cert_type(pkey); + if (i < 0) { + OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_UNKNOWN_CERTIFICATE_TYPE); EVP_PKEY_free(pkey); return 0; } - if (c->privatekey != NULL) { + if (c->pkeys[i].privatekey != NULL) { /* Sanity-check that the private key and the certificate match, unless the * key is opaque (in case of, say, a smartcard). */ - if (!EVP_PKEY_is_opaque(c->privatekey) && - !X509_check_private_key(x, c->privatekey)) { + if (!EVP_PKEY_is_opaque(c->pkeys[i].privatekey) && + !X509_check_private_key(x, c->pkeys[i].privatekey)) { /* don't fail for a cert/key mismatch, just free current private key * (when switching to a different cert & key, first this function should * be used, then ssl_set_pkey */ - EVP_PKEY_free(c->privatekey); - c->privatekey = NULL; + EVP_PKEY_free(c->pkeys[i].privatekey); + c->pkeys[i].privatekey = NULL; /* clear error queue */ ERR_clear_error(); } @@ -221,19 +357,63 @@ static int ssl_set_cert(CERT *c, X509 *x) { EVP_PKEY_free(pkey); - X509_free(c->x509); - c->x509 = X509_up_ref(x); + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509 = X509_up_ref(x); + c->key = &(c->pkeys[i]); return 1; } +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) { + int reason_code; + BIO *in; + int ret = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, + SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, reason_code); + goto end; + } + + ret = SSL_CTX_use_certificate(ctx, x); + +end: + X509_free(x); + BIO_free(in); + return ret; +} + int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const uint8_t *d) { X509 *x; int ret; x = d2i_X509(NULL, &d, (long)len); if (x == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_ASN1, ERR_R_ASN1_LIB); return 0; } @@ -247,13 +427,14 @@ int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) { EVP_PKEY *pkey; if (rsa == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, + ERR_R_PASSED_NULL_PARAMETER); return 0; } pkey = EVP_PKEY_new(); if (pkey == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, ERR_R_EVP_LIB); return 0; } @@ -265,28 +446,113 @@ int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) { return ret; } -int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der, - size_t der_len) { - RSA *rsa = RSA_private_key_from_bytes(der, der_len); +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, + SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, reason_code); + goto end; + } + ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + RSA_free(rsa); + +end: + BIO_free(in); + return ret; +} + +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *d, long len) { + int ret; + const uint8_t *p; + RSA *rsa; + + p = d; + rsa = d2i_RSAPrivateKey(NULL, &p, (long)len); if (rsa == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB); return 0; } - int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); RSA_free(rsa); return ret; } int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { if (pkey == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER); return 0; } return ssl_set_pkey(ctx->cert, pkey); } +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, reason_code); + goto end; + } + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + +end: + BIO_free(in); + return ret; +} + int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *d, long len) { int ret; @@ -296,7 +562,7 @@ int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *d, p = d; pkey = d2i_PrivateKey(type, NULL, &p, (long)len); if (pkey == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_ASN1, ERR_R_ASN1_LIB); return 0; } @@ -305,74 +571,76 @@ int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *d, return ret; } -void SSL_set_private_key_method(SSL *ssl, - const SSL_PRIVATE_KEY_METHOD *key_method) { - ssl->cert->key_method = key_method; -} - -int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids, - size_t num_digests) { - OPENSSL_free(ssl->cert->digest_nids); - - ssl->cert->num_digest_nids = 0; - ssl->cert->digest_nids = BUF_memdup(digest_nids, num_digests*sizeof(int)); - if (ssl->cert->digest_nids == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); - return 0; - } - ssl->cert->num_digest_nids = num_digests; - return 1; -} +/* Read a file that contains our certificate in "PEM" format, possibly followed + * by a sequence of CA certificates that should be sent to the peer in the + * Certificate message. */ +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) { + BIO *in; + int ret = 0; + X509 *x = NULL; -int ssl_has_private_key(SSL *ssl) { - return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL; -} + ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ -int ssl_private_key_type(SSL *ssl) { - if (ssl->cert->key_method != NULL) { - return ssl->cert->key_method->type(ssl); + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_BUF_LIB); + goto end; } - return EVP_PKEY_id(ssl->cert->privatekey); -} -size_t ssl_private_key_max_signature_len(SSL *ssl) { - if (ssl->cert->key_method != NULL) { - return ssl->cert->key_method->max_signature_len(ssl); + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_SYS_LIB); + goto end; } - return EVP_PKEY_size(ssl->cert->privatekey); -} -enum ssl_private_key_result_t ssl_private_key_sign( - SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, const EVP_MD *md, - const uint8_t *in, size_t in_len) { - if (ssl->cert->key_method != NULL) { - return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, in, - in_len); + x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_PEM_LIB); + goto end; } - enum ssl_private_key_result_t ret = ssl_private_key_failure; - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL); - if (ctx == NULL) { - goto end; + ret = SSL_CTX_use_certificate(ctx, x); + + if (ERR_peek_error() != 0) { + ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */ } - size_t len = max_out; - if (!EVP_PKEY_sign_init(ctx) || - !EVP_PKEY_CTX_set_signature_md(ctx, md) || - !EVP_PKEY_sign(ctx, out, &len, in, in_len)) { - goto end; + if (ret) { + /* If we could set up our certificate, now proceed to the CA + * certificates. */ + X509 *ca; + int r; + uint32_t err; + + SSL_CTX_clear_chain_certs(ctx); + + while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata)) != + NULL) { + r = SSL_CTX_add0_chain_cert(ctx, ca); + if (!r) { + X509_free(ca); + ret = 0; + goto end; + } + /* Note that we must not free r if it was successfully added to the chain + * (while we must free the main certificate, since its reference count is + * increased by SSL_CTX_use_certificate). */ + } + + /* When the while loop ends, it's usually just EOF. */ + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_PEM && + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { + ERR_clear_error(); + } else { + ret = 0; /* some real error */ + } } - *out_len = len; - ret = ssl_private_key_success; end: - EVP_PKEY_CTX_free(ctx); + X509_free(x); + BIO_free(in); return ret; } - -enum ssl_private_key_result_t ssl_private_key_sign_complete( - SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) { - /* Only custom keys may be asynchronous. */ - return ssl->cert->key_method->sign_complete(ssl, out, out_len, max_out); -} |