[crypto] Use private data field for cipher algorithms

Following the example of commit 25072c1 ("[crypto] Use private data
field for key exchange algorithms"), extend the definition of a cipher
algorithm to include an opaque private data field, and use this to
eliminate the wrapper functions generated for the various block cipher
modes of operation by ECB_CIPHER(), CBC_CIPHER(), and GCM_CIPHER().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2026-06-19 13:26:00 +01:00
parent d7e89f46b4
commit 21babfc392
11 changed files with 427 additions and 402 deletions
+9 -3
View File
@@ -391,12 +391,14 @@ static void aes_final ( const struct aes_table *table, size_t stride,
/**
* Encrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data
* @v len Length of data
*/
static void aes_encrypt ( void *ctx, const void *src, void *dst, size_t len ) {
static void aes_encrypt ( struct cipher_algorithm *cipher __unused, void *ctx,
const void *src, void *dst, size_t len ) {
struct aes_context *aes = ctx;
union aes_matrix buffer[2];
union aes_matrix *in = &buffer[0];
@@ -427,12 +429,14 @@ static void aes_encrypt ( void *ctx, const void *src, void *dst, size_t len ) {
/**
* Decrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data
* @v len Length of data
*/
static void aes_decrypt ( void *ctx, const void *src, void *dst, size_t len ) {
static void aes_decrypt ( struct cipher_algorithm *cipher __unused, void *ctx,
const void *src, void *dst, size_t len ) {
struct aes_context *aes = ctx;
union aes_matrix buffer[2];
union aes_matrix *in = &buffer[0];
@@ -674,12 +678,14 @@ aes_key_rcon ( uint32_t column, unsigned int rcon ) {
/**
* Set key
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v key Key
* @v keylen Key length
* @ret rc Return status code
*/
static int aes_setkey ( void *ctx, const void *key, size_t keylen ) {
static int aes_setkey ( struct cipher_algorithm *cipher __unused, void *ctx,
const void *key, size_t keylen ) {
struct aes_context *aes = ctx;
union aes_matrix *enc;
union aes_matrix *dec;
+11 -6
View File
@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
/**
* Set ARC4 key
*
* @v cipher Cipher algorithm
* @v ctxv ARC4 encryption context
* @v keyv Key to set
* @v keylen Length of key
@@ -39,7 +40,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
* there is no standard length for an initialisation vector in the
* cipher.
*/
static int arc4_setkey ( void *ctxv, const void *keyv, size_t keylen )
static int arc4_setkey ( struct cipher_algorithm *cipher __unused, void *ctxv,
const void *keyv, size_t keylen )
{
struct arc4_ctx *ctx = ctxv;
const u8 *key = keyv;
@@ -62,6 +64,7 @@ static int arc4_setkey ( void *ctxv, const void *keyv, size_t keylen )
/**
* Perform ARC4 encryption or decryption
*
* @v cipher Cipher algorithm
* @v ctxv ARC4 encryption context
* @v srcv Data to encrypt or decrypt
* @v dstv Location to store encrypted or decrypted data
@@ -75,8 +78,8 @@ static int arc4_setkey ( void *ctxv, const void *keyv, size_t keylen )
* If you pass a @c NULL source or destination pointer, @a len
* keystream bytes will be consumed without encrypting any data.
*/
static void arc4_xor ( void *ctxv, const void *srcv, void *dstv,
size_t len )
static void arc4_xor ( struct cipher_algorithm *cipher __unused, void *ctxv,
const void *srcv, void *dstv, size_t len )
{
struct arc4_ctx *ctx = ctxv;
const u8 *src = srcv;
@@ -109,10 +112,12 @@ static void arc4_xor ( void *ctxv, const void *srcv, void *dstv,
void arc4_skip ( const void *key, size_t keylen, size_t skip,
const void *src, void *dst, size_t msglen )
{
struct cipher_algorithm *cipher = &arc4_algorithm;
struct arc4_ctx ctx;
arc4_setkey ( &ctx, key, keylen );
arc4_xor ( &ctx, NULL, NULL, skip );
arc4_xor ( &ctx, src, dst, msglen );
arc4_setkey ( cipher, &ctx, key, keylen );
arc4_xor ( cipher, &ctx, NULL, NULL, skip );
arc4_xor ( cipher, &ctx, src, dst, msglen );
}
struct cipher_algorithm arc4_algorithm = {
+59 -16
View File
@@ -35,6 +35,43 @@ FILE_SECBOOT ( PERMITTED );
*
*/
/**
* Set key
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v key Key
* @v keylen Key length
* @ret rc Return status code
*/
int cbc_setkey ( struct cipher_algorithm *cipher, void *ctx,
const void *key, size_t keylen ) {
struct cipher_algorithm *raw_cipher = cipher->priv;
size_t blocksize = cipher->blocksize;
size_t ctxsize = cipher->ctxsize;
cbc_context_t ( blocksize, ctxsize ) *context = ctx;
return cipher_setkey ( raw_cipher, context->raw, key, keylen );
}
/**
* Set initialisation vector
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
*/
void cbc_setiv ( struct cipher_algorithm *cipher, void *ctx,
const void *iv, size_t ivlen ) {
size_t blocksize = cipher->blocksize;
size_t ctxsize = cipher->ctxsize;
cbc_context_t ( blocksize, ctxsize ) *context = ctx;
assert ( ivlen == sizeof ( context->cbc ) );
memcpy ( context->cbc, iv, sizeof ( context->cbc ) );
}
/**
* XOR data blocks
*
@@ -57,23 +94,26 @@ static void cbc_xor ( const void *src, void *dst, size_t len ) {
/**
* Encrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data
* @v len Length of data
* @v raw_cipher Underlying cipher algorithm
* @v cbc_ctx CBC context
*/
void cbc_encrypt ( void *ctx, const void *src, void *dst, size_t len,
struct cipher_algorithm *raw_cipher, void *cbc_ctx ) {
size_t blocksize = raw_cipher->blocksize;
void cbc_encrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len ) {
struct cipher_algorithm *raw_cipher = cipher->priv;
size_t blocksize = cipher->blocksize;
size_t ctxsize = cipher->ctxsize;
cbc_context_t ( blocksize, ctxsize ) *context = ctx;
assert ( ( len % blocksize ) == 0 );
while ( len ) {
cbc_xor ( src, cbc_ctx, blocksize );
cipher_encrypt ( raw_cipher, ctx, cbc_ctx, dst, blocksize );
memcpy ( cbc_ctx, dst, blocksize );
cbc_xor ( src, context->cbc, blocksize );
cipher_encrypt ( raw_cipher, context->raw, context->cbc, dst,
blocksize );
memcpy ( context->cbc, dst, blocksize );
dst += blocksize;
src += blocksize;
len -= blocksize;
@@ -83,25 +123,28 @@ void cbc_encrypt ( void *ctx, const void *src, void *dst, size_t len,
/**
* Decrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data
* @v len Length of data
* @v raw_cipher Underlying cipher algorithm
* @v cbc_ctx CBC context
*/
void cbc_decrypt ( void *ctx, const void *src, void *dst, size_t len,
struct cipher_algorithm *raw_cipher, void *cbc_ctx ) {
size_t blocksize = raw_cipher->blocksize;
void cbc_decrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len ) {
struct cipher_algorithm *raw_cipher = cipher->priv;
size_t blocksize = cipher->blocksize;
size_t ctxsize = cipher->ctxsize;
cbc_context_t ( blocksize, ctxsize ) *context = ctx;
uint8_t next_cbc_ctx[blocksize];
assert ( ( len % blocksize ) == 0 );
while ( len ) {
memcpy ( next_cbc_ctx, src, blocksize );
cipher_decrypt ( raw_cipher, ctx, src, dst, blocksize );
cbc_xor ( cbc_ctx, dst, blocksize );
memcpy ( cbc_ctx, next_cbc_ctx, blocksize );
cipher_decrypt ( raw_cipher, context->raw, src, dst,
blocksize );
cbc_xor ( context->cbc, dst, blocksize );
memcpy ( context->cbc, next_cbc_ctx, blocksize );
dst += blocksize;
src += blocksize;
len -= blocksize;
+10 -5
View File
@@ -60,28 +60,33 @@ struct digest_algorithm digest_null = {
.final = digest_null_final,
};
int cipher_null_setkey ( void *ctx __unused, const void *key __unused,
int cipher_null_setkey ( struct cipher_algorithm *cipher __unused,
void *ctx __unused, const void *key __unused,
size_t keylen __unused ) {
/* Do nothing */
return 0;
}
void cipher_null_setiv ( void *ctx __unused, const void *iv __unused,
void cipher_null_setiv ( struct cipher_algorithm *cipher __unused,
void *ctx __unused, const void *iv __unused,
size_t ivlen __unused ) {
/* Do nothing */
}
void cipher_null_encrypt ( void *ctx __unused, const void *src, void *dst,
void cipher_null_encrypt ( struct cipher_algorithm *cipher __unused,
void *ctx __unused, const void *src, void *dst,
size_t len ) {
memcpy ( dst, src, len );
}
void cipher_null_decrypt ( void *ctx __unused, const void *src, void *dst,
void cipher_null_decrypt ( struct cipher_algorithm *cipher __unused,
void *ctx __unused, const void *src, void *dst,
size_t len ) {
memcpy ( dst, src, len );
}
void cipher_null_auth ( void *ctx __unused, void *auth __unused ) {
void cipher_null_auth ( struct cipher_algorithm *cipher __unused,
void *ctx __unused, void *auth __unused ) {
/* Do nothing */
}
+9 -3
View File
@@ -580,12 +580,14 @@ static uint32_t des_rol28 ( uint32_t dword ) {
/**
* Set key
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v key Key
* @v keylen Key length
* @ret rc Return status code
*/
static int des_setkey ( void *ctx, const void *key, size_t keylen ) {
static int des_setkey ( struct cipher_algorithm *cipher __unused, void *ctx,
const void *key, size_t keylen ) {
struct des_context *des = ctx;
union des_round_key *rkey = des->rkey;
union des_block reg;
@@ -640,12 +642,14 @@ static int des_setkey ( void *ctx, const void *key, size_t keylen ) {
/**
* Encrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data
* @v len Length of data
*/
static void des_encrypt ( void *ctx, const void *src, void *dst, size_t len ) {
static void des_encrypt ( struct cipher_algorithm *cipher __unused, void *ctx,
const void *src, void *dst, size_t len ) {
struct des_context *des = ctx;
/* Sanity check */
@@ -658,12 +662,14 @@ static void des_encrypt ( void *ctx, const void *src, void *dst, size_t len ) {
/**
* Decrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data
* @v len Length of data
*/
static void des_decrypt ( void *ctx, const void *src, void *dst, size_t len ) {
static void des_decrypt ( struct cipher_algorithm *cipher __unused, void *ctx,
const void *src, void *dst, size_t len ) {
struct des_context *des = ctx;
/* Sanity check */
+24 -6
View File
@@ -34,17 +34,34 @@ FILE_SECBOOT ( PERMITTED );
*
*/
/**
* Set key
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v key Key
* @v keylen Key length
* @ret rc Return status code
*/
int ecb_setkey ( struct cipher_algorithm *cipher, void *ctx,
const void *key, size_t keylen ) {
struct cipher_algorithm *raw_cipher = cipher->priv;
return cipher_setkey ( raw_cipher, ctx, key, keylen );
}
/**
* Encrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data
* @v len Length of data
* @v raw_cipher Underlying cipher algorithm
*/
void ecb_encrypt ( void *ctx, const void *src, void *dst, size_t len,
struct cipher_algorithm *raw_cipher ) {
void ecb_encrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len ) {
struct cipher_algorithm *raw_cipher = cipher->priv;
size_t blocksize = raw_cipher->blocksize;
assert ( ( len % blocksize ) == 0 );
@@ -60,14 +77,15 @@ void ecb_encrypt ( void *ctx, const void *src, void *dst, size_t len,
/**
* Decrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data
* @v len Length of data
* @v raw_cipher Underlying cipher algorithm
*/
void ecb_decrypt ( void *ctx, const void *src, void *dst, size_t len,
struct cipher_algorithm *raw_cipher ) {
void ecb_decrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len ) {
struct cipher_algorithm *raw_cipher = cipher->priv;
size_t blocksize = raw_cipher->blocksize;
assert ( ( len % blocksize ) == 0 );
+212 -193
View File
@@ -308,77 +308,6 @@ static void gcm_multiply_key ( const union gcm_block *key,
memcpy ( poly, &res, sizeof ( *poly ) );
}
/**
* Encrypt/decrypt/authenticate data
*
* @v context Context
* @v src Input data
* @v dst Output data, or NULL to process additional data
* @v len Length of data
* @v flags Operation flags
*/
static void gcm_process ( struct gcm_context *context, const void *src,
void *dst, size_t len, unsigned int flags ) {
union gcm_block tmp;
uint64_t *total;
size_t frag_len;
unsigned int block;
/* Calculate block number (for debugging) */
block = ( ( ( context->len.len.add + 8 * sizeof ( tmp ) - 1 ) /
( 8 * sizeof ( tmp ) ) ) +
( ( context->len.len.data + 8 * sizeof ( tmp ) - 1 ) /
( 8 * sizeof ( tmp ) ) ) + 1 );
/* Update total length (in bits) */
total = ( ( dst || ( flags & GCM_FL_IV ) ) ?
&context->len.len.data : &context->len.len.add );
*total += ( len * 8 );
/* Process data */
for ( ; len ; src += frag_len, len -= frag_len, block++ ) {
/* Calculate fragment length */
frag_len = len;
if ( frag_len > sizeof ( tmp ) )
frag_len = sizeof ( tmp );
/* Update hash with input data */
gcm_xor ( src, &context->hash, &context->hash, frag_len );
/* Encrypt/decrypt block, if applicable */
if ( dst ) {
/* Increment counter */
gcm_count ( &context->ctr, 1 );
/* Encrypt counter */
DBGC2 ( context, "GCM %p Y[%d]:\n", context, block );
DBGC2_HDA ( context, 0, &context->ctr,
sizeof ( context->ctr ) );
cipher_encrypt ( context->raw_cipher, &context->raw_ctx,
&context->ctr, &tmp, sizeof ( tmp ) );
DBGC2 ( context, "GCM %p E(K,Y[%d]):\n",
context, block );
DBGC2_HDA ( context, 0, &tmp, sizeof ( tmp ) );
/* Encrypt/decrypt data */
gcm_xor ( src, &tmp, dst, frag_len );
dst += frag_len;
/* Update hash with encrypted data, if applicable */
gcm_xor ( &tmp, &context->hash, &context->hash,
( frag_len & flags ) );
}
/* Update hash */
gcm_multiply_key ( &context->key, &context->hash );
DBGC2 ( context, "GCM %p X[%d]:\n", context, block );
DBGC2_HDA ( context, 0, &context->hash,
sizeof ( context->hash ) );
}
}
/**
* Construct hash
*
@@ -401,24 +330,227 @@ static void gcm_hash ( struct gcm_context *context, union gcm_block *hash ) {
}
/**
* Construct tag
* Encrypt/decrypt/authenticate data
*
* @v context Context
* @v tag Tag
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Input data
* @v dst Output data, or NULL to process additional data
* @v len Length of data
* @v flags Operation flags
*/
void gcm_tag ( struct gcm_context *context, union gcm_block *tag ) {
static void gcm_process ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len ) {
struct cipher_algorithm *raw_cipher = cipher->priv;
gcm_context_t ( cipher->ctxsize ) *context = ctx;
unsigned int flags = context->gcm.flags;
union gcm_block tmp;
uint64_t *total;
size_t frag_len;
unsigned int block;
/* Calculate block number (for debugging) */
block = ( ( ( context->gcm.len.len.add + 8 * sizeof ( tmp ) - 1 ) /
( 8 * sizeof ( tmp ) ) ) +
( ( context->gcm.len.len.data + 8 * sizeof ( tmp ) - 1 ) /
( 8 * sizeof ( tmp ) ) ) + 1 );
/* Update total length (in bits) */
total = ( ( dst || ( flags & GCM_FL_IV ) ) ?
&context->gcm.len.len.data : &context->gcm.len.len.add );
*total += ( len * 8 );
/* Process data */
for ( ; len ; src += frag_len, len -= frag_len, block++ ) {
/* Calculate fragment length */
frag_len = len;
if ( frag_len > sizeof ( tmp ) )
frag_len = sizeof ( tmp );
/* Update hash with input data */
gcm_xor ( src, &context->gcm.hash, &context->gcm.hash,
frag_len );
/* Encrypt/decrypt block, if applicable */
if ( dst ) {
/* Increment counter */
gcm_count ( &context->gcm.ctr, 1 );
/* Encrypt counter */
DBGC2 ( context, "GCM %p Y[%d]:\n", context, block );
DBGC2_HDA ( context, 0, &context->gcm.ctr,
sizeof ( context->gcm.ctr ) );
cipher_encrypt ( raw_cipher, &context->raw,
&context->gcm.ctr, &tmp,
sizeof ( tmp ) );
DBGC2 ( context, "GCM %p E(K,Y[%d]):\n",
context, block );
DBGC2_HDA ( context, 0, &tmp, sizeof ( tmp ) );
/* Encrypt/decrypt data */
gcm_xor ( src, &tmp, dst, frag_len );
dst += frag_len;
/* Update hash with encrypted data, if applicable */
gcm_xor ( &tmp, &context->gcm.hash, &context->gcm.hash,
( frag_len & flags ) );
}
/* Update hash */
gcm_multiply_key ( &context->gcm.key, &context->gcm.hash );
DBGC2 ( context, "GCM %p X[%d]:\n", context, block );
DBGC2_HDA ( context, 0, &context->gcm.hash,
sizeof ( context->gcm.hash ) );
}
}
/**
* Set key
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v key Key
* @v keylen Key length
* @ret rc Return status code
*/
int gcm_setkey ( struct cipher_algorithm *cipher, void *ctx,
const void *key, size_t keylen ) {
struct cipher_algorithm *raw_cipher = cipher->priv;
gcm_context_t ( cipher->ctxsize ) *context = ctx;
int rc;
/* Initialise GCM context */
memset ( &context->gcm, 0, sizeof ( context->gcm ) );
/* Set underlying block cipher key */
if ( ( rc = cipher_setkey ( raw_cipher, context->raw, key,
keylen ) ) != 0 )
return rc;
/* Construct GCM hash key */
cipher_encrypt ( raw_cipher, context->raw, &context->gcm.ctr,
&context->gcm.key, sizeof ( context->gcm.key ) );
DBGC2 ( context, "GCM %p H:\n", context );
DBGC2_HDA ( context, 0, &context->gcm.key,
sizeof ( context->gcm.key ) );
/* Reset counter */
context->gcm.ctr.ctr.value = cpu_to_be32 ( 1 );
/* Construct cached tables */
gcm_cache ( &context->gcm.key );
return 0;
}
/**
* Set initialisation vector
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
*/
void gcm_setiv ( struct cipher_algorithm *cipher, void *ctx,
const void *iv, size_t ivlen ) {
gcm_context_t ( cipher->ctxsize ) *context = ctx;
/* Reset non-key state */
memset ( &context->gcm, 0, gcm_offset ( key ) );
build_assert ( gcm_offset ( key ) > gcm_offset ( hash ) );
build_assert ( gcm_offset ( key ) > gcm_offset ( len ) );
build_assert ( gcm_offset ( key ) > gcm_offset ( ctr ) );
/* Reset counter */
context->gcm.ctr.ctr.value = cpu_to_be32 ( 1 );
/* Process initialisation vector */
if ( ivlen == sizeof ( context->gcm.ctr.ctr.iv ) ) {
/* Initialisation vector is exactly 96 bits, use it as-is */
memcpy ( context->gcm.ctr.ctr.iv, iv, ivlen );
} else {
/* Calculate hash over initialisation vector */
context->gcm.flags = GCM_FL_IV;
gcm_process ( cipher, ctx, iv, NULL, ivlen );
gcm_hash ( &context->gcm, &context->gcm.ctr );
assert ( context->gcm.len.len.add == 0 );
/* Reset non-key, non-counter state */
memset ( &context->gcm, 0, gcm_offset ( ctr ) );
build_assert ( gcm_offset ( ctr ) > gcm_offset ( hash ) );
build_assert ( gcm_offset ( ctr ) > gcm_offset ( len ) );
build_assert ( gcm_offset ( ctr ) < gcm_offset ( key ) );
}
DBGC2 ( context, "GCM %p Y[0]:\n", context );
DBGC2_HDA ( context, 0, &context->gcm.ctr,
sizeof ( context->gcm.ctr ) );
}
/**
* Encrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data, or NULL for additional data
* @v len Length of data
*/
void gcm_encrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len ) {
gcm_context_t ( cipher->ctxsize ) *context = ctx;
/* Process data */
context->gcm.flags = GCM_FL_ENCRYPT;
gcm_process ( cipher, ctx, src, dst, len );
}
/**
* Decrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data, or NULL for additional data
* @v len Length of data
*/
void gcm_decrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len ) {
gcm_context_t ( cipher->ctxsize ) *context = ctx;
/* Process data */
context->gcm.flags = 0;
gcm_process ( cipher, ctx, src, dst, len );
}
/**
* Generate authentication tag
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v auth Authentication tag
*/
void gcm_auth ( struct cipher_algorithm *cipher, void *ctx, void *auth ) {
struct cipher_algorithm *raw_cipher = cipher->priv;
gcm_context_t ( cipher->ctxsize ) *context = ctx;
union gcm_block *tag = auth;
union gcm_block tmp;
uint32_t offset;
/* Construct hash */
gcm_hash ( context, tag );
gcm_hash ( &context->gcm, tag );
/* Construct encrypted initial counter value */
memcpy ( &tmp, &context->ctr, sizeof ( tmp ) );
offset = ( ( -context->len.len.data ) / ( 8 * sizeof ( tmp ) ) );
memcpy ( &tmp, &context->gcm.ctr, sizeof ( tmp ) );
offset = ( ( -context->gcm.len.len.data ) / ( 8 * sizeof ( tmp ) ) );
gcm_count ( &tmp, offset );
cipher_encrypt ( context->raw_cipher, &context->raw_ctx, &tmp,
&tmp, sizeof ( tmp ) );
cipher_encrypt ( raw_cipher, &context->raw, &tmp, &tmp,
sizeof ( tmp ) );
DBGC2 ( context, "GCM %p E(K,Y[0]):\n", context );
DBGC2_HDA ( context, 0, &tmp, sizeof ( tmp ) );
@@ -427,116 +559,3 @@ void gcm_tag ( struct gcm_context *context, union gcm_block *tag ) {
DBGC2 ( context, "GCM %p T:\n", context );
DBGC2_HDA ( context, 0, tag, sizeof ( *tag ) );
}
/**
* Set key
*
* @v context Context
* @v key Key
* @v keylen Key length
* @v raw_cipher Underlying cipher
* @ret rc Return status code
*/
int gcm_setkey ( struct gcm_context *context, const void *key, size_t keylen,
struct cipher_algorithm *raw_cipher ) {
int rc;
/* Initialise GCM context */
memset ( context, 0, sizeof ( *context ) );
context->raw_cipher = raw_cipher;
/* Set underlying block cipher key */
if ( ( rc = cipher_setkey ( raw_cipher, context->raw_ctx, key,
keylen ) ) != 0 )
return rc;
/* Construct GCM hash key */
cipher_encrypt ( raw_cipher, context->raw_ctx, &context->ctr,
&context->key, sizeof ( context->key ) );
DBGC2 ( context, "GCM %p H:\n", context );
DBGC2_HDA ( context, 0, &context->key, sizeof ( context->key ) );
/* Reset counter */
context->ctr.ctr.value = cpu_to_be32 ( 1 );
/* Construct cached tables */
gcm_cache ( &context->key );
return 0;
}
/**
* Set initialisation vector
*
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
*/
void gcm_setiv ( struct gcm_context *context, const void *iv, size_t ivlen ) {
/* Reset non-key state */
memset ( context, 0, gcm_offset ( key ) );
build_assert ( gcm_offset ( key ) > gcm_offset ( hash ) );
build_assert ( gcm_offset ( key ) > gcm_offset ( len ) );
build_assert ( gcm_offset ( key ) > gcm_offset ( ctr ) );
build_assert ( gcm_offset ( key ) < gcm_offset ( raw_cipher ) );
build_assert ( gcm_offset ( key ) < gcm_offset ( raw_ctx ) );
/* Reset counter */
context->ctr.ctr.value = cpu_to_be32 ( 1 );
/* Process initialisation vector */
if ( ivlen == sizeof ( context->ctr.ctr.iv ) ) {
/* Initialisation vector is exactly 96 bits, use it as-is */
memcpy ( context->ctr.ctr.iv, iv, ivlen );
} else {
/* Calculate hash over initialisation vector */
gcm_process ( context, iv, NULL, ivlen, GCM_FL_IV );
gcm_hash ( context, &context->ctr );
assert ( context->len.len.add == 0 );
/* Reset non-key, non-counter state */
memset ( context, 0, gcm_offset ( ctr ) );
build_assert ( gcm_offset ( ctr ) > gcm_offset ( hash ) );
build_assert ( gcm_offset ( ctr ) > gcm_offset ( len ) );
build_assert ( gcm_offset ( ctr ) < gcm_offset ( key ) );
build_assert ( gcm_offset ( ctr ) < gcm_offset ( raw_cipher ) );
build_assert ( gcm_offset ( ctr ) < gcm_offset ( raw_ctx ) );
}
DBGC2 ( context, "GCM %p Y[0]:\n", context );
DBGC2_HDA ( context, 0, &context->ctr, sizeof ( context->ctr ) );
}
/**
* Encrypt data
*
* @v context Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data, or NULL for additional data
* @v len Length of data
*/
void gcm_encrypt ( struct gcm_context *context, const void *src, void *dst,
size_t len ) {
/* Process data */
gcm_process ( context, src, dst, len, GCM_FL_ENCRYPT );
}
/**
* Decrypt data
*
* @v context Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data, or NULL for additional data
* @v len Length of data
*/
void gcm_decrypt ( struct gcm_context *context, const void *src, void *dst,
size_t len ) {
/* Process data */
gcm_process ( context, src, dst, len, 0 );
}
+20 -72
View File
@@ -12,46 +12,21 @@ FILE_SECBOOT ( PERMITTED );
#include <ipxe/crypto.h>
/**
* Set key
*
* @v ctx Context
* @v key Key
* @v keylen Key length
* @v raw_cipher Underlying cipher algorithm
* @v cbc_ctx CBC context
* @ret rc Return status code
*/
static inline int cbc_setkey ( void *ctx, const void *key, size_t keylen,
struct cipher_algorithm *raw_cipher,
void *cbc_ctx __unused ) {
/** A cipher-block chaining mode context */
#define cbc_context_t( blocksize, ctxsize ) \
struct { \
uint8_t cbc[ (blocksize) ]; \
uint8_t raw[ (ctxsize) - (blocksize) ]; \
}
return cipher_setkey ( raw_cipher, ctx, key, keylen );
}
/**
* Set initialisation vector
*
* @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, size_t ivlen,
struct cipher_algorithm *raw_cipher,
void *cbc_ctx ) {
assert ( ivlen == raw_cipher->blocksize );
memcpy ( cbc_ctx, iv, raw_cipher->blocksize );
}
extern void cbc_encrypt ( void *ctx, const void *src, void *dst,
size_t len, struct cipher_algorithm *raw_cipher,
void *cbc_ctx );
extern void cbc_decrypt ( void *ctx, const void *src, void *dst,
size_t len, struct cipher_algorithm *raw_cipher,
void *cbc_ctx );
extern int cbc_setkey ( struct cipher_algorithm *cipher, void *ctx,
const void *key, size_t keylen );
extern void cbc_setiv ( struct cipher_algorithm *cipher, void *ctx,
const void *iv, size_t ivlen );
extern void cbc_encrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
extern void cbc_decrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
/**
* Create a cipher-block chaining mode of behaviour of an existing cipher
@@ -64,45 +39,18 @@ extern void cbc_decrypt ( void *ctx, const void *src, void *dst,
*/
#define CBC_CIPHER( _cbc_name, _cbc_cipher, _raw_cipher, _raw_context, \
_blocksize ) \
struct _cbc_name ## _context { \
_raw_context raw_ctx; \
uint8_t cbc_ctx[_blocksize]; \
}; \
static int _cbc_name ## _setkey ( void *ctx, const void *key, \
size_t keylen ) { \
struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
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, \
size_t ivlen ) { \
struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
cbc_setiv ( &_cbc_name ## _ctx->raw_ctx, iv, ivlen, \
&_raw_cipher, &_cbc_name ## _ctx->cbc_ctx ); \
} \
static void _cbc_name ## _encrypt ( void *ctx, const void *src, \
void *dst, size_t len ) { \
struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
cbc_encrypt ( &_cbc_name ## _ctx->raw_ctx, src, dst, len, \
&_raw_cipher, &_cbc_name ## _ctx->cbc_ctx ); \
} \
static void _cbc_name ## _decrypt ( void *ctx, const void *src, \
void *dst, size_t len ) { \
struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
cbc_decrypt ( &_cbc_name ## _ctx->raw_ctx, src, dst, len, \
&_raw_cipher, &_cbc_name ## _ctx->cbc_ctx ); \
} \
struct cipher_algorithm _cbc_cipher = { \
.name = #_cbc_name, \
.ctxsize = sizeof ( struct _cbc_name ## _context ), \
.ctxsize = ( _blocksize + sizeof ( _raw_context ) ), \
.blocksize = _blocksize, \
.alignsize = _blocksize, \
.authsize = 0, \
.setkey = _cbc_name ## _setkey, \
.setiv = _cbc_name ## _setiv, \
.encrypt = _cbc_name ## _encrypt, \
.decrypt = _cbc_name ## _decrypt, \
.setkey = cbc_setkey, \
.setiv = cbc_setiv, \
.encrypt = cbc_encrypt, \
.decrypt = cbc_decrypt, \
.auth = cipher_null_auth, \
.priv = &_raw_cipher, \
};
#endif /* _IPXE_CBC_H */
+32 -19
View File
@@ -82,21 +82,26 @@ struct cipher_algorithm {
size_t authsize;
/** Set key
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v key Key
* @v keylen Key length
* @ret rc Return status code
*/
int ( * setkey ) ( void *ctx, const void *key, size_t keylen );
int ( * setkey ) ( struct cipher_algorithm *cipher, void *ctx,
const void *key, size_t keylen );
/** Set initialisation vector
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
*/
void ( * setiv ) ( void *ctx, const void *iv, size_t ivlen );
void ( * setiv ) ( struct cipher_algorithm *cipher, void *ctx,
const void *iv, size_t ivlen );
/** Encrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data, or NULL for additional data
@@ -104,10 +109,11 @@ struct cipher_algorithm {
*
* @v len is guaranteed to be a multiple of @c blocksize.
*/
void ( * encrypt ) ( void *ctx, const void *src, void *dst,
size_t len );
void ( * encrypt ) ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
/** Decrypt data
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data, or NULL for additional data
@@ -115,14 +121,18 @@ struct cipher_algorithm {
*
* @v len is guaranteed to be a multiple of @c blocksize.
*/
void ( * decrypt ) ( void *ctx, const void *src, void *dst,
size_t len );
void ( * decrypt ) ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
/** Generate authentication tag
*
* @v cipher Cipher algorithm
* @v ctx Context
* @v auth Authentication tag
*/
void ( * auth ) ( void *ctx, void *auth );
void ( * auth ) ( struct cipher_algorithm *cipher, void *ctx,
void *auth );
/** Algorithm private data */
void *priv;
};
/** A public key algorithm */
@@ -283,19 +293,19 @@ digest_final ( struct digest_algorithm *digest, void *ctx, void *out ) {
static inline __attribute__ (( always_inline )) int
cipher_setkey ( struct cipher_algorithm *cipher, void *ctx,
const void *key, size_t keylen ) {
return cipher->setkey ( ctx, key, keylen );
return cipher->setkey ( cipher, ctx, key, keylen );
}
static inline __attribute__ (( always_inline )) void
cipher_setiv ( struct cipher_algorithm *cipher, void *ctx,
const void *iv, size_t ivlen ) {
cipher->setiv ( ctx, iv, ivlen );
cipher->setiv ( cipher, ctx, iv, ivlen );
}
static inline __attribute__ (( always_inline )) void
cipher_encrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len ) {
cipher->encrypt ( ctx, src, dst, len );
cipher->encrypt ( cipher, ctx, src, dst, len );
}
#define cipher_encrypt( cipher, ctx, src, dst, len ) do { \
assert ( ( (len) & ( (cipher)->blocksize - 1 ) ) == 0 ); \
@@ -305,7 +315,7 @@ cipher_encrypt ( struct cipher_algorithm *cipher, void *ctx,
static inline __attribute__ (( always_inline )) void
cipher_decrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len ) {
cipher->decrypt ( ctx, src, dst, len );
cipher->decrypt ( cipher, ctx, src, dst, len );
}
#define cipher_decrypt( cipher, ctx, src, dst, len ) do { \
assert ( ( (len) & ( (cipher)->blocksize - 1 ) ) == 0 ); \
@@ -314,7 +324,7 @@ cipher_decrypt ( struct cipher_algorithm *cipher, void *ctx,
static inline __attribute__ (( always_inline )) void
cipher_auth ( struct cipher_algorithm *cipher, void *ctx, void *auth ) {
cipher->auth ( ctx, auth );
cipher->auth ( cipher, ctx, auth );
}
static inline __attribute__ (( always_inline )) int
@@ -402,13 +412,16 @@ extern void digest_null_update ( struct digest_algorithm *digest, void *ctx,
extern void digest_null_final ( struct digest_algorithm *digest, 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, 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,
size_t len );
extern void cipher_null_auth ( void *ctx, void *auth );
extern int cipher_null_setkey ( struct cipher_algorithm *cipher, void *ctx,
const void *key, size_t keylen );
extern void cipher_null_setiv ( struct cipher_algorithm *cipehr, void *ctx,
const void *iv, size_t ivlen );
extern void cipher_null_encrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
extern void cipher_null_decrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
extern void cipher_null_auth ( struct cipher_algorithm *cipher, void *ctx,
void *auth );
extern int pubkey_null_encrypt ( const struct asn1_cursor *key,
const struct asn1_cursor *plaintext,
+12 -25
View File
@@ -12,13 +12,15 @@ FILE_SECBOOT ( PERMITTED );
#include <ipxe/crypto.h>
extern void ecb_encrypt ( void *ctx, const void *src, void *dst,
size_t len, struct cipher_algorithm *raw_cipher );
extern void ecb_decrypt ( void *ctx, const void *src, void *dst,
size_t len, struct cipher_algorithm *raw_cipher );
extern int ecb_setkey ( struct cipher_algorithm *cipher, void *ctx,
const void *key, size_t keylen );
extern void ecb_encrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
extern void ecb_decrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
/**
* Create a cipher-block chaining mode of behaviour of an existing cipher
* Create an electronic codebook mode of behaviour of an existing cipher
*
* @v _ecb_name Name for the new ECB cipher
* @v _ecb_cipher New cipher algorithm
@@ -28,33 +30,18 @@ extern void ecb_decrypt ( void *ctx, const void *src, void *dst,
*/
#define ECB_CIPHER( _ecb_name, _ecb_cipher, _raw_cipher, _raw_context, \
_blocksize ) \
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, \
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 ) { \
ecb_encrypt ( ctx, src, dst, len, &_raw_cipher ); \
} \
static void _ecb_name ## _decrypt ( void *ctx, const void *src, \
void *dst, size_t len ) { \
ecb_decrypt ( ctx, src, dst, len, &_raw_cipher ); \
} \
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, \
.encrypt = _ecb_name ## _encrypt, \
.decrypt = _ecb_name ## _decrypt, \
.setkey = ecb_setkey, \
.setiv = cipher_null_setiv, \
.encrypt = ecb_encrypt, \
.decrypt = ecb_decrypt, \
.auth = cipher_null_auth, \
.priv = &_raw_cipher, \
};
#endif /* _IPXE_ECB_H */
+29 -54
View File
@@ -53,21 +53,28 @@ struct gcm_context {
union gcm_block ctr;
/** Hash key (H) */
union gcm_block key;
/** Underlying block cipher */
struct cipher_algorithm *raw_cipher;
/** Underlying block cipher context */
uint8_t raw_ctx[0];
/** Processing flags */
unsigned int flags;
};
extern void gcm_tag ( struct gcm_context *context, union gcm_block *tag );
extern int gcm_setkey ( struct gcm_context *context, const void *key,
size_t keylen, struct cipher_algorithm *raw_cipher );
extern void gcm_setiv ( struct gcm_context *context, const void *iv,
size_t ivlen );
extern void gcm_encrypt ( struct gcm_context *context, const void *src,
void *dst, size_t len );
extern void gcm_decrypt ( struct gcm_context *context, const void *src,
void *dst, size_t len );
/** A GCM mode context */
#define gcm_context_t( ctxsize ) \
struct { \
struct gcm_context gcm; \
uint8_t raw[ (ctxsize) - \
sizeof ( struct gcm_context ) ]; \
}
extern int gcm_setkey ( struct cipher_algorithm *cipher, void *ctx,
const void *key, size_t keylen );
extern void gcm_setiv ( struct cipher_algorithm *cipher, void *ctx,
const void *iv, size_t ivlen );
extern void gcm_encrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
extern void gcm_decrypt ( struct cipher_algorithm *cipher, void *ctx,
const void *src, void *dst, size_t len );
extern void gcm_auth ( struct cipher_algorithm *cipher, void *ctx,
void *auth );
/**
* Create a GCM mode of behaviour of an existing cipher
@@ -80,52 +87,20 @@ extern void gcm_decrypt ( struct gcm_context *context, const void *src,
*/
#define GCM_CIPHER( _gcm_name, _gcm_cipher, _raw_cipher, _raw_context, \
_blocksize ) \
struct _gcm_name ## _context { \
/** GCM context */ \
struct gcm_context gcm; \
/** Underlying block cipher context */ \
_raw_context raw; \
}; \
static int _gcm_name ## _setkey ( void *ctx, const void *key, \
size_t keylen ) { \
struct _gcm_name ## _context *context = ctx; \
build_assert ( _blocksize == sizeof ( context->gcm.key ) ); \
build_assert ( offsetof ( typeof ( *context ), gcm ) == 0 ); \
build_assert ( offsetof ( typeof ( *context ), raw ) == \
offsetof ( typeof ( *context ), gcm.raw_ctx ) ); \
return gcm_setkey ( &context->gcm, key, keylen, &_raw_cipher ); \
} \
static void _gcm_name ## _setiv ( void *ctx, const void *iv, \
size_t ivlen ) { \
struct _gcm_name ## _context *context = ctx; \
gcm_setiv ( &context->gcm, iv, ivlen ); \
} \
static void _gcm_name ## _encrypt ( void *ctx, const void *src, \
void *dst, size_t len ) { \
struct _gcm_name ## _context *context = ctx; \
gcm_encrypt ( &context->gcm, src, dst, len ); \
} \
static void _gcm_name ## _decrypt ( void *ctx, const void *src, \
void *dst, size_t len ) { \
struct _gcm_name ## _context *context = ctx; \
gcm_decrypt ( &context->gcm, src, dst, len ); \
} \
static void _gcm_name ## _auth ( void *ctx, void *auth ) { \
struct _gcm_name ## _context *context = ctx; \
union gcm_block *tag = auth; \
gcm_tag ( &context->gcm, tag ); \
} \
static_assert ( _blocksize == sizeof ( union gcm_block ) ); \
struct cipher_algorithm _gcm_cipher = { \
.name = #_gcm_name, \
.ctxsize = sizeof ( struct _gcm_name ## _context ), \
.ctxsize = ( sizeof ( struct gcm_context ) + \
sizeof ( _raw_context ) ), \
.blocksize = 1, \
.alignsize = sizeof ( union gcm_block ), \
.authsize = sizeof ( union gcm_block ), \
.setkey = _gcm_name ## _setkey, \
.setiv = _gcm_name ## _setiv, \
.encrypt = _gcm_name ## _encrypt, \
.decrypt = _gcm_name ## _decrypt, \
.auth = _gcm_name ## _auth, \
.setkey = gcm_setkey, \
.setiv = gcm_setiv, \
.encrypt = gcm_encrypt, \
.decrypt = gcm_decrypt, \
.auth = gcm_auth, \
.priv = &_raw_cipher, \
};
#endif /* _IPXE_GCM_H */