From 30243ad73957a2e1cc4aedc3f23be66cdf399f00 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 28 Oct 2022 16:27:10 +0100 Subject: [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 --- src/include/ipxe/cbc.h | 1 + src/include/ipxe/crypto.h | 18 +++++++++++++++++- src/include/ipxe/ecb.h | 1 + src/include/ipxe/gcm.h | 1 + 4 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src/include/ipxe') diff --git a/src/include/ipxe/cbc.h b/src/include/ipxe/cbc.h index eead045ed..382fc9036 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 842f2f633..ba09c9468 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 1d2ebf716..db22d996d 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 658685486..d93eecd8e 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, \ -- cgit