diff options
author | Michael Brown <mcb30@ipxe.org> | 2022-10-28 16:27:10 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2022-11-07 11:19:48 +0000 |
commit | 30243ad73957a2e1cc4aedc3f23be66cdf399f00 (patch) | |
tree | c0b476b76fed7f2a9c5a3b9ec1ea03f01017a693 | |
parent | d1bc872a2e3b682169da4dd708dfe143d539eaaf (diff) | |
download | ipxe-30243ad73957a2e1cc4aedc3f23be66cdf399f00.zip ipxe-30243ad73957a2e1cc4aedc3f23be66cdf399f00.tar.gz ipxe-30243ad73957a2e1cc4aedc3f23be66cdf399f00.tar.bz2 |
[crypto] Add concept of cipher alignment size
The GCM cipher mode of operation (in common with other counter-based
modes of operation) has a notion of blocksize that does not neatly
fall into our current abstraction: it does operate in 16-byte blocks
but allows for an arbitrary overall data length (i.e. the final block
may be incomplete).
Model this by adding a concept of alignment size. Each call to
encrypt() or decrypt() must begin at a multiple of the alignment size
from the start of the data stream. This allows us to model GCM by
using a block size of 1 byte and an alignment size of 16 bytes.
As a side benefit, this same concept allows us to neatly model the
fact that raw AES can encrypt only a single 16-byte block, by
specifying an alignment size of zero on this cipher.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/crypto/aes.c | 1 | ||||
-rw-r--r-- | src/crypto/arc4.c | 1 | ||||
-rw-r--r-- | src/crypto/crypto_null.c | 1 | ||||
-rw-r--r-- | src/include/ipxe/cbc.h | 1 | ||||
-rw-r--r-- | src/include/ipxe/crypto.h | 18 | ||||
-rw-r--r-- | src/include/ipxe/ecb.h | 1 | ||||
-rw-r--r-- | src/include/ipxe/gcm.h | 1 | ||||
-rw-r--r-- | src/tests/cipher_test.c | 10 |
8 files changed, 33 insertions, 1 deletions
diff --git a/src/crypto/aes.c b/src/crypto/aes.c index aeeaa1d..5200e77 100644 --- a/src/crypto/aes.c +++ b/src/crypto/aes.c @@ -784,6 +784,7 @@ struct cipher_algorithm aes_algorithm = { .name = "aes", .ctxsize = sizeof ( struct aes_context ), .blocksize = AES_BLOCKSIZE, + .alignsize = 0, .authsize = 0, .setkey = aes_setkey, .setiv = cipher_null_setiv, diff --git a/src/crypto/arc4.c b/src/crypto/arc4.c index 4d98abe..3b6adec 100644 --- a/src/crypto/arc4.c +++ b/src/crypto/arc4.c @@ -119,6 +119,7 @@ struct cipher_algorithm arc4_algorithm = { .name = "ARC4", .ctxsize = ARC4_CTX_SIZE, .blocksize = 1, + .alignsize = 1, .authsize = 0, .setkey = arc4_setkey, .setiv = cipher_null_setiv, diff --git a/src/crypto/crypto_null.c b/src/crypto/crypto_null.c index 26cfbfc..0ad463c 100644 --- a/src/crypto/crypto_null.c +++ b/src/crypto/crypto_null.c @@ -84,6 +84,7 @@ struct cipher_algorithm cipher_null = { .name = "null", .ctxsize = 0, .blocksize = 1, + .alignsize = 1, .authsize = 0, .setkey = cipher_null_setkey, .setiv = cipher_null_setiv, diff --git a/src/include/ipxe/cbc.h b/src/include/ipxe/cbc.h index eead045..382fc90 100644 --- a/src/include/ipxe/cbc.h +++ b/src/include/ipxe/cbc.h @@ -95,6 +95,7 @@ struct cipher_algorithm _cbc_cipher = { \ .name = #_cbc_name, \ .ctxsize = sizeof ( struct _cbc_name ## _context ), \ .blocksize = _blocksize, \ + .alignsize = _blocksize, \ .authsize = 0, \ .setkey = _cbc_name ## _setkey, \ .setiv = _cbc_name ## _setiv, \ diff --git a/src/include/ipxe/crypto.h b/src/include/ipxe/crypto.h index 842f2f6..ba09c94 100644 --- a/src/include/ipxe/crypto.h +++ b/src/include/ipxe/crypto.h @@ -51,8 +51,24 @@ struct cipher_algorithm { const char *name; /** Context size */ size_t ctxsize; - /** Block size */ + /** Block size + * + * Every call to encrypt() or decrypt() must be for a multiple + * of this size. + */ size_t blocksize; + /** Alignment size + * + * Every call to encrypt() or decrypt() must begin at a + * multiple of this offset from the start of the stream. + * (Equivalently: all but the last call to encrypt() or + * decrypt() must be for a multiple of this size.) + * + * For ciphers supporting additional data, the main data + * stream and additional data stream are both considered to + * begin at offset zero. + */ + size_t alignsize; /** Authentication tag size */ size_t authsize; /** Set key diff --git a/src/include/ipxe/ecb.h b/src/include/ipxe/ecb.h index 1d2ebf7..db22d99 100644 --- a/src/include/ipxe/ecb.h +++ b/src/include/ipxe/ecb.h @@ -47,6 +47,7 @@ struct cipher_algorithm _ecb_cipher = { \ .name = #_ecb_name, \ .ctxsize = sizeof ( _raw_context ), \ .blocksize = _blocksize, \ + .alignsize = _blocksize, \ .authsize = 0, \ .setkey = _ecb_name ## _setkey, \ .setiv = _ecb_name ## _setiv, \ diff --git a/src/include/ipxe/gcm.h b/src/include/ipxe/gcm.h index 6586854..d93eecd 100644 --- a/src/include/ipxe/gcm.h +++ b/src/include/ipxe/gcm.h @@ -121,6 +121,7 @@ struct cipher_algorithm _gcm_cipher = { \ .name = #_gcm_name, \ .ctxsize = sizeof ( struct _gcm_name ## _context ), \ .blocksize = 1, \ + .alignsize = sizeof ( union gcm_block ), \ .authsize = sizeof ( union gcm_block ), \ .setkey = _gcm_name ## _setkey, \ .setiv = _gcm_name ## _setiv, \ diff --git a/src/tests/cipher_test.c b/src/tests/cipher_test.c index cc732c2..2ead3c8 100644 --- a/src/tests/cipher_test.c +++ b/src/tests/cipher_test.c @@ -131,8 +131,18 @@ void cipher_decrypt_okx ( struct cipher_test *test, const char *file, */ void cipher_okx ( struct cipher_test *test, const char *file, unsigned int line ) { + struct cipher_algorithm *cipher = test->cipher; + size_t len = test->len; + /* Sanity checks */ + okx ( cipher->blocksize != 0, file, line ); + okx ( ( len % cipher->blocksize ) == 0, file, line ); + okx ( ( cipher->alignsize % cipher->blocksize ) == 0, file, line ); + + /* Report encryption test result */ cipher_encrypt_okx ( test, file, line ); + + /* Report decryption test result */ cipher_decrypt_okx ( test, file, line ); } |