]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Add concept of cipher alignment size
authorMichael Brown <mcb30@ipxe.org>
Fri, 28 Oct 2022 15:27:10 +0000 (16:27 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 7 Nov 2022 11:19:48 +0000 (11:19 +0000)
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>
src/crypto/aes.c
src/crypto/arc4.c
src/crypto/crypto_null.c
src/include/ipxe/cbc.h
src/include/ipxe/crypto.h
src/include/ipxe/ecb.h
src/include/ipxe/gcm.h
src/tests/cipher_test.c

index aeeaa1d2c5acfb3eb5800cda3f57f06ea3368ec3..5200e7760b45b212c328310a5b849a5f2843c1fd 100644 (file)
@@ -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,
index 4d98abead47cd28012855e100a22974b81daa618..3b6adec199b3ab56bb61dc5a4c4cce789732d7f2 100644 (file)
@@ -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,
index 26cfbfc4e51a590fdedfbce1c55582642f883e20..0ad463c3e1a4ff44b1c0be6123cbac32970f2741 100644 (file)
@@ -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,
index eead045ed95926b6dd23f236ff57570baa4cf86d..382fc9036c1631b77c26bda64cfe311f3d2108ca 100644 (file)
@@ -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,                          \
index 842f2f63365bad3472f5a0626393d32b1ec235b0..ba09c9468b8b1ad479b26882f4a8471ad123699e 100644 (file)
@@ -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
index 1d2ebf716cf6064e2f12fd07fb81ae4aac919225..db22d996daf0327a2fc9cb871cbe51b62a3ab292 100644 (file)
@@ -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,                          \
index 65868548676f3f7ff06ebc17d2dab3f9da32da15..d93eecd8efab2c0e9f16c8aa3ed03122d7034ad7 100644 (file)
@@ -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,                          \
index cc732c2e08f4b0f10975425532fbf2b4b86a1863..2ead3c827484ae63b1e6681c21d993f4dd7eb3a1 100644 (file)
@@ -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 );
 }