[crypto] Add concept of additional data to cipher algorithms

Some ciphers (such as GCM) support the concept of additional
authenticated data, which does not appear in the ciphertext but may
affect the operation of the cipher.

Allow cipher_encrypt() and cipher_decrypt() to be called with a NULL
destination buffer in order to pass additional data.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/785/head
Michael Brown 2022-10-24 18:49:43 +01:00
parent 8e478e648f
commit 0c383bf00a
4 changed files with 47 additions and 23 deletions

View File

@ -54,25 +54,25 @@ struct cipher_algorithm {
size_t blocksize; size_t blocksize;
/** Set key /** Set key
* *
* @v ctx Context * @v ctx Context
* @v key Key * @v key Key
* @v keylen Key length * @v keylen Key length
* @ret rc Return status code * @ret rc Return status code
*/ */
int ( * setkey ) ( void *ctx, const void *key, size_t keylen ); int ( * setkey ) ( void *ctx, const void *key, size_t keylen );
/** Set initialisation vector /** Set initialisation vector
* *
* @v ctx Context * @v ctx Context
* @v iv Initialisation vector * @v iv Initialisation vector
* @v ivlen Initialisation vector length * @v ivlen Initialisation vector length
*/ */
void ( * setiv ) ( void *ctx, const void *iv, size_t ivlen ); void ( * setiv ) ( void *ctx, const void *iv, size_t ivlen );
/** Encrypt data /** Encrypt data
* *
* @v ctx Context * @v ctx Context
* @v src Data to encrypt * @v src Data to encrypt
* @v dst Buffer for encrypted data * @v dst Buffer for encrypted data, or NULL for additional data
* @v len Length of data * @v len Length of data
* *
* @v len is guaranteed to be a multiple of @c blocksize. * @v len is guaranteed to be a multiple of @c blocksize.
*/ */
@ -80,10 +80,10 @@ struct cipher_algorithm {
size_t len ); size_t len );
/** Decrypt data /** Decrypt data
* *
* @v ctx Context * @v ctx Context
* @v src Data to decrypt * @v src Data to decrypt
* @v dst Buffer for decrypted data * @v dst Buffer for decrypted data, or NULL for additional data
* @v len Length of data * @v len Length of data
* *
* @v len is guaranteed to be a multiple of @c blocksize. * @v len is guaranteed to be a multiple of @c blocksize.
*/ */

View File

@ -86,7 +86,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** AES-128-ECB (same test as AES-128-Core) */ /** AES-128-ECB (same test as AES-128-Core) */
CIPHER_TEST ( aes_128_ecb, &aes_ecb_algorithm, CIPHER_TEST ( aes_128_ecb, &aes_ecb_algorithm,
AES_KEY_NIST_128, AES_IV_NIST_DUMMY, AES_PLAINTEXT_NIST, AES_KEY_NIST_128, AES_IV_NIST_DUMMY, ADDITIONAL(), AES_PLAINTEXT_NIST,
CIPHERTEXT ( 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, CIPHERTEXT ( 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97, 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97,
0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d, 0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d,
@ -98,7 +98,7 @@ CIPHER_TEST ( aes_128_ecb, &aes_ecb_algorithm,
/** AES-128-CBC */ /** AES-128-CBC */
CIPHER_TEST ( aes_128_cbc, &aes_cbc_algorithm, CIPHER_TEST ( aes_128_cbc, &aes_cbc_algorithm,
AES_KEY_NIST_128, AES_IV_NIST_CBC, AES_PLAINTEXT_NIST, AES_KEY_NIST_128, AES_IV_NIST_CBC, ADDITIONAL(), AES_PLAINTEXT_NIST,
CIPHERTEXT ( 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, CIPHERTEXT ( 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46,
0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee,
@ -110,7 +110,7 @@ CIPHER_TEST ( aes_128_cbc, &aes_cbc_algorithm,
/** AES-192-ECB (same test as AES-192-Core) */ /** AES-192-ECB (same test as AES-192-Core) */
CIPHER_TEST ( aes_192_ecb, &aes_ecb_algorithm, CIPHER_TEST ( aes_192_ecb, &aes_ecb_algorithm,
AES_KEY_NIST_192, AES_IV_NIST_DUMMY, AES_PLAINTEXT_NIST, AES_KEY_NIST_192, AES_IV_NIST_DUMMY, ADDITIONAL(), AES_PLAINTEXT_NIST,
CIPHERTEXT ( 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, CIPHERTEXT ( 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f,
0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc, 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc,
0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad, 0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad,
@ -122,7 +122,7 @@ CIPHER_TEST ( aes_192_ecb, &aes_ecb_algorithm,
/** AES-192-CBC */ /** AES-192-CBC */
CIPHER_TEST ( aes_192_cbc, &aes_cbc_algorithm, CIPHER_TEST ( aes_192_cbc, &aes_cbc_algorithm,
AES_KEY_NIST_192, AES_IV_NIST_CBC, AES_PLAINTEXT_NIST, AES_KEY_NIST_192, AES_IV_NIST_CBC, ADDITIONAL(), AES_PLAINTEXT_NIST,
CIPHERTEXT ( 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, CIPHERTEXT ( 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
@ -134,7 +134,7 @@ CIPHER_TEST ( aes_192_cbc, &aes_cbc_algorithm,
/** AES-256-ECB (same test as AES-256-Core) */ /** AES-256-ECB (same test as AES-256-Core) */
CIPHER_TEST ( aes_256_ecb, &aes_ecb_algorithm, CIPHER_TEST ( aes_256_ecb, &aes_ecb_algorithm,
AES_KEY_NIST_256, AES_IV_NIST_DUMMY, AES_PLAINTEXT_NIST, AES_KEY_NIST_256, AES_IV_NIST_DUMMY, ADDITIONAL(), AES_PLAINTEXT_NIST,
CIPHERTEXT ( 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, CIPHERTEXT ( 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c,
0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8, 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8,
0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26, 0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26,
@ -146,7 +146,7 @@ CIPHER_TEST ( aes_256_ecb, &aes_ecb_algorithm,
/** AES-256-CBC */ /** AES-256-CBC */
CIPHER_TEST ( aes_256_cbc, &aes_cbc_algorithm, CIPHER_TEST ( aes_256_cbc, &aes_cbc_algorithm,
AES_KEY_NIST_256, AES_IV_NIST_CBC, AES_PLAINTEXT_NIST, AES_KEY_NIST_256, AES_IV_NIST_CBC, ADDITIONAL(), AES_PLAINTEXT_NIST,
CIPHERTEXT ( 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, CIPHERTEXT ( 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,

View File

@ -63,6 +63,12 @@ void cipher_encrypt_okx ( struct cipher_test *test, const char *file,
file, line ); file, line );
cipher_setiv ( cipher, ctx, test->iv, test->iv_len ); cipher_setiv ( cipher, ctx, test->iv, test->iv_len );
/* Process additional data, if applicable */
if ( test->additional_len ) {
cipher_encrypt ( cipher, ctx, test->additional, NULL,
test->additional_len );
}
/* Perform encryption */ /* Perform encryption */
cipher_encrypt ( cipher, ctx, test->plaintext, ciphertext, len ); cipher_encrypt ( cipher, ctx, test->plaintext, ciphertext, len );
@ -89,7 +95,13 @@ void cipher_decrypt_okx ( struct cipher_test *test, const char *file,
file, line ); file, line );
cipher_setiv ( cipher, ctx, test->iv, test->iv_len ); cipher_setiv ( cipher, ctx, test->iv, test->iv_len );
/* Perform encryption */ /* Process additional data, if applicable */
if ( test->additional_len ) {
cipher_decrypt ( cipher, ctx, test->additional, NULL,
test->additional_len );
}
/* Perform decryption */
cipher_decrypt ( cipher, ctx, test->ciphertext, plaintext, len ); cipher_decrypt ( cipher, ctx, test->ciphertext, plaintext, len );
/* Compare against expected plaintext */ /* Compare against expected plaintext */

View File

@ -25,6 +25,10 @@ struct cipher_test {
const void *iv; const void *iv;
/** Length of initialisation vector */ /** Length of initialisation vector */
size_t iv_len; size_t iv_len;
/** Additional data */
const void *additional;
/** Length of additional data */
size_t additional_len;
/** Plaintext */ /** Plaintext */
const void *plaintext; const void *plaintext;
/** Ciphertext */ /** Ciphertext */
@ -39,6 +43,9 @@ struct cipher_test {
/** Define inline initialisation vector */ /** Define inline initialisation vector */
#define IV(...) { __VA_ARGS__ } #define IV(...) { __VA_ARGS__ }
/** Define inline additional data */
#define ADDITIONAL(...) { __VA_ARGS__ }
/** Define inline plaintext data */ /** Define inline plaintext data */
#define PLAINTEXT(...) { __VA_ARGS__ } #define PLAINTEXT(...) { __VA_ARGS__ }
@ -52,13 +59,16 @@ struct cipher_test {
* @v CIPHER Cipher algorithm * @v CIPHER Cipher algorithm
* @v KEY Key * @v KEY Key
* @v IV Initialisation vector * @v IV Initialisation vector
* @v ADDITIONAL Additional data
* @v PLAINTEXT Plaintext * @v PLAINTEXT Plaintext
* @v CIPHERTEXT Ciphertext * @v CIPHERTEXT Ciphertext
* @ret test Cipher test * @ret test Cipher test
*/ */
#define CIPHER_TEST( name, CIPHER, KEY, IV, PLAINTEXT, CIPHERTEXT ) \ #define CIPHER_TEST( name, CIPHER, KEY, IV, ADDITIONAL, PLAINTEXT, \
CIPHERTEXT ) \
static const uint8_t name ## _key [] = KEY; \ static const uint8_t name ## _key [] = KEY; \
static const uint8_t name ## _iv [] = IV; \ 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 ## _plaintext [] = PLAINTEXT; \
static const uint8_t name ## _ciphertext \ static const uint8_t name ## _ciphertext \
[ sizeof ( name ## _plaintext ) ] = CIPHERTEXT; \ [ sizeof ( name ## _plaintext ) ] = CIPHERTEXT; \
@ -68,6 +78,8 @@ struct cipher_test {
.key_len = sizeof ( name ## _key ), \ .key_len = sizeof ( name ## _key ), \
.iv = name ## _iv, \ .iv = name ## _iv, \
.iv_len = sizeof ( name ## _iv ), \ .iv_len = sizeof ( name ## _iv ), \
.additional = name ## _additional, \
.additional_len = sizeof ( name ## _additional ), \
.plaintext = name ## _plaintext, \ .plaintext = name ## _plaintext, \
.ciphertext = name ## _ciphertext, \ .ciphertext = name ## _ciphertext, \
.len = sizeof ( name ## _plaintext ), \ .len = sizeof ( name ## _plaintext ), \