X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ft1_lib.c;h=5f44f5a112beeb56bc57ee57c22787f6f98c65b0;hp=787f487e4cb753e043795dd1ad9a5b7c34062334;hb=717a265aa5f618fb30f857f240f6b2b0ab7ad4c7;hpb=7b3a4d610731929d4fde15411f9be9b883974980 diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 787f487e4c..5f44f5a112 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -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 - * 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 idx = -1; const SIGALG_LOOKUP *lu = NULL; + s->s3->tmp.cert = NULL; + s->s3->tmp.sigalg = NULL; + if (SSL_IS_TLS13(s)) { size_t i; #ifndef OPENSSL_NO_EC @@ -2357,37 +2367,47 @@ int tls_choose_sigalg(SSL *s, int *al) break; } if (i == s->cert->shared_sigalgslen) { + if (al == NULL) + return 1; *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM); return 0; } } else { - /* Find index corresponding to ciphersuite */ - idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); - /* If no certificate for ciphersuite return */ - if (idx == -1) { - s->s3->tmp.cert = NULL; - s->s3->tmp.sigalg = NULL; - return 1; - } - if (idx == SSL_PKEY_GOST_EC) { - /* Work out which GOST certificate is avaiable */ - if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) { - idx = SSL_PKEY_GOST12_512; - } else if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) { - idx = SSL_PKEY_GOST12_256; - } else if (ssl_has_cert(s, SSL_PKEY_GOST01)) { - idx = SSL_PKEY_GOST01; - } else { + if (s->server) { + /* Find index corresponding to ciphersuite */ + idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); + /* If no certificate for ciphersuite return */ + if (idx == -1) + return 1; + if (idx == SSL_PKEY_GOST_EC) { + /* Work out which GOST certificate is avaiable */ + if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) { + idx = SSL_PKEY_GOST12_512; + } else if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) { + idx = SSL_PKEY_GOST12_256; + } else if (ssl_has_cert(s, SSL_PKEY_GOST01)) { + idx = SSL_PKEY_GOST01; + } else { + if (al == NULL) + 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; SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); return 0; } - } else if (!ssl_has_cert(s, idx)) { - *al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); - return 0; + } else { + /* Find index for client certificate */ + idx = s->cert->key - s->cert->pkeys; + if (!ssl_has_cert(s, idx)) + return 1; } if (SSL_USE_SIGALGS(s)) { @@ -2406,6 +2426,8 @@ int tls_choose_sigalg(SSL *s, int *al) break; } if (i == s->cert->shared_sigalgslen) { + if (al == NULL) + return 1; *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); return 0; @@ -2418,6 +2440,8 @@ int tls_choose_sigalg(SSL *s, int *al) size_t sent_sigslen, i; if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) { + if (al == NULL) + return 1; *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); return 0; @@ -2430,6 +2454,8 @@ int tls_choose_sigalg(SSL *s, int *al) break; } if (i == sent_sigslen) { + if (al == NULL) + return 1; SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); *al = SSL_AD_HANDSHAKE_FAILURE; return 0; @@ -2437,6 +2463,8 @@ int tls_choose_sigalg(SSL *s, int *al) } } else { if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) { + if (al == NULL) + return 1; *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); return 0; @@ -2444,8 +2472,10 @@ int tls_choose_sigalg(SSL *s, int *al) } } if (idx == -1) { - *al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); + if (al != NULL) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); + } return 0; } s->s3->tmp.cert = &s->cert->pkeys[idx];