]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tls] Formalise notions of fixed and record initialisation vectors
authorMichael Brown <mcb30@ipxe.org>
Fri, 28 Oct 2022 12:06:11 +0000 (13:06 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 7 Nov 2022 11:19:48 +0000 (11:19 +0000)
TLS block ciphers always use CBC (as per RFC 5246 section 6.2.3.2)
with a record initialisation vector length that is equal to the cipher
block size, and no fixed initialisation vector.

The initialisation vector for AEAD ciphers such as GCM is less
straightforward, and requires both a fixed and per-record component.

Extend the definition of a cipher suite to include fixed and record
initialisation vector lengths, and generate the fixed portion (if any)
as part of key expansion.

Do not add explicit calls to cipher_setiv() in tls_assemble_block()
and tls_split_block(), since the constraints imposed by RFC 5246 are
specifically chosen to allow implementations to avoid doing so.
(Instead, add a sanity check that the record initialisation vector
length is equal to the cipher block size.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/mishmash/rsa_aes_cbc_sha1.c
src/crypto/mishmash/rsa_aes_cbc_sha256.c
src/include/ipxe/tls.h
src/net/tls.c

index b054a01c73eba32ef9aa4d3526ae9cc2d4294b8f..765ed1138188f3badf1ceaa5335927a03e43f887 100644 (file)
@@ -34,6 +34,8 @@ struct tls_cipher_suite
 tls_dhe_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 03 ) = {
        .code = htons ( TLS_DHE_RSA_WITH_AES_128_CBC_SHA ),
        .key_len = ( 128 / 8 ),
+       .fixed_iv_len = 0,
+       .record_iv_len = AES_BLOCKSIZE,
        .exchange = &tls_dhe_exchange_algorithm,
        .pubkey = &rsa_algorithm,
        .cipher = &aes_cbc_algorithm,
@@ -45,6 +47,8 @@ struct tls_cipher_suite
 tls_dhe_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 04 ) = {
        .code = htons ( TLS_DHE_RSA_WITH_AES_256_CBC_SHA ),
        .key_len = ( 256 / 8 ),
+       .fixed_iv_len = 0,
+       .record_iv_len = AES_BLOCKSIZE,
        .exchange = &tls_dhe_exchange_algorithm,
        .pubkey = &rsa_algorithm,
        .cipher = &aes_cbc_algorithm,
@@ -56,6 +60,8 @@ struct tls_cipher_suite
 tls_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 13 ) = {
        .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ),
        .key_len = ( 128 / 8 ),
+       .fixed_iv_len = 0,
+       .record_iv_len = AES_BLOCKSIZE,
        .exchange = &tls_pubkey_exchange_algorithm,
        .pubkey = &rsa_algorithm,
        .cipher = &aes_cbc_algorithm,
@@ -67,6 +73,8 @@ struct tls_cipher_suite
 tls_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 14 ) = {
        .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ),
        .key_len = ( 256 / 8 ),
+       .fixed_iv_len = 0,
+       .record_iv_len = AES_BLOCKSIZE,
        .exchange = &tls_pubkey_exchange_algorithm,
        .pubkey = &rsa_algorithm,
        .cipher = &aes_cbc_algorithm,
index b003523d56af1403087b42baa7a6cee1708d1596..1cc7dfe27b96f4a272ea5ff4682310e3e27179bf 100644 (file)
@@ -34,6 +34,8 @@ struct tls_cipher_suite
 tls_dhe_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 01 ) = {
        .code = htons ( TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ),
        .key_len = ( 128 / 8 ),
+       .fixed_iv_len = 0,
+       .record_iv_len = AES_BLOCKSIZE,
        .exchange = &tls_dhe_exchange_algorithm,
        .pubkey = &rsa_algorithm,
        .cipher = &aes_cbc_algorithm,
@@ -45,6 +47,8 @@ struct tls_cipher_suite
 tls_dhe_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite ( 02 ) = {
        .code = htons ( TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 ),
        .key_len = ( 256 / 8 ),
+       .fixed_iv_len = 0,
+       .record_iv_len = AES_BLOCKSIZE,
        .exchange = &tls_dhe_exchange_algorithm,
        .pubkey = &rsa_algorithm,
        .cipher = &aes_cbc_algorithm,
@@ -56,6 +60,8 @@ struct tls_cipher_suite
 tls_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 11 ) = {
        .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ),
        .key_len = ( 128 / 8 ),
+       .fixed_iv_len = 0,
+       .record_iv_len = AES_BLOCKSIZE,
        .exchange = &tls_pubkey_exchange_algorithm,
        .pubkey = &rsa_algorithm,
        .cipher = &aes_cbc_algorithm,
@@ -67,6 +73,8 @@ struct tls_cipher_suite
 tls_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite ( 12 ) = {
        .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 ),
        .key_len = ( 256 / 8 ),
+       .fixed_iv_len = 0,
+       .record_iv_len = AES_BLOCKSIZE,
        .exchange = &tls_pubkey_exchange_algorithm,
        .pubkey = &rsa_algorithm,
        .cipher = &aes_cbc_algorithm,
index 0b34dee7c18c9b634253bc9d7672bec572e515f6..8bb1ccceb7f7ac86e8b3093470466c1f589b86b0 100644 (file)
@@ -169,10 +169,14 @@ struct tls_cipher_suite {
        struct cipher_algorithm *cipher;
        /** MAC digest algorithm */
        struct digest_algorithm *digest;
-       /** Key length */
-       uint16_t key_len;
        /** Numeric code (in network-endian order) */
        uint16_t code;
+       /** Key length */
+       uint8_t key_len;
+       /** Fixed initialisation vector length */
+       uint8_t fixed_iv_len;
+       /** Record initialisation vector length */
+       uint8_t record_iv_len;
 };
 
 /** TLS cipher suite table */
@@ -195,6 +199,8 @@ struct tls_cipherspec {
        void *cipher_ctx;
        /** MAC secret */
        void *mac_secret;
+       /** Fixed initialisation vector */
+       void *fixed_iv;
 };
 
 /** A TLS signature and hash algorithm identifier */
index 9ad8448cf3b99ebd836ee6c1b45c1d48dc7fa8a0..f4f8d930d68ff6a97ecb4421ce972a48d937330f 100644 (file)
@@ -664,7 +664,8 @@ static int tls_generate_keys ( struct tls_connection *tls ) {
        struct tls_cipherspec *rx_cipherspec = &tls->rx_cipherspec_pending;
        size_t hash_size = tx_cipherspec->suite->digest->digestsize;
        size_t key_size = tx_cipherspec->suite->key_len;
-       size_t total = ( 2 * ( hash_size + key_size ) );
+       size_t iv_size = tx_cipherspec->suite->fixed_iv_len;
+       size_t total = ( 2 * ( hash_size + key_size + iv_size ) );
        uint8_t key_block[total];
        uint8_t *key;
        int rc;
@@ -714,6 +715,18 @@ static int tls_generate_keys ( struct tls_connection *tls ) {
        DBGC_HD ( tls, key, key_size );
        key += key_size;
 
+       /* TX initialisation vector */
+       memcpy ( tx_cipherspec->fixed_iv, key, iv_size );
+       DBGC ( tls, "TLS %p TX IV:\n", tls );
+       DBGC_HD ( tls, key, iv_size );
+       key += iv_size;
+
+       /* RX initialisation vector */
+       memcpy ( rx_cipherspec->fixed_iv, key, iv_size );
+       DBGC ( tls, "TLS %p RX IV:\n", tls );
+       DBGC_HD ( tls, key, iv_size );
+       key += iv_size;
+
        assert ( ( key_block + total ) == key );
 
        return 0;
@@ -792,9 +805,10 @@ static int tls_set_cipher ( struct tls_connection *tls,
 
        /* Clear out old cipher contents, if any */
        tls_clear_cipher ( tls, cipherspec );
-       
+
        /* Allocate dynamic storage */
-       total = ( pubkey->ctxsize + cipher->ctxsize + digest->digestsize );
+       total = ( pubkey->ctxsize + cipher->ctxsize + digest->digestsize +
+                 suite->fixed_iv_len );
        dynamic = zalloc ( total );
        if ( ! dynamic ) {
                DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
@@ -807,6 +821,7 @@ static int tls_set_cipher ( struct tls_connection *tls,
        cipherspec->pubkey_ctx = dynamic;       dynamic += pubkey->ctxsize;
        cipherspec->cipher_ctx = dynamic;       dynamic += cipher->ctxsize;
        cipherspec->mac_secret = dynamic;       dynamic += digest->digestsize;
+       cipherspec->fixed_iv = dynamic;         dynamic += suite->fixed_iv_len;
        assert ( ( cipherspec->dynamic + total ) == dynamic );
 
        /* Store parameters */
@@ -2627,6 +2642,9 @@ static void * tls_assemble_block ( struct tls_connection *tls,
        void *mac;
        void *padding;
 
+       /* Sanity check */
+       assert ( iv_len == tls->tx_cipherspec.suite->record_iv_len );
+
        /* Calculate block-ciphered struct length */
        padding_len = ( ( blocksize - 1 ) & -( iv_len + len + mac_len + 1 ) );
        *plaintext_len = ( iv_len + len + mac_len + padding_len + 1 );
@@ -2781,6 +2799,9 @@ static int tls_split_block ( struct tls_connection *tls,
        uint8_t *padding;
        size_t padding_len;
 
+       /* Sanity check */
+       assert ( iv_len == tls->rx_cipherspec.suite->record_iv_len );
+
        /* Extract initialisation vector */
        iobuf = list_first_entry ( rx_data, struct io_buffer, list );
        if ( iob_len ( iobuf ) < iv_len ) {