--- google_boringssl/ssl/ssl_cert.cc 2021-02-03 18:29:04.000000000 -0800 +++ boringssl/ssl/ssl_cert.cc 2021-02-03 20:24:49.000000000 -0800 @@ -111,6 +111,25 @@ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * ECC cipher suite support in OpenSSL originally developed by * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ +/* ==================================================================== + * Copyright 2020 Apple Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the “Software”), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ #include @@ -302,6 +321,25 @@ return 1; } +static int cert_set_key( + CERT *cert, + EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method) { + if (privkey == NULL && privkey_method == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (privkey != NULL && privkey_method != NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD); + return 0; + } + + cert->privatekey = UpRef(privkey); + cert->key_method = privkey_method; + + return 1; +} + bool ssl_set_cert(CERT *cert, UniquePtr buffer) { switch (check_leaf_cert_and_privkey(buffer.get(), cert->privatekey.get())) { case leaf_cert_and_privkey_error: @@ -343,6 +381,12 @@ ssl_has_private_key(hs); } +bool ssl_has_raw_public_key_certificate(const SSL_HANDSHAKE *hs) { + return hs->server_certificate_type_negotiated && + hs->server_certificate_type == TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY && + ssl_has_private_key(hs); +} + bool ssl_parse_cert_chain(uint8_t *out_alert, UniquePtr *out_chain, UniquePtr *out_pubkey, @@ -727,11 +771,20 @@ bool ssl_on_certificate_selected(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - if (!ssl_has_certificate(hs)) { + if (!ssl_has_certificate(hs) && + !ssl_has_raw_public_key_certificate(hs)) { // Nothing to do. return true; } + if (ssl_has_raw_public_key_certificate(hs)) { + CBS spki = MakeConstSpan( + ssl->config->server_raw_public_key_certificate.data(), + ssl->config->server_raw_public_key_certificate.size()); + hs->local_pubkey = UniquePtr(EVP_parse_public_key(&spki)); + return hs->local_pubkey != NULL; + } + if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(hs)) { return false; } @@ -886,6 +939,15 @@ privkey, privkey_method); } +int SSL_set_nullchain_and_key(SSL *ssl, + EVP_PKEY *privkey, + const SSL_PRIVATE_KEY_METHOD *privkey_method) { + if (!ssl->config) { + return 0; + } + return cert_set_key(ssl->config->cert.get(), privkey, privkey_method); +} + int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs, size_t num_certs, EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method) { @@ -893,6 +955,12 @@ privkey_method); } +int SSL_CTX_set_nullchain_and_key(SSL_CTX *ctx, + EVP_PKEY *privkey, + const SSL_PRIVATE_KEY_METHOD *privkey_method) { + return cert_set_key(ctx->cert.get(), privkey, privkey_method); +} + const STACK_OF(CRYPTO_BUFFER)* SSL_CTX_get0_chain(const SSL_CTX *ctx) { return ctx->cert->chain.get(); }