Abort handshake if signature algorithm used not supported by peer.
This commit is contained in:
parent
d18b716d25
commit
ec4a50b3c3
7 changed files with 63 additions and 34 deletions
6
CHANGES
6
CHANGES
|
@ -4,6 +4,12 @@
|
||||||
|
|
||||||
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
|
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
|
||||||
|
|
||||||
|
*) If an attempt is made to use a signature algorithm not in the peer
|
||||||
|
preference list abort the handshake. If client has no suitable
|
||||||
|
signature algorithms in response to a certificate request do not
|
||||||
|
use the certificate.
|
||||||
|
[Steve Henson]
|
||||||
|
|
||||||
*) If server EC tmp key is not in client preference list abort handshake.
|
*) If server EC tmp key is not in client preference list abort handshake.
|
||||||
[Steve Henson]
|
[Steve Henson]
|
||||||
|
|
||||||
|
|
|
@ -1750,25 +1750,12 @@ int ssl3_get_key_exchange(SSL *s)
|
||||||
{
|
{
|
||||||
if (TLS1_get_version(s) >= TLS1_2_VERSION)
|
if (TLS1_get_version(s) >= TLS1_2_VERSION)
|
||||||
{
|
{
|
||||||
int sigalg = tls12_get_sigid(pkey);
|
int rv = tls12_check_peer_sigalg(&md, s, p, pkey);
|
||||||
/* Should never happen */
|
if (rv == -1)
|
||||||
if (sigalg == -1)
|
|
||||||
{
|
|
||||||
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
else if (rv == 0)
|
||||||
/* Check key type is consistent with signature */
|
|
||||||
if (sigalg != (int)p[1])
|
|
||||||
{
|
{
|
||||||
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_TYPE);
|
al = SSL_AD_DECODE_ERROR;
|
||||||
al=SSL_AD_DECODE_ERROR;
|
|
||||||
goto f_err;
|
|
||||||
}
|
|
||||||
md = tls12_get_hash(p[0]);
|
|
||||||
if (md == NULL)
|
|
||||||
{
|
|
||||||
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST);
|
|
||||||
al=SSL_AD_DECODE_ERROR;
|
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
#ifdef SSL_DEBUG
|
#ifdef SSL_DEBUG
|
||||||
|
@ -3161,13 +3148,17 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check a certificate can be used for client authentication. Currently
|
/* Check a certificate can be used for client authentication. Currently
|
||||||
* just check cert exists and if static DH client certificates can be used.
|
* check cert exists, if we have a suitable digest for TLS 1.2 and if
|
||||||
|
* static DH client certificates can be used.
|
||||||
*/
|
*/
|
||||||
static int ssl3_check_client_certificate(SSL *s)
|
static int ssl3_check_client_certificate(SSL *s)
|
||||||
{
|
{
|
||||||
unsigned long alg_k;
|
unsigned long alg_k;
|
||||||
if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey)
|
if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey)
|
||||||
return 0;
|
return 0;
|
||||||
|
/* If no suitable signature algorithm can't use certificate */
|
||||||
|
if (TLS1_get_version(s) >= TLS1_2_VERSION && !s->cert->key->digest)
|
||||||
|
return 0;
|
||||||
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
||||||
/* See if we can use client certificate for fixed DH */
|
/* See if we can use client certificate for fixed DH */
|
||||||
if (alg_k & (SSL_kDHr|SSL_kDHd))
|
if (alg_k & (SSL_kDHr|SSL_kDHd))
|
||||||
|
|
|
@ -3051,26 +3051,15 @@ int ssl3_get_cert_verify(SSL *s)
|
||||||
{
|
{
|
||||||
if (TLS1_get_version(s) >= TLS1_2_VERSION)
|
if (TLS1_get_version(s) >= TLS1_2_VERSION)
|
||||||
{
|
{
|
||||||
int sigalg = tls12_get_sigid(pkey);
|
int rv = tls12_check_peer_sigalg(&md, s, p, pkey);
|
||||||
/* Should never happen */
|
if (rv == -1)
|
||||||
if (sigalg == -1)
|
|
||||||
{
|
{
|
||||||
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
|
al = SSL_AD_INTERNAL_ERROR;
|
||||||
al=SSL_AD_INTERNAL_ERROR;
|
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
/* Check key type is consistent with signature */
|
else if (rv == 0)
|
||||||
if (sigalg != (int)p[1])
|
|
||||||
{
|
{
|
||||||
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_TYPE);
|
al = SSL_AD_DECODE_ERROR;
|
||||||
al=SSL_AD_DECODE_ERROR;
|
|
||||||
goto f_err;
|
|
||||||
}
|
|
||||||
md = tls12_get_hash(p[0]);
|
|
||||||
if (md == NULL)
|
|
||||||
{
|
|
||||||
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_UNKNOWN_DIGEST);
|
|
||||||
al=SSL_AD_DECODE_ERROR;
|
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
#ifdef SSL_DEBUG
|
#ifdef SSL_DEBUG
|
||||||
|
|
|
@ -2452,6 +2452,7 @@ void ERR_load_SSL_strings(void);
|
||||||
#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206
|
#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206
|
||||||
#define SSL_F_SSL_VERIFY_CERT_CHAIN 207
|
#define SSL_F_SSL_VERIFY_CERT_CHAIN 207
|
||||||
#define SSL_F_SSL_WRITE 208
|
#define SSL_F_SSL_WRITE 208
|
||||||
|
#define SSL_F_TLS12_CHECK_PEER_SIGALG 333
|
||||||
#define SSL_F_TLS1_CERT_VERIFY_MAC 286
|
#define SSL_F_TLS1_CERT_VERIFY_MAC 286
|
||||||
#define SSL_F_TLS1_CHANGE_CIPHER_STATE 209
|
#define SSL_F_TLS1_CHANGE_CIPHER_STATE 209
|
||||||
#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT 274
|
#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT 274
|
||||||
|
|
|
@ -288,6 +288,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
||||||
{ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE), "SSL_use_RSAPrivateKey_file"},
|
{ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE), "SSL_use_RSAPrivateKey_file"},
|
||||||
{ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN), "ssl_verify_cert_chain"},
|
{ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN), "ssl_verify_cert_chain"},
|
||||||
{ERR_FUNC(SSL_F_SSL_WRITE), "SSL_write"},
|
{ERR_FUNC(SSL_F_SSL_WRITE), "SSL_write"},
|
||||||
|
{ERR_FUNC(SSL_F_TLS12_CHECK_PEER_SIGALG), "tls12_check_peer_sigalg"},
|
||||||
{ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC), "tls1_cert_verify_mac"},
|
{ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC), "tls1_cert_verify_mac"},
|
||||||
{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE), "tls1_change_cipher_state"},
|
{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE), "tls1_change_cipher_state"},
|
||||||
{ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT), "TLS1_CHECK_SERVERHELLO_TLSEXT"},
|
{ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT), "TLS1_CHECK_SERVERHELLO_TLSEXT"},
|
||||||
|
|
|
@ -1252,6 +1252,8 @@ int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
|
||||||
long ssl_get_algorithm2(SSL *s);
|
long ssl_get_algorithm2(SSL *s);
|
||||||
int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
|
int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
|
||||||
size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs);
|
size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs);
|
||||||
|
int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
|
||||||
|
const unsigned char *sig, EVP_PKEY *pkey);
|
||||||
void ssl_set_client_disabled(SSL *s);
|
void ssl_set_client_disabled(SSL *s);
|
||||||
|
|
||||||
int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen);
|
int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen);
|
||||||
|
|
39
ssl/t1_lib.c
39
ssl/t1_lib.c
|
@ -680,6 +680,45 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
|
||||||
return sizeof(tls12_sigalgs);
|
return sizeof(tls12_sigalgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Check signature algorithm is consistent with sent supported signature
|
||||||
|
* algorithms and if so return relevant digest.
|
||||||
|
*/
|
||||||
|
int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
|
||||||
|
const unsigned char *sig, EVP_PKEY *pkey)
|
||||||
|
{
|
||||||
|
const unsigned char *sent_sigs;
|
||||||
|
size_t sent_sigslen, i;
|
||||||
|
int sigalg = tls12_get_sigid(pkey);
|
||||||
|
/* Should never happen */
|
||||||
|
if (sigalg == -1)
|
||||||
|
return -1;
|
||||||
|
/* Check key type is consistent with signature */
|
||||||
|
if (sigalg != (int)sig[1])
|
||||||
|
{
|
||||||
|
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Check signature matches a type we sent */
|
||||||
|
sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
|
||||||
|
for (i = 0; i < sent_sigslen; i+=2, sent_sigs+=2)
|
||||||
|
{
|
||||||
|
if (sig[0] == sent_sigs[0] && sig[1] == sent_sigs[1])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Allow fallback to SHA1 if not strict mode */
|
||||||
|
if (i == sent_sigslen && (sig[0] != TLSEXT_hash_sha1 || s->cert->cert_flags & SSL_CERT_FLAG_TLS_STRICT))
|
||||||
|
{
|
||||||
|
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*pmd = tls12_get_hash(sig[0]);
|
||||||
|
if (*pmd == NULL)
|
||||||
|
{
|
||||||
|
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_UNKNOWN_DIGEST);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/* Get a mask of disabled algorithms: an algorithm is disabled
|
/* Get a mask of disabled algorithms: an algorithm is disabled
|
||||||
* if it isn't supported or doesn't appear in supported signature
|
* if it isn't supported or doesn't appear in supported signature
|
||||||
* algorithms. Unlike ssl_cipher_get_disabled this applies to a specific
|
* algorithms. Unlike ssl_cipher_get_disabled this applies to a specific
|
||||||
|
|
Loading…
Reference in a new issue