Kaynağa Gözat

[tls] Formalise the definition of a TLS cipher suite

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 yıl önce
ebeveyn
işleme
c8f52cccfb
2 değiştirilmiş dosya ile 125 ekleme ve 84 silme
  1. 11
    3
      src/include/ipxe/tls.h
  2. 114
    81
      src/net/tls.c

+ 11
- 3
src/include/ipxe/tls.h Dosyayı Görüntüle

@@ -99,8 +99,8 @@ enum tls_tx_pending {
99 99
 	TLS_TX_FINISHED = 0x0010,
100 100
 };
101 101
 
102
-/** A TLS cipher specification */
103
-struct tls_cipherspec {
102
+/** A TLS cipher suite */
103
+struct tls_cipher_suite {
104 104
 	/** Public-key encryption algorithm */
105 105
 	struct pubkey_algorithm *pubkey;
106 106
 	/** Bulk encryption cipher algorithm */
@@ -108,7 +108,15 @@ struct tls_cipherspec {
108 108
 	/** MAC digest algorithm */
109 109
 	struct digest_algorithm *digest;
110 110
 	/** Key length */
111
-	size_t key_len;
111
+	uint16_t key_len;
112
+	/** Numeric code (in network-endian order) */
113
+	uint16_t code;
114
+};
115
+
116
+/** A TLS cipher specification */
117
+struct tls_cipherspec {
118
+	/** Cipher suite */
119
+	struct tls_cipher_suite *suite;
112 120
 	/** Dynamically-allocated storage */
113 121
 	void *dynamic;
114 122
 	/** Public key encryption context */

+ 114
- 81
src/net/tls.c Dosyayı Görüntüle

@@ -346,9 +346,9 @@ static void tls_generate_master_secret ( struct tls_session *tls ) {
346 346
 static int tls_generate_keys ( struct tls_session *tls ) {
347 347
 	struct tls_cipherspec *tx_cipherspec = &tls->tx_cipherspec_pending;
348 348
 	struct tls_cipherspec *rx_cipherspec = &tls->rx_cipherspec_pending;
349
-	size_t hash_size = tx_cipherspec->digest->digestsize;
350
-	size_t key_size = tx_cipherspec->key_len;
351
-	size_t iv_size = tx_cipherspec->cipher->blocksize;
349
+	size_t hash_size = tx_cipherspec->suite->digest->digestsize;
350
+	size_t key_size = tx_cipherspec->suite->key_len;
351
+	size_t iv_size = tx_cipherspec->suite->cipher->blocksize;
352 352
 	size_t total = ( 2 * ( hash_size + key_size + iv_size ) );
353 353
 	uint8_t key_block[total];
354 354
 	uint8_t *key;
@@ -376,7 +376,7 @@ static int tls_generate_keys ( struct tls_session *tls ) {
376 376
 	key += hash_size;
377 377
 
378 378
 	/* TX key */
379
-	if ( ( rc = cipher_setkey ( tx_cipherspec->cipher,
379
+	if ( ( rc = cipher_setkey ( tx_cipherspec->suite->cipher,
380 380
 				    tx_cipherspec->cipher_ctx,
381 381
 				    key, key_size ) ) != 0 ) {
382 382
 		DBGC ( tls, "TLS %p could not set TX key: %s\n",
@@ -388,7 +388,7 @@ static int tls_generate_keys ( struct tls_session *tls ) {
388 388
 	key += key_size;
389 389
 
390 390
 	/* RX key */
391
-	if ( ( rc = cipher_setkey ( rx_cipherspec->cipher,
391
+	if ( ( rc = cipher_setkey ( rx_cipherspec->suite->cipher,
392 392
 				    rx_cipherspec->cipher_ctx,
393 393
 				    key, key_size ) ) != 0 ) {
394 394
 		DBGC ( tls, "TLS %p could not set TX key: %s\n",
@@ -400,13 +400,15 @@ static int tls_generate_keys ( struct tls_session *tls ) {
400 400
 	key += key_size;
401 401
 
402 402
 	/* TX initialisation vector */
403
-	cipher_setiv ( tx_cipherspec->cipher, tx_cipherspec->cipher_ctx, key );
403
+	cipher_setiv ( tx_cipherspec->suite->cipher,
404
+		       tx_cipherspec->cipher_ctx, key );
404 405
 	DBGC ( tls, "TLS %p TX IV:\n", tls );
405 406
 	DBGC_HD ( tls, key, iv_size );
406 407
 	key += iv_size;
407 408
 
408 409
 	/* RX initialisation vector */
409
-	cipher_setiv ( rx_cipherspec->cipher, rx_cipherspec->cipher_ctx, key );
410
+	cipher_setiv ( rx_cipherspec->suite->cipher,
411
+		       rx_cipherspec->cipher_ctx, key );
410 412
 	DBGC ( tls, "TLS %p RX IV:\n", tls );
411 413
 	DBGC_HD ( tls, key, iv_size );
412 414
 	key += iv_size;
@@ -423,6 +425,70 @@ static int tls_generate_keys ( struct tls_session *tls ) {
423 425
  ******************************************************************************
424 426
  */
425 427
 
428
+/** Null cipher suite */
429
+struct tls_cipher_suite tls_cipher_suite_null = {
430
+	.pubkey = &pubkey_null,
431
+	.cipher = &cipher_null,
432
+	.digest = &digest_null,
433
+};
434
+
435
+/** Supported cipher suites, in order of preference */
436
+struct tls_cipher_suite tls_cipher_suites[] = {
437
+	{
438
+		.code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 ),
439
+		.key_len = ( 256 / 8 ),
440
+		.pubkey = &pubkey_null, /* FIXME */
441
+		.cipher = &aes_cbc_algorithm,
442
+		.digest = &sha256_algorithm,
443
+	},
444
+	{
445
+		.code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ),
446
+		.key_len = ( 128 / 8 ),
447
+		.pubkey = &pubkey_null, /* FIXME */
448
+		.cipher = &aes_cbc_algorithm,
449
+		.digest = &sha256_algorithm,
450
+	},
451
+	{
452
+		.code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ),
453
+		.key_len = ( 256 / 8 ),
454
+		.pubkey = &pubkey_null, /* FIXME */
455
+		.cipher = &aes_cbc_algorithm,
456
+		.digest = &sha1_algorithm,
457
+	},
458
+	{
459
+		.code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ),
460
+		.key_len = ( 128 / 8 ),
461
+		.pubkey = &pubkey_null, /* FIXME */
462
+		.cipher = &aes_cbc_algorithm,
463
+		.digest = &sha1_algorithm,
464
+	},
465
+};
466
+
467
+/** Number of supported cipher suites */
468
+#define TLS_NUM_CIPHER_SUITES \
469
+	( sizeof ( tls_cipher_suites ) / sizeof ( tls_cipher_suites[0] ) )
470
+
471
+/**
472
+ * Identify cipher suite
473
+ *
474
+ * @v cipher_suite	Cipher suite specification
475
+ * @ret suite		Cipher suite, or NULL
476
+ */
477
+static struct tls_cipher_suite *
478
+tls_find_cipher_suite ( unsigned int cipher_suite ) {
479
+	struct tls_cipher_suite *suite;
480
+	unsigned int i;
481
+
482
+	/* Identify cipher suite */
483
+	for ( i = 0 ; i < TLS_NUM_CIPHER_SUITES ; i++ ) {
484
+		suite = &tls_cipher_suites[i];
485
+		if ( suite->code == cipher_suite )
486
+			return suite;
487
+	}
488
+
489
+	return NULL;
490
+}
491
+
426 492
 /**
427 493
  * Clear cipher suite
428 494
  *
@@ -432,9 +498,7 @@ static void tls_clear_cipher ( struct tls_session *tls __unused,
432 498
 			       struct tls_cipherspec *cipherspec ) {
433 499
 	free ( cipherspec->dynamic );
434 500
 	memset ( cipherspec, 0, sizeof ( cipherspec ) );
435
-	cipherspec->pubkey = &pubkey_null;
436
-	cipherspec->cipher = &cipher_null;
437
-	cipherspec->digest = &digest_null;
501
+	cipherspec->suite = &tls_cipher_suite_null;
438 502
 }
439 503
 
440 504
 /**
@@ -442,18 +506,15 @@ static void tls_clear_cipher ( struct tls_session *tls __unused,
442 506
  *
443 507
  * @v tls		TLS session
444 508
  * @v cipherspec	TLS cipher specification
445
- * @v pubkey		Public-key encryption elgorithm
446
- * @v cipher		Bulk encryption cipher algorithm
447
- * @v digest		MAC digest algorithm
448
- * @v key_len		Key length
509
+ * @v suite		Cipher suite
449 510
  * @ret rc		Return status code
450 511
  */
451 512
 static int tls_set_cipher ( struct tls_session *tls,
452 513
 			    struct tls_cipherspec *cipherspec,
453
-			    struct pubkey_algorithm *pubkey,
454
-			    struct cipher_algorithm *cipher,
455
-			    struct digest_algorithm *digest,
456
-			    size_t key_len ) {
514
+			    struct tls_cipher_suite *suite ) {
515
+	struct pubkey_algorithm *pubkey = suite->pubkey;
516
+	struct cipher_algorithm *cipher = suite->cipher;
517
+	struct digest_algorithm *digest = suite->digest;
457 518
 	size_t total;
458 519
 	void *dynamic;
459 520
 
@@ -479,10 +540,7 @@ static int tls_set_cipher ( struct tls_session *tls,
479 540
 	assert ( ( cipherspec->dynamic + total ) == dynamic );
480 541
 
481 542
 	/* Store parameters */
482
-	cipherspec->pubkey = pubkey;
483
-	cipherspec->cipher = cipher;
484
-	cipherspec->digest = digest;
485
-	cipherspec->key_len = key_len;
543
+	cipherspec->suite = suite;
486 544
 
487 545
 	return 0;
488 546
 }
@@ -496,49 +554,28 @@ static int tls_set_cipher ( struct tls_session *tls,
496 554
  */
497 555
 static int tls_select_cipher ( struct tls_session *tls,
498 556
 			       unsigned int cipher_suite ) {
499
-	struct pubkey_algorithm *pubkey = &pubkey_null;
500
-	struct cipher_algorithm *cipher = &cipher_null;
501
-	struct digest_algorithm *digest = &digest_null;
502
-	unsigned int key_len = 0;
557
+	struct tls_cipher_suite *suite;
503 558
 	int rc;
504 559
 
505
-	switch ( cipher_suite ) {
506
-	case htons ( TLS_RSA_WITH_AES_128_CBC_SHA ):
507
-		key_len = ( 128 / 8 );
508
-		cipher = &aes_cbc_algorithm;
509
-		digest = &sha1_algorithm;
510
-		break;
511
-	case htons ( TLS_RSA_WITH_AES_256_CBC_SHA ):
512
-		key_len = ( 256 / 8 );
513
-		cipher = &aes_cbc_algorithm;
514
-		digest = &sha1_algorithm;
515
-		break;
516
-	case htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ):
517
-		key_len = ( 128 / 8 );
518
-		cipher = &aes_cbc_algorithm;
519
-		digest = &sha256_algorithm;
520
-		break;
521
-	case htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 ):
522
-		key_len = ( 256 / 8 );
523
-		cipher = &aes_cbc_algorithm;
524
-		digest = &sha256_algorithm;
525
-		break;
526
-	default:
560
+	/* Identify cipher suite */
561
+	suite = tls_find_cipher_suite ( cipher_suite );
562
+	if ( ! suite ) {
527 563
 		DBGC ( tls, "TLS %p does not support cipher %04x\n",
528 564
 		       tls, ntohs ( cipher_suite ) );
529 565
 		return -ENOTSUP;
530 566
 	}
531 567
 
532 568
 	/* Set ciphers */
533
-	if ( ( rc = tls_set_cipher ( tls, &tls->tx_cipherspec_pending, pubkey,
534
-				     cipher, digest, key_len ) ) != 0 )
569
+	if ( ( rc = tls_set_cipher ( tls, &tls->tx_cipherspec_pending,
570
+				     suite ) ) != 0 )
535 571
 		return rc;
536
-	if ( ( rc = tls_set_cipher ( tls, &tls->rx_cipherspec_pending, pubkey,
537
-				     cipher, digest, key_len ) ) != 0 )
572
+	if ( ( rc = tls_set_cipher ( tls, &tls->rx_cipherspec_pending,
573
+				     suite ) ) != 0 )
538 574
 		return rc;
539 575
 
540
-	DBGC ( tls, "TLS %p selected %s-%s-%d-%s\n", tls,
541
-	       pubkey->name, cipher->name, ( key_len * 8 ), digest->name );
576
+	DBGC ( tls, "TLS %p selected %s-%s-%d-%s\n", tls, suite->pubkey->name,
577
+	       suite->cipher->name, ( suite->key_len * 8 ),
578
+	       suite->digest->name );
542 579
 
543 580
 	return 0;
544 581
 }
@@ -556,10 +593,7 @@ static int tls_change_cipher ( struct tls_session *tls,
556 593
 			       struct tls_cipherspec *active ) {
557 594
 
558 595
 	/* Sanity check */
559
-	if ( /* FIXME (when pubkey is not hard-coded to RSA):
560
-	      * ( pending->pubkey == &pubkey_null ) || */
561
-	     ( pending->cipher == &cipher_null ) ||
562
-	     ( pending->digest == &digest_null ) ) {
596
+	if ( pending->suite == &tls_cipher_suite_null ) {
563 597
 		DBGC ( tls, "TLS %p refusing to use null cipher\n", tls );
564 598
 		return -ENOTSUP;
565 599
 	}
@@ -687,7 +721,7 @@ static int tls_send_client_hello ( struct tls_session *tls ) {
687 721
 		uint8_t random[32];
688 722
 		uint8_t session_id_len;
689 723
 		uint16_t cipher_suite_len;
690
-		uint16_t cipher_suites[4];
724
+		uint16_t cipher_suites[TLS_NUM_CIPHER_SUITES];
691 725
 		uint8_t compression_methods_len;
692 726
 		uint8_t compression_methods[1];
693 727
 		uint16_t extensions_len;
@@ -704,6 +738,7 @@ static int tls_send_client_hello ( struct tls_session *tls ) {
704 738
 			} __attribute__ (( packed )) server_name;
705 739
 		} __attribute__ (( packed )) extensions;
706 740
 	} __attribute__ (( packed )) hello;
741
+	unsigned int i;
707 742
 
708 743
 	memset ( &hello, 0, sizeof ( hello ) );
709 744
 	hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) |
@@ -712,10 +747,8 @@ static int tls_send_client_hello ( struct tls_session *tls ) {
712 747
 	hello.version = htons ( tls->version );
713 748
 	memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) );
714 749
 	hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) );
715
-	hello.cipher_suites[0] = htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 );
716
-	hello.cipher_suites[1] = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 );
717
-	hello.cipher_suites[2] = htons ( TLS_RSA_WITH_AES_256_CBC_SHA );
718
-	hello.cipher_suites[3] = htons ( TLS_RSA_WITH_AES_128_CBC_SHA );
750
+	for ( i = 0 ; i < TLS_NUM_CIPHER_SUITES ; i++ )
751
+		hello.cipher_suites[i] = tls_cipher_suites[i].code;
719 752
 	hello.compression_methods_len = sizeof ( hello.compression_methods );
720 753
 	hello.extensions_len = htons ( sizeof ( hello.extensions ) );
721 754
 	hello.extensions.server_name_type = htons ( TLS_SERVER_NAME );
@@ -1252,7 +1285,7 @@ static void tls_hmac ( struct tls_session *tls __unused,
1252 1285
 		       struct tls_cipherspec *cipherspec,
1253 1286
 		       uint64_t seq, struct tls_header *tlshdr,
1254 1287
 		       const void *data, size_t len, void *hmac ) {
1255
-	struct digest_algorithm *digest = cipherspec->digest;
1288
+	struct digest_algorithm *digest = cipherspec->suite->digest;
1256 1289
 	uint8_t digest_ctx[digest->ctxsize];
1257 1290
 
1258 1291
 	hmac_init ( digest, digest_ctx, cipherspec->mac_secret,
@@ -1278,7 +1311,7 @@ static void tls_hmac ( struct tls_session *tls __unused,
1278 1311
 static void * __malloc tls_assemble_stream ( struct tls_session *tls,
1279 1312
 				    const void *data, size_t len,
1280 1313
 				    void *digest, size_t *plaintext_len ) {
1281
-	size_t mac_len = tls->tx_cipherspec.digest->digestsize;
1314
+	size_t mac_len = tls->tx_cipherspec.suite->digest->digestsize;
1282 1315
 	void *plaintext;
1283 1316
 	void *content;
1284 1317
 	void *mac;
@@ -1313,8 +1346,8 @@ static void * __malloc tls_assemble_stream ( struct tls_session *tls,
1313 1346
 static void * tls_assemble_block ( struct tls_session *tls,
1314 1347
 				   const void *data, size_t len,
1315 1348
 				   void *digest, size_t *plaintext_len ) {
1316
-	size_t blocksize = tls->tx_cipherspec.cipher->blocksize;
1317
-	size_t mac_len = tls->tx_cipherspec.digest->digestsize;
1349
+	size_t blocksize = tls->tx_cipherspec.suite->cipher->blocksize;
1350
+	size_t mac_len = tls->tx_cipherspec.suite->digest->digestsize;
1318 1351
 	size_t iv_len;
1319 1352
 	size_t padding_len;
1320 1353
 	void *plaintext;
@@ -1362,11 +1395,12 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
1362 1395
 	struct tls_header plaintext_tlshdr;
1363 1396
 	struct tls_header *tlshdr;
1364 1397
 	struct tls_cipherspec *cipherspec = &tls->tx_cipherspec;
1398
+	struct cipher_algorithm *cipher = cipherspec->suite->cipher;
1365 1399
 	void *plaintext = NULL;
1366 1400
 	size_t plaintext_len;
1367 1401
 	struct io_buffer *ciphertext = NULL;
1368 1402
 	size_t ciphertext_len;
1369
-	size_t mac_len = cipherspec->digest->digestsize;
1403
+	size_t mac_len = cipherspec->suite->digest->digestsize;
1370 1404
 	uint8_t mac[mac_len];
1371 1405
 	int rc;
1372 1406
 
@@ -1380,7 +1414,7 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
1380 1414
 		   data, len, mac );
1381 1415
 
1382 1416
 	/* Allocate and assemble plaintext struct */
1383
-	if ( is_stream_cipher ( cipherspec->cipher ) ) {
1417
+	if ( is_stream_cipher ( cipher ) ) {
1384 1418
 		plaintext = tls_assemble_stream ( tls, data, len, mac,
1385 1419
 						  &plaintext_len );
1386 1420
 	} else {
@@ -1413,10 +1447,9 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
1413 1447
 	tlshdr->version = htons ( tls->version );
1414 1448
 	tlshdr->length = htons ( plaintext_len );
1415 1449
 	memcpy ( cipherspec->cipher_next_ctx, cipherspec->cipher_ctx,
1416
-		 cipherspec->cipher->ctxsize );
1417
-	cipher_encrypt ( cipherspec->cipher, cipherspec->cipher_next_ctx,
1418
-			 plaintext, iob_put ( ciphertext, plaintext_len ),
1419
-			 plaintext_len );
1450
+		 cipher->ctxsize );
1451
+	cipher_encrypt ( cipher, cipherspec->cipher_next_ctx, plaintext,
1452
+			 iob_put ( ciphertext, plaintext_len ), plaintext_len );
1420 1453
 
1421 1454
 	/* Free plaintext as soon as possible to conserve memory */
1422 1455
 	free ( plaintext );
@@ -1433,8 +1466,7 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
1433 1466
 	/* Update TX state machine to next record */
1434 1467
 	tls->tx_seq += 1;
1435 1468
 	memcpy ( tls->tx_cipherspec.cipher_ctx,
1436
-		 tls->tx_cipherspec.cipher_next_ctx,
1437
-		 tls->tx_cipherspec.cipher->ctxsize );
1469
+		 tls->tx_cipherspec.cipher_next_ctx, cipher->ctxsize );
1438 1470
 
1439 1471
  done:
1440 1472
 	free ( plaintext );
@@ -1462,7 +1494,7 @@ static int tls_split_stream ( struct tls_session *tls,
1462 1494
 	size_t mac_len;
1463 1495
 
1464 1496
 	/* Decompose stream-ciphered data */
1465
-	mac_len = tls->rx_cipherspec.digest->digestsize;
1497
+	mac_len = tls->rx_cipherspec.suite->digest->digestsize;
1466 1498
 	if ( plaintext_len < mac_len ) {
1467 1499
 		DBGC ( tls, "TLS %p received underlength record\n", tls );
1468 1500
 		DBGC_HD ( tls, plaintext, plaintext_len );
@@ -1514,10 +1546,10 @@ static int tls_split_block ( struct tls_session *tls,
1514 1546
 
1515 1547
 	/* TLSv1.1 and later use an explicit IV */
1516 1548
 	iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ?
1517
-		   tls->rx_cipherspec.cipher->blocksize : 0 );
1549
+		   tls->rx_cipherspec.suite->cipher->blocksize : 0 );
1518 1550
 
1519 1551
 	/* Decompose block-ciphered data */
1520
-	mac_len = tls->rx_cipherspec.digest->digestsize;
1552
+	mac_len = tls->rx_cipherspec.suite->digest->digestsize;
1521 1553
 	padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) );
1522 1554
 	if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) {
1523 1555
 		DBGC ( tls, "TLS %p received underlength record\n", tls );
@@ -1559,12 +1591,13 @@ static int tls_new_ciphertext ( struct tls_session *tls,
1559 1591
 				struct tls_header *tlshdr, void *ciphertext ) {
1560 1592
 	struct tls_header plaintext_tlshdr;
1561 1593
 	struct tls_cipherspec *cipherspec = &tls->rx_cipherspec;
1594
+	struct cipher_algorithm *cipher = cipherspec->suite->cipher;
1562 1595
 	size_t record_len = ntohs ( tlshdr->length );
1563 1596
 	void *plaintext = NULL;
1564 1597
 	void *data;
1565 1598
 	size_t len;
1566 1599
 	void *mac;
1567
-	size_t mac_len = cipherspec->digest->digestsize;
1600
+	size_t mac_len = cipherspec->suite->digest->digestsize;
1568 1601
 	uint8_t verify_mac[mac_len];
1569 1602
 	int rc;
1570 1603
 
@@ -1578,11 +1611,11 @@ static int tls_new_ciphertext ( struct tls_session *tls,
1578 1611
 	}
1579 1612
 
1580 1613
 	/* Decrypt the record */
1581
-	cipher_decrypt ( cipherspec->cipher, cipherspec->cipher_ctx,
1614
+	cipher_decrypt ( cipher, cipherspec->cipher_ctx,
1582 1615
 			 ciphertext, plaintext, record_len );
1583 1616
 
1584 1617
 	/* Split record into content and MAC */
1585
-	if ( is_stream_cipher ( cipherspec->cipher ) ) {
1618
+	if ( is_stream_cipher ( cipher ) ) {
1586 1619
 		if ( ( rc = tls_split_stream ( tls, plaintext, record_len,
1587 1620
 					       &data, &len, &mac ) ) != 0 )
1588 1621
 			goto done;

Loading…
İptal
Kaydet