diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 53aa9b453..87309c3e1 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -138,6 +138,25 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE.
  */
+/* ====================================================================
+ * 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.
+ */
 
 #ifndef OPENSSL_HEADER_SSL_H
 #define OPENSSL_HEADER_SSL_H
@@ -1136,6 +1155,16 @@ OPENSSL_EXPORT 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);
 
+// SSL_CTX_set_nullchain_and_key sets the private key for a
+// TLS client or server. Reference to the given |EVP_PKEY|
+// object is added as needed. Exactly one of |privkey| or |privkey_method|
+// may be non-NULL. Returns one on success and zero on error.
+// Note the lack of a corresponding public-key certificate.
+// See SSL_CTX_set_server_raw_public_key_certificate.
+OPENSSL_EXPORT int SSL_CTX_set_nullchain_and_key(
+    SSL_CTX *ctx,
+    EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method);
+
 // SSL_set_chain_and_key sets the certificate chain and private key for a TLS
 // client or server. References to the given |CRYPTO_BUFFER| and |EVP_PKEY|
 // objects are added as needed. Exactly one of |privkey| or |privkey_method|
@@ -1144,6 +1173,16 @@ OPENSSL_EXPORT int SSL_set_chain_and_key(
     SSL *ssl, CRYPTO_BUFFER *const *certs, size_t num_certs, EVP_PKEY *privkey,
     const SSL_PRIVATE_KEY_METHOD *privkey_method);
 
+// SSL_set_nullchain_and_key sets the private key for a TLS
+// client or server. Reference to the given |EVP_PKEY|
+// object is added as needed. Exactly one of |privkey| or |privkey_method|
+// may be non-NULL. Returns one on success and zero on error.
+// Note the lack of a corresponding public-key certificate.
+// See SSL_set_server_raw_public_key_certificate.
+OPENSSL_EXPORT int SSL_set_nullchain_and_key(
+    SSL *ssl, EVP_PKEY *privkey,
+    const SSL_PRIVATE_KEY_METHOD *privkey_method);
+
 // SSL_CTX_get0_chain returns the list of |CRYPTO_BUFFER|s that were set by
 // |SSL_CTX_set_chain_and_key|. Reference counts are not incremented by this
 // call. The return value may be |NULL| if no chain has been set.
@@ -3023,6 +3062,21 @@ OPENSSL_EXPORT void SSL_get0_peer_application_settings(const SSL *ssl,
 OPENSSL_EXPORT int SSL_has_application_settings(const SSL *ssl);
 
 
+// Server Certificate Type.
+
+#define TLSEXT_CERTIFICATETYPE_X509 0
+#define TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY 2
+
+OPENSSL_EXPORT int SSL_CTX_set_server_raw_public_key_certificate(
+    SSL_CTX *ctx, const uint8_t *raw_public_key, unsigned raw_public_key_len);
+
+OPENSSL_EXPORT int SSL_CTX_has_server_raw_public_key_certificate(SSL_CTX *ctx);
+
+OPENSSL_EXPORT int SSL_set_server_raw_public_key_certificate(
+    SSL *ssl, const uint8_t *raw_public_key, unsigned raw_public_key_len);
+
+OPENSSL_EXPORT int SSL_has_server_raw_public_key_certificate(SSL *ssl);
+
 // Certificate compression.
 //
 // Certificates in TLS 1.3 can be compressed (RFC 8879). BoringSSL supports this
diff --git a/src/include/openssl/tls1.h b/src/include/openssl/tls1.h
index 772fb87a3..be605c1aa 100644
--- a/src/include/openssl/tls1.h
+++ b/src/include/openssl/tls1.h
@@ -146,6 +146,25 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE.
  */
+/* ====================================================================
+ * 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.
+ */
 
 #ifndef OPENSSL_HEADER_TLS1_H
 #define OPENSSL_HEADER_TLS1_H
@@ -197,6 +216,9 @@ extern "C" {
 // ExtensionType value from RFC 7301
 #define TLSEXT_TYPE_application_layer_protocol_negotiation 16
 
+// ExtensionType value from RFC 7250
+#define TLSEXT_TYPE_server_certificate_type 20
+
 // ExtensionType value from RFC 7685
 #define TLSEXT_TYPE_padding 21
 
diff --git a/src/ssl/extensions.cc b/src/ssl/extensions.cc
index 5ee280221..2692e5478 100644
--- a/src/ssl/extensions.cc
+++ b/src/ssl/extensions.cc
@@ -105,6 +105,25 @@
  * This product includes cryptographic software written by Eric Young
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
+/* ====================================================================
+ * 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 <openssl/ssl.h>
 
@@ -3094,6 +3113,146 @@ bool ssl_negotiate_alps(SSL_HANDSHAKE *hs, uint8_t *out_alert,
   return true;
 }
 
+// Server Certificate Type
+
+static bool ext_server_certificate_type_add_clienthello(const SSL_HANDSHAKE *hs,
+                                                        CBB *out,
+                                                        CBB *out_compressible,
+                                                        ssl_client_hello_type_t type) {
+
+  if (hs->max_version <= TLS1_2_VERSION) {
+    return true;
+  }
+
+  if (hs->config->server_certificate_type_list.empty()) {
+    return true;
+  }
+
+  CBB contents, server_certificate_types;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_server_certificate_type) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u8_length_prefixed(&contents, &server_certificate_types) ||
+      !CBB_add_bytes(&server_certificate_types,
+                     hs->config->server_certificate_type_list.data(),
+                     hs->config->server_certificate_type_list.size()) ||
+      !CBB_flush(out)) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool ssl_is_certificate_type_allowed(CBS *certificate_type_list,
+                                            uint8_t certificate_type)
+{
+  uint8_t supported_certificate_type;
+  while (CBS_len(certificate_type_list) > 0) {
+    if (!CBS_get_u8(certificate_type_list,
+                    &supported_certificate_type)) {
+      break;
+    }
+
+    if (supported_certificate_type != certificate_type) {
+      continue;
+    }
+
+    return true;
+  }
+
+  return false;
+}
+
+static bool ext_server_certificate_type_parse_serverhello(SSL_HANDSHAKE *hs,
+                                                          uint8_t *out_alert,
+                                                          CBS *content)
+{
+  if (hs->max_version <= TLS1_2_VERSION ||
+      hs->config->server_certificate_type_list.empty()) {
+    return true;
+  }
+
+  // Strict
+  if (!content) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return false;
+  }
+
+  CBS certificate_type_list =
+    MakeConstSpan(hs->config->server_certificate_type_list);
+
+  uint8_t certificate_type;
+  if (CBS_get_u8(content, &certificate_type) &&
+      ssl_is_certificate_type_allowed(&certificate_type_list,
+                                      certificate_type)) {
+    hs->server_certificate_type = certificate_type;
+    hs->server_certificate_type_negotiated = 1;
+    return true;
+  }
+
+  OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+  *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+  return false;
+}
+
+static bool ext_server_certificate_type_parse_clienthello(SSL_HANDSHAKE *hs,
+                                                          uint8_t *out_alert,
+                                                          CBS *content)
+{
+  if (!content) {
+    return true;
+  }
+
+  if (hs->max_version <= TLS1_2_VERSION ||
+      hs->config->server_certificate_type_list.empty()) {
+    return true;
+  }
+
+  CBS certificate_type_list =
+    MakeConstSpan(hs->config->server_certificate_type_list);
+
+  CBS type_list;
+  if (!CBS_get_u8_length_prefixed(content, &type_list)) {
+    type_list.len = 0;
+  }
+
+  uint8_t type;
+  while(CBS_len(&type_list) > 0) {
+    if (!CBS_get_u8(&type_list, &type)) {
+      break;
+    }
+
+    if (!ssl_is_certificate_type_allowed(&certificate_type_list, type)) {
+      continue;
+    }
+
+    hs->server_certificate_type = type;
+    hs->server_certificate_type_negotiated = 1;
+    return true;
+  }
+
+  *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+  return false;
+}
+
+static bool ext_server_certificate_type_add_serverhello(SSL_HANDSHAKE *hs,
+                                                        CBB *out)
+{
+  if (!hs->server_certificate_type_negotiated) {
+    return true;
+  }
+
+  CBB contents;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_server_certificate_type) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u8(&contents, hs->server_certificate_type) ||
+      !CBB_flush(out)) {
+     return false;
+  }
+
+  return true;
+}
+
 // kExtensions contains all the supported extensions.
 static const struct tls_extension kExtensions[] = {
   {
@@ -3267,6 +3426,13 @@ static const struct tls_extension kExtensions[] = {
     ignore_parse_clienthello,
     ext_alps_add_serverhello,
   },
+  {
+    TLSEXT_TYPE_server_certificate_type,
+    ext_server_certificate_type_add_clienthello,
+    ext_server_certificate_type_parse_serverhello,
+    ext_server_certificate_type_parse_clienthello,
+    ext_server_certificate_type_add_serverhello,
+  },
 };
 
 #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
diff --git a/src/ssl/handshake.cc b/src/ssl/handshake.cc
index 8d5a23872..b9ac70dfe 100644
--- a/src/ssl/handshake.cc
+++ b/src/ssl/handshake.cc
@@ -109,6 +109,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 <openssl/ssl.h>
 
@@ -150,6 +169,7 @@ SSL_HANDSHAKE::SSL_HANDSHAKE(SSL *ssl_arg)
       cert_compression_negotiated(false),
       apply_jdk11_workaround(false),
       can_release_private_key(false),
+      server_certificate_type_negotiated(false),
       channel_id_negotiated(false) {
   assert(ssl);
 
@@ -365,7 +385,21 @@ enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs) {
 
   uint8_t alert = SSL_AD_CERTIFICATE_UNKNOWN;
   enum ssl_verify_result_t ret;
-  if (hs->config->custom_verify_callback != nullptr) {
+  if (hs->server_certificate_type_negotiated &&
+      hs->server_certificate_type == TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY) {
+    ret = ssl_verify_invalid;
+    EVP_PKEY *peer_pubkey = hs->peer_pubkey.get();
+    CBS spki = MakeConstSpan(ssl->config->server_raw_public_key_certificate);
+    EVP_PKEY *pubkey = EVP_parse_public_key(&spki);
+    if (!pubkey) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      alert = SSL_AD_INTERNAL_ERROR;
+    } else if (EVP_PKEY_cmp(peer_pubkey, pubkey) == 1 /* Equal */) {
+      ret = ssl_verify_ok;
+    } else {
+      alert = SSL_AD_BAD_CERTIFICATE;
+    }
+  } else if (hs->config->custom_verify_callback != nullptr) {
     ret = hs->config->custom_verify_callback(ssl, &alert);
     switch (ret) {
       case ssl_verify_ok:
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 1e6da2153..f04888384 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -138,6 +138,25 @@
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE.
  */
+/* ====================================================================
+ * 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.
+ */
 
 #ifndef OPENSSL_HEADER_SSL_INTERNAL_H
 #define OPENSSL_HEADER_SSL_INTERNAL_H
@@ -1286,6 +1305,8 @@ int ssl_write_buffer_flush(SSL *ssl);
 // configured.
 bool ssl_has_certificate(const SSL_HANDSHAKE *hs);
 
+bool ssl_has_raw_public_key_certificate(const SSL_HANDSHAKE *hs);
+
 // ssl_parse_cert_chain parses a certificate list from |cbs| in the format used
 // by a TLS Certificate message. On success, it advances |cbs| and returns
 // true. Otherwise, it returns false and sets |*out_alert| to an alert to send
@@ -1887,6 +1908,8 @@ struct SSL_HANDSHAKE {
   // |cert_compression_negotiated| is true.
   uint16_t cert_compression_alg_id;
 
+  uint8_t server_certificate_type;
+
   // ech_hpke_ctx is the HPKE context used in ECH. On the server, it is
   // initialized if |ech_status| is |ssl_ech_accepted|. On the client, it is
   // initialized if |selected_ech_config| is not nullptr.
@@ -2037,6 +2060,8 @@ struct SSL_HANDSHAKE {
   // cert_compression_negotiated is true iff |cert_compression_alg_id| is valid.
   bool cert_compression_negotiated : 1;
 
+  bool server_certificate_type_negotiated : 1;
+
   // apply_jdk11_workaround is true if the peer is probably a JDK 11 client
   // which implemented TLS 1.3 incorrectly.
   bool apply_jdk11_workaround : 1;
@@ -3049,6 +3074,9 @@ struct SSL_CONFIG {
   // along with their corresponding ALPS values.
   GrowableArray<ALPSConfig> alps_configs;
 
+  Array<uint8_t> server_certificate_type_list;
+  Array<uint8_t> server_raw_public_key_certificate;
+
   // Contains the QUIC transport params that this endpoint will send.
   Array<uint8_t> quic_transport_params;
 
@@ -3648,6 +3676,9 @@ struct ssl_ctx_st {
   // format.
   bssl::Array<uint8_t> alpn_client_proto_list;
 
+  bssl::Array<uint8_t> server_certificate_type_list;
+  bssl::Array<uint8_t> server_raw_public_key_certificate;
+
   // SRTP profiles we are willing to do from RFC 5764
   bssl::UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> srtp_profiles;
 
diff --git a/src/ssl/ssl_cert.cc b/src/ssl/ssl_cert.cc
index aa46a8bb6..d90840fce 100644
--- a/src/ssl/ssl_cert.cc
+++ b/src/ssl/ssl_cert.cc
@@ -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 <openssl/ssl.h>
 
@@ -302,6 +321,25 @@ static int cert_set_chain_and_key(
   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<CRYPTO_BUFFER> buffer) {
   switch (check_leaf_cert_and_privkey(buffer.get(), cert->privatekey.get())) {
     case leaf_cert_and_privkey_error:
@@ -343,6 +381,12 @@ bool ssl_has_certificate(const SSL_HANDSHAKE *hs) {
          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<STACK_OF(CRYPTO_BUFFER)> *out_chain,
                           UniquePtr<EVP_PKEY> *out_pubkey,
@@ -721,11 +765,20 @@ bool ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey,
 
 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_PKEY>(EVP_parse_public_key(&spki));
+    return hs->local_pubkey != NULL;
+  }
+
   if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(hs)) {
     return false;
   }
@@ -880,6 +933,15 @@ int SSL_set_chain_and_key(SSL *ssl, CRYPTO_BUFFER *const *certs,
                                 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) {
@@ -887,6 +949,12 @@ int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs,
                                 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();
 }
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 838761af5..e4f1a12b7 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -137,6 +137,25 @@
  * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
  * OTHERWISE. */
+/* ====================================================================
+ * 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 <openssl/ssl.h>
 
@@ -687,6 +706,11 @@ SSL *SSL_new(SSL_CTX *ctx) {
   ssl->config->handoff = ctx->handoff;
   ssl->quic_method = ctx->quic_method;
 
+  ssl->config->server_certificate_type_list.CopyFrom(
+    ctx->server_certificate_type_list);
+  ssl->config->server_raw_public_key_certificate.CopyFrom(
+    ctx->server_raw_public_key_certificate);
+
   if (!ssl->method->ssl_new(ssl.get()) ||
       !ssl->ctx->x509_method->ssl_new(ssl->s3->hs.get())) {
     return nullptr;
@@ -3140,6 +3164,53 @@ int SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg) {
   return 1;
 }
 
+int SSL_CTX_set_server_raw_public_key_certificate(SSL_CTX *ctx,
+  const uint8_t *raw_public_key, unsigned raw_public_key_len) {
+  if (!ctx->server_raw_public_key_certificate.CopyFrom(
+    MakeConstSpan(raw_public_key, raw_public_key_len))) {
+    return 0; /* Failure */
+  }
+
+  if (!ctx->server_certificate_type_list.Init(1)) {
+    return 0;
+  }
+  ctx->server_certificate_type_list[0] = TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY;
+
+  return 1; /* Success */
+}
+
+int SSL_CTX_has_server_raw_public_key_certificate(SSL_CTX *ctx) {
+  return !ctx->server_raw_public_key_certificate.empty();
+}
+
+int SSL_set_server_raw_public_key_certificate(SSL *ssl,
+  const uint8_t *raw_public_key, unsigned raw_public_key_len) {
+  if (!ssl->config) {
+    return 0; /* Failure */
+  }
+
+  if (!ssl->config->server_raw_public_key_certificate.CopyFrom(
+    MakeConstSpan(raw_public_key, raw_public_key_len))) {
+    return 0;
+  }
+
+  if (!ssl->config->server_certificate_type_list.Init(1)) {
+    return 0;
+  }
+  ssl->config->server_certificate_type_list[0] =
+    TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY;
+
+  return 1; /* Success */
+}
+
+int SSL_has_server_raw_public_key_certificate(SSL *ssl) {
+  if (!ssl->config) {
+    return 0; /* Failure */
+  }
+
+  return !ssl->config->server_raw_public_key_certificate.empty();
+}
+
 namespace fips202205 {
 
 // (References are to SP 800-52r2):
diff --git a/src/ssl/tls13_both.cc b/src/ssl/tls13_both.cc
index 5ab5a1c93..79135613e 100644
--- a/src/ssl/tls13_both.cc
+++ b/src/ssl/tls13_both.cc
@@ -11,6 +11,25 @@
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+/* ====================================================================
+ * 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 <openssl/ssl.h>
 
@@ -197,7 +216,16 @@ bool tls13_process_certificate(SSL_HANDSHAKE *hs, const SSLMessage &msg,
       return false;
     }
 
-    if (sk_CRYPTO_BUFFER_num(certs.get()) == 0) {
+    if (hs->server_certificate_type_negotiated &&
+        hs->server_certificate_type == TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY) {
+      pkey = UniquePtr<EVP_PKEY>(EVP_parse_public_key(&certificate));
+      if (!pkey) {
+        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+        OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+        return false;
+      }
+    }
+    else if (sk_CRYPTO_BUFFER_num(certs.get()) == 0) {
       pkey = ssl_cert_parse_pubkey(&certificate);
       if (!pkey) {
         ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
@@ -299,7 +327,10 @@ bool tls13_process_certificate(SSL_HANDSHAKE *hs, const SSLMessage &msg,
   }
 
   if (sk_CRYPTO_BUFFER_num(hs->new_session->certs.get()) == 0) {
-    if (!allow_anonymous) {
+    if (!allow_anonymous &&
+        !(hs->server_certificate_type_negotiated &&
+         hs->server_certificate_type ==
+           TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED);
       return false;
@@ -416,6 +447,20 @@ bool tls13_add_certificate(SSL_HANDSHAKE *hs) {
     return false;
   }
 
+  if (hs->server_certificate_type_negotiated &&
+      hs->server_certificate_type == TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY) {
+    CBB leaf, extensions;
+    if (!CBB_add_u24_length_prefixed(&certificate_list, &leaf) ||
+        !CBB_add_bytes(&leaf,
+                       ssl->config->server_raw_public_key_certificate.data(),
+                       ssl->config->server_raw_public_key_certificate.size()) ||
+        !CBB_add_u16_length_prefixed(&certificate_list, &extensions)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return false;
+    }
+    return ssl_add_message_cbb(ssl, cbb.get());
+  }
+
   if (!ssl_has_certificate(hs)) {
     return ssl_add_message_cbb(ssl, cbb.get());
   }
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 9d26f4e00..a92689761 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -11,6 +11,25 @@
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+/* ====================================================================
+ * 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 <openssl/ssl.h>
 
@@ -860,7 +879,8 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
 
   // Send the server Certificate message, if necessary.
   if (!ssl->s3->session_reused) {
-    if (!ssl_has_certificate(hs)) {
+    if (!ssl_has_certificate(hs) &&
+        !ssl_has_raw_public_key_certificate(hs)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
       return ssl_hs_error;
     }
