diff options
-rw-r--r-- | crypto/err/ssl.errordata | 1 | ||||
-rw-r--r-- | include/openssl/ssl.h | 1 | ||||
-rw-r--r-- | ssl/handshake_client.c | 5 | ||||
-rw-r--r-- | ssl/handshake_server.c | 5 | ||||
-rw-r--r-- | ssl/internal.h | 7 | ||||
-rw-r--r-- | ssl/t1_lib.c | 35 | ||||
-rw-r--r-- | ssl/test/runner/runner.go | 7 |
7 files changed, 42 insertions, 19 deletions
diff --git a/crypto/err/ssl.errordata b/crypto/err/ssl.errordata index 700f9df1..23143444 100644 --- a/crypto/err/ssl.errordata +++ b/crypto/err/ssl.errordata @@ -77,6 +77,7 @@ SSL,174,NO_CERTIFICATE_SET SSL,175,NO_CIPHERS_AVAILABLE SSL,176,NO_CIPHERS_PASSED SSL,177,NO_CIPHER_MATCH +SSL,253,NO_COMMON_SIGNATURE_ALGORITHMS SSL,178,NO_COMPRESSION_SPECIFIED SSL,179,NO_METHOD_SPECIFIED SSL,180,NO_P256_SUPPORT diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 2ae5ab1a..7c272668 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -4660,6 +4660,7 @@ OPENSSL_EXPORT int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); #define SSL_R_SHUTDOWN_WHILE_IN_INIT 250 #define SSL_R_INVALID_OUTER_RECORD_TYPE 251 #define SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY 252 +#define SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS 253 #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c index a80ae8ca..4333ca0d 100644 --- a/ssl/handshake_client.c +++ b/ssl/handshake_client.c @@ -1792,7 +1792,10 @@ static int ssl3_send_cert_verify(SSL *ssl) { goto err; } - uint16_t signature_algorithm = tls1_choose_signature_algorithm(ssl); + uint16_t signature_algorithm; + if (!tls1_choose_signature_algorithm(ssl, &signature_algorithm)) { + goto err; + } if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { /* Write out the digest type in TLS 1.2. */ if (!CBB_add_u16(&body, signature_algorithm)) { diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c index 0b9b871c..ca253b46 100644 --- a/ssl/handshake_server.c +++ b/ssl/handshake_server.c @@ -1045,7 +1045,10 @@ static int ssl3_send_server_key_exchange(SSL *ssl) { } /* Determine the signature algorithm. */ - uint16_t signature_algorithm = tls1_choose_signature_algorithm(ssl); + uint16_t signature_algorithm; + if (!tls1_choose_signature_algorithm(ssl, &signature_algorithm)) { + goto err; + } if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { if (!CBB_add_u16(&body, signature_algorithm)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); diff --git a/ssl/internal.h b/ssl/internal.h index 03a13208..e451d15f 100644 --- a/ssl/internal.h +++ b/ssl/internal.h @@ -1215,9 +1215,10 @@ uint16_t ssl3_protocol_version(const SSL *ssl); uint32_t ssl_get_algorithm_prf(const SSL *ssl); int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *sigalgs); -/* tls1_choose_signature_algorithm returns a signature algorithm for use with - * |ssl|'s private key based on the peer's preferences the digests supported. */ -uint16_t tls1_choose_signature_algorithm(SSL *ssl); +/* tls1_choose_signature_algorithm sets |*out| to a signature algorithm for use + * with |ssl|'s private key based on the peer's preferences and the digests + * supported. It returns one on success and zero on error. */ +int tls1_choose_signature_algorithm(SSL *ssl, uint16_t *out); size_t tls12_get_psigalgs(SSL *ssl, const uint16_t **psigs); diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index f1551c85..c05bc4f7 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -2586,7 +2586,7 @@ int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *in_sigalgs) { return 1; } -uint16_t tls1_choose_signature_algorithm(SSL *ssl) { +int tls1_choose_signature_algorithm(SSL *ssl, uint16_t *out) { CERT *cert = ssl->cert; int type = ssl_private_key_type(ssl); size_t i, j; @@ -2595,9 +2595,11 @@ uint16_t tls1_choose_signature_algorithm(SSL *ssl) { * handshake. It is fixed at MD5-SHA1 for RSA and SHA1 for ECDSA. */ if (ssl3_protocol_version(ssl) < TLS1_2_VERSION) { if (type == EVP_PKEY_RSA) { - return SSL_SIGN_RSA_PKCS1_MD5_SHA1; + *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1; + } else { + *out = SSL_SIGN_ECDSA_SHA1; } - return SSL_SIGN_ECDSA_SHA1; + return 1; } const uint16_t *sigalgs = kDefaultSignatureAlgorithms; @@ -2608,24 +2610,35 @@ uint16_t tls1_choose_signature_algorithm(SSL *ssl) { sigalgs_len = cert->sigalgs_len; } + const uint16_t *peer_sigalgs = cert->peer_sigalgs; + size_t peer_sigalgs_len = cert->peer_sigalgslen; + if (peer_sigalgs_len == 0) { + /* If the client didn't specify any signature_algorithms extension then + * we can assume that it supports SHA1. See + * http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ + static const uint16_t kDefaultPeerAlgorithms[] = {SSL_SIGN_RSA_PKCS1_SHA1, + SSL_SIGN_ECDSA_SHA1}; + peer_sigalgs = kDefaultPeerAlgorithms; + peer_sigalgs_len = + sizeof(kDefaultPeerAlgorithms) / sizeof(kDefaultPeerAlgorithms); + } + for (i = 0; i < sigalgs_len; i++) { - for (j = 0; j < cert->peer_sigalgslen; j++) { - uint16_t signature_algorithm = cert->peer_sigalgs[j]; + for (j = 0; j < peer_sigalgs_len; j++) { + uint16_t signature_algorithm = peer_sigalgs[j]; /* SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal value and should never be * negotiated. */ if (signature_algorithm != SSL_SIGN_RSA_PKCS1_MD5_SHA1 && signature_algorithm == sigalgs[i] && tls12_get_pkey_type(signature_algorithm) == type) { - return signature_algorithm; + *out = signature_algorithm; + return 1; } } } - /* If no suitable digest may be found, default to SHA-1. */ - if (type == EVP_PKEY_RSA) { - return SSL_SIGN_RSA_PKCS1_SHA1; - } - return SSL_SIGN_ECDSA_SHA1; + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS); + return 0; } int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len) { diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index 60127da8..5d5facfc 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -4876,7 +4876,7 @@ func addSignatureAlgorithmTests() { // // TODO(davidben): Add TLS 1.3 versions of these. testCases = append(testCases, testCase{ - name: "Agree-Digest-Fallback", + name: "NoCommonAlgorithms", config: Config{ MaxVersion: VersionTLS12, ClientAuth: RequireAnyClientCert, @@ -4889,8 +4889,9 @@ func addSignatureAlgorithmTests() { "-cert-file", path.Join(*resourceDir, rsaCertificateFile), "-key-file", path.Join(*resourceDir, rsaKeyFile), }, - digestPrefs: "SHA256", - expectedPeerSignatureAlgorithm: signatureRSAPKCS1WithSHA1, + digestPrefs: "SHA256", + shouldFail: true, + expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:", }) testCases = append(testCases, testCase{ name: "Agree-Digest-SHA256", |