mirror of
https://github.com/ipxe/ipxe
synced 2026-06-29 00:07:28 +03:00
[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:
+10
-2
@@ -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
@@ -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 );
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 )
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 ) );
|
||||
|
||||
Reference in New Issue
Block a user