提交 717a265a 编写于 作者: D Dr. Stephen Henson

Add client side support to tls_choose_sigalg.

Select appropriate signature algorithm and certificate for client
authentication using tls_choose_sigalg.

A lot of selection logic is very similar except not finding a
certificate is not a fatal error: we just do not present a
certificate.

For TLS 1.2 and earlier we only check the current certificate
is suitable (for compatibility with previous logic) for TLS 1.3
(where there are no compatibility issues) we support multiple
client certificates for different algorithms.
Reviewed-by: NRich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2643)
上级 0cb8c9d8
...@@ -2316,13 +2316,23 @@ int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy) ...@@ -2316,13 +2316,23 @@ int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy)
/* /*
* Choose an appropriate signature algorithm based on available certificates * Choose an appropriate signature algorithm based on available certificates
* Set current certificate and digest to match chosen algorithm. * Sets chosen certificate and signature algorithm.
*
* For servers if we fail to find a required certificate it is a fatal error
* and an appropriate error code is set and the TLS alert set in *al.
*
* For clients al is set to NULL. If a certificate is not suitable it is not
* a fatal error: we will either try another certificate or not present one
* to the server. In this case no error is set.
*/ */
int tls_choose_sigalg(SSL *s, int *al) int tls_choose_sigalg(SSL *s, int *al)
{ {
int idx = -1; int idx = -1;
const SIGALG_LOOKUP *lu = NULL; const SIGALG_LOOKUP *lu = NULL;
s->s3->tmp.cert = NULL;
s->s3->tmp.sigalg = NULL;
if (SSL_IS_TLS13(s)) { if (SSL_IS_TLS13(s)) {
size_t i; size_t i;
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
...@@ -2357,37 +2367,47 @@ int tls_choose_sigalg(SSL *s, int *al) ...@@ -2357,37 +2367,47 @@ int tls_choose_sigalg(SSL *s, int *al)
break; break;
} }
if (i == s->cert->shared_sigalgslen) { if (i == s->cert->shared_sigalgslen) {
if (al == NULL)
return 1;
*al = SSL_AD_HANDSHAKE_FAILURE; *al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSLerr(SSL_F_TLS_CHOOSE_SIGALG,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM); SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0; return 0;
} }
} else { } else {
/* Find index corresponding to ciphersuite */ if (s->server) {
idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); /* Find index corresponding to ciphersuite */
/* If no certificate for ciphersuite return */ idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
if (idx == -1) { /* If no certificate for ciphersuite return */
s->s3->tmp.cert = NULL; if (idx == -1)
s->s3->tmp.sigalg = NULL; return 1;
return 1; if (idx == SSL_PKEY_GOST_EC) {
} /* Work out which GOST certificate is avaiable */
if (idx == SSL_PKEY_GOST_EC) { if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) {
/* Work out which GOST certificate is avaiable */ idx = SSL_PKEY_GOST12_512;
if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) { } else if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) {
idx = SSL_PKEY_GOST12_512; idx = SSL_PKEY_GOST12_256;
} else if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) { } else if (ssl_has_cert(s, SSL_PKEY_GOST01)) {
idx = SSL_PKEY_GOST12_256; idx = SSL_PKEY_GOST01;
} else if (ssl_has_cert(s, SSL_PKEY_GOST01)) { } else {
idx = SSL_PKEY_GOST01; if (al == NULL)
} else { return 1;
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
return 0;
}
} else if (!ssl_has_cert(s, idx)) {
if (al == NULL)
return 1;
*al = SSL_AD_INTERNAL_ERROR; *al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
return 0; return 0;
} }
} else if (!ssl_has_cert(s, idx)) { } else {
*al = SSL_AD_INTERNAL_ERROR; /* Find index for client certificate */
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); idx = s->cert->key - s->cert->pkeys;
return 0; if (!ssl_has_cert(s, idx))
return 1;
} }
if (SSL_USE_SIGALGS(s)) { if (SSL_USE_SIGALGS(s)) {
...@@ -2406,6 +2426,8 @@ int tls_choose_sigalg(SSL *s, int *al) ...@@ -2406,6 +2426,8 @@ int tls_choose_sigalg(SSL *s, int *al)
break; break;
} }
if (i == s->cert->shared_sigalgslen) { if (i == s->cert->shared_sigalgslen) {
if (al == NULL)
return 1;
*al = SSL_AD_INTERNAL_ERROR; *al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
return 0; return 0;
...@@ -2418,6 +2440,8 @@ int tls_choose_sigalg(SSL *s, int *al) ...@@ -2418,6 +2440,8 @@ int tls_choose_sigalg(SSL *s, int *al)
size_t sent_sigslen, i; size_t sent_sigslen, i;
if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) { if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) {
if (al == NULL)
return 1;
*al = SSL_AD_INTERNAL_ERROR; *al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
return 0; return 0;
...@@ -2430,6 +2454,8 @@ int tls_choose_sigalg(SSL *s, int *al) ...@@ -2430,6 +2454,8 @@ int tls_choose_sigalg(SSL *s, int *al)
break; break;
} }
if (i == sent_sigslen) { if (i == sent_sigslen) {
if (al == NULL)
return 1;
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
*al = SSL_AD_HANDSHAKE_FAILURE; *al = SSL_AD_HANDSHAKE_FAILURE;
return 0; return 0;
...@@ -2437,6 +2463,8 @@ int tls_choose_sigalg(SSL *s, int *al) ...@@ -2437,6 +2463,8 @@ int tls_choose_sigalg(SSL *s, int *al)
} }
} else { } else {
if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) { if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) {
if (al == NULL)
return 1;
*al = SSL_AD_INTERNAL_ERROR; *al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
return 0; return 0;
...@@ -2444,8 +2472,10 @@ int tls_choose_sigalg(SSL *s, int *al) ...@@ -2444,8 +2472,10 @@ int tls_choose_sigalg(SSL *s, int *al)
} }
} }
if (idx == -1) { if (idx == -1) {
*al = SSL_AD_INTERNAL_ERROR; if (al != NULL) {
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); *al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
}
return 0; return 0;
} }
s->s3->tmp.cert = &s->cert->pkeys[idx]; s->s3->tmp.cert = &s->cert->pkeys[idx];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册