Module Name: src Committed By: msaitoh Date: Fri Jun 6 06:42:08 UTC 2014
Modified Files: src/crypto/dist/openssl/crypto/bn [netbsd-5-2]: bn.h bn_lib.c src/crypto/dist/openssl/crypto/ec [netbsd-5-2]: ec2_mult.c src/crypto/dist/openssl/ssl [netbsd-5-2]: d1_both.c s3_clnt.c s3_pkt.c s3_srvr.c ssl3.h Log Message: Pull up following revision(s) (requested by spz in ticket #1908): crypto/dist/openssl/crypto/bn/bn.h patch crypto/dist/openssl/crypto/bn/bn_lib.c patch crypto/dist/openssl/crypto/ec/ec2_mult.c patch crypto/dist/openssl/ssl/d1_both.c patch crypto/dist/openssl/ssl/s3_clnt.c patch crypto/dist/openssl/ssl/s3_pkt.c patch crypto/dist/openssl/ssl/s3_srvr.c patch crypto/dist/openssl/ssl/ssl3.h patch *) Fix for SSL/TLS MITM flaw. An attacker using a carefully crafted handshake can force the use of weak keying material in OpenSSL SSL/TLS clients and servers. Thanks to KIKUCHI Masashi (Lepidum Co. Ltd.) for discovering and researching this issue. (CVE-2014-0224) [KIKUCHI Masashi, Steve Henson] *) Fix DTLS recursion flaw. By sending an invalid DTLS handshake to an OpenSSL DTLS client the code can be made to recurse eventually crashing in a DoS attack. Thanks to Imre Rad (Search-Lab Ltd.) for discovering this issue. (CVE-2014-0221) [Imre Rad, Steve Henson] *) Fix DTLS invalid fragment vulnerability. A buffer overrun attack can be triggered by sending invalid DTLS fragments to an OpenSSL DTLS client or server. This is potentially exploitable to run arbitrary code on a vulnerable client or server. Thanks to Jüri Aedla for reporting this issue. (CVE-2014-0195) [Jüri Aedla, Steve Henson] *) Fix bug in TLS code where clients enable anonymous ECDH ciphersuites are subject to a denial of service attack. Thanks to Felix Gröbert and Ivan Fratric at Google for discovering this issue. (CVE-2014-3470) [Felix Gröbert, Ivan Fratric, Steve Henson] To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.12.2.1 src/crypto/dist/openssl/crypto/bn/bn.h cvs rdiff -u -r1.7 -r1.7.2.1 src/crypto/dist/openssl/crypto/bn/bn_lib.c cvs rdiff -u -r1.1.1.2 -r1.1.1.2.2.1 \ src/crypto/dist/openssl/crypto/ec/ec2_mult.c cvs rdiff -u -r1.3.4.2 -r1.3.4.2.6.1 src/crypto/dist/openssl/ssl/d1_both.c cvs rdiff -u -r1.12.4.3 -r1.12.4.3.4.1 src/crypto/dist/openssl/ssl/s3_clnt.c cvs rdiff -u -r1.9.4.3 -r1.9.4.3.6.1 src/crypto/dist/openssl/ssl/s3_pkt.c cvs rdiff -u -r1.15.4.4 -r1.15.4.4.4.1 src/crypto/dist/openssl/ssl/s3_srvr.c cvs rdiff -u -r1.8 -r1.8.2.1 src/crypto/dist/openssl/ssl/ssl3.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/crypto/dist/openssl/crypto/bn/bn.h diff -u src/crypto/dist/openssl/crypto/bn/bn.h:1.12 src/crypto/dist/openssl/crypto/bn/bn.h:1.12.2.1 --- src/crypto/dist/openssl/crypto/bn/bn.h:1.12 Fri May 9 21:49:39 2008 +++ src/crypto/dist/openssl/crypto/bn/bn.h Fri Jun 6 06:42:08 2014 @@ -520,6 +520,8 @@ BIGNUM *BN_mod_inverse(BIGNUM *ret, BIGNUM *BN_mod_sqrt(BIGNUM *ret, const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx); +void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords); + /* Deprecated versions */ #ifndef OPENSSL_NO_DEPRECATED BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe, @@ -742,11 +744,20 @@ int RAND_pseudo_bytes(unsigned char *buf #define bn_fix_top(a) bn_check_top(a) +#define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2) +#define bn_wcheck_size(bn, words) \ + do { \ + const BIGNUM *_bnum2 = (bn); \ + assert(words <= (_bnum2)->dmax && words >= (_bnum2)->top); \ + } while(0) + #else /* !BN_DEBUG */ #define bn_pollute(a) #define bn_check_top(a) #define bn_fix_top(a) bn_correct_top(a) +#define bn_check_size(bn, bits) +#define bn_wcheck_size(bn, words) #endif Index: src/crypto/dist/openssl/crypto/bn/bn_lib.c diff -u src/crypto/dist/openssl/crypto/bn/bn_lib.c:1.7 src/crypto/dist/openssl/crypto/bn/bn_lib.c:1.7.2.1 --- src/crypto/dist/openssl/crypto/bn/bn_lib.c:1.7 Fri May 9 21:49:39 2008 +++ src/crypto/dist/openssl/crypto/bn/bn_lib.c Fri Jun 6 06:42:08 2014 @@ -843,3 +843,55 @@ int bn_cmp_part_words(const BN_ULONG *a, } return bn_cmp_words(a,b,cl); } + +/* + * Constant-time conditional swap of a and b. + * a and b are swapped if condition is not 0. The code assumes that at most one bit of condition is set. + * nwords is the number of words to swap. The code assumes that at least nwords are allocated in both a and b, + * and that no more than nwords are used by either a or b. + * a and b cannot be the same number + */ +void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) + { + BN_ULONG t; + int i; + + bn_wcheck_size(a, nwords); + bn_wcheck_size(b, nwords); + + assert(a != b); + assert((condition & (condition - 1)) == 0); + assert(sizeof(BN_ULONG) >= sizeof(int)); + + condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1; + + t = (a->top^b->top) & condition; + a->top ^= t; + b->top ^= t; + +#define BN_CONSTTIME_SWAP(ind) \ + do { \ + t = (a->d[ind] ^ b->d[ind]) & condition; \ + a->d[ind] ^= t; \ + b->d[ind] ^= t; \ + } while (0) + + + switch (nwords) { + default: + for (i = 10; i < nwords; i++) + BN_CONSTTIME_SWAP(i); + /* Fallthrough */ + case 10: BN_CONSTTIME_SWAP(9); /* Fallthrough */ + case 9: BN_CONSTTIME_SWAP(8); /* Fallthrough */ + case 8: BN_CONSTTIME_SWAP(7); /* Fallthrough */ + case 7: BN_CONSTTIME_SWAP(6); /* Fallthrough */ + case 6: BN_CONSTTIME_SWAP(5); /* Fallthrough */ + case 5: BN_CONSTTIME_SWAP(4); /* Fallthrough */ + case 4: BN_CONSTTIME_SWAP(3); /* Fallthrough */ + case 3: BN_CONSTTIME_SWAP(2); /* Fallthrough */ + case 2: BN_CONSTTIME_SWAP(1); /* Fallthrough */ + case 1: BN_CONSTTIME_SWAP(0); + } +#undef BN_CONSTTIME_SWAP +} Index: src/crypto/dist/openssl/crypto/ec/ec2_mult.c diff -u src/crypto/dist/openssl/crypto/ec/ec2_mult.c:1.1.1.2 src/crypto/dist/openssl/crypto/ec/ec2_mult.c:1.1.1.2.2.1 --- src/crypto/dist/openssl/crypto/ec/ec2_mult.c:1.1.1.2 Fri May 9 21:34:25 2008 +++ src/crypto/dist/openssl/crypto/ec/ec2_mult.c Fri Jun 6 06:42:08 2014 @@ -208,16 +208,19 @@ static int gf2m_Mxy(const EC_GROUP *grou /* Computes scalar*point and stores the result in r. * point can not equal r. - * Uses algorithm 2P of + * Uses a modified algorithm 2P of * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). + * + * To protect against side-channel attack the function uses constant time swap, + * avoiding conditional branches. */ static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx) { BIGNUM *x1, *x2, *z1, *z2; int ret = 0, i, j; - BN_ULONG mask; + BN_ULONG mask,word; if (r == point) { @@ -244,6 +247,11 @@ static int ec_GF2m_montgomery_point_mult x2 = &r->X; z2 = &r->Y; + bn_wexpand(x1, group->field.top); + bn_wexpand(z1, group->field.top); + bn_wexpand(x2, group->field.top); + bn_wexpand(z2, group->field.top); + if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */ if (!BN_one(z1)) goto err; /* z1 = 1 */ if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */ @@ -264,21 +272,17 @@ static int ec_GF2m_montgomery_point_mult for (; i >= 0; i--) { - for (; j >= 0; j--) + word = scalar->d[i]; + while (mask) { - if (scalar->d[i] & mask) - { - if (!gf2m_Madd(group, &point->X, x1, z1, x2, z2, ctx)) goto err; - if (!gf2m_Mdouble(group, x2, z2, ctx)) goto err; - } - else - { - if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; - if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; - } + BN_consttime_swap(word & mask, x1, x2, group->field.top); + BN_consttime_swap(word & mask, z1, z2, group->field.top); + if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; + if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; + BN_consttime_swap(word & mask, x1, x2, group->field.top); + BN_consttime_swap(word & mask, z1, z2, group->field.top); mask >>= 1; } - j = BN_BITS2 - 1; mask = BN_TBIT; } Index: src/crypto/dist/openssl/ssl/d1_both.c diff -u src/crypto/dist/openssl/ssl/d1_both.c:1.3.4.2 src/crypto/dist/openssl/ssl/d1_both.c:1.3.4.2.6.1 --- src/crypto/dist/openssl/ssl/d1_both.c:1.3.4.2 Sun Jul 5 14:11:17 2009 +++ src/crypto/dist/openssl/ssl/d1_both.c Fri Jun 6 06:42:08 2014 @@ -566,6 +566,12 @@ dtls1_process_out_of_seq_message(SSL *s, seq64be[6] = (unsigned char) (msg_hdr->seq>>8); seq64be[7] = (unsigned char) msg_hdr->seq; item = pqueue_find(s->d1->buffered_messages, seq64be); + + if (item != NULL && ((hm_fragment *) (item->data))->msg_header.msg_len != msg_hdr->msg_len) + { + item = NULL; /* let's see if Coverity will complain about this */ + goto err; + } /* Discard the message if sequence number was already there, is * too far in the future or the fragment is already in the queue */ @@ -627,6 +633,7 @@ dtls1_get_message_fragment(SSL *s, int s int i,al; struct hm_header_st msg_hdr; + redo: /* see if we have the required fragment already */ if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok) { @@ -674,8 +681,7 @@ dtls1_get_message_fragment(SSL *s, int s s->msg_callback_arg); s->init_num = 0; - return dtls1_get_message_fragment(s, st1, stn, - max, ok); + goto redo; } else /* Incorrectly formated Hello request */ { Index: src/crypto/dist/openssl/ssl/s3_clnt.c diff -u src/crypto/dist/openssl/ssl/s3_clnt.c:1.12.4.3 src/crypto/dist/openssl/ssl/s3_clnt.c:1.12.4.3.4.1 --- src/crypto/dist/openssl/ssl/s3_clnt.c:1.12.4.3 Fri Dec 10 21:42:16 2010 +++ src/crypto/dist/openssl/ssl/s3_clnt.c Fri Jun 6 06:42:08 2014 @@ -503,6 +503,7 @@ int ssl3_connect(SSL *s) case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: + s->s3->flags |= SSL3_FLAGS_CCS_OK; ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret <= 0) goto end; @@ -2214,6 +2215,13 @@ int ssl3_send_client_key_exchange(SSL *s int ecdh_clnt_cert = 0; int field_size = 0; + if (s->session->sess_cert == NULL) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE); + goto err; + } + /* Did we send out the client's * ECDH share for use in premaster * computation as part of client certificate? Index: src/crypto/dist/openssl/ssl/s3_pkt.c diff -u src/crypto/dist/openssl/ssl/s3_pkt.c:1.9.4.3 src/crypto/dist/openssl/ssl/s3_pkt.c:1.9.4.3.6.1 --- src/crypto/dist/openssl/ssl/s3_pkt.c:1.9.4.3 Sun Mar 28 15:20:11 2010 +++ src/crypto/dist/openssl/ssl/s3_pkt.c Fri Jun 6 06:42:08 2014 @@ -624,6 +624,10 @@ static int do_ssl3_write(SSL *s, int typ /* if it went, fall through and send more stuff */ } + if (wb->buf == NULL) + if (!ssl3_setup_buffers(s)) + return -1; + if (len == 0 && !create_empty_fragment) return 0; @@ -1158,6 +1162,15 @@ start: goto f_err; } + if (!(s->s3->flags & SSL3_FLAGS_CCS_OK)) + { + al=SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_CCS_RECEIVED_EARLY); + goto f_err; + } + + s->s3->flags &= ~SSL3_FLAGS_CCS_OK; + rr->length=0; if (s->msg_callback) @@ -1290,7 +1303,7 @@ int ssl3_do_change_cipher_spec(SSL *s) if (s->s3->tmp.key_block == NULL) { - if (s->session == NULL) + if (s->session == NULL || s->session->master_key_length == 0) { /* might happen if dtls1_read_bytes() calls this */ SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY); Index: src/crypto/dist/openssl/ssl/s3_srvr.c diff -u src/crypto/dist/openssl/ssl/s3_srvr.c:1.15.4.4 src/crypto/dist/openssl/ssl/s3_srvr.c:1.15.4.4.4.1 --- src/crypto/dist/openssl/ssl/s3_srvr.c:1.15.4.4 Fri Dec 10 21:42:16 2010 +++ src/crypto/dist/openssl/ssl/s3_srvr.c Fri Jun 6 06:42:08 2014 @@ -546,6 +546,7 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: + s->s3->flags |= SSL3_FLAGS_CCS_OK; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; @@ -556,6 +557,7 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: + s->s3->flags |= SSL3_FLAGS_CCS_OK; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; Index: src/crypto/dist/openssl/ssl/ssl3.h diff -u src/crypto/dist/openssl/ssl/ssl3.h:1.8 src/crypto/dist/openssl/ssl/ssl3.h:1.8.2.1 --- src/crypto/dist/openssl/ssl/ssl3.h:1.8 Fri May 9 21:49:42 2008 +++ src/crypto/dist/openssl/ssl/ssl3.h Fri Jun 6 06:42:08 2014 @@ -375,6 +375,9 @@ typedef struct ssl3_buffer_st #define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002 #define SSL3_FLAGS_POP_BUFFER 0x0004 #define TLS1_FLAGS_TLS_PADDING_BUG 0x0008 +#define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010 +#define TLS1_FLAGS_KEEP_HANDSHAKE 0x0020 +#define SSL3_FLAGS_CCS_OK 0x0080 typedef struct ssl3_state_st {