|  | @@ -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 |  
 |