Slightly simplify ServerKeyExchange handling. The current logic requires each key exchange extract the key. It also leaves handling X509_get_pubkey failure to the anonymous cipher suite case which has an escape hatch where it goes back to check ssl3_check_cert_and_algorithm. Instead, get the key iff we know we have a signature to check. Change-Id: If7154c7156aad3b89489defe4c1d951eeebf0089 Reviewed-on: https://boringssl-review.googlesource.com/5045 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index d7ed14f..e1b8eb0 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c
@@ -1191,12 +1191,6 @@ SSL_R_BAD_DH_P_LENGTH); goto err; } - - if (alg_a & SSL_aRSA) { - pkey = X509_get_pubkey(s->session->sess_cert->peer_cert); - } - /* else anonymous DH, so no certificate or pkey. */ - s->session->sess_cert->peer_dh_tmp = dh; dh = NULL; } else if (alg_k & SSL_kECDHE) { @@ -1251,16 +1245,6 @@ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_ECPOINT); goto f_err; } - - /* The ECC/TLS specification does not mention the use of DSA to sign - * ECParameters in the server key exchange message. We do support RSA and - * ECDSA. */ - if (alg_a & (SSL_aRSA|SSL_aECDSA)) { - pkey = X509_get_pubkey(s->session->sess_cert->peer_cert); - } else { - /* Otherwise this is ECDHE_PSK, so no public key. */ - assert(alg_a == SSL_aPSK); - } EC_KEY_set_public_key(ecdh, srvr_ecpoint); s->session->sess_cert->peer_ecdh_tmp = ecdh; ecdh = NULL; @@ -1281,9 +1265,12 @@ CBS_init(¶meter, CBS_data(&server_key_exchange_orig), CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange)); - /* if it was signed, check the signature */ - if (pkey != NULL) { - CBS signature; + /* ServerKeyExchange should be signed by the server's public key. */ + if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { + pkey = X509_get_pubkey(s->session->sess_cert->peer_cert); + if (pkey == NULL) { + goto err; + } if (SSL_USE_SIGALGS(s)) { if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey)) { @@ -1296,6 +1283,7 @@ } /* The last field in |server_key_exchange| is the signature. */ + CBS signature; if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) || CBS_len(&server_key_exchange) != 0) { al = SSL_AD_DECODE_ERROR; @@ -1318,16 +1306,9 @@ goto f_err; } } else { - if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { - /* Might be wrong key type, check it */ - if (ssl3_check_cert_and_algorithm(s)) { - /* Otherwise this shouldn't happen */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - ERR_R_INTERNAL_ERROR); - } - goto err; - } - /* still data left over */ + /* PSK ciphers are the only supported certificate-less ciphers. */ + assert(alg_a == SSL_aPSK); + if (CBS_len(&server_key_exchange) > 0) { al = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,