[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>
pull/798/head
Michael Brown 2022-10-28 16:27:10 +01:00
parent d1bc872a2e
commit 30243ad739
8 changed files with 33 additions and 1 deletions

View 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,

View 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,

View 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,

View 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, \

View 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

View 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, \

View 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, \

View 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 );
}