Module Name:    src
Committed By:   msaitoh
Date:           Fri Jun  6 06:36:44 UTC 2014

Modified Files:
        src/crypto/dist/openssl/crypto/bn [netbsd-5]: bn.h bn_lib.c
        src/crypto/dist/openssl/crypto/ec [netbsd-5]: ec2_mult.c
        src/crypto/dist/openssl/ssl [netbsd-5]: 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.4.1 src/crypto/dist/openssl/crypto/bn/bn.h
cvs rdiff -u -r1.7 -r1.7.4.1 src/crypto/dist/openssl/crypto/bn/bn_lib.c
cvs rdiff -u -r1.1.1.2 -r1.1.1.2.4.1 \
    src/crypto/dist/openssl/crypto/ec/ec2_mult.c
cvs rdiff -u -r1.3.4.2 -r1.3.4.3 src/crypto/dist/openssl/ssl/d1_both.c
cvs rdiff -u -r1.12.4.3 -r1.12.4.4 src/crypto/dist/openssl/ssl/s3_clnt.c
cvs rdiff -u -r1.9.4.3 -r1.9.4.4 src/crypto/dist/openssl/ssl/s3_pkt.c
cvs rdiff -u -r1.15.4.4 -r1.15.4.5 src/crypto/dist/openssl/ssl/s3_srvr.c
cvs rdiff -u -r1.8 -r1.8.4.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.4.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:36:44 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.4.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:36:44 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.4.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:36:44 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.3
--- 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:36:44 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.4
--- 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:36:44 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.4
--- 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:36:44 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.5
--- 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:36:44 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.4.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:36:44 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
 	{

Reply via email to