[crypto] Ensure that a closed channel is left with unusable ciphers We currently protect against a consumer that erroneously uses values generated from the ephemeral master secret after closing a previously opened channel, by deliberately replacing the ephemeral master secret rather than zeroing it when the channel is closed. Extend this concept to protect against a consumer that erroneously uses the ciphers after closing a previously opened channel (or that erroneously uses the ciphers from a channel that failed to open successfully), by using the dead ciphers by default and by enabling the plaintext (null) ciphers when and only when the channel has been successfully opened. Signed-off-by: Michael Brown <mcb30@ipxe.org>
diff --git a/src/crypto/channel.c b/src/crypto/channel.c index c2252cd..36e2254 100644 --- a/src/crypto/channel.c +++ b/src/crypto/channel.c
@@ -1070,7 +1070,7 @@ * cipher-related failure, to guard against code paths that may fail * to check for cipher errors. */ -static struct cipher_algorithm channel_dead_cipher = { +struct cipher_algorithm channel_dead_cipher = { .name = "dead", .ctxsize = 0, .blocksize = 1, @@ -1197,29 +1197,6 @@ */ /** - * Reset secure channel - * - * @v channel Secure channel - */ -static void channel_reset ( struct secure_channel *channel ) { - - /* Reset ciphers to plaintext */ - channel_clear_cipher ( &channel->tx ); - channel_clear_cipher ( &channel->rx ); - channel->tx.cipher = &cipher_null; - channel->rx.cipher = &cipher_null; - assert ( channel->tx.ctx == NULL ); - assert ( channel->rx.ctx == NULL ); - - /* Clear security properties */ - channel_unkey ( channel ); - assert ( channel->props.keyed == 0 ); - assert ( channel->props.bound == NULL ); - assert ( channel->props.confirmed == NULL ); - assert ( channel->props.established == NULL ); -} - -/** * Open secure channel * * @v channel Secure channel @@ -1234,16 +1211,34 @@ assert ( channel->op->reset != NULL ); assert ( channel->op->apply != NULL ); assert ( channel->op->verify != NULL ); + + /* Clear security properties (which should already be clear) */ + assert ( channel->props.keyed == 0 ); + assert ( channel->props.bound == NULL ); + assert ( channel->props.confirmed == NULL ); + assert ( channel->props.established == NULL ); + channel_unkey ( channel ); + assert ( channel->props.keyed == 0 ); + assert ( channel->props.bound == NULL ); + assert ( channel->props.confirmed == NULL ); + assert ( channel->props.established == NULL ); + + /* Reset ciphers (which should already have no contexts) */ assert ( channel->tx.ctx == NULL ); assert ( channel->rx.ctx == NULL ); - - /* Reset ciphers and security properties */ - channel_reset ( channel ); + channel_clear_cipher ( &channel->tx ); + channel_clear_cipher ( &channel->rx ); + assert ( channel->tx.ctx == NULL ); + assert ( channel->rx.ctx == NULL ); /* Initialise ephemeral master secret */ if ( ( rc = channel_ephemeral_init ( channel ) ) != 0 ) return rc; + /* Enable initial plaintext ciphers */ + channel->tx.cipher = &cipher_null; + channel->rx.cipher = &cipher_null; + DBGC ( channel, "CHANNEL %p opened\n", channel ); return 0; } @@ -1275,6 +1270,10 @@ /* Clear security properties */ channel_unkey ( channel ); + assert ( channel->props.keyed == 0 ); + assert ( channel->props.bound == NULL ); + assert ( channel->props.confirmed == NULL ); + assert ( channel->props.established == NULL ); /* Replace ephemeral master secret * @@ -1301,8 +1300,18 @@ */ void channel_close ( struct secure_channel *channel ) { - /* Reset channel */ - channel_reset ( channel ); + /* Clear security properties */ + channel_unkey ( channel ); + assert ( channel->props.keyed == 0 ); + assert ( channel->props.bound == NULL ); + assert ( channel->props.confirmed == NULL ); + assert ( channel->props.established == NULL ); + + /* Reset ciphers */ + channel_clear_cipher ( &channel->tx ); + channel_clear_cipher ( &channel->rx ); + assert ( channel->tx.ctx == NULL ); + assert ( channel->rx.ctx == NULL ); /* Replace ephemeral master secret *
diff --git a/src/include/ipxe/channel.h b/src/include/ipxe/channel.h index fb90cf9..570ac2f 100644 --- a/src/include/ipxe/channel.h +++ b/src/include/ipxe/channel.h
@@ -245,6 +245,8 @@ const void *auth, size_t len ); }; +extern struct cipher_algorithm channel_dead_cipher; + /** * Initialise secure channel * @@ -255,6 +257,8 @@ struct secure_channel_operations *op ) { channel->op = op; + channel->tx.cipher = &channel_dead_cipher; + channel->rx.cipher = &channel_dead_cipher; } /**