[crypto] Allow cipher_setiv() to return an error

GCM ciphers can accept initialisation vectors of any length.  Move the
responsibility for checking the initialisation vector length from the
caller into the implementation of cipher_setiv().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2026-06-19 14:11:46 +01:00
parent 21babfc392
commit 2420211e7f
11 changed files with 71 additions and 37 deletions
+10 -2
View File
@@ -26,6 +26,7 @@ FILE_SECBOOT ( PERMITTED );
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <ipxe/crypto.h>
#include <ipxe/cbc.h>
@@ -61,15 +62,22 @@ int cbc_setkey ( struct cipher_algorithm *cipher, void *ctx,
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
* @ret rc Return status code
*/
void cbc_setiv ( struct cipher_algorithm *cipher, void *ctx,
int 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 ) );
/* Check length */
if ( ivlen != sizeof ( context->cbc ) )
return -ENOTSUP;
/* Record IV */
memcpy ( context->cbc, iv, sizeof ( context->cbc ) );
return 0;
}
/**
+7 -1
View File
@@ -941,12 +941,18 @@ static int cms_cipher_key ( struct cms_message *cms,
}
/* Set cipher initialization vector */
cipher_setiv ( cipher, ctx, cms->iv.data, cms->iv.len );
if ( ( rc = cipher_setiv ( cipher, ctx, cms->iv.data,
cms->iv.len ) ) != 0 ) {
DBGC ( cms, "CMS %p could not set cipher IV: %s\n",
cms, strerror ( rc ) );
goto err_setiv;
}
if ( cms->iv.len ) {
DBGC ( cms, "CMS %p cipher IV:\n", cms );
DBGC_HDA ( cms, 0, cms->iv.data, cms->iv.len );
}
err_setiv:
err_setkey:
err_decrypt:
free ( cipher_key.data );
+2 -1
View File
@@ -67,10 +67,11 @@ int cipher_null_setkey ( struct cipher_algorithm *cipher __unused,
return 0;
}
void cipher_null_setiv ( struct cipher_algorithm *cipher __unused,
int cipher_null_setiv ( struct cipher_algorithm *cipher __unused,
void *ctx __unused, const void *iv __unused,
size_t ivlen __unused ) {
/* Do nothing */
return 0;
}
void cipher_null_encrypt ( struct cipher_algorithm *cipher __unused,
+3 -1
View File
@@ -452,8 +452,9 @@ int gcm_setkey ( struct cipher_algorithm *cipher, void *ctx,
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
* @ret rc Return status code
*/
void gcm_setiv ( struct cipher_algorithm *cipher, void *ctx,
int gcm_setiv ( struct cipher_algorithm *cipher, void *ctx,
const void *iv, size_t ivlen ) {
gcm_context_t ( cipher->ctxsize ) *context = ctx;
@@ -490,6 +491,7 @@ void gcm_setiv ( struct cipher_algorithm *cipher, void *ctx,
DBGC2 ( context, "GCM %p Y[0]:\n", context );
DBGC2_HDA ( context, 0, &context->gcm.ctr,
sizeof ( context->gcm.ctr ) );
return 0;
}
/**
+1 -1
View File
@@ -21,7 +21,7 @@ FILE_SECBOOT ( PERMITTED );
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,
extern int 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 );
+5 -4
View File
@@ -96,8 +96,9 @@ struct cipher_algorithm {
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
* @ret rc Return status code
*/
void ( * setiv ) ( struct cipher_algorithm *cipher, void *ctx,
int ( * setiv ) ( struct cipher_algorithm *cipher, void *ctx,
const void *iv, size_t ivlen );
/** Encrypt data
*
@@ -296,10 +297,10 @@ cipher_setkey ( struct cipher_algorithm *cipher, void *ctx,
return cipher->setkey ( cipher, ctx, key, keylen );
}
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
cipher_setiv ( struct cipher_algorithm *cipher, void *ctx,
const void *iv, size_t ivlen ) {
cipher->setiv ( cipher, ctx, iv, ivlen );
return cipher->setiv ( cipher, ctx, iv, ivlen );
}
static inline __attribute__ (( always_inline )) void
@@ -414,7 +415,7 @@ extern void digest_null_final ( struct digest_algorithm *digest, void *ctx,
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,
extern int 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 );
+1
View File
@@ -451,6 +451,7 @@ FILE_SECBOOT ( PERMITTED );
#define ERRFILE_ecdsa ( ERRFILE_OTHER | 0x00690000 )
#define ERRFILE_crypto_null ( ERRFILE_OTHER | 0x006a0000 )
#define ERRFILE_ffdhe ( ERRFILE_OTHER | 0x006b0000 )
#define ERRFILE_cbc ( ERRFILE_OTHER | 0x006c0000 )
/** @} */
+1 -1
View File
@@ -67,7 +67,7 @@ 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,
extern int 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 );
+10 -10
View File
@@ -1017,6 +1017,8 @@ static int peerblk_parse_iv ( struct peerdist_block *peerblk, size_t buf_len,
peerblk_msg_blk_t ( digestsize, buf_len, vrf_len, blksize ) *msg =
peerblk->buffer.data;
size_t len = peerblk->buffer.len;
size_t ivlen;
int rc;
/* Check message length */
if ( len < sizeof ( *msg ) ) {
@@ -1025,18 +1027,16 @@ static int peerblk_parse_iv ( struct peerdist_block *peerblk, size_t buf_len,
peerblk->segment, peerblk->block, len );
return -ERANGE;
}
/* Check initialisation vector size */
if ( ntohl ( msg->msg.iv.iv.blksize ) != blksize ) {
DBGC ( peerblk, "PEERBLK %p %d.%d incorrect IV size %d\n",
peerblk, peerblk->segment, peerblk->block,
ntohl ( msg->msg.iv.iv.blksize ) );
return -EPROTO;
}
ivlen = ntohl ( msg->msg.iv.iv.blksize );
/* Set initialisation vector */
cipher_setiv ( peerblk->cipher, peerblk->cipherctx, msg->msg.iv.data,
blksize );
if ( ( rc = cipher_setiv ( peerblk->cipher, peerblk->cipherctx,
msg->msg.iv.data, ivlen ) ) != 0 ) {
DBGC ( peerblk, "PEERBLK %p %d.%d could not set IV: %s\n",
peerblk, peerblk->segment, peerblk->block,
strerror ( rc ) );
return rc;
}
return 0;
}
+13 -3
View File
@@ -3089,8 +3089,12 @@ static int tls_send_record ( struct tls_connection *tls, unsigned int type,
sizeof ( iv.rec ) ) ) != 0 ) {
goto err_random;
}
cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv,
sizeof ( iv ) );
if ( ( rc = cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv,
sizeof ( iv ) ) ) != 0 ) {
DBGC ( tls, "TLS %p could not set TX IV: %s\n",
tls, strerror ( rc ) );
goto err_setiv;
}
/* Construct and process authentication data */
authhdr.seq = cpu_to_be64 ( tls->tx.seq );
@@ -3171,6 +3175,7 @@ static int tls_send_record ( struct tls_connection *tls, unsigned int type,
return 0;
err_deliver:
err_setiv:
err_random:
free_iob ( iobuf );
return rc;
@@ -3304,7 +3309,12 @@ static int tls_new_ciphertext ( struct tls_connection *tls,
authhdr.header.length = htons ( len );
/* Set initialisation vector */
cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv, sizeof ( iv ) );
if ( ( rc = cipher_setiv ( cipher, cipherspec->cipher_ctx, &iv,
sizeof ( iv ) ) ) != 0 ) {
DBGC ( tls, "TLS %p could not set RX IV: %s\n",
tls, strerror ( rc ) );
return rc;
}
/* Process authentication data, if applicable */
if ( is_auth_cipher ( cipher ) ) {
+10 -5
View File
@@ -62,7 +62,8 @@ void cipher_encrypt_okx ( struct cipher_test *test, const char *file,
/* Initialise cipher */
okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0,
file, line );
cipher_setiv ( cipher, ctx, test->iv, test->iv_len );
okx ( cipher_setiv ( cipher, ctx, test->iv, test->iv_len ) == 0,
file, line );
/* Process additional data, if applicable */
if ( test->additional_len ) {
@@ -83,7 +84,8 @@ void cipher_encrypt_okx ( struct cipher_test *test, const char *file,
okx ( memcmp ( auth, test->auth, test->auth_len ) == 0, file, line );
/* Reset initialisation vector */
cipher_setiv ( cipher, ctx, test->iv, test->iv_len );
okx ( cipher_setiv ( cipher, ctx, test->iv, test->iv_len ) == 0,
file, line );
/* Process additional data, if applicable */
if ( test->additional_len ) {
@@ -121,7 +123,8 @@ void cipher_decrypt_okx ( struct cipher_test *test, const char *file,
/* Initialise cipher */
okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0,
file, line );
cipher_setiv ( cipher, ctx, test->iv, test->iv_len );
okx ( cipher_setiv ( cipher, ctx, test->iv, test->iv_len ) == 0,
file, line );
/* Process additional data, if applicable */
if ( test->additional_len ) {
@@ -142,7 +145,8 @@ void cipher_decrypt_okx ( struct cipher_test *test, const char *file,
okx ( memcmp ( auth, test->auth, test->auth_len ) == 0, file, line );
/* Reset initialisation vector */
cipher_setiv ( cipher, ctx, test->iv, test->iv_len );
okx ( cipher_setiv ( cipher, ctx, test->iv, test->iv_len ) == 0,
file, line );
/* Process additional data, if applicable */
if ( test->additional_len ) {
@@ -219,7 +223,8 @@ cipher_cost ( struct cipher_algorithm *cipher, size_t key_len,
/* Initialise cipher */
rc = cipher_setkey ( cipher, ctx, key, key_len );
assert ( rc == 0 );
cipher_setiv ( cipher, ctx, iv, sizeof ( iv ) );
rc = cipher_setiv ( cipher, ctx, iv, sizeof ( iv ) );
assert ( rc == 0 );
/* Profile cipher operation */
memset ( &profiler, 0, sizeof ( profiler ) );