diff options
Diffstat (limited to 'openssl/ssl/s3_srvr.c')
-rw-r--r-- | openssl/ssl/s3_srvr.c | 113 |
1 files changed, 63 insertions, 50 deletions
diff --git a/openssl/ssl/s3_srvr.c b/openssl/ssl/s3_srvr.c index 286750128..c23d98708 100644 --- a/openssl/ssl/s3_srvr.c +++ b/openssl/ssl/s3_srvr.c @@ -154,6 +154,7 @@ #include <stdio.h> #include "ssl_locl.h" #include "kssl_lcl.h" +#include "../crypto/constant_time_locl.h" #include <openssl/buffer.h> #include <openssl/rand.h> #include <openssl/objects.h> @@ -410,9 +411,8 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or anon ECDH, */ /* normal PSK or KRB5 or SRP */ - if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) - && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) - && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) + if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aKRB5|SSL_aSRP)) + && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { ret=ssl3_send_server_certificate(s); if (ret <= 0) goto end; @@ -515,7 +515,9 @@ int ssl3_accept(SSL *s) * (against the specs, but s3_clnt.c accepts this for SSL 3) */ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* never request cert in Kerberos ciphersuites */ - (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) + (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) || + /* don't request certificate for SRP auth */ + (s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP) /* With normal PSK Certificates and * Certificate Requests are omitted */ || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) @@ -1846,7 +1848,7 @@ int ssl3_send_server_key_exchange(SSL *s) n+=2+nr[i]; } - if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) + if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP)) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md)) @@ -2166,6 +2168,10 @@ int ssl3_get_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_RSA if (alg_k & SSL_kRSA) { + unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; + int decrypt_len; + unsigned char decrypt_good, version_good; + /* FIX THIS UP EAY EAY EAY EAY */ if (s->s3->tmp.use_rsa_tmp) { @@ -2213,54 +2219,61 @@ int ssl3_get_client_key_exchange(SSL *s) n=i; } - i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING); - - al = -1; - - if (i != SSL_MAX_MASTER_KEY_LENGTH) - { - al=SSL_AD_DECODE_ERROR; - /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */ - } - - if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff)))) - { - /* The premaster secret must contain the same version number as the - * ClientHello to detect version rollback attacks (strangely, the - * protocol does not offer such protection for DH ciphersuites). - * However, buggy clients exist that send the negotiated protocol - * version instead if the server does not support the requested - * protocol version. - * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */ - if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) && - (p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff)))) - { - al=SSL_AD_DECODE_ERROR; - /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */ + /* We must not leak whether a decryption failure occurs because + * of Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see + * RFC 2246, section 7.4.7.1). The code follows that advice of + * the TLS RFC and generates a random premaster secret for the + * case that the decrypt fails. See + * https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */ - /* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack - * (http://eprint.iacr.org/2003/052/) exploits the version - * number check as a "bad version oracle" -- an alert would - * reveal that the plaintext corresponding to some ciphertext - * made up by the adversary is properly formatted except - * that the version number is wrong. To avoid such attacks, - * we should treat this just like any other decryption error. */ - } + /* should be RAND_bytes, but we cannot work around a failure. */ + if (RAND_pseudo_bytes(rand_premaster_secret, + sizeof(rand_premaster_secret)) <= 0) + goto err; + decrypt_len = RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING); + ERR_clear_error(); + + /* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH. + * decrypt_good will be 0xff if so and zero otherwise. */ + decrypt_good = constant_time_eq_int_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH); + + /* If the version in the decrypted pre-master secret is correct + * then version_good will be 0xff, otherwise it'll be zero. + * The Klima-Pokorny-Rosa extension of Bleichenbacher's attack + * (http://eprint.iacr.org/2003/052/) exploits the version + * number check as a "bad version oracle". Thus version checks + * are done in constant time and are treated like any other + * decryption error. */ + version_good = constant_time_eq_8(p[0], (unsigned)(s->client_version>>8)); + version_good &= constant_time_eq_8(p[1], (unsigned)(s->client_version&0xff)); + + /* The premaster secret must contain the same version number as + * the ClientHello to detect version rollback attacks + * (strangely, the protocol does not offer such protection for + * DH ciphersuites). However, buggy clients exist that send the + * negotiated protocol version instead if the server does not + * support the requested protocol version. If + * SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */ + if (s->options & SSL_OP_TLS_ROLLBACK_BUG) + { + unsigned char workaround_good; + workaround_good = constant_time_eq_8(p[0], (unsigned)(s->version>>8)); + workaround_good &= constant_time_eq_8(p[1], (unsigned)(s->version&0xff)); + version_good |= workaround_good; + } + + /* Both decryption and version must be good for decrypt_good + * to remain non-zero (0xff). */ + decrypt_good &= version_good; + + /* Now copy rand_premaster_secret over p using + * decrypt_good_mask. */ + for (i = 0; i < (int) sizeof(rand_premaster_secret); i++) + { + p[i] = constant_time_select_8(decrypt_good, p[i], + rand_premaster_secret[i]); } - if (al != -1) - { - /* Some decryption failure -- use random value instead as countermeasure - * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding - * (see RFC 2246, section 7.4.7.1). */ - ERR_clear_error(); - i = SSL_MAX_MASTER_KEY_LENGTH; - p[0] = s->client_version >> 8; - p[1] = s->client_version & 0xff; - if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be RAND_bytes, but we cannot work around a failure */ - goto err; - } - s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, |