X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=ssl%2Ft1_lib.c;h=3e00cdbfd03f89e100d7f44c40817460d4333f1c;hb=a34a9df0712ac27256ec48e6f88c61064613ac08;hp=d6a841a82fa4241d0c7f64f46b2384183268876a;hpb=8fd19b20beca97a2ef804058f099cf54f12f7614;p=openssl.git diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index d6a841a82f..3e00cdbfd0 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -730,16 +730,16 @@ static const SIGALG_LOOKUP sigalg_lookup_tbl[] = { NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN, NID_undef, NID_undef}, {"rsa_pkcs1_sha256", TLSEXT_SIGALG_rsa_pkcs1_sha256, - NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA_SIGN, + NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA, NID_sha256WithRSAEncryption, NID_undef}, {"rsa_pkcs1_sha384", TLSEXT_SIGALG_rsa_pkcs1_sha384, - NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA_SIGN, + NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA, NID_sha384WithRSAEncryption, NID_undef}, {"rsa_pkcs1_sha512", TLSEXT_SIGALG_rsa_pkcs1_sha512, - NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA_SIGN, + NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA, NID_sha512WithRSAEncryption, NID_undef}, {"rsa_pkcs1_sha1", TLSEXT_SIGALG_rsa_pkcs1_sha1, - NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA_SIGN, + NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA, NID_sha1WithRSAEncryption, NID_undef}, #ifndef OPENSSL_NO_DSA {NULL, TLSEXT_SIGALG_dsa_sha256, @@ -770,6 +770,26 @@ static const SIGALG_LOOKUP sigalg_lookup_tbl[] = { NID_undef, NID_undef} #endif }; +/* Legacy sigalgs for TLS < 1.2 RSA TLS signatures */ +static const SIGALG_LOOKUP legacy_rsa_sigalg = { + "rsa_pkcs1_md5_sha1", 0, + NID_md5_sha1, SSL_MD_MD5_SHA1_IDX, + EVP_PKEY_RSA, SSL_PKEY_RSA, + NID_undef, NID_undef +}; + +/* + * Default signature algorithm values used if signature algorithms not present. + * From RFC5246. Note: order must match certificate index order. + */ +static const uint16_t tls_default_sigalg[] = { + TLSEXT_SIGALG_rsa_pkcs1_sha1, /* SSL_PKEY_RSA */ + TLSEXT_SIGALG_dsa_sha1, /* SSL_PKEY_DSA_SIGN */ + TLSEXT_SIGALG_ecdsa_sha1, /* SSL_PKEY_ECC */ + TLSEXT_SIGALG_gostr34102001_gostr3411, /* SSL_PKEY_GOST01 */ + TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, /* SSL_PKEY_GOST12_256 */ + TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 /* SSL_PKEY_GOST12_512 */ +}; /* Lookup TLS signature algorithm */ static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg) @@ -784,6 +804,35 @@ static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg) } return NULL; } +/* + * Return a signature algorithm for TLS < 1.2 where the signature type + * is fixed by the certificate type. + */ +static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx) +{ + if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg)) + return NULL; + if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) { + const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]); + + if (lu == NULL || ssl_md(lu->hash_idx) == NULL) { + return NULL; + } + return lu; + } + return &legacy_rsa_sigalg; +} +/* Set peer sigalg based key type */ +int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey) +{ + int idx = ssl_cert_type(NULL, pkey); + + const SIGALG_LOOKUP *lu = tls1_get_legacy_sigalg(s, idx); + if (lu == NULL) + return 0; + s->s3->tmp.peer_sigalg = lu; + return 1; +} static int tls_sigalg_get_sig(uint16_t sigalg) { @@ -868,7 +917,7 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey) if (SSL_IS_TLS13(s)) { /* For TLS 1.3 check curve matches signature algorithm */ - if (curve != lu->curve) { + if (lu->curve != NID_undef && curve != lu->curve) { SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE); return 0; } @@ -1022,10 +1071,9 @@ void ssl_set_default_md(SSL *s) #endif #ifndef OPENSSL_NO_RSA if (SSL_USE_SIGALGS(s)) - pmd[SSL_PKEY_RSA_SIGN] = ssl_md(SSL_MD_SHA1_IDX); + pmd[SSL_PKEY_RSA] = ssl_md(SSL_MD_SHA1_IDX); else - pmd[SSL_PKEY_RSA_SIGN] = ssl_md(SSL_MD_MD5_SHA1_IDX); - pmd[SSL_PKEY_RSA_ENC] = pmd[SSL_PKEY_RSA_SIGN]; + pmd[SSL_PKEY_RSA] = ssl_md(SSL_MD_MD5_SHA1_IDX); #endif #ifndef OPENSSL_NO_EC pmd[SSL_PKEY_ECC] = ssl_md(SSL_MD_SHA1_IDX); @@ -1253,8 +1301,8 @@ TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick, } /* Attempt to decrypt session data */ /* Move p after IV to start of encrypted ticket, update length */ - p = etick + 16 + EVP_CIPHER_CTX_iv_length(ctx); - eticklen -= 16 + EVP_CIPHER_CTX_iv_length(ctx); + p = etick + TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx); + eticklen -= TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx); sdec = OPENSSL_malloc(eticklen); if (sdec == NULL || EVP_DecryptUpdate(ctx, sdec, &slen, p, (int)eticklen) <= 0) { @@ -1358,13 +1406,13 @@ static int tls12_get_pkey_idx(int sig_nid) switch (sig_nid) { #ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: - return SSL_PKEY_RSA_SIGN; + return SSL_PKEY_RSA; /* * For now return RSA key for PSS. When we support PSS only keys * this will need to be updated. */ case EVP_PKEY_RSA_PSS: - return SSL_PKEY_RSA_SIGN; + return SSL_PKEY_RSA; #endif #ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: @@ -1605,10 +1653,6 @@ int tls1_process_sigalgs(SSL *s) md = ssl_md(sigptr->hash_idx); pmd[idx] = md; pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN; - if (idx == SSL_PKEY_RSA_SIGN) { - pvalid[SSL_PKEY_RSA_ENC] = CERT_PKEY_EXPLICIT_SIGN; - pmd[SSL_PKEY_RSA_ENC] = md; - } } } /* @@ -1626,9 +1670,8 @@ int tls1_process_sigalgs(SSL *s) pmd[SSL_PKEY_DSA_SIGN] = EVP_sha1(); #endif #ifndef OPENSSL_NO_RSA - if (pmd[SSL_PKEY_RSA_SIGN] == NULL) { - pmd[SSL_PKEY_RSA_SIGN] = EVP_sha1(); - pmd[SSL_PKEY_RSA_ENC] = EVP_sha1(); + if (pmd[SSL_PKEY_RSA] == NULL) { + pmd[SSL_PKEY_RSA] = EVP_sha1(); } #endif #ifndef OPENSSL_NO_EC @@ -1945,8 +1988,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, /* If no sigalgs extension use defaults from RFC5246 */ else { switch (idx) { - case SSL_PKEY_RSA_ENC: - case SSL_PKEY_RSA_SIGN: + case SSL_PKEY_RSA: rsign = EVP_PKEY_RSA; default_nid = NID_sha1WithRSAEncryption; break; @@ -2133,8 +2175,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, /* Set validity of certificates in an SSL structure */ void tls1_set_cert_validity(SSL *s) { - tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_ENC); - tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_SIGN); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA); tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN); tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC); tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01); @@ -2160,8 +2201,9 @@ DH *ssl_get_auto_dh(SSL *s) else dh_secbits = 80; } else { - CERT_PKEY *cpk = ssl_get_server_send_pkey(s); - dh_secbits = EVP_PKEY_security_bits(cpk->privatekey); + if (s->s3->tmp.cert == NULL) + return NULL; + dh_secbits = EVP_PKEY_security_bits(s->s3->tmp.cert->privatekey); } if (dh_secbits >= 128) { @@ -2276,8 +2318,11 @@ 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. */ -int tls_choose_sigalg(SSL *s) +int tls_choose_sigalg(SSL *s, int *al) { + int idx; + const SIGALG_LOOKUP *lu = NULL; + if (SSL_IS_TLS13(s)) { size_t i; #ifndef OPENSSL_NO_EC @@ -2286,51 +2331,119 @@ int tls_choose_sigalg(SSL *s) /* Look for a certificate matching shared sigaglgs */ for (i = 0; i < s->cert->shared_sigalgslen; i++) { - const SIGALG_LOOKUP *lu = s->cert->shared_sigalgs[i]; - int idx; - const EVP_MD *md; - CERT_PKEY *c; + lu = s->cert->shared_sigalgs[i]; /* Skip RSA if not PSS */ if (lu->sig == EVP_PKEY_RSA) continue; - md = ssl_md(lu->hash_idx); - if (md == NULL) + if (ssl_md(lu->hash_idx) == NULL) continue; idx = lu->sig_idx; - c = &s->cert->pkeys[idx]; - if (c->x509 == NULL || c->privatekey == NULL) { - if (idx != SSL_PKEY_RSA_SIGN) + if (!ssl_has_cert(s, idx)) continue; - idx = SSL_PKEY_RSA_ENC; - c = s->cert->pkeys + idx; - if (c->x509 == NULL || c->privatekey == NULL) - continue; - } if (lu->sig == EVP_PKEY_EC) { #ifndef OPENSSL_NO_EC if (curve == -1) { - EC_KEY *ec = EVP_PKEY_get0_EC_KEY(c->privatekey); + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[idx].privatekey); curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); } - if (curve != lu->curve) + if (lu->curve != NID_undef && curve != lu->curve) continue; #else continue; #endif } - s->s3->tmp.sigalg = lu; - s->s3->tmp.cert_idx = idx; - s->s3->tmp.md[idx] = md; - s->cert->key = s->cert->pkeys + idx; + break; + } + if (i == s->cert->shared_sigalgslen) { + *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; } - return 0; + 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 { + *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; + } + + if (SSL_USE_SIGALGS(s)) { + if (s->s3->tmp.peer_sigalgs != NULL) { + size_t i; + + /* + * Find highest preference signature algorithm matching + * cert type + */ + for (i = 0; i < s->cert->shared_sigalgslen; i++) { + lu = s->cert->shared_sigalgs[i]; + if (lu->sig_idx == idx) + break; + if (idx == SSL_PKEY_RSA && lu->sig == EVP_PKEY_RSA_PSS) + break; + } + if (i == s->cert->shared_sigalgslen) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + /* + * If we have no sigalg use defaults + */ + const uint16_t *sent_sigs; + size_t sent_sigslen, i; + + if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Check signature matches a type we sent */ + sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs); + for (i = 0; i < sent_sigslen; i++, sent_sigs++) { + if (lu->sigalg == *sent_sigs) + break; + } + if (i == sent_sigslen) { + SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); + *al = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + } + } else { + if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR); + return 0; + } + } } - /* - * FIXME: could handle previous TLS versions in an appropriate way - * and tidy up certificate and signature algorithm handling. - */ + s->s3->tmp.cert = &s->cert->pkeys[idx]; + s->s3->tmp.sigalg = lu; return 1; }