From 52f72d298abd81a6102ddddf2fff4918e4b077ce Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 25 Oct 2022 12:59:06 +0100 Subject: [crypto] Expose null crypto algorithm methods for reuse Signed-off-by: Michael Brown --- src/crypto/crypto_null.c | 62 ++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 33 deletions(-) (limited to 'src/crypto/crypto_null.c') diff --git a/src/crypto/crypto_null.c b/src/crypto/crypto_null.c index 15a1c538b..91077177c 100644 --- a/src/crypto/crypto_null.c +++ b/src/crypto/crypto_null.c @@ -32,16 +32,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include -static void digest_null_init ( void *ctx __unused ) { +void digest_null_init ( void *ctx __unused ) { /* Do nothing */ } -static void digest_null_update ( void *ctx __unused, const void *src __unused, - size_t len __unused ) { +void digest_null_update ( void *ctx __unused, const void *src __unused, + size_t len __unused ) { /* Do nothing */ } -static void digest_null_final ( void *ctx __unused, void *out __unused ) { +void digest_null_final ( void *ctx __unused, void *out __unused ) { /* Do nothing */ } @@ -55,24 +55,23 @@ struct digest_algorithm digest_null = { .final = digest_null_final, }; -static int cipher_null_setkey ( void *ctx __unused, const void *key __unused, - size_t keylen __unused ) { +int cipher_null_setkey ( void *ctx __unused, const void *key __unused, + size_t keylen __unused ) { /* Do nothing */ return 0; } -static void cipher_null_setiv ( void *ctx __unused, - const void *iv __unused ) { +void cipher_null_setiv ( void *ctx __unused, const void *iv __unused ) { /* Do nothing */ } -static void cipher_null_encrypt ( void *ctx __unused, const void *src, - void *dst, size_t len ) { +void cipher_null_encrypt ( void *ctx __unused, const void *src, void *dst, + size_t len ) { memcpy ( dst, src, len ); } -static void cipher_null_decrypt ( void *ctx __unused, const void *src, - void *dst, size_t len ) { +void cipher_null_decrypt ( void *ctx __unused, const void *src, void *dst, + size_t len ) { memcpy ( dst, src, len ); } @@ -86,45 +85,42 @@ struct cipher_algorithm cipher_null = { .decrypt = cipher_null_decrypt, }; -static int pubkey_null_init ( void *ctx __unused, const void *key __unused, - size_t key_len __unused ) { +int pubkey_null_init ( void *ctx __unused, const void *key __unused, + size_t key_len __unused ) { return 0; } -static size_t pubkey_null_max_len ( void *ctx __unused ) { +size_t pubkey_null_max_len ( void *ctx __unused ) { return 0; } -static int pubkey_null_encrypt ( void *ctx __unused, - const void *plaintext __unused, - size_t plaintext_len __unused, - void *ciphertext __unused ) { +int pubkey_null_encrypt ( void *ctx __unused, const void *plaintext __unused, + size_t plaintext_len __unused, + void *ciphertext __unused ) { return 0; } -static int pubkey_null_decrypt ( void *ctx __unused, - const void *ciphertext __unused, - size_t ciphertext_len __unused, - void *plaintext __unused ) { +int pubkey_null_decrypt ( void *ctx __unused, const void *ciphertext __unused, + size_t ciphertext_len __unused, + void *plaintext __unused ) { return 0; } -static int pubkey_null_sign ( void *ctx __unused, - struct digest_algorithm *digest __unused, - const void *value __unused, - void *signature __unused ) { +int pubkey_null_sign ( void *ctx __unused, + struct digest_algorithm *digest __unused, + const void *value __unused, void *signature __unused ) { return 0; } -static int pubkey_null_verify ( void *ctx __unused, - struct digest_algorithm *digest __unused, - const void *value __unused, - const void *signature __unused , - size_t signature_len __unused ) { +int pubkey_null_verify ( void *ctx __unused, + struct digest_algorithm *digest __unused, + const void *value __unused, + const void *signature __unused , + size_t signature_len __unused ) { return 0; } -static void pubkey_null_final ( void *ctx __unused ) { +void pubkey_null_final ( void *ctx __unused ) { /* Do nothing */ } -- cgit v1.2.3-55-g7522 From 8e478e648fb68ac6f07e4e5cd80a5c1fefcb1cf5 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 24 Oct 2022 16:52:24 +0100 Subject: [crypto] Allow initialisation vector length to vary from cipher blocksize Signed-off-by: Michael Brown --- src/crypto/crypto_null.c | 3 ++- src/include/ipxe/cbc.h | 10 +++++++--- src/include/ipxe/crypto.h | 9 +++++---- src/include/ipxe/ecb.h | 5 +++-- src/net/peerblk.c | 3 ++- src/net/tls.c | 4 ++-- src/tests/cipher_test.c | 6 +++--- 7 files changed, 24 insertions(+), 16 deletions(-) (limited to 'src/crypto/crypto_null.c') diff --git a/src/crypto/crypto_null.c b/src/crypto/crypto_null.c index 91077177c..ef6041b5b 100644 --- a/src/crypto/crypto_null.c +++ b/src/crypto/crypto_null.c @@ -61,7 +61,8 @@ int cipher_null_setkey ( void *ctx __unused, const void *key __unused, return 0; } -void cipher_null_setiv ( void *ctx __unused, const void *iv __unused ) { +void cipher_null_setiv ( void *ctx __unused, const void *iv __unused, + size_t ivlen __unused ) { /* Do nothing */ } diff --git a/src/include/ipxe/cbc.h b/src/include/ipxe/cbc.h index 18a94e144..5c8740365 100644 --- a/src/include/ipxe/cbc.h +++ b/src/include/ipxe/cbc.h @@ -33,12 +33,15 @@ static inline int cbc_setkey ( void *ctx, const void *key, size_t keylen, * * @v ctx Context * @v iv Initialisation vector + * @v ivlen Initialisation vector length * @v raw_cipher Underlying cipher algorithm * @v cbc_ctx CBC context */ -static inline void cbc_setiv ( void *ctx __unused, const void *iv, +static inline void cbc_setiv ( void *ctx __unused, + const void *iv, size_t ivlen, struct cipher_algorithm *raw_cipher, void *cbc_ctx ) { + assert ( ivlen == raw_cipher->blocksize ); memcpy ( cbc_ctx, iv, raw_cipher->blocksize ); } @@ -70,9 +73,10 @@ static int _cbc_name ## _setkey ( void *ctx, const void *key, \ return cbc_setkey ( &_cbc_name ## _ctx->raw_ctx, key, keylen, \ &_raw_cipher, &_cbc_name ## _ctx->cbc_ctx );\ } \ -static void _cbc_name ## _setiv ( void *ctx, const void *iv ) { \ +static void _cbc_name ## _setiv ( void *ctx, const void *iv, \ + size_t ivlen ) { \ struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \ - cbc_setiv ( &_cbc_name ## _ctx->raw_ctx, iv, \ + cbc_setiv ( &_cbc_name ## _ctx->raw_ctx, iv, ivlen, \ &_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \ } \ static void _cbc_name ## _encrypt ( void *ctx, const void *src, \ diff --git a/src/include/ipxe/crypto.h b/src/include/ipxe/crypto.h index 34ab38930..931be0502 100644 --- a/src/include/ipxe/crypto.h +++ b/src/include/ipxe/crypto.h @@ -64,8 +64,9 @@ struct cipher_algorithm { * * @v ctx Context * @v iv Initialisation vector + * @v ivlen Initialisation vector length */ - void ( * setiv ) ( void *ctx, const void *iv ); + void ( * setiv ) ( void *ctx, const void *iv, size_t ivlen ); /** Encrypt data * * @v ctx Context @@ -190,8 +191,8 @@ static inline int cipher_setkey ( struct cipher_algorithm *cipher, } static inline void cipher_setiv ( struct cipher_algorithm *cipher, - void *ctx, const void *iv ) { - cipher->setiv ( ctx, iv ); + void *ctx, const void *iv, size_t ivlen ) { + cipher->setiv ( ctx, iv, ivlen ); } static inline void cipher_encrypt ( struct cipher_algorithm *cipher, @@ -268,7 +269,7 @@ extern void digest_null_update ( void *ctx, const void *src, size_t len ); extern void digest_null_final ( void *ctx, void *out ); extern int cipher_null_setkey ( void *ctx, const void *key, size_t keylen ); -extern void cipher_null_setiv ( void *ctx, const void *iv ); +extern void cipher_null_setiv ( void *ctx, const void *iv, size_t ivlen ); extern void cipher_null_encrypt ( void *ctx, const void *src, void *dst, size_t len ); extern void cipher_null_decrypt ( void *ctx, const void *src, void *dst, diff --git a/src/include/ipxe/ecb.h b/src/include/ipxe/ecb.h index 4e6aa3c81..6c40c6126 100644 --- a/src/include/ipxe/ecb.h +++ b/src/include/ipxe/ecb.h @@ -31,8 +31,9 @@ static int _ecb_name ## _setkey ( void *ctx, const void *key, \ size_t keylen ) { \ return cipher_setkey ( &_raw_cipher, ctx, key, keylen ); \ } \ -static void _ecb_name ## _setiv ( void *ctx, const void *iv ) { \ - cipher_setiv ( &_raw_cipher, ctx, iv ); \ +static void _ecb_name ## _setiv ( void *ctx, const void *iv, \ + size_t ivlen ) { \ + cipher_setiv ( &_raw_cipher, ctx, iv, ivlen ); \ } \ static void _ecb_name ## _encrypt ( void *ctx, const void *src, \ void *dst, size_t len ) { \ diff --git a/src/net/peerblk.c b/src/net/peerblk.c index f8994f42c..bbd5f16ed 100644 --- a/src/net/peerblk.c +++ b/src/net/peerblk.c @@ -1033,7 +1033,8 @@ static int peerblk_parse_iv ( struct peerdist_block *peerblk, size_t buf_len, } /* Set initialisation vector */ - cipher_setiv ( peerblk->cipher, peerblk->cipherctx, msg->msg.iv.data ); + cipher_setiv ( peerblk->cipher, peerblk->cipherctx, msg->msg.iv.data, + blksize ); return 0; } diff --git a/src/net/tls.c b/src/net/tls.c index 4aa4d9e29..3545f12db 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -717,14 +717,14 @@ static int tls_generate_keys ( struct tls_connection *tls ) { /* TX initialisation vector */ cipher_setiv ( tx_cipherspec->suite->cipher, - tx_cipherspec->cipher_ctx, key ); + tx_cipherspec->cipher_ctx, key, iv_size ); DBGC ( tls, "TLS %p TX IV:\n", tls ); DBGC_HD ( tls, key, iv_size ); key += iv_size; /* RX initialisation vector */ cipher_setiv ( rx_cipherspec->suite->cipher, - rx_cipherspec->cipher_ctx, key ); + rx_cipherspec->cipher_ctx, key, iv_size ); DBGC ( tls, "TLS %p RX IV:\n", tls ); DBGC_HD ( tls, key, iv_size ); key += iv_size; diff --git a/src/tests/cipher_test.c b/src/tests/cipher_test.c index 800d6c138..5361502ff 100644 --- a/src/tests/cipher_test.c +++ b/src/tests/cipher_test.c @@ -61,7 +61,7 @@ void cipher_encrypt_okx ( struct cipher_test *test, const char *file, /* Initialise cipher */ okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0, file, line ); - cipher_setiv ( cipher, ctx, test->iv ); + cipher_setiv ( cipher, ctx, test->iv, test->iv_len ); /* Perform encryption */ cipher_encrypt ( cipher, ctx, test->plaintext, ciphertext, len ); @@ -87,7 +87,7 @@ void cipher_decrypt_okx ( struct cipher_test *test, const char *file, /* Initialise cipher */ okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0, file, line ); - cipher_setiv ( cipher, ctx, test->iv ); + cipher_setiv ( cipher, ctx, test->iv, test->iv_len ); /* Perform encryption */ cipher_decrypt ( cipher, ctx, test->ciphertext, plaintext, len ); @@ -143,7 +143,7 @@ cipher_cost ( struct cipher_algorithm *cipher, size_t key_len, /* Initialise cipher */ rc = cipher_setkey ( cipher, ctx, key, key_len ); assert ( rc == 0 ); - cipher_setiv ( cipher, ctx, iv ); + cipher_setiv ( cipher, ctx, iv, sizeof ( iv ) ); /* Profile cipher operation */ memset ( &profiler, 0, sizeof ( profiler ) ); -- cgit v1.2.3-55-g7522 From da81214cec87201dc18c0ce71224367e13a6edfb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 24 Oct 2022 19:20:41 +0100 Subject: [crypto] Add concept of authentication tag to cipher algorithms Some ciphers (such as GCM) support the concept of a tag that can be used to authenticate the encrypted data. Add a cipher method for generating an authentication tag. Signed-off-by: Michael Brown --- src/crypto/aes.c | 2 ++ src/crypto/arc4.c | 2 ++ src/crypto/crypto_null.c | 6 ++++++ src/include/ipxe/cbc.h | 2 ++ src/include/ipxe/crypto.h | 18 ++++++++++++++++++ src/include/ipxe/ecb.h | 2 ++ src/tests/aes_test.c | 12 ++++++------ src/tests/cipher_test.c | 14 ++++++++++++++ src/tests/cipher_test.h | 13 ++++++++++++- 9 files changed, 64 insertions(+), 7 deletions(-) (limited to 'src/crypto/crypto_null.c') diff --git a/src/crypto/aes.c b/src/crypto/aes.c index d7393285f..4a7668b6b 100644 --- a/src/crypto/aes.c +++ b/src/crypto/aes.c @@ -783,10 +783,12 @@ struct cipher_algorithm aes_algorithm = { .name = "aes", .ctxsize = sizeof ( struct aes_context ), .blocksize = AES_BLOCKSIZE, + .authsize = 0, .setkey = aes_setkey, .setiv = cipher_null_setiv, .encrypt = aes_encrypt, .decrypt = aes_decrypt, + .auth = cipher_null_auth, }; /* AES in Electronic Codebook mode */ diff --git a/src/crypto/arc4.c b/src/crypto/arc4.c index 0dba2fc59..4d98abead 100644 --- a/src/crypto/arc4.c +++ b/src/crypto/arc4.c @@ -119,8 +119,10 @@ struct cipher_algorithm arc4_algorithm = { .name = "ARC4", .ctxsize = ARC4_CTX_SIZE, .blocksize = 1, + .authsize = 0, .setkey = arc4_setkey, .setiv = cipher_null_setiv, .encrypt = arc4_xor, .decrypt = arc4_xor, + .auth = cipher_null_auth, }; diff --git a/src/crypto/crypto_null.c b/src/crypto/crypto_null.c index ef6041b5b..26cfbfc4e 100644 --- a/src/crypto/crypto_null.c +++ b/src/crypto/crypto_null.c @@ -76,14 +76,20 @@ void cipher_null_decrypt ( void *ctx __unused, const void *src, void *dst, memcpy ( dst, src, len ); } +void cipher_null_auth ( void *ctx __unused, void *auth __unused ) { + /* Do nothing */ +} + struct cipher_algorithm cipher_null = { .name = "null", .ctxsize = 0, .blocksize = 1, + .authsize = 0, .setkey = cipher_null_setkey, .setiv = cipher_null_setiv, .encrypt = cipher_null_encrypt, .decrypt = cipher_null_decrypt, + .auth = cipher_null_auth, }; int pubkey_null_init ( void *ctx __unused, const void *key __unused, diff --git a/src/include/ipxe/cbc.h b/src/include/ipxe/cbc.h index 5c8740365..eead045ed 100644 --- a/src/include/ipxe/cbc.h +++ b/src/include/ipxe/cbc.h @@ -95,10 +95,12 @@ struct cipher_algorithm _cbc_cipher = { \ .name = #_cbc_name, \ .ctxsize = sizeof ( struct _cbc_name ## _context ), \ .blocksize = _blocksize, \ + .authsize = 0, \ .setkey = _cbc_name ## _setkey, \ .setiv = _cbc_name ## _setiv, \ .encrypt = _cbc_name ## _encrypt, \ .decrypt = _cbc_name ## _decrypt, \ + .auth = cipher_null_auth, \ }; #endif /* _IPXE_CBC_H */ diff --git a/src/include/ipxe/crypto.h b/src/include/ipxe/crypto.h index d41448024..e807aeb52 100644 --- a/src/include/ipxe/crypto.h +++ b/src/include/ipxe/crypto.h @@ -52,6 +52,8 @@ struct cipher_algorithm { size_t ctxsize; /** Block size */ size_t blocksize; + /** Authentication tag size */ + size_t authsize; /** Set key * * @v ctx Context @@ -89,6 +91,12 @@ struct cipher_algorithm { */ void ( * decrypt ) ( void *ctx, const void *src, void *dst, size_t len ); + /** Generate authentication tag + * + * @v ctx Context + * @v auth Authentication tag + */ + void ( * auth ) ( void *ctx, void *auth ); }; /** A public key algorithm */ @@ -215,10 +223,19 @@ static inline void cipher_decrypt ( struct cipher_algorithm *cipher, cipher_decrypt ( (cipher), (ctx), (src), (dst), (len) ); \ } while ( 0 ) +static inline void cipher_auth ( struct cipher_algorithm *cipher, void *ctx, + void *auth ) { + cipher->auth ( ctx, auth ); +} + static inline int is_stream_cipher ( struct cipher_algorithm *cipher ) { return ( cipher->blocksize == 1 ); } +static inline int is_auth_cipher ( struct cipher_algorithm *cipher ) { + return cipher->authsize; +} + static inline int pubkey_init ( struct pubkey_algorithm *pubkey, void *ctx, const void *key, size_t key_len ) { return pubkey->init ( ctx, key, key_len ); @@ -274,6 +291,7 @@ extern void cipher_null_encrypt ( void *ctx, const void *src, void *dst, size_t len ); extern void cipher_null_decrypt ( void *ctx, const void *src, void *dst, size_t len ); +extern void cipher_null_auth ( void *ctx, void *auth ); extern int pubkey_null_init ( void *ctx, const void *key, size_t key_len ); extern size_t pubkey_null_max_len ( void *ctx ); diff --git a/src/include/ipxe/ecb.h b/src/include/ipxe/ecb.h index 6c40c6126..1d2ebf716 100644 --- a/src/include/ipxe/ecb.h +++ b/src/include/ipxe/ecb.h @@ -47,10 +47,12 @@ struct cipher_algorithm _ecb_cipher = { \ .name = #_ecb_name, \ .ctxsize = sizeof ( _raw_context ), \ .blocksize = _blocksize, \ + .authsize = 0, \ .setkey = _ecb_name ## _setkey, \ .setiv = _ecb_name ## _setiv, \ .encrypt = _ecb_name ## _encrypt, \ .decrypt = _ecb_name ## _decrypt, \ + .auth = cipher_null_auth, \ }; #endif /* _IPXE_ECB_H */ diff --git a/src/tests/aes_test.c b/src/tests/aes_test.c index e7201fca6..be119c8d8 100644 --- a/src/tests/aes_test.c +++ b/src/tests/aes_test.c @@ -94,7 +94,7 @@ CIPHER_TEST ( aes_128_ecb, &aes_ecb_algorithm, 0x43, 0xb1, 0xcd, 0x7f, 0x59, 0x8e, 0xce, 0x23, 0x88, 0x1b, 0x00, 0xe3, 0xed, 0x03, 0x06, 0x88, 0x7b, 0x0c, 0x78, 0x5e, 0x27, 0xe8, 0xad, 0x3f, - 0x82, 0x23, 0x20, 0x71, 0x04, 0x72, 0x5d, 0xd4 ) ); + 0x82, 0x23, 0x20, 0x71, 0x04, 0x72, 0x5d, 0xd4 ), AUTH() ); /** AES-128-CBC */ CIPHER_TEST ( aes_128_cbc, &aes_cbc_algorithm, @@ -106,7 +106,7 @@ CIPHER_TEST ( aes_128_cbc, &aes_cbc_algorithm, 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, - 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 ) ); + 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 ), AUTH() ); /** AES-192-ECB (same test as AES-192-Core) */ CIPHER_TEST ( aes_192_ecb, &aes_ecb_algorithm, @@ -118,7 +118,7 @@ CIPHER_TEST ( aes_192_ecb, &aes_ecb_algorithm, 0xef, 0x7a, 0xfd, 0x22, 0x70, 0xe2, 0xe6, 0x0a, 0xdc, 0xe0, 0xba, 0x2f, 0xac, 0xe6, 0x44, 0x4e, 0x9a, 0x4b, 0x41, 0xba, 0x73, 0x8d, 0x6c, 0x72, - 0xfb, 0x16, 0x69, 0x16, 0x03, 0xc1, 0x8e, 0x0e ) ); + 0xfb, 0x16, 0x69, 0x16, 0x03, 0xc1, 0x8e, 0x0e ), AUTH() ); /** AES-192-CBC */ CIPHER_TEST ( aes_192_cbc, &aes_cbc_algorithm, @@ -130,7 +130,7 @@ CIPHER_TEST ( aes_192_cbc, &aes_cbc_algorithm, 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0, 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0, 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81, - 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd ) ); + 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd ), AUTH() ); /** AES-256-ECB (same test as AES-256-Core) */ CIPHER_TEST ( aes_256_ecb, &aes_ecb_algorithm, @@ -142,7 +142,7 @@ CIPHER_TEST ( aes_256_ecb, &aes_ecb_algorithm, 0xb6, 0xed, 0x21, 0xb9, 0x9c, 0xa6, 0xf4, 0xf9, 0xf1, 0x53, 0xe7, 0xb1, 0xbe, 0xaf, 0xed, 0x1d, 0x23, 0x30, 0x4b, 0x7a, 0x39, 0xf9, 0xf3, 0xff, - 0x06, 0x7d, 0x8d, 0x8f, 0x9e, 0x24, 0xec, 0xc7 ) ); + 0x06, 0x7d, 0x8d, 0x8f, 0x9e, 0x24, 0xec, 0xc7 ), AUTH() ); /** AES-256-CBC */ CIPHER_TEST ( aes_256_cbc, &aes_cbc_algorithm, @@ -154,7 +154,7 @@ CIPHER_TEST ( aes_256_cbc, &aes_cbc_algorithm, 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, - 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b ) ); + 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b ), AUTH() ); /** * Perform AES self-test diff --git a/src/tests/cipher_test.c b/src/tests/cipher_test.c index c49b4b69b..cc732c2e0 100644 --- a/src/tests/cipher_test.c +++ b/src/tests/cipher_test.c @@ -57,6 +57,7 @@ void cipher_encrypt_okx ( struct cipher_test *test, const char *file, size_t len = test->len; uint8_t ctx[cipher->ctxsize]; uint8_t ciphertext[len]; + uint8_t auth[cipher->authsize]; /* Initialise cipher */ okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0, @@ -65,6 +66,7 @@ void cipher_encrypt_okx ( struct cipher_test *test, const char *file, /* Process additional data, if applicable */ if ( test->additional_len ) { + okx ( is_auth_cipher ( cipher ), file, line ); cipher_encrypt ( cipher, ctx, test->additional, NULL, test->additional_len ); } @@ -74,6 +76,11 @@ void cipher_encrypt_okx ( struct cipher_test *test, const char *file, /* Compare against expected ciphertext */ okx ( memcmp ( ciphertext, test->ciphertext, len ) == 0, file, line ); + + /* Check authentication tag */ + okx ( cipher->authsize == test->auth_len, file, line ); + cipher_auth ( cipher, ctx, auth ); + okx ( memcmp ( auth, test->auth, test->auth_len ) == 0, file, line ); } /** @@ -89,6 +96,7 @@ void cipher_decrypt_okx ( struct cipher_test *test, const char *file, size_t len = test->len; uint8_t ctx[cipher->ctxsize]; uint8_t plaintext[len]; + uint8_t auth[cipher->authsize]; /* Initialise cipher */ okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0, @@ -97,6 +105,7 @@ void cipher_decrypt_okx ( struct cipher_test *test, const char *file, /* Process additional data, if applicable */ if ( test->additional_len ) { + okx ( is_auth_cipher ( cipher ), file, line ); cipher_decrypt ( cipher, ctx, test->additional, NULL, test->additional_len ); } @@ -106,6 +115,11 @@ void cipher_decrypt_okx ( struct cipher_test *test, const char *file, /* Compare against expected plaintext */ okx ( memcmp ( plaintext, test->plaintext, len ) == 0, file, line ); + + /* Check authentication tag */ + okx ( cipher->authsize == test->auth_len, file, line ); + cipher_auth ( cipher, ctx, auth ); + okx ( memcmp ( auth, test->auth, test->auth_len ) == 0, file, line ); } /** diff --git a/src/tests/cipher_test.h b/src/tests/cipher_test.h index 4139a7788..519d12e8d 100644 --- a/src/tests/cipher_test.h +++ b/src/tests/cipher_test.h @@ -35,6 +35,10 @@ struct cipher_test { const void *ciphertext; /** Length of text */ size_t len; + /** Authentication tag */ + const void *auth; + /** Length of authentication tag */ + size_t auth_len; }; /** Define inline key */ @@ -52,6 +56,9 @@ struct cipher_test { /** Define inline ciphertext data */ #define CIPHERTEXT(...) { __VA_ARGS__ } +/** Define inline authentication tag */ +#define AUTH(...) { __VA_ARGS__ } + /** * Define a cipher test * @@ -62,16 +69,18 @@ struct cipher_test { * @v ADDITIONAL Additional data * @v PLAINTEXT Plaintext * @v CIPHERTEXT Ciphertext + * @v AUTH Authentication tag * @ret test Cipher test */ #define CIPHER_TEST( name, CIPHER, KEY, IV, ADDITIONAL, PLAINTEXT, \ - CIPHERTEXT ) \ + CIPHERTEXT, AUTH ) \ static const uint8_t name ## _key [] = KEY; \ static const uint8_t name ## _iv [] = IV; \ static const uint8_t name ## _additional [] = ADDITIONAL; \ static const uint8_t name ## _plaintext [] = PLAINTEXT; \ static const uint8_t name ## _ciphertext \ [ sizeof ( name ## _plaintext ) ] = CIPHERTEXT; \ + static const uint8_t name ## _auth [] = AUTH; \ static struct cipher_test name = { \ .cipher = CIPHER, \ .key = name ## _key, \ @@ -83,6 +92,8 @@ struct cipher_test { .plaintext = name ## _plaintext, \ .ciphertext = name ## _ciphertext, \ .len = sizeof ( name ## _plaintext ), \ + .auth = name ## _auth, \ + .auth_len = sizeof ( name ## _auth ), \ } extern void cipher_encrypt_okx ( struct cipher_test *test, const char *file, -- cgit v1.2.3-55-g7522 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/crypto/aes.c | 1 + src/crypto/arc4.c | 1 + src/crypto/crypto_null.c | 1 + src/include/ipxe/cbc.h | 1 + src/include/ipxe/crypto.h | 18 +++++++++++++++++- src/include/ipxe/ecb.h | 1 + src/include/ipxe/gcm.h | 1 + src/tests/cipher_test.c | 10 ++++++++++ 8 files changed, 33 insertions(+), 1 deletion(-) (limited to 'src/crypto/crypto_null.c') diff --git a/src/crypto/aes.c b/src/crypto/aes.c index aeeaa1d2c..5200e7760 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 4d98abead..3b6adec19 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 26cfbfc4e..0ad463c3e 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 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, \ diff --git a/src/tests/cipher_test.c b/src/tests/cipher_test.c index cc732c2e0..2ead3c827 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 ); } -- cgit v1.2.3-55-g7522