As part of the SignatureAlgorithm change in the TLS 1.3 specification, the existing signature/hash combinations are replaced with a combined signature algorithm identifier. This change maintains the existing APIs while fixing the internal representations. The signing code currently still treats the SignatureAlgorithm as a decomposed value, which will be fixed as part of a separate CL. Change-Id: I0cd1660d74ad9bcf55ce5da4449bf2922660be36 Reviewed-on: https://boringssl-review.googlesource.com/8480 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com>kris/onging/CECPQ3_patch15
@@ -2958,10 +2958,9 @@ OPENSSL_EXPORT SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx); | |||||
* respectively. */ | * respectively. */ | ||||
OPENSSL_EXPORT int SSL_get_shutdown(const SSL *ssl); | 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); | |||||
/* SSL_get_peer_signature_algorithm returns the signature algorithm used by the | |||||
* peer. If not applicable, it returns zero. */ | |||||
OPENSSL_EXPORT uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl); | |||||
/* TODO(davidben): Remove this when wpa_supplicant in Android has synced with | /* TODO(davidben): Remove this when wpa_supplicant in Android has synced with | ||||
* upstream. */ | * upstream. */ | ||||
@@ -3193,6 +3192,14 @@ OPENSSL_EXPORT void SSL_load_error_strings(void); | |||||
OPENSSL_EXPORT int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, | OPENSSL_EXPORT int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, | ||||
const char *profiles); | const char *profiles); | ||||
/* 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|. | |||||
* | |||||
* TODO(davidben): Remove once Chromium switches to | |||||
* |SSL_get_peer_signature_algorithm|. */ | |||||
OPENSSL_EXPORT uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl); | |||||
/* SSL_set_tlsext_use_srtp calls |SSL_set_srtp_profiles|. It returns zero on | /* SSL_set_tlsext_use_srtp calls |SSL_set_srtp_profiles|. It returns zero on | ||||
* success and one on failure. | * success and one on failure. | ||||
* | * | ||||
@@ -4248,10 +4255,9 @@ typedef struct ssl3_state_st { | |||||
* False Start. The client may write data at this point. */ | * False Start. The client may write data at this point. */ | ||||
char in_false_start; | 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_signature_algorithm is the signature algorithm used to authenticate | |||||
* the peer, or zero if not applicable. */ | |||||
uint16_t peer_signature_algorithm; | |||||
/* ecdh_ctx is the current ECDH instance. */ | /* ecdh_ctx is the current ECDH instance. */ | ||||
SSL_ECDH_CTX ecdh_ctx; | SSL_ECDH_CTX ecdh_ctx; | ||||
@@ -261,6 +261,16 @@ extern "C" { | |||||
#define TLSEXT_hash_sha384 5 | #define TLSEXT_hash_sha384 5 | ||||
#define TLSEXT_hash_sha512 6 | #define TLSEXT_hash_sha512 6 | ||||
#define SSL_SIGN_RSA_PKCS1_SHA1 0x0201 | |||||
#define SSL_SIGN_RSA_PKCS1_SHA256 0x0401 | |||||
#define SSL_SIGN_RSA_PKCS1_SHA384 0x0501 | |||||
#define SSL_SIGN_RSA_PKCS1_SHA512 0x0601 | |||||
#define SSL_SIGN_ECDSA_SHA1 0x0203 | |||||
#define SSL_SIGN_ECDSA_SECP256R1_SHA256 0x0403 | |||||
#define SSL_SIGN_ECDSA_SECP384R1_SHA384 0x0503 | |||||
#define SSL_SIGN_ECDSA_SECP521R1_SHA512 0x0603 | |||||
/* Flag set for unrecognised algorithms */ | /* Flag set for unrecognised algorithms */ | ||||
#define TLSEXT_nid_unknown 0x1000000 | #define TLSEXT_nid_unknown 0x1000000 | ||||
@@ -1311,17 +1311,16 @@ static int ssl3_get_server_key_exchange(SSL *ssl) { | |||||
const EVP_MD *md = NULL; | const EVP_MD *md = NULL; | ||||
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | ||||
uint8_t hash, signature; | |||||
if (!CBS_get_u8(&server_key_exchange, &hash) || | |||||
!CBS_get_u8(&server_key_exchange, &signature)) { | |||||
uint16_t signature_algorithm; | |||||
if (!CBS_get_u16(&server_key_exchange, &signature_algorithm)) { | |||||
al = SSL_AD_DECODE_ERROR; | al = SSL_AD_DECODE_ERROR; | ||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | ||||
goto f_err; | goto f_err; | ||||
} | } | ||||
if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature, pkey)) { | |||||
if (!tls12_check_peer_sigalg(ssl, &md, &al, signature_algorithm, pkey)) { | |||||
goto f_err; | goto f_err; | ||||
} | } | ||||
ssl->s3->tmp.server_key_exchange_hash = hash; | |||||
ssl->s3->tmp.peer_signature_algorithm = signature_algorithm; | |||||
} else if (pkey->type == EVP_PKEY_RSA) { | } else if (pkey->type == EVP_PKEY_RSA) { | ||||
md = EVP_md5_sha1(); | md = EVP_md5_sha1(); | ||||
} else { | } else { | ||||
@@ -1823,7 +1822,7 @@ static int ssl3_send_cert_verify(SSL *ssl) { | |||||
const EVP_MD *md = NULL; | const EVP_MD *md = NULL; | ||||
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | ||||
md = tls1_choose_signing_digest(ssl); | md = tls1_choose_signing_digest(ssl); | ||||
if (!tls12_add_sigandhash(ssl, &body, md)) { | |||||
if (!tls12_add_sigalg(ssl, &body, md)) { | |||||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | ||||
goto err; | goto err; | ||||
} | } | ||||
@@ -1254,7 +1254,7 @@ static int ssl3_send_server_key_exchange(SSL *ssl) { | |||||
const EVP_MD *md; | const EVP_MD *md; | ||||
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | ||||
md = tls1_choose_signing_digest(ssl); | md = tls1_choose_signing_digest(ssl); | ||||
if (!tls12_add_sigandhash(ssl, &body, md)) { | |||||
if (!tls12_add_sigalg(ssl, &body, md)) { | |||||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | ||||
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); | ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); | ||||
goto err; | goto err; | ||||
@@ -1335,16 +1335,22 @@ static int add_cert_types(SSL *ssl, CBB *cbb) { | |||||
/* Get configured signature algorithms. */ | /* Get configured signature algorithms. */ | ||||
int have_rsa_sign = 0; | int have_rsa_sign = 0; | ||||
int have_ecdsa_sign = 0; | int have_ecdsa_sign = 0; | ||||
const uint8_t *sig; | |||||
size_t siglen = tls12_get_psigalgs(ssl, &sig); | |||||
const uint16_t *sig_algs; | |||||
size_t sig_algs_len = tls12_get_psigalgs(ssl, &sig_algs); | |||||
size_t i; | size_t i; | ||||
for (i = 0; i < siglen; i += 2, sig += 2) { | |||||
switch (sig[1]) { | |||||
case TLSEXT_signature_rsa: | |||||
for (i = 0; i < sig_algs_len; i++) { | |||||
switch (sig_algs[i]) { | |||||
case SSL_SIGN_RSA_PKCS1_SHA512: | |||||
case SSL_SIGN_RSA_PKCS1_SHA384: | |||||
case SSL_SIGN_RSA_PKCS1_SHA256: | |||||
case SSL_SIGN_RSA_PKCS1_SHA1: | |||||
have_rsa_sign = 1; | have_rsa_sign = 1; | ||||
break; | break; | ||||
case TLSEXT_signature_ecdsa: | |||||
case SSL_SIGN_ECDSA_SECP521R1_SHA512: | |||||
case SSL_SIGN_ECDSA_SECP384R1_SHA384: | |||||
case SSL_SIGN_ECDSA_SECP256R1_SHA256: | |||||
case SSL_SIGN_ECDSA_SHA1: | |||||
have_ecdsa_sign = 1; | have_ecdsa_sign = 1; | ||||
break; | break; | ||||
} | } | ||||
@@ -1378,12 +1384,18 @@ static int ssl3_send_certificate_request(SSL *ssl) { | |||||
} | } | ||||
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | ||||
const uint8_t *sigalgs; | |||||
const uint16_t *sigalgs; | |||||
size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs); | size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs); | ||||
if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) || | |||||
!CBB_add_bytes(&sigalgs_cbb, sigalgs, sigalgs_len)) { | |||||
if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) { | |||||
goto err; | goto err; | ||||
} | } | ||||
size_t i; | |||||
for (i = 0; i < sigalgs_len; i++) { | |||||
if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) { | |||||
goto err; | |||||
} | |||||
} | |||||
} | } | ||||
STACK_OF(X509_NAME) *sk = SSL_get_client_CA_list(ssl); | STACK_OF(X509_NAME) *sk = SSL_get_client_CA_list(ssl); | ||||
@@ -1888,16 +1900,16 @@ static int ssl3_get_cert_verify(SSL *ssl) { | |||||
/* Determine the digest type if needbe. */ | /* Determine the digest type if needbe. */ | ||||
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { | ||||
uint8_t hash, signature_type; | |||||
if (!CBS_get_u8(&certificate_verify, &hash) || | |||||
!CBS_get_u8(&certificate_verify, &signature_type)) { | |||||
uint16_t signature_algorithm; | |||||
if (!CBS_get_u16(&certificate_verify, &signature_algorithm)) { | |||||
al = SSL_AD_DECODE_ERROR; | al = SSL_AD_DECODE_ERROR; | ||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | ||||
goto f_err; | goto f_err; | ||||
} | } | ||||
if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature_type, pkey)) { | |||||
if (!tls12_check_peer_sigalg(ssl, &md, &al, signature_algorithm, pkey)) { | |||||
goto f_err; | goto f_err; | ||||
} | } | ||||
ssl->s3->tmp.peer_signature_algorithm = signature_algorithm; | |||||
} | } | ||||
/* Compute the digest. */ | /* Compute the digest. */ | ||||
@@ -747,12 +747,6 @@ enum ssl_hash_message_t { | |||||
ssl_hash_message, | ssl_hash_message, | ||||
}; | }; | ||||
/* Structure containing decoded values of signature algorithms extension */ | |||||
typedef struct tls_sigalgs_st { | |||||
uint8_t rsign; | |||||
uint8_t rhash; | |||||
} TLS_SIGALGS; | |||||
typedef struct cert_st { | typedef struct cert_st { | ||||
X509 *x509; | X509 *x509; | ||||
EVP_PKEY *privatekey; | EVP_PKEY *privatekey; | ||||
@@ -777,7 +771,7 @@ typedef struct cert_st { | |||||
/* peer_sigalgs are the algorithm/hash pairs that the peer supports. These | /* peer_sigalgs are the algorithm/hash pairs that the peer supports. These | ||||
* are taken from the contents of signature algorithms extension for a server | * are taken from the contents of signature algorithms extension for a server | ||||
* or from the CertificateRequest for a client. */ | * or from the CertificateRequest for a client. */ | ||||
TLS_SIGALGS *peer_sigalgs; | |||||
uint16_t *peer_sigalgs; | |||||
/* peer_sigalgslen is the number of entries in |peer_sigalgs|. */ | /* peer_sigalgslen is the number of entries in |peer_sigalgs|. */ | ||||
size_t peer_sigalgslen; | size_t peer_sigalgslen; | ||||
@@ -1142,13 +1136,10 @@ int tls_process_ticket(SSL *ssl, SSL_SESSION **out_session, | |||||
size_t ticket_len, const uint8_t *session_id, | size_t ticket_len, const uint8_t *session_id, | ||||
size_t session_id_len); | size_t session_id_len); | ||||
/* tls12_add_sigandhash assembles the SignatureAndHashAlgorithm corresponding to | |||||
* |ssl|'s private key and |md|. The two-byte value is written to |out|. It | |||||
* returns one on success and zero on failure. */ | |||||
int tls12_add_sigandhash(SSL *ssl, CBB *out, const EVP_MD *md); | |||||
int tls12_get_sigid(int pkey_type); | |||||
const EVP_MD *tls12_get_hash(uint8_t hash_alg); | |||||
/* tls12_add_sigalg picks the SignatureScheme corresponding to |ssl|'s private | |||||
* key and |md| and writes it to |out|. It returns one on success and zero on | |||||
* failure. */ | |||||
int tls12_add_sigalg(SSL *ssl, CBB *out, const EVP_MD *md); | |||||
/* tls1_channel_id_hash computes the hash to be signed by Channel ID and writes | /* tls1_channel_id_hash computes the hash to be signed by Channel ID and writes | ||||
* it to |out|, which must contain at least |EVP_MAX_MD_SIZE| bytes. It returns | * it to |out|, which must contain at least |EVP_MAX_MD_SIZE| bytes. It returns | ||||
@@ -1220,14 +1211,14 @@ int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *sigalgs); | |||||
* based on the peer's preferences the digests supported. */ | * based on the peer's preferences the digests supported. */ | ||||
const EVP_MD *tls1_choose_signing_digest(SSL *ssl); | const EVP_MD *tls1_choose_signing_digest(SSL *ssl); | ||||
size_t tls12_get_psigalgs(SSL *ssl, const uint8_t **psigs); | |||||
size_t tls12_get_psigalgs(SSL *ssl, const uint16_t **psigs); | |||||
/* tls12_check_peer_sigalg checks that |hash| and |signature| are consistent | |||||
* with |pkey| and |ssl|'s sent, supported signature algorithms and, if so, | |||||
/* tls12_check_peer_sigalg checks that |signature_algorithm| is consistent with | |||||
* the |pkey| and |ssl|'s sent, supported signature algorithms and, if so, | |||||
* writes the relevant digest into |*out_md| and returns 1. Otherwise it | * writes the relevant digest into |*out_md| and returns 1. Otherwise it | ||||
* returns 0 and writes an alert into |*out_alert|. */ | * returns 0 and writes an alert into |*out_alert|. */ | ||||
int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *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); | |||||
uint16_t signature_algorithm, EVP_PKEY *pkey); | |||||
void ssl_set_client_disabled(SSL *ssl); | void ssl_set_client_disabled(SSL *ssl); | ||||
#endif /* OPENSSL_HEADER_SSL_INTERNAL_H */ | #endif /* OPENSSL_HEADER_SSL_INTERNAL_H */ |
@@ -2812,8 +2812,12 @@ uint64_t SSL_get_write_sequence(const SSL *ssl) { | |||||
return ret; | return ret; | ||||
} | } | ||||
uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl) { | |||||
return ssl->s3->tmp.peer_signature_algorithm; | |||||
} | |||||
uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl) { | uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl) { | ||||
return ssl->s3->tmp.server_key_exchange_hash; | |||||
return (uint8_t) (SSL_get_peer_signature_algorithm(ssl) >> 8); | |||||
} | } | ||||
size_t SSL_get_client_random(const SSL *ssl, uint8_t *out, size_t max_out) { | size_t SSL_get_client_random(const SSL *ssl, uint8_t *out, size_t max_out) { | ||||
@@ -498,39 +498,36 @@ done: | |||||
/* List of supported signature algorithms and hashes. Should make this | /* List of supported signature algorithms and hashes. Should make this | ||||
* customisable at some point, for now include everything we support. */ | * customisable at some point, for now include everything we support. */ | ||||
#define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa, | |||||
static const uint16_t kDefaultSignatureAlgorithms[] = { | |||||
SSL_SIGN_RSA_PKCS1_SHA512, | |||||
SSL_SIGN_ECDSA_SECP521R1_SHA512, | |||||
#define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa, | |||||
SSL_SIGN_RSA_PKCS1_SHA384, | |||||
SSL_SIGN_ECDSA_SECP384R1_SHA384, | |||||
#define tlsext_sigalg(md) tlsext_sigalg_rsa(md) tlsext_sigalg_ecdsa(md) | |||||
SSL_SIGN_RSA_PKCS1_SHA256, | |||||
SSL_SIGN_ECDSA_SECP256R1_SHA256, | |||||
static const uint8_t tls12_sigalgs[] = { | |||||
tlsext_sigalg(TLSEXT_hash_sha512) | |||||
tlsext_sigalg(TLSEXT_hash_sha384) | |||||
tlsext_sigalg(TLSEXT_hash_sha256) | |||||
tlsext_sigalg(TLSEXT_hash_sha1) | |||||
SSL_SIGN_RSA_PKCS1_SHA1, | |||||
SSL_SIGN_ECDSA_SHA1, | |||||
}; | }; | ||||
size_t tls12_get_psigalgs(SSL *ssl, const uint8_t **psigs) { | |||||
*psigs = tls12_sigalgs; | |||||
return sizeof(tls12_sigalgs); | |||||
size_t tls12_get_psigalgs(SSL *ssl, const uint16_t **psigs) { | |||||
*psigs = kDefaultSignatureAlgorithms; | |||||
return sizeof(kDefaultSignatureAlgorithms) / | |||||
sizeof(kDefaultSignatureAlgorithms[0]); | |||||
} | } | ||||
static int tls12_get_pkey_type(uint16_t sig_alg); | |||||
static const EVP_MD *tls12_get_hash(uint16_t sig_alg); | |||||
int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *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) { | |||||
const uint8_t *sent_sigs; | |||||
uint16_t signature_algorithm, EVP_PKEY *pkey) { | |||||
const uint16_t *sent_sigs; | |||||
size_t sent_sigslen, i; | size_t sent_sigslen, i; | ||||
int sigalg = tls12_get_sigid(pkey->type); | |||||
/* Should never happen */ | |||||
if (sigalg == -1) { | |||||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||||
*out_alert = SSL_AD_INTERNAL_ERROR; | |||||
return 0; | |||||
} | |||||
/* Check key type is consistent with signature */ | /* Check key type is consistent with signature */ | ||||
if (sigalg != signature) { | |||||
if (pkey->type != tls12_get_pkey_type(signature_algorithm)) { | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); | OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); | ||||
*out_alert = SSL_AD_ILLEGAL_PARAMETER; | *out_alert = SSL_AD_ILLEGAL_PARAMETER; | ||||
return 0; | return 0; | ||||
@@ -538,8 +535,8 @@ int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert, | |||||
/* Check signature matches a type we sent */ | /* Check signature matches a type we sent */ | ||||
sent_sigslen = tls12_get_psigalgs(ssl, &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]) { | |||||
for (i = 0; i < sent_sigslen; i++) { | |||||
if (signature_algorithm == sent_sigs[i]) { | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -550,7 +547,7 @@ int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert, | |||||
return 0; | return 0; | ||||
} | } | ||||
*out_md = tls12_get_hash(hash); | |||||
*out_md = tls12_get_hash(signature_algorithm); | |||||
if (*out_md == NULL) { | if (*out_md == NULL) { | ||||
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_DIGEST); | OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_DIGEST); | ||||
*out_alert = SSL_AD_ILLEGAL_PARAMETER; | *out_alert = SSL_AD_ILLEGAL_PARAMETER; | ||||
@@ -566,7 +563,7 @@ int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert, | |||||
* settings. */ | * settings. */ | ||||
void ssl_set_client_disabled(SSL *ssl) { | void ssl_set_client_disabled(SSL *ssl) { | ||||
CERT *c = ssl->cert; | CERT *c = ssl->cert; | ||||
const uint8_t *sigalgs; | |||||
const uint16_t *sigalgs; | |||||
size_t i, sigalgslen; | size_t i, sigalgslen; | ||||
int have_rsa = 0, have_ecdsa = 0; | int have_rsa = 0, have_ecdsa = 0; | ||||
c->mask_a = 0; | c->mask_a = 0; | ||||
@@ -575,13 +572,19 @@ void ssl_set_client_disabled(SSL *ssl) { | |||||
/* Now go through all signature algorithms seeing if we support any for RSA, | /* Now go through all signature algorithms seeing if we support any for RSA, | ||||
* DSA, ECDSA. Do this for all versions not just TLS 1.2. */ | * DSA, ECDSA. Do this for all versions not just TLS 1.2. */ | ||||
sigalgslen = tls12_get_psigalgs(ssl, &sigalgs); | sigalgslen = tls12_get_psigalgs(ssl, &sigalgs); | ||||
for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) { | |||||
switch (sigalgs[1]) { | |||||
case TLSEXT_signature_rsa: | |||||
for (i = 0; i < sigalgslen; i++) { | |||||
switch (sigalgs[i]) { | |||||
case SSL_SIGN_RSA_PKCS1_SHA512: | |||||
case SSL_SIGN_RSA_PKCS1_SHA384: | |||||
case SSL_SIGN_RSA_PKCS1_SHA256: | |||||
case SSL_SIGN_RSA_PKCS1_SHA1: | |||||
have_rsa = 1; | have_rsa = 1; | ||||
break; | break; | ||||
case TLSEXT_signature_ecdsa: | |||||
case SSL_SIGN_ECDSA_SECP521R1_SHA512: | |||||
case SSL_SIGN_ECDSA_SECP384R1_SHA384: | |||||
case SSL_SIGN_ECDSA_SECP256R1_SHA256: | |||||
case SSL_SIGN_ECDSA_SHA1: | |||||
have_ecdsa = 1; | have_ecdsa = 1; | ||||
break; | break; | ||||
} | } | ||||
@@ -1043,15 +1046,24 @@ static int ext_sigalgs_add_clienthello(SSL *ssl, CBB *out) { | |||||
return 1; | return 1; | ||||
} | } | ||||
const uint8_t *sigalgs_data; | |||||
const uint16_t *sigalgs_data; | |||||
const size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs_data); | const size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs_data); | ||||
CBB contents, sigalgs; | CBB contents, sigalgs; | ||||
if (!CBB_add_u16(out, TLSEXT_TYPE_signature_algorithms) || | if (!CBB_add_u16(out, TLSEXT_TYPE_signature_algorithms) || | ||||
!CBB_add_u16_length_prefixed(out, &contents) || | !CBB_add_u16_length_prefixed(out, &contents) || | ||||
!CBB_add_u16_length_prefixed(&contents, &sigalgs) || | |||||
!CBB_add_bytes(&sigalgs, sigalgs_data, sigalgs_len) || | |||||
!CBB_flush(out)) { | |||||
!CBB_add_u16_length_prefixed(&contents, &sigalgs)) { | |||||
return 0; | |||||
} | |||||
size_t i; | |||||
for (i = 0; i < sigalgs_len; i++) { | |||||
if (!CBB_add_u16(&sigalgs, sigalgs_data[i])) { | |||||
return 0; | |||||
} | |||||
} | |||||
if (!CBB_flush(out)) { | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -2516,51 +2528,44 @@ done: | |||||
return ret; | return ret; | ||||
} | } | ||||
/* Tables to translate from NIDs to TLS v1.2 ids */ | |||||
/* Tables to translate from NIDs to TLS v1.2 ids | |||||
* | |||||
* TODO(svaldez): Remove decomposition of SignatureAlgorithm IDs. */ | |||||
typedef struct { | typedef struct { | ||||
int nid; | |||||
int id; | |||||
int pkey_type; | |||||
int md_type; | |||||
uint16_t id; | |||||
} tls12_lookup; | } tls12_lookup; | ||||
static const tls12_lookup tls12_md[] = { | |||||
{NID_sha1, TLSEXT_hash_sha1}, | |||||
{NID_sha256, TLSEXT_hash_sha256}, | |||||
{NID_sha384, TLSEXT_hash_sha384}, | |||||
{NID_sha512, TLSEXT_hash_sha512}, | |||||
static const tls12_lookup kTLS12SignatureAlgorithmIDs[] = { | |||||
{EVP_PKEY_RSA, NID_sha512, SSL_SIGN_RSA_PKCS1_SHA512}, | |||||
{EVP_PKEY_EC, NID_sha512, SSL_SIGN_ECDSA_SECP521R1_SHA512}, | |||||
{EVP_PKEY_RSA, NID_sha384, SSL_SIGN_RSA_PKCS1_SHA384}, | |||||
{EVP_PKEY_EC, NID_sha384, SSL_SIGN_ECDSA_SECP384R1_SHA384}, | |||||
{EVP_PKEY_RSA, NID_sha256, SSL_SIGN_RSA_PKCS1_SHA256}, | |||||
{EVP_PKEY_EC, NID_sha256, SSL_SIGN_ECDSA_SECP256R1_SHA256}, | |||||
{EVP_PKEY_RSA, NID_sha1, SSL_SIGN_RSA_PKCS1_SHA1}, | |||||
{EVP_PKEY_EC, NID_sha1, SSL_SIGN_ECDSA_SHA1}, | |||||
}; | }; | ||||
static const tls12_lookup tls12_sig[] = {{EVP_PKEY_RSA, TLSEXT_signature_rsa}, | |||||
{EVP_PKEY_EC, TLSEXT_signature_ecdsa}}; | |||||
int tls12_add_sigalg(SSL *ssl, CBB *out, const EVP_MD *md) { | |||||
int pkey_type = ssl_private_key_type(ssl); | |||||
int md_type = EVP_MD_type(md); | |||||
static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen) { | |||||
size_t i; | size_t i; | ||||
for (i = 0; i < tlen; i++) { | |||||
if (table[i].nid == nid) { | |||||
return table[i].id; | |||||
for (i = 0; i < sizeof(kTLS12SignatureAlgorithmIDs) / sizeof(tls12_lookup); | |||||
i++) { | |||||
if (kTLS12SignatureAlgorithmIDs[i].pkey_type == pkey_type && | |||||
kTLS12SignatureAlgorithmIDs[i].md_type == md_type) { | |||||
return CBB_add_u16(out, kTLS12SignatureAlgorithmIDs[i].id); | |||||
} | } | ||||
} | } | ||||
return -1; | |||||
} | |||||
int tls12_get_sigid(int pkey_type) { | |||||
return tls12_find_id(pkey_type, tls12_sig, | |||||
sizeof(tls12_sig) / sizeof(tls12_lookup)); | |||||
} | |||||
int tls12_add_sigandhash(SSL *ssl, CBB *out, const EVP_MD *md) { | |||||
int md_id = tls12_find_id(EVP_MD_type(md), tls12_md, | |||||
sizeof(tls12_md) / sizeof(tls12_lookup)); | |||||
int sig_id = tls12_get_sigid(ssl_private_key_type(ssl)); | |||||
return md_id != -1 && | |||||
sig_id != -1 && | |||||
CBB_add_u8(out, (uint8_t)md_id) && | |||||
CBB_add_u8(out, (uint8_t)sig_id); | |||||
return 0; | |||||
} | } | ||||
const EVP_MD *tls12_get_hash(uint8_t hash_alg) { | |||||
switch (hash_alg) { | |||||
static const EVP_MD *tls12_get_hash(uint16_t sig_alg) { | |||||
switch (sig_alg >> 8) { | |||||
case TLSEXT_hash_sha1: | case TLSEXT_hash_sha1: | ||||
return EVP_sha1(); | return EVP_sha1(); | ||||
@@ -2580,8 +2585,8 @@ const EVP_MD *tls12_get_hash(uint8_t hash_alg) { | |||||
/* tls12_get_pkey_type returns the EVP_PKEY type corresponding to TLS signature | /* tls12_get_pkey_type returns the EVP_PKEY type corresponding to TLS signature | ||||
* algorithm |sig_alg|. It returns -1 if the type is unknown. */ | * algorithm |sig_alg|. It returns -1 if the type is unknown. */ | ||||
static int tls12_get_pkey_type(uint8_t sig_alg) { | |||||
switch (sig_alg) { | |||||
static int tls12_get_pkey_type(uint16_t sig_alg) { | |||||
switch (sig_alg & 0xff) { | |||||
case TLSEXT_signature_rsa: | case TLSEXT_signature_rsa: | ||||
return EVP_PKEY_RSA; | return EVP_PKEY_RSA; | ||||
@@ -2593,9 +2598,6 @@ static int tls12_get_pkey_type(uint8_t sig_alg) { | |||||
} | } | ||||
} | } | ||||
OPENSSL_COMPILE_ASSERT(sizeof(TLS_SIGALGS) == 2, | |||||
sizeof_tls_sigalgs_is_not_two); | |||||
int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *in_sigalgs) { | int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *in_sigalgs) { | ||||
/* Extension ignored for inappropriate versions */ | /* Extension ignored for inappropriate versions */ | ||||
if (ssl3_protocol_version(ssl) < TLS1_2_VERSION) { | if (ssl3_protocol_version(ssl) < TLS1_2_VERSION) { | ||||
@@ -2620,9 +2622,9 @@ int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *in_sigalgs) { | |||||
return 1; | return 1; | ||||
} | } | ||||
/* This multiplication doesn't overflow because sizeof(TLS_SIGALGS) is two | |||||
* (statically asserted above) and we just divided |num_sigalgs| by two. */ | |||||
cert->peer_sigalgs = OPENSSL_malloc(num_sigalgs * sizeof(TLS_SIGALGS)); | |||||
/* This multiplication doesn't overflow because sizeof(uint16_t) is two | |||||
* and we just divided |num_sigalgs| by two. */ | |||||
cert->peer_sigalgs = OPENSSL_malloc(num_sigalgs * sizeof(uint16_t)); | |||||
if (cert->peer_sigalgs == NULL) { | if (cert->peer_sigalgs == NULL) { | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -2633,9 +2635,7 @@ int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *in_sigalgs) { | |||||
size_t i; | size_t i; | ||||
for (i = 0; i < num_sigalgs; i++) { | for (i = 0; i < num_sigalgs; i++) { | ||||
TLS_SIGALGS *const sigalg = &cert->peer_sigalgs[i]; | |||||
if (!CBS_get_u8(&sigalgs, &sigalg->rhash) || | |||||
!CBS_get_u8(&sigalgs, &sigalg->rsign)) { | |||||
if (!CBS_get_u16(&sigalgs, &cert->peer_sigalgs[i])) { | |||||
return 0; | return 0; | ||||
} | } | ||||
} | } | ||||
@@ -2662,10 +2662,10 @@ const EVP_MD *tls1_choose_signing_digest(SSL *ssl) { | |||||
for (i = 0; i < num_digest_nids; i++) { | for (i = 0; i < num_digest_nids; i++) { | ||||
const int digest_nid = digest_nids[i]; | const int digest_nid = digest_nids[i]; | ||||
for (j = 0; j < cert->peer_sigalgslen; j++) { | for (j = 0; j < cert->peer_sigalgslen; j++) { | ||||
const EVP_MD *md = tls12_get_hash(cert->peer_sigalgs[j].rhash); | |||||
const EVP_MD *md = tls12_get_hash(cert->peer_sigalgs[j]); | |||||
if (md == NULL || | if (md == NULL || | ||||
digest_nid != EVP_MD_type(md) || | digest_nid != EVP_MD_type(md) || | ||||
tls12_get_pkey_type(cert->peer_sigalgs[j].rsign) != type) { | |||||
tls12_get_pkey_type(cert->peer_sigalgs[j]) != type) { | |||||
continue; | continue; | ||||
} | } | ||||