I think the siv code could benefit from a funtion to create a cmac digest in one step, without the update/digest split and the intermediate buffer. That would be something like
cmac128_message(const struct cmac128_key *key, const void *cipher, nettle_crypt_func *encrypt, size_t digest_length, uint8_t *digest, size_t message_length, const uint8_t *message);
Then the key need to be taken out from the cmac128_ctx. I'm trying that out, on the branch cmac-layout. Patch below. What do you think?
Regards, /Niels
commit 9b41e3b82b567abb68c1b7fc3b1e6b1a4ed87b26 Author: Niels Möller nisse@lysator.liu.se Date: 2019-06-01 10:30:29 +0200
New struct cmac128_key.
diff --git a/ChangeLog b/ChangeLog index 53cdc41d..a7a4355f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2019-06-01 Niels Möller nisse@lysator.liu.se + + * cmac.h (struct cmac128_key): New struct. + * cmac.h (struct cmac128_ctx): Use struct cmac128_key. + * cmac.c (cmac128_set_key, cmac128_digest): Update accordingly. + 2019-05-12 Niels Möller nisse@lysator.liu.se
Delete old libdes/openssl compatibility interface. diff --git a/cmac.c b/cmac.c index ed3b5eb8..07d805f3 100644 --- a/cmac.c +++ b/cmac.c @@ -83,8 +83,8 @@ cmac128_set_key(struct cmac128_ctx *ctx, const void *cipher, /* step 1 - generate subkeys k1 and k2 */ encrypt(cipher, 16, L->b, const_zero);
- block_mulx(&ctx->K1, L); - block_mulx(&ctx->K2, &ctx->K1); + block_mulx(&ctx->key.K1, L); + block_mulx(&ctx->key.K2, &ctx->key.K1); }
#define MIN(x,y) ((x)<(y)?(x):(y)) @@ -148,11 +148,11 @@ cmac128_digest(struct cmac128_ctx *ctx, const void *cipher, if (ctx->index < 16) { ctx->block.b[ctx->index] = 0x80; - memxor(ctx->block.b, ctx->K2.b, 16); + memxor(ctx->block.b, ctx->key.K2.b, 16); } else { - memxor(ctx->block.b, ctx->K1.b, 16); + memxor(ctx->block.b, ctx->key.K1.b, 16); }
memxor3(Y.b, ctx->block.b, ctx->X.b, 16); diff --git a/cmac.h b/cmac.h index 6d107982..9d972ea5 100644 --- a/cmac.h +++ b/cmac.h @@ -55,18 +55,22 @@ extern "C" { #define cmac_aes256_update nettle_cmac_aes256_update #define cmac_aes256_digest nettle_cmac_aes256_digest
-struct cmac128_ctx +struct cmac128_key { - /* Key */ union nettle_block16 K1; union nettle_block16 K2; +}; + +struct cmac128_ctx +{ + struct cmac128_key key;
/* MAC state */ union nettle_block16 X;
/* Block buffer */ - union nettle_block16 block; size_t index; + union nettle_block16 block; };
void
On Sat, Jun 1, 2019 at 10:42 AM Niels Möller nisse@lysator.liu.se wrote:
I think the siv code could benefit from a funtion to create a cmac digest in one step, without the update/digest split and the intermediate buffer. That would be something like
cmac128_message(const struct cmac128_key *key, const void *cipher, nettle_crypt_func *encrypt, size_t digest_length, uint8_t *digest, size_t message_length, const uint8_t *message);
Then the key need to be taken out from the cmac128_ctx. I'm trying that out, on the branch cmac-layout. Patch below. What do you think?
Do you see significant performance benefits? Being consistent in hashing/MAC APIs is also a benefit for the library and I think the change should be balanced against that.
regards, Nikos
Nikos Mavrogiannopoulos n.mavrogiannopoulos@gmail.com writes:
Then the key need to be taken out from the cmac128_ctx. I'm trying that out, on the branch cmac-layout. Patch below. What do you think?
Do you see significant performance benefits?
Main benefit is that it makes it possible to make the context argument to siv_cmac_aes128_encrypt_message and similar functions const.
With a const context, one can, e.g., create a single siv_cmac_aes128_ctx instance, call the _set_key method once, and then share it between multiple threads processing messages independently.
With the current code (on the siv-mode branch), _siv_s2v uses parts of the context struct as working storage for cmac128_update, instead of using local temporaries. This clobbering of the context is a side effect with no benefit to the caller.
If we can change
#define SIV_CMAC_CTX(type) { struct CMAC128_CTX(type) siv_cmac; type siv_cipher; }
to
#define SIV_CMAC_CTX(type) { struct cmac128_key siv_cmac; type siv_cipher; }
then only the _set_key method needs to modify this context.
Being consistent in hashing/MAC APIs is also a benefit for the library and I think the change should be balanced against that.
It's not necessarily a change to the advertised cmac api (the new struct cmac128_key stays inside struct cmac128_ctx, and applications are not expected to depend on the details of the context struct), but it would be a small api/abi break, which is why I'd prefer to make the change before we make the release including the new cmac code.
At least the specific functions, cmac_aes*, should stay unchanged, for consistency with other macs.
For the general ones, cmac128_set_key, _update, _digest, maybe they should take a separate cmac128_key argument, and maybe be demoted to internal for now? For siv, we would need some variant of cmac_set_key function that takes only a cmac128_key argument, not a cmac128_ctx, and the new cmac128_message. These could be internal or public.
Regards, /Niels
nisse@lysator.liu.se (Niels Möller) writes:
I think the siv code could benefit from a funtion to create a cmac digest in one step, without the update/digest split and the intermediate buffer. That would be something like
cmac128_message(const struct cmac128_key *key, const void *cipher, nettle_crypt_func *encrypt, size_t digest_length, uint8_t *digest, size_t message_length, const uint8_t *message);
I haven't added a function like this, but I've now done the changes needed for const context to the siv_*_message functions.
For CMAC, the lowest-level functions now take cmac128_key and cmac128_ctx as separate arguments, the former const where appropriate. These changes pushed to master, and it's similar to how gcm is done.
I then merged these changes into the siv-mode branch, and updated it accordingly. The _siv_s2v function now takes a const struct cmac128_key argument, and uses a local struct cmac128_ctx with _init, _update, _digest to process the strings with cmac. This enables use of const further up the call chain.
Regards, /Niels
On Thu, Jun 6, 2019 at 9:44 AM Niels Möller nisse@lysator.liu.se wrote:
nisse@lysator.liu.se (Niels Möller) writes:
I think the siv code could benefit from a funtion to create a cmac digest in one step, without the update/digest split and the intermediate buffer. That would be something like
cmac128_message(const struct cmac128_key *key, const void *cipher, nettle_crypt_func *encrypt, size_t digest_length, uint8_t *digest, size_t message_length, const uint8_t *message);
I haven't added a function like this, but I've now done the changes needed for const context to the siv_*_message functions.
For CMAC, the lowest-level functions now take cmac128_key and cmac128_ctx as separate arguments, the former const where appropriate. These changes pushed to master, and it's similar to how gcm is done.
I then merged these changes into the siv-mode branch, and updated it accordingly. The _siv_s2v function now takes a const struct cmac128_key argument, and uses a local struct cmac128_ctx with _init, _update, _digest to process the strings with cmac. This enables use of const further up the call chain.
That seems nice. Let me know if you need anything from me regarding that.
regards, Nikos
nettle-bugs@lists.lysator.liu.se