Browse Source

[tls] Support TLS version 1.2

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
015c936791
2 changed files with 78 additions and 35 deletions
  1. 6
    0
      src/include/ipxe/tls.h
  2. 72
    35
      src/net/tls.c

+ 6
- 0
src/include/ipxe/tls.h View File

@@ -16,6 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
16 16
 #include <ipxe/crypto.h>
17 17
 #include <ipxe/md5.h>
18 18
 #include <ipxe/sha1.h>
19
+#include <ipxe/sha256.h>
19 20
 #include <ipxe/x509.h>
20 21
 
21 22
 /** A TLS header */
@@ -40,6 +41,9 @@ struct tls_header {
40 41
 /** TLS version 1.1 */
41 42
 #define TLS_VERSION_TLS_1_1 0x0302
42 43
 
44
+/** TLS version 1.2 */
45
+#define TLS_VERSION_TLS_1_2 0x0303
46
+
43 47
 /** Change cipher content type */
44 48
 #define TLS_TYPE_CHANGE_CIPHER 20
45 49
 
@@ -165,6 +169,8 @@ struct tls_session {
165 169
 	uint8_t handshake_md5_ctx[MD5_CTX_SIZE];
166 170
 	/** SHA1 context for handshake verification */
167 171
 	uint8_t handshake_sha1_ctx[SHA1_CTX_SIZE];
172
+	/** SHA256 context for handshake verification */
173
+	uint8_t handshake_sha256_ctx[SHA256_CTX_SIZE];
168 174
 
169 175
 	/** Hack: server RSA public key */
170 176
 	struct x509_rsa_public_key rsa;

+ 72
- 35
src/net/tls.c View File

@@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
33 33
 #include <ipxe/hmac.h>
34 34
 #include <ipxe/md5.h>
35 35
 #include <ipxe/sha1.h>
36
+#include <ipxe/sha256.h>
36 37
 #include <ipxe/aes.h>
37 38
 #include <ipxe/rsa.h>
38 39
 #include <ipxe/iobuf.h>
@@ -247,32 +248,40 @@ static void tls_prf ( struct tls_session *tls, void *secret, size_t secret_len,
247 248
 	size_t subsecret_len;
248 249
 	void *md5_secret;
249 250
 	void *sha1_secret;
250
-	uint8_t out_md5[out_len];
251
-	uint8_t out_sha1[out_len];
251
+	uint8_t buf[out_len];
252 252
 	unsigned int i;
253 253
 
254 254
 	va_start ( seeds, out_len );
255 255
 
256
-	/* Split secret into two, with an overlap of up to one byte */
257
-	subsecret_len = ( ( secret_len + 1 ) / 2 );
258
-	md5_secret = secret;
259
-	sha1_secret = ( secret + secret_len - subsecret_len );
256
+	if ( tls->version >= TLS_VERSION_TLS_1_2 ) {
257
+		/* Use P_SHA256 for TLSv1.2 and later */
258
+		tls_p_hash_va ( tls, &sha256_algorithm, secret, secret_len,
259
+				out, out_len, seeds );
260
+	} else {
261
+		/* Use combination of P_MD5 and P_SHA-1 for TLSv1.1
262
+		 * and earlier
263
+		 */
260 264
 
261
-	/* Calculate MD5 portion */
262
-	va_copy ( tmp, seeds );
263
-	tls_p_hash_va ( tls, &md5_algorithm, md5_secret, subsecret_len,
264
-			out_md5, out_len, seeds );
265
-	va_end ( tmp );
265
+		/* Split secret into two, with an overlap of up to one byte */
266
+		subsecret_len = ( ( secret_len + 1 ) / 2 );
267
+		md5_secret = secret;
268
+		sha1_secret = ( secret + secret_len - subsecret_len );
266 269
 
267
-	/* Calculate SHA1 portion */
268
-	va_copy ( tmp, seeds );
269
-	tls_p_hash_va ( tls, &sha1_algorithm, sha1_secret, subsecret_len,
270
-			out_sha1, out_len, seeds );
271
-	va_end ( tmp );
270
+		/* Calculate MD5 portion */
271
+		va_copy ( tmp, seeds );
272
+		tls_p_hash_va ( tls, &md5_algorithm, md5_secret,
273
+				subsecret_len, out, out_len, seeds );
274
+		va_end ( tmp );
275
+
276
+		/* Calculate SHA1 portion */
277
+		va_copy ( tmp, seeds );
278
+		tls_p_hash_va ( tls, &sha1_algorithm, sha1_secret,
279
+				subsecret_len, buf, out_len, seeds );
280
+		va_end ( tmp );
272 281
 
273
-	/* XOR the two portions together into the final output buffer */
274
-	for ( i = 0 ; i < out_len ; i++ ) {
275
-		*( ( uint8_t * ) out + i ) = ( out_md5[i] ^ out_sha1[i] );
282
+		/* XOR the two portions together into the final output buffer */
283
+		for ( i = 0 ; i < out_len ; i++ )
284
+			*( ( uint8_t * ) out + i ) ^= buf[i];
276 285
 	}
277 286
 
278 287
 	va_end ( seeds );
@@ -569,6 +578,24 @@ static void tls_add_handshake ( struct tls_session *tls,
569 578
 
570 579
 	digest_update ( &md5_algorithm, tls->handshake_md5_ctx, data, len );
571 580
 	digest_update ( &sha1_algorithm, tls->handshake_sha1_ctx, data, len );
581
+	digest_update ( &sha256_algorithm, tls->handshake_sha256_ctx,
582
+			data, len );
583
+}
584
+
585
+/**
586
+ * Size of handshake output buffer
587
+ *
588
+ * @v tls		TLS session
589
+ */
590
+static size_t tls_verify_handshake_len ( struct tls_session *tls ) {
591
+
592
+	if ( tls->version >= TLS_VERSION_TLS_1_2 ) {
593
+		/* Use SHA-256 for TLSv1.2 and later */
594
+		return SHA256_DIGEST_SIZE;
595
+	} else {
596
+		/* Use MD5+SHA1 for TLSv1.1 and earlier */
597
+		return ( MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE );
598
+	}
572 599
 }
573 600
 
574 601
 /**
@@ -577,21 +604,30 @@ static void tls_add_handshake ( struct tls_session *tls,
577 604
  * @v tls		TLS session
578 605
  * @v out		Output buffer
579 606
  *
580
- * Calculates the MD5+SHA1 digest over all handshake messages seen so
581
- * far.
607
+ * Calculates the MD5+SHA1 or SHA256 digest over all handshake
608
+ * messages seen so far.
582 609
  */
583 610
 static void tls_verify_handshake ( struct tls_session *tls, void *out ) {
584
-	struct digest_algorithm *md5 = &md5_algorithm;
585
-	struct digest_algorithm *sha1 = &sha1_algorithm;
586
-	uint8_t md5_ctx[md5->ctxsize];
587
-	uint8_t sha1_ctx[sha1->ctxsize];
588
-	void *md5_digest = out;
589
-	void *sha1_digest = ( out + md5->digestsize );
590
-
591
-	memcpy ( md5_ctx, tls->handshake_md5_ctx, sizeof ( md5_ctx ) );
592
-	memcpy ( sha1_ctx, tls->handshake_sha1_ctx, sizeof ( sha1_ctx ) );
593
-	digest_final ( md5, md5_ctx, md5_digest );
594
-	digest_final ( sha1, sha1_ctx, sha1_digest );
611
+	union {
612
+		uint8_t md5[MD5_CTX_SIZE];
613
+		uint8_t sha1[SHA1_CTX_SIZE];
614
+		uint8_t sha256[SHA256_CTX_SIZE];
615
+	} ctx;
616
+
617
+	if ( tls->version >= TLS_VERSION_TLS_1_2 ) {
618
+		/* Use SHA-256 for TLSv1.2 and later */
619
+		memcpy ( ctx.sha256, tls->handshake_sha256_ctx,
620
+			 sizeof ( ctx.sha256 ) );
621
+		digest_final ( &sha256_algorithm, ctx.sha256, out );
622
+	} else {
623
+		/* Use MD5+SHA1 for TLSv1.1 and earlier */
624
+		memcpy ( ctx.md5, tls->handshake_md5_ctx, sizeof ( ctx.md5 ) );
625
+		digest_final ( &md5_algorithm, ctx.md5, out );
626
+		memcpy ( ctx.sha1, tls->handshake_sha1_ctx,
627
+			 sizeof ( ctx.sha1 ) );
628
+		digest_final ( &sha1_algorithm, ctx.sha1,
629
+			       ( out + MD5_DIGEST_SIZE ) );
630
+	}
595 631
 }
596 632
 
597 633
 /******************************************************************************
@@ -770,7 +806,7 @@ static int tls_send_finished ( struct tls_session *tls ) {
770 806
 		uint32_t type_length;
771 807
 		uint8_t verify_data[12];
772 808
 	} __attribute__ (( packed )) finished;
773
-	uint8_t digest[MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE];
809
+	uint8_t digest[ tls_verify_handshake_len ( tls ) ];
774 810
 
775 811
 	memset ( &finished, 0, sizeof ( finished ) );
776 812
 	finished.type_length = ( cpu_to_le32 ( TLS_FINISHED ) |
@@ -1047,7 +1083,7 @@ static int tls_new_finished ( struct tls_session *tls,
1047 1083
 		char next[0];
1048 1084
 	} __attribute__ (( packed )) *finished = data;
1049 1085
 	void *end = finished->next;
1050
-	uint8_t digest[MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE];
1086
+	uint8_t digest[ tls_verify_handshake_len ( tls ) ];
1051 1087
 	uint8_t verify_data[ sizeof ( finished->verify_data ) ];
1052 1088
 
1053 1089
 	/* Sanity check */
@@ -1869,7 +1905,7 @@ int add_tls ( struct interface *xfer, const char *name,
1869 1905
 	tls->name = name;
1870 1906
 	intf_init ( &tls->plainstream, &tls_plainstream_desc, &tls->refcnt );
1871 1907
 	intf_init ( &tls->cipherstream, &tls_cipherstream_desc, &tls->refcnt );
1872
-	tls->version = TLS_VERSION_TLS_1_1;
1908
+	tls->version = TLS_VERSION_TLS_1_2;
1873 1909
 	tls_clear_cipher ( tls, &tls->tx_cipherspec );
1874 1910
 	tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
1875 1911
 	tls_clear_cipher ( tls, &tls->rx_cipherspec );
@@ -1886,6 +1922,7 @@ int add_tls ( struct interface *xfer, const char *name,
1886 1922
 	}
1887 1923
 	digest_init ( &md5_algorithm, tls->handshake_md5_ctx );
1888 1924
 	digest_init ( &sha1_algorithm, tls->handshake_sha1_ctx );
1925
+	digest_init ( &sha256_algorithm, tls->handshake_sha256_ctx );
1889 1926
 	tls->tx_pending = TLS_TX_CLIENT_HELLO;
1890 1927
 	process_init ( &tls->process, &tls_process_desc, &tls->refcnt );
1891 1928
 

Loading…
Cancel
Save