mirror of
https://github.com/ipxe/ipxe
synced 2026-07-02 20:10:19 +03:00
[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:
+9
-3
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user