Fold away certificate slots mechanism.

This allows us to remove the confusing EVP_PKEY argument to the
SSL_PRIVATE_KEY_METHOD wrapper functions. It also simplifies some of the
book-keeping around the CERT structure, as well as the API for
configuring certificates themselves. The current one is a little odd as
some functions automatically route to the slot while others affect the
most recently touched slot. Others still (extra_certs) apply to all
slots, making them not terribly useful.

Consumers with complex needs should use cert_cb or the early callback
(select_certificate_cb) to configure whatever they like based on the
ClientHello.

BUG=486295

Change-Id: Ice29ffeb867fa4959898b70dfc50fc00137f01f3
Reviewed-on: https://boringssl-review.googlesource.com/5351
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/internal.h b/ssl/internal.h
index 838fce7..327f52b 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -254,17 +254,12 @@
                        STACK_OF(SSL_CIPHER) **out_cipher_list_by_id,
                        const char *rule_str);
 
-/* SSL_PKEY_* denote certificate types. */
-#define SSL_PKEY_RSA 0
-#define SSL_PKEY_ECC 1
-#define SSL_PKEY_NUM 2
-
 /* ssl_cipher_get_value returns the cipher suite id of |cipher|. */
 uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher);
 
-/* ssl_cipher_get_cert_index returns the |SSL_PKEY_*| value corresponding to the
- * certificate type of |cipher| or -1 if there is none. */
-int ssl_cipher_get_cert_index(const SSL_CIPHER *cipher);
+/* ssl_cipher_get_key_type returns the |EVP_PKEY_*| value corresponding to the
+ * server key used in |cipher| or |EVP_PKEY_NONE| if there is none. */
+int ssl_cipher_get_key_type(const SSL_CIPHER *cipher);
 
 /* ssl_cipher_has_server_public_key returns 1 if |cipher| involves a server
  * public key in the key exchange, sent in a server Certificate message.
@@ -353,21 +348,17 @@
 
 /* ssl_private_key_* call the corresponding function on the
  * |SSL_PRIVATE_KEY_METHOD| for |ssl|, if configured. Otherwise, they implement
- * the operation on |pkey|.
- *
- * TODO(davidben): The |EVP_PKEY| must be passed in to due to the multiple
- * certificate slots feature. Remove it. */
+ * the operation with |EVP_PKEY|. */
 
-int ssl_private_key_type(SSL *ssl, const EVP_PKEY *pkey);
+int ssl_private_key_type(SSL *ssl);
 
-int ssl_private_key_supports_digest(SSL *ssl, const EVP_PKEY *pkey,
-                                    const EVP_MD *md);
+int ssl_private_key_supports_digest(SSL *ssl, const EVP_MD *md);
 
-size_t ssl_private_key_max_signature_len(SSL *ssl, const EVP_PKEY *pkey);
+size_t ssl_private_key_max_signature_len(SSL *ssl);
 
 enum ssl_private_key_result_t ssl_private_key_sign(
-    SSL *ssl, EVP_PKEY *pkey, uint8_t *out, size_t *out_len, size_t max_out,
-    const EVP_MD *md, const uint8_t *in, size_t in_len);
+    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);
 
 enum ssl_private_key_result_t ssl_private_key_sign_complete(
     SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out);
@@ -516,13 +507,6 @@
   ssl_hash_message,
 };
 
-typedef struct cert_pkey_st {
-  X509 *x509;
-  EVP_PKEY *privatekey;
-  /* Chain for this certificate */
-  STACK_OF(X509) *chain;
-} CERT_PKEY;
-
 /* Structure containing decoded values of signature algorithms extension */
 typedef struct tls_sigalgs_st {
   uint8_t rsign;
@@ -530,10 +514,10 @@
 } TLS_SIGALGS;
 
 typedef struct cert_st {
-  /* Current active set */
-  CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array
-                   * Probably it would make more sense to store
-                   * an index, not a pointer. */
+  X509 *x509;
+  EVP_PKEY *privatekey;
+  /* Chain for this certificate */
+  STACK_OF(X509) *chain;
 
   /* key_method, if non-NULL, is a set of callbacks to call for private key
    * operations. */
@@ -562,7 +546,6 @@
    * keys. If NULL, a curve is selected automatically. See
    * |SSL_CTX_set_tmp_ecdh_callback|. */
   EC_KEY *(*ecdh_tmp_cb)(SSL *ssl, int is_export, int keysize);
-  CERT_PKEY pkeys[SSL_PKEY_NUM];
 
   /* Server-only: client_certificate_types is list of certificate types to
    * include in the CertificateRequest message.
@@ -845,21 +828,18 @@
     STACK_OF(SSL_CIPHER) *ciphers);
 struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *s);
 
-int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain);
-int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain);
-int ssl_cert_add0_chain_cert(CERT *c, X509 *x);
-int ssl_cert_add1_chain_cert(CERT *c, X509 *x);
-int ssl_cert_select_current(CERT *c, X509 *x);
-void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg);
+int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain);
+int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain);
+int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509);
+int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509);
+void ssl_cert_set_cert_cb(CERT *cert,
+                          int (*cb)(SSL *ssl, void *arg), void *arg);
 
 int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk);
-int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l);
+int ssl_add_cert_chain(SSL *s, unsigned long *l);
 int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags);
 int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref);
-CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
-EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *c);
 void ssl_update_cache(SSL *s, int mode);
-int ssl_cert_type(EVP_PKEY *pkey);
 
 /* ssl_get_compatible_server_ciphers determines the key exchange and
  * authentication cipher suite masks compatible with the server configuration
@@ -918,7 +898,7 @@
 int ssl3_cert_verify_mac(SSL *s, int md_nid, uint8_t *p);
 int ssl3_finish_mac(SSL *s, const uint8_t *buf, int len);
 void ssl3_free_digest_list(SSL *s);
-int ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk);
+int ssl3_output_cert_chain(SSL *s);
 const SSL_CIPHER *ssl3_choose_cipher(
     SSL *ssl, STACK_OF(SSL_CIPHER) *clnt,
     struct ssl_cipher_preference_list_st *srvr);
@@ -1112,8 +1092,10 @@
                        size_t ticket_len, const uint8_t *session_id,
                        size_t session_id_len);
 
-int tls12_get_sigandhash(SSL *ssl, uint8_t *p, const EVP_PKEY *pk,
-                         const EVP_MD *md);
+/* tls12_get_sigandhash assembles the SignatureAndHashAlgorithm corresponding to
+ * |ssl|'s private key and |md|. The two-byte value is written to |p|. It
+ * returns one on success and zero on failure. */
+int tls12_get_sigandhash(SSL *ssl, uint8_t *p, const EVP_MD *md);
 int tls12_get_sigid(int pkey_type);
 const EVP_MD *tls12_get_hash(uint8_t hash_alg);
 
@@ -1178,9 +1160,9 @@
 uint32_t ssl_get_algorithm2(SSL *s);
 int tls1_process_sigalgs(SSL *s, const CBS *sigalgs);
 
-/* tls1_choose_signing_digest returns a digest for use with |pkey| based on the
- * peer's preferences recorded for |s| and the digests supported by |pkey|. */
-const EVP_MD *tls1_choose_signing_digest(SSL *s, EVP_PKEY *pkey);
+/* tls1_choose_signing_digest returns a digest for use with |ssl|'s private key
+ * based on the peer's preferences the digests supported. */
+const EVP_MD *tls1_choose_signing_digest(SSL *ssl);
 
 size_t tls12_get_psigalgs(SSL *s, const uint8_t **psigs);
 int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, SSL *s,
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 4bbf1c2..017bda4 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -301,17 +301,11 @@
   return ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
 }
 
-int ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk) {
+int ssl3_output_cert_chain(SSL *s) {
   uint8_t *p;
   unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s);
 
-  if (cpk == NULL) {
-    /* TLSv1 sends a chain with nothing in it, instead of an alert. */
-    if (!BUF_MEM_grow_clean(s->init_buf, l)) {
-      OPENSSL_PUT_ERROR(SSL, ssl3_output_cert_chain, ERR_R_BUF_LIB);
-      return 0;
-    }
-  } else if (!ssl_add_cert_chain(s, cpk, &l)) {
+  if (!ssl_add_cert_chain(s, &l)) {
     return 0;
   }
 
@@ -502,17 +496,6 @@
   return 1;
 }
 
-int ssl_cert_type(EVP_PKEY *pkey) {
-  switch (pkey->type) {
-    case EVP_PKEY_RSA:
-      return SSL_PKEY_RSA;
-    case EVP_PKEY_EC:
-      return SSL_PKEY_ECC;
-    default:
-      return -1;
-  }
-}
-
 int ssl_verify_alarm_type(long type) {
   int al;
 
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 40df103..d004f2b 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -930,15 +930,9 @@
   }
 
   /* Check the certificate's type matches the cipher. */
-  int cert_type = ssl_cert_type(pkey);
-  if (cert_type < 0) {
-    OPENSSL_PUT_ERROR(SSL, ssl3_check_certificate_for_cipher,
-                      SSL_R_UNKNOWN_CERTIFICATE_TYPE);
-    goto err;
-  }
-  int expected_type = ssl_cipher_get_cert_index(cipher);
-  assert(expected_type >= 0);
-  if (cert_type != expected_type) {
+  int expected_type = ssl_cipher_get_key_type(cipher);
+  assert(expected_type != EVP_PKEY_NONE);
+  if (pkey->type != expected_type) {
     OPENSSL_PUT_ERROR(SSL, ssl3_check_certificate_for_cipher,
                       SSL_R_WRONG_CERTIFICATE_TYPE);
     goto err;
@@ -2020,8 +2014,7 @@
     uint8_t *p = ssl_handshake_start(s);
     size_t signature_length = 0;
     unsigned long n = 0;
-    EVP_PKEY *pkey = s->cert->key->privatekey;
-    assert(pkey != NULL || s->cert->key_method != NULL);
+    assert(s->cert->privatekey != NULL || s->cert->key_method != NULL);
 
     if (s->state == SSL3_ST_CW_CERT_VRFY_A) {
       uint8_t *buf = (uint8_t *)s->init_buf->data;
@@ -2031,8 +2024,8 @@
 
       /* Write out the digest type if need be. */
       if (SSL_USE_SIGALGS(s)) {
-        md = tls1_choose_signing_digest(s, pkey);
-        if (!tls12_get_sigandhash(s, p, pkey, md)) {
+        md = tls1_choose_signing_digest(s);
+        if (!tls12_get_sigandhash(s, p, md)) {
           OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_INTERNAL_ERROR);
           return -1;
         }
@@ -2041,7 +2034,7 @@
       }
 
       /* Compute the digest. */
-      const int pkey_type = ssl_private_key_type(s, pkey);
+      const int pkey_type = ssl_private_key_type(s);
       if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey_type)) {
         return -1;
       }
@@ -2053,7 +2046,7 @@
       }
 
       /* Sign the digest. */
-      signature_length = ssl_private_key_max_signature_len(s, pkey);
+      signature_length = ssl_private_key_max_signature_len(s);
       if (p + 2 + signature_length > buf + SSL3_RT_MAX_PLAIN_LENGTH) {
         OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify,
                           SSL_R_DATA_LENGTH_TOO_LONG);
@@ -2061,7 +2054,7 @@
       }
 
       s->rwstate = SSL_PRIVATE_KEY_OPERATION;
-      sign_result = ssl_private_key_sign(s, pkey, &p[2], &signature_length,
+      sign_result = ssl_private_key_sign(s, &p[2], &signature_length,
                                          signature_length, md, digest,
                                          digest_length);
     } else {
@@ -2070,7 +2063,7 @@
         p += 2;
         n += 2;
       }
-      signature_length = ssl_private_key_max_signature_len(s, pkey);
+      signature_length = ssl_private_key_max_signature_len(s);
       s->rwstate = SSL_PRIVATE_KEY_OPERATION;
       sign_result = ssl_private_key_sign_complete(s, &p[2], &signature_length,
                                                   signature_length);
@@ -2098,9 +2091,9 @@
 
 /* ssl3_has_client_certificate returns true if a client certificate is
  * configured. */
-static int ssl3_has_client_certificate(SSL *s) {
-  return s->cert && s->cert->key->x509 && (s->cert->key->privatekey ||
-                                           s->cert->key_method);
+static int ssl3_has_client_certificate(SSL *ssl) {
+  return ssl->cert && ssl->cert->x509 && (ssl->cert->privatekey ||
+                                          ssl->cert->key_method);
 }
 
 int ssl3_send_client_certificate(SSL *s) {
@@ -2179,8 +2172,14 @@
   }
 
   if (s->state == SSL3_ST_CW_CERT_C) {
-    CERT_PKEY *cert_pkey = (s->s3->tmp.cert_req == 2) ? NULL : s->cert->key;
-    if (!ssl3_output_cert_chain(s, cert_pkey)) {
+    if (s->s3->tmp.cert_req == 2) {
+      /* Send an empty Certificate message. */
+      uint8_t *p = ssl_handshake_start(s);
+      l2n3(0, p);
+      if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, 3)) {
+        return -1;
+      }
+    } else if (!ssl3_output_cert_chain(s)) {
       return -1;
     }
     s->state = SSL3_ST_CW_CERT_D;
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 0f685e7..c4e0704 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -390,12 +390,12 @@
       }
 
     case SSL_CTRL_GET_CHAIN_CERTS:
-      *(STACK_OF(X509) **)parg = s->cert->key->chain;
+      *(STACK_OF(X509) **)parg = s->cert->chain;
       ret = 1;
       break;
 
     case SSL_CTRL_SELECT_CURRENT_CERT:
-      return ssl_cert_select_current(s->cert, (X509 *)parg);
+      return 1;
 
     case SSL_CTRL_GET_CURVES: {
       const uint16_t *clist = s->s3->tmp.peer_ellipticcurvelist;
@@ -493,26 +493,16 @@
       return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg);
 
     case SSL_CTRL_EXTRA_CHAIN_CERT:
-      if (ctx->extra_certs == NULL) {
-        ctx->extra_certs = sk_X509_new_null();
-        if (ctx->extra_certs == NULL) {
-          return 0;
-        }
-      }
-      sk_X509_push(ctx->extra_certs, (X509 *)parg);
-      break;
+      return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg);
 
     case SSL_CTRL_GET_EXTRA_CHAIN_CERTS:
-      if (ctx->extra_certs == NULL) {
-        *(STACK_OF(X509) **)parg = ctx->cert->key->chain;
-      } else {
-        *(STACK_OF(X509) **)parg = ctx->extra_certs;
-      }
+    case SSL_CTRL_GET_CHAIN_CERTS:
+      *(STACK_OF(X509) **)parg = ctx->cert->chain;
       break;
 
     case SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS:
-      sk_X509_pop_free(ctx->extra_certs, X509_free);
-      ctx->extra_certs = NULL;
+      sk_X509_pop_free(ctx->cert->chain, X509_free);
+      ctx->cert->chain = NULL;
       break;
 
     case SSL_CTRL_CHAIN:
@@ -529,12 +519,8 @@
         return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg);
       }
 
-    case SSL_CTRL_GET_CHAIN_CERTS:
-      *(STACK_OF(X509) **)parg = ctx->cert->key->chain;
-      break;
-
     case SSL_CTRL_SELECT_CURRENT_CERT:
-      return ssl_cert_select_current(ctx->cert, (X509 *)parg);
+      return 1;
 
     default:
       return 0;
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 3130a3f..ceab0ae 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -1418,7 +1418,7 @@
     }
 
     if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
-      pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher);
+      pkey = s->cert->privatekey;
       if (pkey == NULL) {
         al = SSL_AD_DECODE_ERROR;
         goto f_err;
@@ -1478,8 +1478,8 @@
 
       /* Determine signature algorithm. */
       if (SSL_USE_SIGALGS(s)) {
-        md = tls1_choose_signing_digest(s, pkey);
-        if (!tls12_get_sigandhash(s, p, pkey, md)) {
+        md = tls1_choose_signing_digest(s);
+        if (!tls12_get_sigandhash(s, p, md)) {
           /* Should never happen */
           al = SSL_AD_INTERNAL_ERROR;
           OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange,
@@ -1692,7 +1692,7 @@
     uint8_t good;
     size_t rsa_size, decrypt_len, premaster_index, j;
 
-    pkey = s->cert->pkeys[SSL_PKEY_RSA].privatekey;
+    pkey = s->cert->privatekey;
     if (pkey == NULL || pkey->type != EVP_PKEY_RSA || pkey->pkey.rsa == NULL) {
       al = SSL_AD_HANDSHAKE_FAILURE;
       OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
@@ -2291,17 +2291,8 @@
 }
 
 int ssl3_send_server_certificate(SSL *s) {
-  CERT_PKEY *cpk;
-
   if (s->state == SSL3_ST_SW_CERT_A) {
-    cpk = ssl_get_server_send_pkey(s);
-    if (cpk == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ssl3_send_server_certificate,
-                        ERR_R_INTERNAL_ERROR);
-      return 0;
-    }
-
-    if (!ssl3_output_cert_chain(s, cpk)) {
+    if (!ssl3_output_cert_chain(s)) {
       return 0;
     }
     s->state = SSL3_ST_SW_CERT_B;
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index a442ec3..a389cc4 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -149,34 +149,24 @@
 }
 
 CERT *ssl_cert_new(void) {
-  CERT *ret;
-
-  ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
+  CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
   if (ret == NULL) {
     OPENSSL_PUT_ERROR(SSL, ssl_cert_new, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
   memset(ret, 0, sizeof(CERT));
 
-  ret->key = &ret->pkeys[SSL_PKEY_RSA];
   return ret;
 }
 
 CERT *ssl_cert_dup(CERT *cert) {
-  CERT *ret;
-  int i;
-
-  ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
+  CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
   if (ret == NULL) {
     OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
   memset(ret, 0, sizeof(CERT));
 
-  ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
-  /* or ret->key = ret->pkeys + (cert->key - cert->pkeys), if you find that
-   * more readable */
-
   ret->mask_k = cert->mask_k;
   ret->mask_a = cert->mask_a;
 
@@ -208,23 +198,19 @@
   ret->ecdh_nid = cert->ecdh_nid;
   ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
 
-  for (i = 0; i < SSL_PKEY_NUM; i++) {
-    CERT_PKEY *cpk = cert->pkeys + i;
-    CERT_PKEY *rpk = ret->pkeys + i;
-    if (cpk->x509 != NULL) {
-      rpk->x509 = X509_up_ref(cpk->x509);
-    }
+  if (cert->x509 != NULL) {
+    ret->x509 = X509_up_ref(cert->x509);
+  }
 
-    if (cpk->privatekey != NULL) {
-      rpk->privatekey = EVP_PKEY_up_ref(cpk->privatekey);
-    }
+  if (cert->privatekey != NULL) {
+    ret->privatekey = EVP_PKEY_up_ref(cert->privatekey);
+  }
 
-    if (cpk->chain) {
-      rpk->chain = X509_chain_up_ref(cpk->chain);
-      if (!rpk->chain) {
-        OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE);
-        goto err;
-      }
+  if (cert->chain) {
+    ret->chain = X509_chain_up_ref(cert->chain);
+    if (!ret->chain) {
+      OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE);
+      goto err;
     }
   }
 
@@ -277,27 +263,17 @@
 }
 
 /* Free up and clear all certificates and chains */
-void ssl_cert_clear_certs(CERT *c) {
-  int i;
-  if (c == NULL) {
+void ssl_cert_clear_certs(CERT *cert) {
+  if (cert == NULL) {
     return;
   }
 
-  for (i = 0; i < SSL_PKEY_NUM; i++) {
-    CERT_PKEY *cpk = c->pkeys + i;
-    if (cpk->x509) {
-      X509_free(cpk->x509);
-      cpk->x509 = NULL;
-    }
-    if (cpk->privatekey) {
-      EVP_PKEY_free(cpk->privatekey);
-      cpk->privatekey = NULL;
-    }
-    if (cpk->chain) {
-      sk_X509_pop_free(cpk->chain, X509_free);
-      cpk->chain = NULL;
-    }
-  }
+  X509_free(cert->x509);
+  cert->x509 = NULL;
+  EVP_PKEY_free(cert->privatekey);
+  cert->privatekey = NULL;
+  sk_X509_pop_free(cert->chain, X509_free);
+  cert->chain = NULL;
 }
 
 void ssl_cert_free(CERT *c) {
@@ -319,28 +295,24 @@
   OPENSSL_free(c);
 }
 
-int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain) {
-  CERT_PKEY *cpk = c->key;
-  if (!cpk) {
-    return 0;
-  }
-  sk_X509_pop_free(cpk->chain, X509_free);
-  cpk->chain = chain;
+int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
+  sk_X509_pop_free(cert->chain, X509_free);
+  cert->chain = chain;
   return 1;
 }
 
-int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain) {
+int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain) {
   STACK_OF(X509) *dchain;
-  if (!chain) {
-    return ssl_cert_set0_chain(c, NULL);
+  if (chain == NULL) {
+    return ssl_cert_set0_chain(cert, NULL);
   }
 
   dchain = X509_chain_up_ref(chain);
-  if (!dchain) {
+  if (dchain == NULL) {
     return 0;
   }
 
-  if (!ssl_cert_set0_chain(c, dchain)) {
+  if (!ssl_cert_set0_chain(cert, dchain)) {
     sk_X509_pop_free(dchain, X509_free);
     return 0;
   }
@@ -348,54 +320,26 @@
   return 1;
 }
 
-int ssl_cert_add0_chain_cert(CERT *c, X509 *x) {
-  CERT_PKEY *cpk = c->key;
-  if (!cpk) {
-    return 0;
+int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509) {
+  if (cert->chain == NULL) {
+    cert->chain = sk_X509_new_null();
   }
-
-  if (!cpk->chain) {
-    cpk->chain = sk_X509_new_null();
-  }
-  if (!cpk->chain || !sk_X509_push(cpk->chain, x)) {
+  if (cert->chain == NULL || !sk_X509_push(cert->chain, x509)) {
     return 0;
   }
 
   return 1;
 }
 
-int ssl_cert_add1_chain_cert(CERT *c, X509 *x) {
-  if (!ssl_cert_add0_chain_cert(c, x)) {
+int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509) {
+  if (!ssl_cert_add0_chain_cert(cert, x509)) {
     return 0;
   }
 
-  X509_up_ref(x);
+  X509_up_ref(x509);
   return 1;
 }
 
-int ssl_cert_select_current(CERT *c, X509 *x) {
-  int i;
-  if (x == NULL) {
-    return 0;
-  }
-
-  for (i = 0; i < SSL_PKEY_NUM; i++) {
-    if (c->pkeys[i].x509 == x) {
-      c->key = &c->pkeys[i];
-      return 1;
-    }
-  }
-
-  for (i = 0; i < SSL_PKEY_NUM; i++) {
-    if (c->pkeys[i].x509 && !X509_cmp(c->pkeys[i].x509, x)) {
-      c->key = &c->pkeys[i];
-      return 1;
-    }
-  }
-
-  return 0;
-}
-
 void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) {
   c->cert_cb = cb;
   c->cert_cb_arg = arg;
@@ -789,13 +733,14 @@
 }
 
 /* Add certificate chain to internal SSL BUF_MEM structure. */
-int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) {
-  BUF_MEM *buf = s->init_buf;
+int ssl_add_cert_chain(SSL *ssl, unsigned long *l) {
+  CERT *cert = ssl->cert;
+  BUF_MEM *buf = ssl->init_buf;
   int no_chain = 0;
   size_t i;
 
-  X509 *x = cpk->x509;
-  STACK_OF(X509) *extra_certs;
+  X509 *x = cert->x509;
+  STACK_OF(X509) *chain = cert->chain;
   X509_STORE *chain_store;
 
   if (x == NULL) {
@@ -803,20 +748,13 @@
     return 0;
   }
 
-  if (s->cert->chain_store) {
-    chain_store = s->cert->chain_store;
+  if (ssl->cert->chain_store) {
+    chain_store = ssl->cert->chain_store;
   } else {
-    chain_store = s->ctx->cert_store;
+    chain_store = ssl->ctx->cert_store;
   }
 
-  /* If we have a certificate specific chain use it, else use parent ctx. */
-  if (cpk && cpk->chain) {
-    extra_certs = cpk->chain;
-  } else {
-    extra_certs = s->ctx->extra_certs;
-  }
-
-  if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) {
+  if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) || chain != NULL) {
     no_chain = 1;
   }
 
@@ -825,8 +763,8 @@
       return 0;
     }
 
-    for (i = 0; i < sk_X509_num(extra_certs); i++) {
-      x = sk_X509_value(extra_certs, i);
+    for (i = 0; i < sk_X509_num(chain); i++) {
+      x = sk_X509_value(chain, i);
       if (!ssl_add_cert_to_buf(buf, l, x)) {
         return 0;
       }
@@ -856,15 +794,14 @@
 }
 
 /* Build a certificate chain for current certificate */
-int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) {
-  CERT_PKEY *cpk = c->key;
+int ssl_build_cert_chain(CERT *cert, X509_STORE *chain_store, int flags) {
   X509_STORE_CTX xs_ctx;
   STACK_OF(X509) *chain = NULL, *untrusted = NULL;
   X509 *x;
   int i, rv = 0;
   uint32_t error;
 
-  if (!cpk->x509) {
+  if (cert->x509 == NULL) {
     OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, SSL_R_NO_CERTIFICATE_SET);
     goto err;
   }
@@ -877,8 +814,8 @@
       goto err;
     }
 
-    for (j = 0; j < sk_X509_num(cpk->chain); j++) {
-      x = sk_X509_value(cpk->chain, j);
+    for (j = 0; j < sk_X509_num(cert->chain); j++) {
+      x = sk_X509_value(cert->chain, j);
       if (!X509_STORE_add_cert(chain_store, x)) {
         error = ERR_peek_last_error();
         if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
@@ -890,7 +827,7 @@
     }
 
     /* Add EE cert too: it might be self signed */
-    if (!X509_STORE_add_cert(chain_store, cpk->x509)) {
+    if (!X509_STORE_add_cert(chain_store, cert->x509)) {
       error = ERR_peek_last_error();
       if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
           ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
@@ -899,16 +836,16 @@
       ERR_clear_error();
     }
   } else {
-    if (c->chain_store) {
-      chain_store = c->chain_store;
+    if (cert->chain_store) {
+      chain_store = cert->chain_store;
     }
 
     if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) {
-      untrusted = cpk->chain;
+      untrusted = cert->chain;
     }
   }
 
-  if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) {
+  if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cert->x509, untrusted)) {
     OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, ERR_R_X509_LIB);
     goto err;
   }
@@ -936,8 +873,8 @@
   }
 
   X509_STORE_CTX_cleanup(&xs_ctx);
-  if (cpk->chain) {
-    sk_X509_pop_free(cpk->chain, X509_free);
+  if (cert->chain) {
+    sk_X509_pop_free(cert->chain, X509_free);
   }
 
   /* Remove EE certificate from chain */
@@ -955,7 +892,7 @@
     }
   }
 
-  cpk->chain = chain;
+  cert->chain = chain;
   if (rv == 0) {
     rv = 1;
   }
diff --git a/ssl/ssl_cipher.c b/ssl/ssl_cipher.c
index 1a8c0b2..ca0807f 100644
--- a/ssl/ssl_cipher.c
+++ b/ssl/ssl_cipher.c
@@ -1676,16 +1676,16 @@
 
 const char *SSL_COMP_get_name(const COMP_METHOD *comp) { return NULL; }
 
-int ssl_cipher_get_cert_index(const SSL_CIPHER *cipher) {
+int ssl_cipher_get_key_type(const SSL_CIPHER *cipher) {
   uint32_t alg_a = cipher->algorithm_auth;
 
   if (alg_a & SSL_aECDSA) {
-    return SSL_PKEY_ECC;
+    return EVP_PKEY_EC;
   } else if (alg_a & SSL_aRSA) {
-    return SSL_PKEY_RSA;
+    return EVP_PKEY_RSA;
   }
 
-  return -1;
+  return EVP_PKEY_NONE;
 }
 
 int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher) {
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 0064b43..6a694b3 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -799,20 +799,19 @@
 
 /* Fix this so it checks all the valid key/cert options */
 int SSL_CTX_check_private_key(const SSL_CTX *ctx) {
-  if (ctx == NULL || ctx->cert == NULL || ctx->cert->key->x509 == NULL) {
+  if (ctx == NULL || ctx->cert == NULL || ctx->cert->x509 == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key,
                       SSL_R_NO_CERTIFICATE_ASSIGNED);
     return 0;
   }
 
-  if (ctx->cert->key->privatekey == NULL) {
+  if (ctx->cert->privatekey == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key,
                       SSL_R_NO_PRIVATE_KEY_ASSIGNED);
     return 0;
   }
 
-  return X509_check_private_key(ctx->cert->key->x509,
-                                ctx->cert->key->privatekey);
+  return X509_check_private_key(ctx->cert->x509, ctx->cert->privatekey);
 }
 
 /* Fix this function so that it takes an optional type parameter */
@@ -828,20 +827,19 @@
     return 0;
   }
 
-  if (ssl->cert->key->x509 == NULL) {
+  if (ssl->cert->x509 == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_check_private_key,
                       SSL_R_NO_CERTIFICATE_ASSIGNED);
     return 0;
   }
 
-  if (ssl->cert->key->privatekey == NULL) {
+  if (ssl->cert->privatekey == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_check_private_key,
                       SSL_R_NO_PRIVATE_KEY_ASSIGNED);
     return 0;
   }
 
-  return X509_check_private_key(ssl->cert->key->x509,
-                                ssl->cert->key->privatekey);
+  return X509_check_private_key(ssl->cert->x509, ssl->cert->privatekey);
 }
 
 int SSL_accept(SSL *s) {
@@ -1716,8 +1714,6 @@
 
   CRYPTO_new_ex_data(&g_ex_data_class_ssl_ctx, ret, &ret->ex_data);
 
-  ret->extra_certs = NULL;
-
   ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
 
   ret->tlsext_servername_callback = 0;
@@ -1781,7 +1777,6 @@
   ssl_cipher_preference_list_free(ctx->cipher_list_tls11);
   ssl_cert_free(ctx->cert);
   sk_X509_NAME_pop_free(ctx->client_CA, X509_NAME_free);
-  sk_X509_pop_free(ctx->extra_certs, X509_free);
   sk_SRTP_PROTECTION_PROFILE_free(ctx->srtp_profiles);
   OPENSSL_free(ctx->psk_identity_hint);
   OPENSSL_free(ctx->tlsext_ecpointformatlist);
@@ -1827,17 +1822,12 @@
   ssl_cert_set_cert_cb(s->cert, cb, arg);
 }
 
-static int ssl_has_key(SSL *s, size_t idx) {
-  CERT_PKEY *cpk = &s->cert->pkeys[idx];
-  return cpk->x509 && cpk->privatekey;
-}
-
 void ssl_get_compatible_server_ciphers(SSL *s, uint32_t *out_mask_k,
                                        uint32_t *out_mask_a) {
   CERT *c = s->cert;
-  int have_rsa_cert, dh_tmp;
+  int have_rsa_cert = 0, dh_tmp;
   uint32_t mask_k, mask_a;
-  int have_ecc_cert, ecdsa_ok;
+  int have_ecc_cert = 0, ecdsa_ok;
   X509 *x;
 
   if (c == NULL) {
@@ -1849,8 +1839,13 @@
 
   dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
 
-  have_rsa_cert = ssl_has_key(s, SSL_PKEY_RSA);
-  have_ecc_cert = ssl_has_key(s, SSL_PKEY_ECC);
+  if (s->cert->x509 != NULL && s->cert->privatekey != NULL) {
+    if (s->cert->privatekey->type == EVP_PKEY_RSA) {
+      have_rsa_cert = 1;
+    } else if (s->cert->privatekey->type == EVP_PKEY_EC) {
+      have_ecc_cert = 1;
+    }
+  }
   mask_k = 0;
   mask_a = 0;
 
@@ -1865,7 +1860,7 @@
   /* An ECC certificate may be usable for ECDSA cipher suites depending on the
    * key usage extension and on the client's curve preferences. */
   if (have_ecc_cert) {
-    x = c->pkeys[SSL_PKEY_ECC].x509;
+    x = c->x509;
     /* This call populates extension flags (ex_flags). */
     X509_check_purpose(x, -1, 0);
     ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE)
@@ -1895,47 +1890,6 @@
   *out_mask_a = mask_a;
 }
 
-static int ssl_get_server_cert_index(const SSL *s) {
-  int idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
-  if (idx == -1) {
-    OPENSSL_PUT_ERROR(SSL, ssl_get_server_cert_index, ERR_R_INTERNAL_ERROR);
-  }
-  return idx;
-}
-
-CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) {
-  int i = ssl_get_server_cert_index(s);
-
-  /* This may or may not be an error. */
-  if (i < 0) {
-    return NULL;
-  }
-
-  /* May be NULL. */
-  return &s->cert->pkeys[i];
-}
-
-EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher) {
-  uint32_t alg_a = cipher->algorithm_auth;
-  CERT *c = s->cert;
-  int idx = -1;
-
-  if ((alg_a & SSL_aRSA) &&
-      (c->pkeys[SSL_PKEY_RSA].privatekey != NULL)) {
-    idx = SSL_PKEY_RSA;
-  } else if ((alg_a & SSL_aECDSA) &&
-             (c->pkeys[SSL_PKEY_ECC].privatekey != NULL)) {
-    idx = SSL_PKEY_ECC;
-  }
-
-  if (idx == -1) {
-    OPENSSL_PUT_ERROR(SSL, ssl_get_sign_pkey, ERR_R_INTERNAL_ERROR);
-    return NULL;
-  }
-
-  return c->pkeys[idx].privatekey;
-}
-
 void ssl_update_cache(SSL *s, int mode) {
   /* Never cache sessions with empty session IDs. */
   if (s->session->session_id_length == 0) {
@@ -2164,7 +2118,7 @@
 
 X509 *SSL_get_certificate(const SSL *s) {
   if (s->cert != NULL) {
-    return s->cert->key->x509;
+    return s->cert->x509;
   }
 
   return NULL;
@@ -2172,7 +2126,7 @@
 
 EVP_PKEY *SSL_get_privatekey(const SSL *s) {
   if (s->cert != NULL) {
-    return s->cert->key->privatekey;
+    return s->cert->privatekey;
   }
 
   return NULL;
@@ -2180,7 +2134,7 @@
 
 X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
   if (ctx->cert != NULL) {
-    return ctx->cert->key->x509;
+    return ctx->cert->x509;
   }
 
   return NULL;
@@ -2188,7 +2142,7 @@
 
 EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) {
   if (ctx->cert != NULL) {
-    return ctx->cert->key->privatekey;
+    return ctx->cert->privatekey;
   }
 
   return NULL;
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index b95b231..8432455 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -69,6 +69,10 @@
 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, SSL_use_certificate, ERR_R_PASSED_NULL_PARAMETER);
@@ -160,28 +164,24 @@
 }
 
 static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) {
-  int i;
-
-  i = ssl_cert_type(pkey);
-  if (i < 0) {
+  if (!is_key_type_supported(pkey->type)) {
     OPENSSL_PUT_ERROR(SSL, ssl_set_pkey, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
     return 0;
   }
 
-  if (c->pkeys[i].x509 != NULL) {
+  if (c->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->pkeys[i].x509, pkey)) {
-      X509_free(c->pkeys[i].x509);
-      c->pkeys[i].x509 = NULL;
+        !X509_check_private_key(c->x509, pkey)) {
+      X509_free(c->x509);
+      c->x509 = NULL;
       return 0;
     }
   }
 
-  EVP_PKEY_free(c->pkeys[i].privatekey);
-  c->pkeys[i].privatekey = EVP_PKEY_up_ref(pkey);
-  c->key = &(c->pkeys[i]);
+  EVP_PKEY_free(c->privatekey);
+  c->privatekey = EVP_PKEY_up_ref(pkey);
 
   return 1;
 }
@@ -324,32 +324,28 @@
 }
 
 static int ssl_set_cert(CERT *c, X509 *x) {
-  EVP_PKEY *pkey;
-  int i;
-
-  pkey = X509_get_pubkey(x);
+  EVP_PKEY *pkey = X509_get_pubkey(x);
   if (pkey == NULL) {
     OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_X509_LIB);
     return 0;
   }
 
-  i = ssl_cert_type(pkey);
-  if (i < 0) {
+  if (!is_key_type_supported(pkey->type)) {
     OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
     EVP_PKEY_free(pkey);
     return 0;
   }
 
-  if (c->pkeys[i].privatekey != NULL) {
+  if (c->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->pkeys[i].privatekey) &&
-        !X509_check_private_key(x, c->pkeys[i].privatekey)) {
+    if (!EVP_PKEY_is_opaque(c->privatekey) &&
+        !X509_check_private_key(x, c->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->pkeys[i].privatekey);
-      c->pkeys[i].privatekey = NULL;
+      EVP_PKEY_free(c->privatekey);
+      c->privatekey = NULL;
       /* clear error queue */
       ERR_clear_error();
     }
@@ -357,9 +353,8 @@
 
   EVP_PKEY_free(pkey);
 
-  X509_free(c->pkeys[i].x509);
-  c->pkeys[i].x509 = X509_up_ref(x);
-  c->key = &(c->pkeys[i]);
+  X509_free(c->x509);
+  c->x509 = X509_up_ref(x);
 
   return 1;
 }
@@ -650,38 +645,37 @@
   ssl->cert->key_method = key_method;
 }
 
-int ssl_private_key_type(SSL *ssl, const EVP_PKEY *pkey) {
+int ssl_private_key_type(SSL *ssl) {
   if (ssl->cert->key_method != NULL) {
     return ssl->cert->key_method->type(ssl);
   }
-  return EVP_PKEY_id(pkey);
+  return EVP_PKEY_id(ssl->cert->privatekey);
 }
 
-int ssl_private_key_supports_digest(SSL *ssl, const EVP_PKEY *pkey,
-                                    const EVP_MD *md) {
+int ssl_private_key_supports_digest(SSL *ssl, const EVP_MD *md) {
   if (ssl->cert->key_method != NULL) {
     return ssl->cert->key_method->supports_digest(ssl, md);
   }
-  return EVP_PKEY_supports_digest(pkey, md);
+  return EVP_PKEY_supports_digest(ssl->cert->privatekey, md);
 }
 
-size_t ssl_private_key_max_signature_len(SSL *ssl, const EVP_PKEY *pkey) {
+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);
   }
-  return EVP_PKEY_size(pkey);
+  return EVP_PKEY_size(ssl->cert->privatekey);
 }
 
 enum ssl_private_key_result_t ssl_private_key_sign(
-    SSL *ssl, EVP_PKEY *pkey, uint8_t *out, size_t *out_len, size_t max_out,
-    const EVP_MD *md, const uint8_t *in, size_t in_len) {
+    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);
   }
 
   enum ssl_private_key_result_t ret = ssl_private_key_failure;
-  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
+  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
   if (ctx == NULL) {
     goto end;
   }
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index e867e35..7daa864 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -2438,8 +2438,7 @@
                        sizeof(tls12_sig) / sizeof(tls12_lookup));
 }
 
-int tls12_get_sigandhash(SSL *ssl, uint8_t *p, const EVP_PKEY *pk,
-                         const EVP_MD *md) {
+int tls12_get_sigandhash(SSL *ssl, uint8_t *p, const EVP_MD *md) {
   int sig_id, md_id;
 
   if (!md) {
@@ -2452,7 +2451,7 @@
     return 0;
   }
 
-  sig_id = tls12_get_sigid(ssl_private_key_type(ssl, pk));
+  sig_id = tls12_get_sigid(ssl_private_key_type(ssl));
   if (sig_id == -1) {
     return 0;
   }
@@ -2602,17 +2601,17 @@
   return 1;
 }
 
-const EVP_MD *tls1_choose_signing_digest(SSL *s, EVP_PKEY *pkey) {
-  CERT *c = s->cert;
-  int type = ssl_private_key_type(s, pkey);
+const EVP_MD *tls1_choose_signing_digest(SSL *ssl) {
+  CERT *cert = ssl->cert;
+  int type = ssl_private_key_type(ssl);
   size_t i;
 
   /* Select the first shared digest supported by our key. */
-  for (i = 0; i < c->shared_sigalgslen; i++) {
-    const EVP_MD *md = tls12_get_hash(c->shared_sigalgs[i].rhash);
+  for (i = 0; i < cert->shared_sigalgslen; i++) {
+    const EVP_MD *md = tls12_get_hash(cert->shared_sigalgs[i].rhash);
     if (md == NULL ||
-        tls12_get_pkey_type(c->shared_sigalgs[i].rsign) != type ||
-        !ssl_private_key_supports_digest(s, pkey, md)) {
+        tls12_get_pkey_type(cert->shared_sigalgs[i].rsign) != type ||
+        !ssl_private_key_supports_digest(ssl, md)) {
       continue;
     }
     return md;