From 93a77f9e2c66a4e63f732bb0d04695b4f951febb Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Tue, 31 Jan 2017 17:45:00 +0000 Subject: [PATCH] Add function tls_choose_sigalg(). New function tls_choose_sigalg(). This is a signature algorithm version of ssl3_choose_cipher(): it picks and sets the appropriate signature algorithm and certificate based on shared signature algorithms. Reviewed-by: Rich Salz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/2339) --- ssl/ssl_locl.h | 6 ++++++ ssl/t1_lib.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 53a33e9fdf..d0c4eb91a5 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1287,6 +1287,10 @@ typedef struct ssl3_state_st { unsigned char *psk; size_t psklen; # endif + /* Signature algorithm we actually use */ + const SIGALG_LOOKUP *sigalg; + /* Index of certificate we use */ + int cert_idx; /* * signature algorithms peer reports: e.g. supported signature * algorithms extension for server or as part of a certificate @@ -2257,6 +2261,8 @@ __owur int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee); __owur int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *ex, int vfy); +int tls_choose_sigalg(SSL *s); + __owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md); void ssl_clear_hash_ctx(EVP_MD_CTX **hash); __owur long ssl_get_algorithm2(SSL *s); diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 384a8c1ecb..dd1e86573b 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -2270,3 +2270,60 @@ int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy) } return 1; } + +/* + * Choose an appropriate signature algorithm based on available certificates + * Set current certificate and digest to match chosen algorithm. + */ +int tls_choose_sigalg(SSL *s) +{ + if (SSL_IS_TLS13(s)) { + size_t i; + int curve = -1; + + /* Look for a certificate matching shared sigaglgs */ + for (i = 0; i < s->cert->shared_sigalgslen; i++) { + const SIGALG_LOOKUP *lu = s->cert->shared_sigalgs[i]; + int idx; + const EVP_MD *md; + CERT_PKEY *c; + + /* Skip RSA if not PSS */ + if (lu->sig == EVP_PKEY_RSA) + continue; + md = ssl_md(lu->hash_idx); + if (md == NULL) + continue; + idx = lu->sig_idx; + c = &s->cert->pkeys[idx]; + if (c->x509 == NULL || c->privatekey == NULL) { + if (idx != SSL_PKEY_RSA_SIGN) + continue; + idx = SSL_PKEY_RSA_ENC; + c = s->cert->pkeys + idx; + if (c->x509 == NULL || c->privatekey == NULL) + continue; + } + if (lu->sig == EVP_PKEY_EC) { + if (curve == -1) { + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(c->privatekey); + + curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + } + if (curve != lu->curve) + continue; + } + s->s3->tmp.sigalg = lu; + s->s3->tmp.cert_idx = idx; + s->s3->tmp.md[idx] = md; + s->cert->key = s->cert->pkeys + idx; + return 1; + } + return 0; + } + /* + * FIXME: could handle previous TLS versions in an appropriate way + * and tidy up certificate and signature algorithm handling. + */ + return 1; +} -- 2.39.2