diff options
author | David Benjamin <davidben@chromium.org> | 2015-11-02 20:02:20 +0300 |
---|---|---|
committer | Adam Langley <agl@google.com> | 2015-11-07 01:35:28 +0300 |
commit | 6e8076577486a5d3d67682dbc4acae932daa6731 (patch) | |
tree | fbdbe9de19eb380892e6e6a559945333f41ccc9f | |
parent | 788be4a3f47cea5fcb86abf59321c729057830ed (diff) |
Add SSL_get_server_key_exchange_hash.
This exposes the ServerKeyExchange signature hash type used in the most recent
handshake, for histogramming on the client.
BUG=549662
Change-Id: I8a4e00ac735b1ecd2c2df824112c3a0bc62332a7
Reviewed-on: https://boringssl-review.googlesource.com/6413
Reviewed-by: Adam Langley <agl@google.com>
-rw-r--r-- | include/openssl/ssl.h | 10 | ||||
-rw-r--r-- | ssl/internal.h | 9 | ||||
-rw-r--r-- | ssl/s3_clnt.c | 10 | ||||
-rw-r--r-- | ssl/s3_srvr.c | 14 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 3 | ||||
-rw-r--r-- | ssl/t1_lib.c | 22 | ||||
-rw-r--r-- | ssl/test/bssl_shim.cc | 9 | ||||
-rw-r--r-- | ssl/test/runner/runner.go | 13 | ||||
-rw-r--r-- | ssl/test/test_config.cc | 2 | ||||
-rw-r--r-- | ssl/test/test_config.h | 1 |
10 files changed, 70 insertions, 23 deletions
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index bf53d5e4..38d838d3 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -2911,6 +2911,11 @@ OPENSSL_EXPORT SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx); * respectively. */ OPENSSL_EXPORT int SSL_get_shutdown(const SSL *ssl); +/* SSL_get_server_key_exchange_hash, on a client, returns the hash the server + * used to sign the ServerKeyExchange in TLS 1.2. If not applicable, it returns + * |TLSEXT_hash_none|. */ +OPENSSL_EXPORT uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl); + /* Deprecated functions. */ @@ -4157,6 +4162,11 @@ typedef struct ssl3_state_st { * False Start. The client may write data at this point. */ char in_false_start; + /* server_key_exchange_hash, on a client, is the hash the server used to + * sign the ServerKeyExchange in TLS 1.2. If not applicable, it is + * |TLSEXT_hash_none|. */ + uint8_t server_key_exchange_hash; + /* peer_dh_tmp, on a client, is the server's DHE public key. */ DH *peer_dh_tmp; diff --git a/ssl/internal.h b/ssl/internal.h index aa8c4ef6..520131e6 100644 --- a/ssl/internal.h +++ b/ssl/internal.h @@ -1294,8 +1294,13 @@ int tls1_parse_peer_sigalgs(SSL *s, const CBS *sigalgs); 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, - CBS *cbs, EVP_PKEY *pkey); + +/* tls12_check_peer_sigalg checks that |hash| and |signature| are consistent + * with |pkey| and |ssl|'s sent, supported signature algorithms and, if so, + * writes the relevant digest into |*out_md| and returns 1. Otherwise it + * returns 0 and writes an alert into |*out_alert|. */ +int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert, + uint8_t hash, uint8_t signature, EVP_PKEY *pkey); void ssl_set_client_disabled(SSL *s); #endif /* OPENSSL_HEADER_SSL_INTERNAL_H */ diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 04c06ddb..843403b3 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -1244,9 +1244,17 @@ int ssl3_get_server_key_exchange(SSL *s) { } if (SSL_USE_SIGALGS(s)) { - if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey)) { + uint8_t hash, signature; + if (!CBS_get_u8(&server_key_exchange, &hash) || + !CBS_get_u8(&server_key_exchange, &signature)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } + if (!tls12_check_peer_sigalg(s, &md, &al, hash, signature, pkey)) { + goto f_err; + } + s->s3->tmp.server_key_exchange_hash = hash; } else if (pkey->type == EVP_PKEY_RSA) { md = EVP_md5_sha1(); } else { diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index fad2d0a9..8cfa0e6c 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -2056,9 +2056,17 @@ int ssl3_get_cert_verify(SSL *s) { CBS_init(&certificate_verify, s->init_msg, n); /* Determine the digest type if needbe. */ - if (SSL_USE_SIGALGS(s) && - !tls12_check_peer_sigalg(&md, &al, s, &certificate_verify, pkey)) { - goto f_err; + if (SSL_USE_SIGALGS(s)) { + uint8_t hash, signature_type; + if (!CBS_get_u8(&certificate_verify, &hash) || + !CBS_get_u8(&certificate_verify, &signature_type)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + if (!tls12_check_peer_sigalg(s, &md, &al, hash, signature_type, pkey)) { + goto f_err; + } } /* Compute the digest. */ diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 68eb4ac0..16c24dfa 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -2651,6 +2651,9 @@ int SSL_get_ivs(const SSL *ssl, const uint8_t **out_read_iv, } return 1; + +uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl) { + return ssl->s3->tmp.server_key_exchange_hash; } int SSL_clear(SSL *ssl) { diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 301d49a1..9a290283 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -640,16 +640,11 @@ size_t tls12_get_psigalgs(SSL *s, const uint8_t **psigs) { return sizeof(tls12_sigalgs); } -/* tls12_check_peer_sigalg parses a SignatureAndHashAlgorithm out of |cbs|. It - * checks it is consistent with |s|'s sent supported signature algorithms and, - * if so, writes the relevant digest into |*out_md| and returns 1. Otherwise it - * returns 0 and writes an alert into |*out_alert|. */ -int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, SSL *s, - CBS *cbs, EVP_PKEY *pkey) { +int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert, + uint8_t hash, uint8_t signature, EVP_PKEY *pkey) { const uint8_t *sent_sigs; size_t sent_sigslen, i; int sigalg = tls12_get_sigid(pkey->type); - uint8_t hash, signature; /* Should never happen */ if (sigalg == -1) { @@ -658,13 +653,6 @@ int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, SSL *s, return 0; } - if (!CBS_get_u8(cbs, &hash) || - !CBS_get_u8(cbs, &signature)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } - /* Check key type is consistent with signature */ if (sigalg != signature) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); @@ -681,8 +669,8 @@ int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, SSL *s, return 0; } - if (s->server && (!tls1_check_curve_id(s, curve_id) || - comp_id != TLSEXT_ECPOINTFORMAT_uncompressed)) { + if (ssl->server && (!tls1_check_curve_id(ssl, curve_id) || + comp_id != TLSEXT_ECPOINTFORMAT_uncompressed)) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE); *out_alert = SSL_AD_ILLEGAL_PARAMETER; return 0; @@ -690,7 +678,7 @@ int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, SSL *s, } /* Check signature matches a type we sent */ - sent_sigslen = tls12_get_psigalgs(s, &sent_sigs); + sent_sigslen = tls12_get_psigalgs(ssl, &sent_sigs); for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) { if (hash == sent_sigs[0] && signature == sent_sigs[1]) { break; diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc index fe3dd6f3..07ba9f59 100644 --- a/ssl/test/bssl_shim.cc +++ b/ssl/test/bssl_shim.cc @@ -1061,6 +1061,15 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) { } } + if (config->expect_server_key_exchange_hash != 0 && + config->expect_server_key_exchange_hash != + SSL_get_server_key_exchange_hash(ssl)) { + fprintf(stderr, "ServerKeyExchange hash was %d, wanted %d.\n", + SSL_get_server_key_exchange_hash(ssl), + config->expect_server_key_exchange_hash); + return false; + } + if (!config->is_server) { /* Clients should expect a peer certificate chain iff this was not a PSK * cipher suite. */ diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index 158f0823..6ab71cf2 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -4026,6 +4026,19 @@ func addSigningHashTests() { }, }, }) + + testCases = append(testCases, testCase{ + name: "SigningHash-ServerKeyExchange-Verify-" + hash.name, + config: Config{ + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + SignatureAndHashes: []signatureAndHash{ + {signatureRSA, 42}, + {signatureRSA, hash.id}, + {signatureRSA, 255}, + }, + }, + flags: []string{"-expect-server-key-exchange-hash", strconv.Itoa(int(hash.id))}, + }) } // Test that hash resolution takes the signature type into account. diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc index 8b540c3a..50e6b234 100644 --- a/ssl/test/test_config.cc +++ b/ssl/test/test_config.cc @@ -141,6 +141,8 @@ const Flag<int> kIntFlags[] = { { "-mtu", &TestConfig::mtu }, { "-export-keying-material", &TestConfig::export_keying_material }, { "-expect-total-renegotiations", &TestConfig::expect_total_renegotiations }, + { "-expect-server-key-exchange-hash", + &TestConfig::expect_server_key_exchange_hash }, }; } // namespace diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h index a72d66b7..9f295aeb 100644 --- a/ssl/test/test_config.h +++ b/ssl/test/test_config.h @@ -100,6 +100,7 @@ struct TestConfig { bool renegotiate_freely = false; bool renegotiate_ignore = false; bool disable_npn = false; + int expect_server_key_exchange_hash = 0; }; bool ParseConfig(int argc, char **argv, TestConfig *out_config); |