mirror of
https://github.com/ipxe/ipxe
synced 2026-10-07 15:05:42 +03:00
[crypto] Reject zero-length IVs for GCM ciphers
A zero-length IV is not permitted by the NIST GCM specification, since it would lead to leaking the authentication key. The only existing code path that can currently lead to the use of a GCM cipher with a zero-length initialisation vector is CMS decryption. Modifying a CMS encrypted message to include a zero-length IV would leak information required to obtain the authentication key into the transient decrypted image, but this transient image would then fail the GCM authentication tag check and so the decrypted plaintext would be immediately overwritten (with the re-encrypted ciphertext). Improve robustness by rejecting a zero-length initialisation vector for a GCM cipher, and add a test case to ensure that this rejection remains in place in future. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
+7
-1
@@ -37,6 +37,7 @@ FILE_SECBOOT ( PERMITTED );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <byteswap.h>
|
||||
#include <ipxe/crypto.h>
|
||||
#include <ipxe/gcm.h>
|
||||
@@ -473,7 +474,7 @@ int gcm_setiv ( struct cipher_algorithm *cipher, void *ctx,
|
||||
/* Initialisation vector is exactly 96 bits, use it as-is */
|
||||
memcpy ( context->gcm.ctr.ctr.iv, iv, ivlen );
|
||||
|
||||
} else {
|
||||
} else if ( ivlen ) {
|
||||
|
||||
/* Calculate hash over initialisation vector */
|
||||
context->gcm.flags = GCM_FL_IV;
|
||||
@@ -486,6 +487,11 @@ int gcm_setiv ( struct cipher_algorithm *cipher, void *ctx,
|
||||
build_assert ( gcm_offset ( ctr ) > gcm_offset ( hash ) );
|
||||
build_assert ( gcm_offset ( ctr ) > gcm_offset ( len ) );
|
||||
build_assert ( gcm_offset ( ctr ) < gcm_offset ( key ) );
|
||||
|
||||
} else {
|
||||
|
||||
/* Zero-length IVs are not permitted */
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
DBGC2 ( context, "GCM %p Y[0]:\n", context );
|
||||
|
||||
@@ -457,6 +457,7 @@ FILE_SECBOOT ( PERMITTED );
|
||||
#define ERRFILE_cbc ( ERRFILE_OTHER | 0x006c0000 )
|
||||
#define ERRFILE_channel ( ERRFILE_OTHER | 0x006d0000 )
|
||||
#define ERRFILE_tlskey ( ERRFILE_OTHER | 0x006e0000 )
|
||||
#define ERRFILE_gcm ( ERRFILE_OTHER | 0x006f0000 )
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -357,6 +357,10 @@ CIPHER_TEST ( gcm_test_18, &aes_gcm_algorithm, GCM_KEY_256,
|
||||
AUTH ( 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8,
|
||||
0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a ) );
|
||||
|
||||
/** Zero-length IV */
|
||||
CIPHER_TEST ( gcm_empty_iv, &aes_gcm_algorithm, GCM_KEY_256, IV(),
|
||||
ADDITIONAL(), PLAINTEXT(), CIPHERTEXT(), AUTH() );
|
||||
|
||||
/**
|
||||
* Perform Galois/Counter Mode self-test
|
||||
*
|
||||
@@ -384,6 +388,7 @@ static void gcm_test_exec ( void ) {
|
||||
cipher_ok ( &gcm_test_16 );
|
||||
cipher_ok ( &gcm_test_17 );
|
||||
cipher_ok ( &gcm_test_18 );
|
||||
cipher_iv_fail_ok ( &gcm_empty_iv );
|
||||
|
||||
/* Speed tests */
|
||||
for ( keylen = 128 ; keylen <= 256 ; keylen += 64 ) {
|
||||
|
||||
Reference in New Issue
Block a user