Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- testsuite/cmac-test.c | 100 +++++++++++------------------------------- testsuite/testutils.c | 64 +++++++++++++++++++++++++++ testsuite/testutils.h | 6 +++ 3 files changed, 96 insertions(+), 74 deletions(-)
diff --git a/testsuite/cmac-test.c b/testsuite/cmac-test.c index 31662d1b6c1b..b1d4aa30dfbe 100644 --- a/testsuite/cmac-test.c +++ b/testsuite/cmac-test.c @@ -2,83 +2,35 @@ #include "nettle-internal.h" #include "cmac.h"
+const struct nettle_mac nettle_cmac_aes128 = +{ + "CMAC-AES128", + sizeof(struct cmac_aes128_ctx), + CMAC128_DIGEST_SIZE, + AES128_KEY_SIZE, + + (nettle_set_key_func*) cmac_aes128_set_key, + (nettle_hash_update_func*) cmac_aes128_update, + (nettle_hash_digest_func*) cmac_aes128_digest +}; + +const struct nettle_mac nettle_cmac_aes256 = +{ + "CMAC-AES256", + sizeof(struct cmac_aes256_ctx), + CMAC128_DIGEST_SIZE, + AES256_KEY_SIZE, + + (nettle_set_key_func*) cmac_aes256_set_key, + (nettle_hash_update_func*) cmac_aes256_update, + (nettle_hash_digest_func*) cmac_aes256_digest +}; + #define test_cmac_aes128(key, msg, ref) \ - test_cmac_hash ((nettle_set_key_func*) cmac_aes128_set_key, \ - (nettle_hash_update_func*) cmac_aes128_update, \ - (nettle_hash_digest_func*) cmac_aes128_digest, \ - sizeof(struct cmac_aes128_ctx), \ - key, msg, ref) + test_mac(&nettle_cmac_aes128, key, msg, ref)
#define test_cmac_aes256(key, msg, ref) \ - test_cmac_hash ((nettle_set_key_func*) cmac_aes256_set_key, \ - (nettle_hash_update_func*) cmac_aes256_update, \ - (nettle_hash_digest_func*) cmac_aes256_digest, \ - sizeof(struct cmac_aes256_ctx), \ - key, msg, ref) - -static void -test_cmac_hash (nettle_set_key_func *set_key, - nettle_hash_update_func *update, - nettle_hash_digest_func *digest, size_t ctx_size, - const struct tstring *key, const struct tstring *msg, - const struct tstring *ref) -{ - void *ctx; - uint8_t hash[16]; - unsigned i; - - ctx = xalloc(ctx_size); - - ASSERT (ref->length == sizeof(hash)); - ASSERT (key->length == 16 || key->length == 32); - set_key (ctx, key->data); - update (ctx, msg->length, msg->data); - digest (ctx, sizeof(hash), hash); - if (!MEMEQ (ref->length, ref->data, hash)) - { - fprintf (stderr, "cmac_hash failed, msg: "); - print_hex (msg->length, msg->data); - fprintf(stderr, "Output:"); - print_hex (16, hash); - fprintf(stderr, "Expected:"); - tstring_print_hex(ref); - fprintf(stderr, "\n"); - FAIL(); - } - - /* attempt to re-use the structure */ - update (ctx, msg->length, msg->data); - digest (ctx, sizeof(hash), hash); - if (!MEMEQ (ref->length, ref->data, hash)) - { - fprintf (stderr, "cmac_hash failed on re-use, msg: "); - print_hex (msg->length, msg->data); - fprintf(stderr, "Output:"); - print_hex (16, hash); - fprintf(stderr, "Expected:"); - tstring_print_hex(ref); - fprintf(stderr, "\n"); - FAIL(); - } - - /* attempt byte-by-byte hashing */ - set_key (ctx, key->data); - for (i=0;i<msg->length;i++) - update (ctx, 1, msg->data+i); - digest (ctx, sizeof(hash), hash); - if (!MEMEQ (ref->length, ref->data, hash)) - { - fprintf (stderr, "cmac_hash failed on byte-by-byte, msg: "); - print_hex (msg->length, msg->data); - fprintf(stderr, "Output:"); - print_hex (16, hash); - fprintf(stderr, "Expected:"); - tstring_print_hex(ref); - fprintf(stderr, "\n"); - FAIL(); - } - free (ctx); -} + test_mac(&nettle_cmac_aes256, key, msg, ref)
void test_main(void) diff --git a/testsuite/testutils.c b/testsuite/testutils.c index 337e4c4c7cd1..2a19c0ac8205 100644 --- a/testsuite/testutils.c +++ b/testsuite/testutils.c @@ -924,6 +924,70 @@ test_hash_large(const struct nettle_hash *hash, free(data); }
+void +test_mac(const struct nettle_mac *mac, + const struct tstring *key, + const struct tstring *msg, + const struct tstring *digest) +{ + void *ctx = xalloc(mac->context_size); + uint8_t *hash = xalloc(mac->digest_size); + unsigned i; + + + ASSERT (digest->length == mac->digest_size); + ASSERT (key->length == mac->key_size); + mac->set_key (ctx, key->data); + mac->update (ctx, msg->length, msg->data); + mac->digest (ctx, digest->length, hash); + + if (!MEMEQ (digest->length, digest->data, hash)) + { + fprintf (stderr, "test_mac failed, msg: "); + print_hex (msg->length, msg->data); + fprintf(stderr, "Output:"); + print_hex (mac->digest_size, hash); + fprintf(stderr, "Expected:"); + tstring_print_hex(digest); + fprintf(stderr, "\n"); + FAIL(); + } + + /* attempt to re-use the structure */ + mac->update (ctx, msg->length, msg->data); + mac->digest (ctx, digest->length, hash); + if (!MEMEQ (digest->length, digest->data, hash)) + { + fprintf (stderr, "test_mac: failed on re-use, msg: "); + print_hex (msg->length, msg->data); + fprintf(stderr, "Output:"); + print_hex (mac->digest_size, hash); + fprintf(stderr, "Expected:"); + tstring_print_hex(digest); + fprintf(stderr, "\n"); + FAIL(); + } + + /* attempt byte-by-byte hashing */ + mac->set_key (ctx, key->data); + for (i=0;i<msg->length;i++) + mac->update (ctx, 1, msg->data+i); + mac->digest (ctx, digest->length, hash); + if (!MEMEQ (digest->length, digest->data, hash)) + { + fprintf (stderr, "cmac_hash failed on byte-by-byte, msg: "); + print_hex (msg->length, msg->data); + fprintf(stderr, "Output:"); + print_hex (16, hash); + fprintf(stderr, "Expected:"); + tstring_print_hex(digest); + fprintf(stderr, "\n"); + FAIL(); + } + free (ctx); + free (hash); +} + void test_armor(const struct nettle_armor *armor, size_t data_length, diff --git a/testsuite/testutils.h b/testsuite/testutils.h index ded57db6ab4f..f4ea38da9deb 100644 --- a/testsuite/testutils.h +++ b/testsuite/testutils.h @@ -170,6 +170,12 @@ test_hash_large(const struct nettle_hash *hash, uint8_t c, const struct tstring *digest);
+void +test_mac(const struct nettle_mac *mac, + const struct tstring *key, + const struct tstring *msg, + const struct tstring *digest); + void test_armor(const struct nettle_armor *armor, size_t data_length,
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- cmac.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++- cmac.h | 69 +++++++++++++++++++++++++++ nettle-types.h | 7 +++ 3 files changed, 200 insertions(+), 1 deletion(-)
diff --git a/cmac.c b/cmac.c index c5a59b18e572..e93e26947b19 100644 --- a/cmac.c +++ b/cmac.c @@ -1,9 +1,10 @@ /* - AES-CMAC-128 (rfc 4493) + AES-CMAC-128 (rfc 4493) / CMAC-64 Copyright (C) Stefan Metzmacher 2012 Copyright (C) Jeremy Allison 2012 Copyright (C) Michael Adam 2012 Copyright (C) 2017, Red Hat Inc. + Copyright (C) 2019, Dmitry Eremin-Solenikov
This file is part of GNU Nettle.
@@ -56,6 +57,15 @@ block_mulx(union nettle_block16 *dst, dst->u64[0] = (src->u64[0] << 1) | (src->u64[1] >> 63); dst->u64[1] = (src->u64[1] << 1) ^ (0x87 & -carry); } + +static void +block_mulx8(union nettle_block8 *dst, + const union nettle_block8 *src) +{ + uint64_t carry = src->u64 >> 63; + + dst->u64 = (src->u64 << 1) ^ (0x1b & -carry); +} #else /* !WORDS_BIGENDIAN */ #define LE_SHIFT(x) ((((x) & 0x7f7f7f7f7f7f7f7f) << 1) | \ (((x) & 0x8080808080808080) >> 15)) @@ -67,6 +77,15 @@ block_mulx(union nettle_block16 *dst, dst->u64[0] = LE_SHIFT(src->u64[0]) | ((src->u64[1] & 0x80) << 49); dst->u64[1] = LE_SHIFT(src->u64[1]) ^ (0x8700000000000000 & -carry); } + +static void +block_mulx8(union nettle_block8 *dst, + const union nettle_block8 *src) +{ + uint64_t carry = (src->u64 & 0x80) >> 7; + + dst->u64 = LE_SHIFT(src->u64) ^ (0x1b00000000000000 & -carry); +} #endif /* !WORDS_BIGENDIAN */
void @@ -173,3 +192,107 @@ cmac128_digest(struct cmac128_ctx *ctx, const struct cmac128_key *key, /* reset state for re-use */ cmac128_init(ctx); } + +void +cmac64_set_key(struct cmac64_key *key, const void *cipher, + nettle_cipher_func *encrypt) +{ + static const union nettle_block8 zero_block; + union nettle_block8 L; + + /* step 1 - generate subkeys k1 and k2 */ + encrypt(cipher, 8, L.b, zero_block.b); + + block_mulx8(&key->K1, &L); + block_mulx8(&key->K2, &key->K1); +} + +void +cmac64_init(struct cmac64_ctx *ctx) +{ + memset(&ctx->X, 0, sizeof(ctx->X)); + ctx->index = 0; +} + +void +cmac64_update(struct cmac64_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg) +{ + union nettle_block16 Y; + /* + * check if we expand the block + */ + if (ctx->index < 8) + { + size_t len = MIN(8 - ctx->index, msg_len); + memcpy(&ctx->block.b[ctx->index], msg, len); + msg += len; + msg_len -= len; + ctx->index += len; + } + + if (msg_len == 0) { + /* if it is still the last block, we are done */ + return; + } + + /* + * now checksum everything but the last block + */ + memxor3(Y.b, ctx->X.b, ctx->block.b, 8); + encrypt(cipher, 8, ctx->X.b, Y.b); + + while (msg_len > 8) + { + memxor3(Y.b, ctx->X.b, msg, 8); + encrypt(cipher, 8, ctx->X.b, Y.b); + msg += 8; + msg_len -= 8; + } + + /* + * copy the last block, it will be processed in + * cmac64_digest(). + */ + memcpy(ctx->block.b, msg, msg_len); + ctx->index = msg_len; +} + +void +cmac64_digest(struct cmac64_ctx *ctx, const struct cmac64_key *key, + const void *cipher, nettle_cipher_func *encrypt, + unsigned length, uint8_t *dst) +{ + union nettle_block8 Y; + + memset(ctx->block.b+ctx->index, 0, sizeof(ctx->block.b)-ctx->index); + + /* re-use ctx->block for memxor output */ + if (ctx->index < 8) + { + ctx->block.b[ctx->index] = 0x80; + memxor(ctx->block.b, key->K2.b, 8); + } + else + { + memxor(ctx->block.b, key->K1.b, 8); + } + + memxor3(Y.b, ctx->block.b, ctx->X.b, 8); + + assert(length <= 8); + if (length == 8) + { + encrypt(cipher, 8, dst, Y.b); + } + else + { + encrypt(cipher, 8, ctx->block.b, Y.b); + memcpy(dst, ctx->block.b, length); + } + + /* reset state for re-use */ + memset(&ctx->X, 0, sizeof(ctx->X)); + ctx->index = 0; +} diff --git a/cmac.h b/cmac.h index 3c5b7bea3e55..0cf9462d2120 100644 --- a/cmac.h +++ b/cmac.h @@ -44,6 +44,7 @@ extern "C" { #endif
#define CMAC128_DIGEST_SIZE 16 +#define CMAC64_DIGEST_SIZE 8
#define cmac128_set_key nettle_cmac128_set_key #define cmac128_init nettle_cmac128_init @@ -56,6 +57,11 @@ extern "C" { #define cmac_aes256_update nettle_cmac_aes256_update #define cmac_aes256_digest nettle_cmac_aes256_digest
+#define cmac64_set_key nettle_cmac64_set_key +#define cmac64_init nettle_cmac64_init +#define cmac64_update nettle_cmac64_update +#define cmac64_digest nettle_cmac64_digest + struct cmac128_key { union nettle_block16 K1; @@ -72,6 +78,22 @@ struct cmac128_ctx size_t index; };
+struct cmac64_key +{ + union nettle_block8 K1; + union nettle_block8 K2; +}; + +struct cmac64_ctx +{ + /* MAC state */ + union nettle_block8 X; + + /* Block buffer */ + union nettle_block8 block; + size_t index; +}; + void cmac128_set_key(struct cmac128_key *key, const void *cipher, nettle_cipher_func *encrypt); @@ -118,6 +140,53 @@ cmac128_digest(struct cmac128_ctx *ctx, const struct cmac128_key *key, (nettle_cipher_func *) (encrypt), \ (length), (digest)))
+void +cmac64_set_key(struct cmac64_key *key, const void *cipher, + nettle_cipher_func *encrypt); + +void +cmac64_init(struct cmac64_ctx *ctx); + +void +cmac64_update(struct cmac64_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg); + +void +cmac64_digest(struct cmac64_ctx *ctx, const struct cmac64_key *key, + const void *cipher, nettle_cipher_func *encrypt, + unsigned length, uint8_t *digest); + + +#define CMAC64_CTX(type) \ + { struct cmac64_key key; struct cmac64_ctx ctx; type cipher; } + +/* NOTE: Avoid using NULL, as we don't include anything defining it. */ +#define CMAC64_SET_KEY(self, set_key, encrypt, cmac_key) \ + do { \ + (set_key)(&(self)->cipher, (cmac_key)); \ + if (0) (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0); \ + cmac64_set_key(&(self)->key, &(self)->cipher, \ + (nettle_cipher_func *) (encrypt)); \ + cmac64_init(&(self)->ctx); \ + } while (0) + +#define CMAC64_UPDATE(self, encrypt, length, src) \ + (0 ? (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0) \ + : cmac64_update(&(self)->ctx, &(self)->cipher, \ + (nettle_cipher_func *)encrypt, \ + (length), (src))) + +#define CMAC64_DIGEST(self, encrypt, length, digest) \ + (0 ? (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0) \ + : cmac64_digest(&(self)->ctx, &(self)->key, \ + &(self)->cipher, \ + (nettle_cipher_func *) (encrypt), \ + (length), (digest))) + struct cmac_aes128_ctx CMAC128_CTX(struct aes128_ctx);
void diff --git a/nettle-types.h b/nettle-types.h index 87292ac69730..e06c85c48f8c 100644 --- a/nettle-types.h +++ b/nettle-types.h @@ -65,6 +65,13 @@ union nettle_block16 uint64_t u64[2]; };
+union nettle_block8 +{ + uint8_t b[8]; + unsigned long w[8 / sizeof(unsigned long)]; + uint64_t u64; +}; + /* Randomness. Used by key generation and dsa signature creation. */ typedef void nettle_random_func(void *ctx, size_t length, uint8_t *dst);
Dmitry Eremin-Solenikov dbaryshkov@gmail.com writes:
+union nettle_block8 +{
- uint8_t b[8];
- unsigned long w[8 / sizeof(unsigned long)];
- uint64_t u64;
+};
The "unsigned long w" seems unneeded (in nettle_block16, it could also be retired; it's from a time when Nettle didn't use uint64_t).
Maybe one could do without this union and simply use uint64_t, but then one would need some casts to (uint8_t *). So a union may be clearer.
Regards, /Niels
ср, 3 июл. 2019 г. в 00:15, Niels Möller nisse@lysator.liu.se:
Dmitry Eremin-Solenikov dbaryshkov@gmail.com writes:
+union nettle_block8 +{
- uint8_t b[8];
- unsigned long w[8 / sizeof(unsigned long)];
- uint64_t u64;
+};
The "unsigned long w" seems unneeded (in nettle_block16, it could also be retired; it's from a time when Nettle didn't use uint64_t).
Ok, I'll drop both usecases.
Maybe one could do without this union and simply use uint64_t, but then one would need some casts to (uint8_t *). So a union may be clearer.
I preferred union because of symmetry with CMAC-128 code.
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- cmac.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++- cmac.h | 69 +++++++++++++++++++++++++++ nettle-types.h | 6 +++ 3 files changed, 199 insertions(+), 1 deletion(-)
diff --git a/cmac.c b/cmac.c index 70ce8132d9d1..36ad8e58e45e 100644 --- a/cmac.c +++ b/cmac.c @@ -1,9 +1,10 @@ /* - AES-CMAC-128 (rfc 4493) + AES-CMAC-128 (rfc 4493) / CMAC-64 Copyright (C) Stefan Metzmacher 2012 Copyright (C) Jeremy Allison 2012 Copyright (C) Michael Adam 2012 Copyright (C) 2017, Red Hat Inc. + Copyright (C) 2019, Dmitry Eremin-Solenikov
This file is part of GNU Nettle.
@@ -57,6 +58,15 @@ _cmac128_block_mulx(union nettle_block16 *dst, dst->u64[0] = (src->u64[0] << 1) | (src->u64[1] >> 63); dst->u64[1] = (src->u64[1] << 1) ^ (0x87 & -carry); } + +static void +block_mulx8(union nettle_block8 *dst, + const union nettle_block8 *src) +{ + uint64_t carry = src->u64 >> 63; + + dst->u64 = (src->u64 << 1) ^ (0x1b & -carry); +} #else /* !WORDS_BIGENDIAN */ #define LE_SHIFT(x) ((((x) & 0x7f7f7f7f7f7f7f7f) << 1) | \ (((x) & 0x8080808080808080) >> 15)) @@ -68,6 +78,15 @@ _cmac128_block_mulx(union nettle_block16 *dst, dst->u64[0] = LE_SHIFT(src->u64[0]) | ((src->u64[1] & 0x80) << 49); dst->u64[1] = LE_SHIFT(src->u64[1]) ^ (0x8700000000000000 & -carry); } + +static void +block_mulx8(union nettle_block8 *dst, + const union nettle_block8 *src) +{ + uint64_t carry = (src->u64 & 0x80) >> 7; + + dst->u64 = LE_SHIFT(src->u64) ^ (0x1b00000000000000 & -carry); +} #endif /* !WORDS_BIGENDIAN */
void @@ -174,3 +193,107 @@ cmac128_digest(struct cmac128_ctx *ctx, const struct cmac128_key *key, /* reset state for re-use */ cmac128_init(ctx); } + +void +cmac64_set_key(struct cmac64_key *key, const void *cipher, + nettle_cipher_func *encrypt) +{ + static const union nettle_block8 zero_block; + union nettle_block8 L; + + /* step 1 - generate subkeys k1 and k2 */ + encrypt(cipher, 8, L.b, zero_block.b); + + block_mulx8(&key->K1, &L); + block_mulx8(&key->K2, &key->K1); +} + +void +cmac64_init(struct cmac64_ctx *ctx) +{ + memset(&ctx->X, 0, sizeof(ctx->X)); + ctx->index = 0; +} + +void +cmac64_update(struct cmac64_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg) +{ + union nettle_block16 Y; + /* + * check if we expand the block + */ + if (ctx->index < 8) + { + size_t len = MIN(8 - ctx->index, msg_len); + memcpy(&ctx->block.b[ctx->index], msg, len); + msg += len; + msg_len -= len; + ctx->index += len; + } + + if (msg_len == 0) { + /* if it is still the last block, we are done */ + return; + } + + /* + * now checksum everything but the last block + */ + memxor3(Y.b, ctx->X.b, ctx->block.b, 8); + encrypt(cipher, 8, ctx->X.b, Y.b); + + while (msg_len > 8) + { + memxor3(Y.b, ctx->X.b, msg, 8); + encrypt(cipher, 8, ctx->X.b, Y.b); + msg += 8; + msg_len -= 8; + } + + /* + * copy the last block, it will be processed in + * cmac64_digest(). + */ + memcpy(ctx->block.b, msg, msg_len); + ctx->index = msg_len; +} + +void +cmac64_digest(struct cmac64_ctx *ctx, const struct cmac64_key *key, + const void *cipher, nettle_cipher_func *encrypt, + unsigned length, uint8_t *dst) +{ + union nettle_block8 Y; + + memset(ctx->block.b+ctx->index, 0, sizeof(ctx->block.b)-ctx->index); + + /* re-use ctx->block for memxor output */ + if (ctx->index < 8) + { + ctx->block.b[ctx->index] = 0x80; + memxor(ctx->block.b, key->K2.b, 8); + } + else + { + memxor(ctx->block.b, key->K1.b, 8); + } + + memxor3(Y.b, ctx->block.b, ctx->X.b, 8); + + assert(length <= 8); + if (length == 8) + { + encrypt(cipher, 8, dst, Y.b); + } + else + { + encrypt(cipher, 8, ctx->block.b, Y.b); + memcpy(dst, ctx->block.b, length); + } + + /* reset state for re-use */ + memset(&ctx->X, 0, sizeof(ctx->X)); + ctx->index = 0; +} diff --git a/cmac.h b/cmac.h index 3c5b7bea3e55..0cf9462d2120 100644 --- a/cmac.h +++ b/cmac.h @@ -44,6 +44,7 @@ extern "C" { #endif
#define CMAC128_DIGEST_SIZE 16 +#define CMAC64_DIGEST_SIZE 8
#define cmac128_set_key nettle_cmac128_set_key #define cmac128_init nettle_cmac128_init @@ -56,6 +57,11 @@ extern "C" { #define cmac_aes256_update nettle_cmac_aes256_update #define cmac_aes256_digest nettle_cmac_aes256_digest
+#define cmac64_set_key nettle_cmac64_set_key +#define cmac64_init nettle_cmac64_init +#define cmac64_update nettle_cmac64_update +#define cmac64_digest nettle_cmac64_digest + struct cmac128_key { union nettle_block16 K1; @@ -72,6 +78,22 @@ struct cmac128_ctx size_t index; };
+struct cmac64_key +{ + union nettle_block8 K1; + union nettle_block8 K2; +}; + +struct cmac64_ctx +{ + /* MAC state */ + union nettle_block8 X; + + /* Block buffer */ + union nettle_block8 block; + size_t index; +}; + void cmac128_set_key(struct cmac128_key *key, const void *cipher, nettle_cipher_func *encrypt); @@ -118,6 +140,53 @@ cmac128_digest(struct cmac128_ctx *ctx, const struct cmac128_key *key, (nettle_cipher_func *) (encrypt), \ (length), (digest)))
+void +cmac64_set_key(struct cmac64_key *key, const void *cipher, + nettle_cipher_func *encrypt); + +void +cmac64_init(struct cmac64_ctx *ctx); + +void +cmac64_update(struct cmac64_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg); + +void +cmac64_digest(struct cmac64_ctx *ctx, const struct cmac64_key *key, + const void *cipher, nettle_cipher_func *encrypt, + unsigned length, uint8_t *digest); + + +#define CMAC64_CTX(type) \ + { struct cmac64_key key; struct cmac64_ctx ctx; type cipher; } + +/* NOTE: Avoid using NULL, as we don't include anything defining it. */ +#define CMAC64_SET_KEY(self, set_key, encrypt, cmac_key) \ + do { \ + (set_key)(&(self)->cipher, (cmac_key)); \ + if (0) (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0); \ + cmac64_set_key(&(self)->key, &(self)->cipher, \ + (nettle_cipher_func *) (encrypt)); \ + cmac64_init(&(self)->ctx); \ + } while (0) + +#define CMAC64_UPDATE(self, encrypt, length, src) \ + (0 ? (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0) \ + : cmac64_update(&(self)->ctx, &(self)->cipher, \ + (nettle_cipher_func *)encrypt, \ + (length), (src))) + +#define CMAC64_DIGEST(self, encrypt, length, digest) \ + (0 ? (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0) \ + : cmac64_digest(&(self)->ctx, &(self)->key, \ + &(self)->cipher, \ + (nettle_cipher_func *) (encrypt), \ + (length), (digest))) + struct cmac_aes128_ctx CMAC128_CTX(struct aes128_ctx);
void diff --git a/nettle-types.h b/nettle-types.h index 87292ac69730..5addf3600d69 100644 --- a/nettle-types.h +++ b/nettle-types.h @@ -65,6 +65,12 @@ union nettle_block16 uint64_t u64[2]; };
+union nettle_block8 +{ + uint8_t b[8]; + uint64_t u64; +}; + /* Randomness. Used by key generation and dsa signature creation. */ typedef void nettle_random_func(void *ctx, size_t length, uint8_t *dst);
Dmitry Eremin-Solenikov dbaryshkov@gmail.com writes:
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com
cmac.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++- cmac.h | 69 +++++++++++++++++++++++++++ nettle-types.h | 6 +++ 3 files changed, 199 insertions(+), 1 deletion(-)
diff --git a/cmac.c b/cmac.c index 70ce8132d9d1..36ad8e58e45e 100644 --- a/cmac.c +++ b/cmac.c @@ -1,9 +1,10 @@ /*
- AES-CMAC-128 (rfc 4493)
AES-CMAC-128 (rfc 4493) / CMAC-64 Copyright (C) Stefan Metzmacher 2012 Copyright (C) Jeremy Allison 2012 Copyright (C) Michael Adam 2012 Copyright (C) 2017, Red Hat Inc.
Copyright (C) 2019, Dmitry Eremin-Solenikov
This file is part of GNU Nettle.
@@ -57,6 +58,15 @@ _cmac128_block_mulx(union nettle_block16 *dst, dst->u64[0] = (src->u64[0] << 1) | (src->u64[1] >> 63); dst->u64[1] = (src->u64[1] << 1) ^ (0x87 & -carry); }
+static void +block_mulx8(union nettle_block8 *dst,
const union nettle_block8 *src)
+{
- uint64_t carry = src->u64 >> 63;
- dst->u64 = (src->u64 << 1) ^ (0x1b & -carry);
+} #else /* !WORDS_BIGENDIAN */ #define LE_SHIFT(x) ((((x) & 0x7f7f7f7f7f7f7f7f) << 1) | \ (((x) & 0x8080808080808080) >> 15)) @@ -68,6 +78,15 @@ _cmac128_block_mulx(union nettle_block16 *dst, dst->u64[0] = LE_SHIFT(src->u64[0]) | ((src->u64[1] & 0x80) << 49); dst->u64[1] = LE_SHIFT(src->u64[1]) ^ (0x8700000000000000 & -carry); }
Patch looks nice, thanks! Is any of the implementation shared with cmac128? I think it would be nice to move it to a separate source file cmac64.c. Sharing the cmac.h header file is fine.
BTW, I'm sorry for the duplicated effort on nettle_block16 w; I'm traveling and online only sporadically, so I gave it a try without being up to date with your work.
Regards, /Niels
Hello,
вт, 9 июл. 2019 г. в 00:56, Niels Möller nisse@lysator.liu.se:
Dmitry Eremin-Solenikov dbaryshkov@gmail.com writes:
Patch looks nice, thanks! Is any of the implementation shared with cmac128? I think it would be nice to move it to a separate source file cmac64.c. Sharing the cmac.h header file is fine.
It shares LE_SHIFT(). I'll resend this patch as a followup.
BTW, I'm sorry for the duplicated effort on nettle_block16 w; I'm traveling and online only sporadically, so I gave it a try without being up to date with your work.
No problem. Now you have two proposals and can compare them ;-)
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- Makefile.in | 2 +- cmac.h | 69 +++++++++++++++++++ cmac64.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++ nettle-types.h | 6 ++ 4 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 cmac64.c
diff --git a/Makefile.in b/Makefile.in index b54e64b053c3..bad2baf3a29e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -102,7 +102,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ gcm-aes256.c gcm-aes256-meta.c \ gcm-camellia128.c gcm-camellia128-meta.c \ gcm-camellia256.c gcm-camellia256-meta.c \ - cmac.c cmac-aes128.c cmac-aes256.c \ + cmac.c cmac64.c cmac-aes128.c cmac-aes256.c \ gosthash94.c gosthash94-meta.c \ hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \ hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c \ diff --git a/cmac.h b/cmac.h index 3c5b7bea3e55..0cf9462d2120 100644 --- a/cmac.h +++ b/cmac.h @@ -44,6 +44,7 @@ extern "C" { #endif
#define CMAC128_DIGEST_SIZE 16 +#define CMAC64_DIGEST_SIZE 8
#define cmac128_set_key nettle_cmac128_set_key #define cmac128_init nettle_cmac128_init @@ -56,6 +57,11 @@ extern "C" { #define cmac_aes256_update nettle_cmac_aes256_update #define cmac_aes256_digest nettle_cmac_aes256_digest
+#define cmac64_set_key nettle_cmac64_set_key +#define cmac64_init nettle_cmac64_init +#define cmac64_update nettle_cmac64_update +#define cmac64_digest nettle_cmac64_digest + struct cmac128_key { union nettle_block16 K1; @@ -72,6 +78,22 @@ struct cmac128_ctx size_t index; };
+struct cmac64_key +{ + union nettle_block8 K1; + union nettle_block8 K2; +}; + +struct cmac64_ctx +{ + /* MAC state */ + union nettle_block8 X; + + /* Block buffer */ + union nettle_block8 block; + size_t index; +}; + void cmac128_set_key(struct cmac128_key *key, const void *cipher, nettle_cipher_func *encrypt); @@ -118,6 +140,53 @@ cmac128_digest(struct cmac128_ctx *ctx, const struct cmac128_key *key, (nettle_cipher_func *) (encrypt), \ (length), (digest)))
+void +cmac64_set_key(struct cmac64_key *key, const void *cipher, + nettle_cipher_func *encrypt); + +void +cmac64_init(struct cmac64_ctx *ctx); + +void +cmac64_update(struct cmac64_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg); + +void +cmac64_digest(struct cmac64_ctx *ctx, const struct cmac64_key *key, + const void *cipher, nettle_cipher_func *encrypt, + unsigned length, uint8_t *digest); + + +#define CMAC64_CTX(type) \ + { struct cmac64_key key; struct cmac64_ctx ctx; type cipher; } + +/* NOTE: Avoid using NULL, as we don't include anything defining it. */ +#define CMAC64_SET_KEY(self, set_key, encrypt, cmac_key) \ + do { \ + (set_key)(&(self)->cipher, (cmac_key)); \ + if (0) (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0); \ + cmac64_set_key(&(self)->key, &(self)->cipher, \ + (nettle_cipher_func *) (encrypt)); \ + cmac64_init(&(self)->ctx); \ + } while (0) + +#define CMAC64_UPDATE(self, encrypt, length, src) \ + (0 ? (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0) \ + : cmac64_update(&(self)->ctx, &(self)->cipher, \ + (nettle_cipher_func *)encrypt, \ + (length), (src))) + +#define CMAC64_DIGEST(self, encrypt, length, digest) \ + (0 ? (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0) \ + : cmac64_digest(&(self)->ctx, &(self)->key, \ + &(self)->cipher, \ + (nettle_cipher_func *) (encrypt), \ + (length), (digest))) + struct cmac_aes128_ctx CMAC128_CTX(struct aes128_ctx);
void diff --git a/cmac64.c b/cmac64.c new file mode 100644 index 000000000000..9b711d6698ab --- /dev/null +++ b/cmac64.c @@ -0,0 +1,177 @@ +/* + AES-CMAC-128 (rfc 4493) / CMAC-64 + Copyright (C) Stefan Metzmacher 2012 + Copyright (C) Jeremy Allison 2012 + Copyright (C) Michael Adam 2012 + Copyright (C) 2017, Red Hat Inc. + Copyright (C) 2019, Dmitry Eremin-Solenikov + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include "cmac.h" + +#include "memxor.h" +#include "nettle-internal.h" +#include "macros.h" + +/* shift one and XOR with 0x87. */ +#if WORDS_BIGENDIAN +static void +_cmac64_block_mulx(union nettle_block8 *dst, + const union nettle_block8 *src) +{ + uint64_t carry = src->u64 >> 63; + + dst->u64 = (src->u64 << 1) ^ (0x1b & -carry); +} +#else /* !WORDS_BIGENDIAN */ +#define LE_SHIFT(x) ((((x) & 0x7f7f7f7f7f7f7f7f) << 1) | \ + (((x) & 0x8080808080808080) >> 15)) +static void +_cmac64_block_mulx(union nettle_block8 *dst, + const union nettle_block8 *src) +{ + uint64_t carry = (src->u64 & 0x80) >> 7; + + dst->u64 = LE_SHIFT(src->u64) ^ (0x1b00000000000000 & -carry); +} +#endif /* !WORDS_BIGENDIAN */ + +void +cmac64_set_key(struct cmac64_key *key, const void *cipher, + nettle_cipher_func *encrypt) +{ + static const union nettle_block8 zero_block; + union nettle_block8 L; + + /* step 1 - generate subkeys k1 and k2 */ + encrypt(cipher, 8, L.b, zero_block.b); + + _cmac64_block_mulx(&key->K1, &L); + _cmac64_block_mulx(&key->K2, &key->K1); +} + +void +cmac64_init(struct cmac64_ctx *ctx) +{ + memset(&ctx->X, 0, sizeof(ctx->X)); + ctx->index = 0; +} + +#define MIN(x,y) ((x)<(y)?(x):(y)) + +void +cmac64_update(struct cmac64_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg) +{ + union nettle_block16 Y; + /* + * check if we expand the block + */ + if (ctx->index < 8) + { + size_t len = MIN(8 - ctx->index, msg_len); + memcpy(&ctx->block.b[ctx->index], msg, len); + msg += len; + msg_len -= len; + ctx->index += len; + } + + if (msg_len == 0) { + /* if it is still the last block, we are done */ + return; + } + + /* + * now checksum everything but the last block + */ + memxor3(Y.b, ctx->X.b, ctx->block.b, 8); + encrypt(cipher, 8, ctx->X.b, Y.b); + + while (msg_len > 8) + { + memxor3(Y.b, ctx->X.b, msg, 8); + encrypt(cipher, 8, ctx->X.b, Y.b); + msg += 8; + msg_len -= 8; + } + + /* + * copy the last block, it will be processed in + * cmac64_digest(). + */ + memcpy(ctx->block.b, msg, msg_len); + ctx->index = msg_len; +} + +void +cmac64_digest(struct cmac64_ctx *ctx, const struct cmac64_key *key, + const void *cipher, nettle_cipher_func *encrypt, + unsigned length, uint8_t *dst) +{ + union nettle_block8 Y; + + memset(ctx->block.b+ctx->index, 0, sizeof(ctx->block.b)-ctx->index); + + /* re-use ctx->block for memxor output */ + if (ctx->index < 8) + { + ctx->block.b[ctx->index] = 0x80; + memxor(ctx->block.b, key->K2.b, 8); + } + else + { + memxor(ctx->block.b, key->K1.b, 8); + } + + memxor3(Y.b, ctx->block.b, ctx->X.b, 8); + + assert(length <= 8); + if (length == 8) + { + encrypt(cipher, 8, dst, Y.b); + } + else + { + encrypt(cipher, 8, ctx->block.b, Y.b); + memcpy(dst, ctx->block.b, length); + } + + /* reset state for re-use */ + memset(&ctx->X, 0, sizeof(ctx->X)); + ctx->index = 0; +} diff --git a/nettle-types.h b/nettle-types.h index 87292ac69730..5addf3600d69 100644 --- a/nettle-types.h +++ b/nettle-types.h @@ -65,6 +65,12 @@ union nettle_block16 uint64_t u64[2]; };
+union nettle_block8 +{ + uint8_t b[8]; + uint64_t u64; +}; + /* Randomness. Used by key generation and dsa signature creation. */ typedef void nettle_random_func(void *ctx, size_t length, uint8_t *dst);
Dmitry Eremin-Solenikov dbaryshkov@gmail.com writes:
--- /dev/null +++ b/cmac64.c @@ -0,0 +1,177 @@ +/*
- AES-CMAC-128 (rfc 4493) / CMAC-64
I've now merged this and the cmac_des3 patch onto a branch "cmac64". What's an authoritative reference for cmac64 and cmac using des? RFC4493 doesn't seem quite right. Is it NIST SP 800-38B, mentioned in a comment with the tests?
Regards, /Niels
Hello,
чт, 11 июл. 2019 г. в 00:05, Niels Möller nisse@lysator.liu.se:
Dmitry Eremin-Solenikov dbaryshkov@gmail.com writes:
--- /dev/null +++ b/cmac64.c @@ -0,0 +1,177 @@ +/*
- AES-CMAC-128 (rfc 4493) / CMAC-64
I've now merged this and the cmac_des3 patch onto a branch "cmac64".
Thank you!
What's an authoritative reference for cmac64 and cmac using des? RFC4493 doesn't seem quite right. Is it NIST SP 800-38B, mentioned in a comment with the tests?
Yes, it is.
nisse@lysator.liu.se (Niels Möller) writes:
I've now merged this and the cmac_des3 patch onto a branch "cmac64".
And now pushed to master, together with the documentation update.
Thanks, /Niels
Implement CMAC using TrippleDES as underlying cipher.
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- Makefile.in | 2 +- cmac-des3.c | 61 +++++++++++++++++++++++++++++++++++++++++++ cmac.h | 17 ++++++++++++ testsuite/cmac-test.c | 32 +++++++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 cmac-des3.c
diff --git a/Makefile.in b/Makefile.in index 537e97d19bea..2e60c2f70ac6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -101,7 +101,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ gcm-aes256.c gcm-aes256-meta.c \ gcm-camellia128.c gcm-camellia128-meta.c \ gcm-camellia256.c gcm-camellia256-meta.c \ - cmac.c cmac-aes128.c cmac-aes256.c \ + cmac.c cmac-aes128.c cmac-aes256.c cmac-des3.c \ gosthash94.c gosthash94-meta.c \ hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \ hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c \ diff --git a/cmac-des3.c b/cmac-des3.c new file mode 100644 index 000000000000..d2d55ca43e75 --- /dev/null +++ b/cmac-des3.c @@ -0,0 +1,61 @@ +/* cmac-des3.c + + CMAC using TrippleDES as the underlying cipher. + + Copyright (C) 2019 Dmitry Eremin-Solenikov + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> + +#include "cmac.h" + +void +cmac_des3_set_key (struct cmac_des3_ctx *ctx, const uint8_t *key) +{ + CMAC64_SET_KEY (ctx, des3_set_key, des3_encrypt, key); +} + +void +cmac_des3_update (struct cmac_des3_ctx *ctx, + size_t length, const uint8_t *data) +{ + CMAC64_UPDATE (ctx, des3_encrypt, length, data); +} + +void +cmac_des3_digest (struct cmac_des3_ctx *ctx, + size_t length, uint8_t *digest) +{ + CMAC64_DIGEST (ctx, des3_encrypt, length, digest); +} + diff --git a/cmac.h b/cmac.h index 0cf9462d2120..ecad3778f71e 100644 --- a/cmac.h +++ b/cmac.h @@ -37,6 +37,7 @@ #define NETTLE_CMAC_H_INCLUDED
#include "aes.h" +#include "des.h" #include "nettle-types.h"
#ifdef __cplusplus @@ -61,6 +62,9 @@ extern "C" { #define cmac64_init nettle_cmac64_init #define cmac64_update nettle_cmac64_update #define cmac64_digest nettle_cmac64_digest +#define cmac_des3_set_key nettle_cmac_des3_set_key +#define cmac_des3_update nettle_cmac_des3_update +#define cmac_des3_digest nettle_cmac_des3_digest
struct cmac128_key { @@ -213,6 +217,19 @@ void cmac_aes256_digest(struct cmac_aes256_ctx *ctx, size_t length, uint8_t *digest);
+struct cmac_des3_ctx CMAC64_CTX(struct des3_ctx); + +void +cmac_des3_set_key(struct cmac_des3_ctx *ctx, const uint8_t *key); + +void +cmac_des3_update(struct cmac_des3_ctx *ctx, + size_t length, const uint8_t *data); + +void +cmac_des3_digest(struct cmac_des3_ctx *ctx, + size_t length, uint8_t *digest); + #ifdef __cplusplus } #endif diff --git a/testsuite/cmac-test.c b/testsuite/cmac-test.c index b1d4aa30dfbe..9d6682777dcf 100644 --- a/testsuite/cmac-test.c +++ b/testsuite/cmac-test.c @@ -26,12 +26,27 @@ const struct nettle_mac nettle_cmac_aes256 = (nettle_hash_digest_func*) cmac_aes256_digest };
+const struct nettle_mac nettle_cmac_des3 = +{ + "CMAC-3DES", + sizeof(struct cmac_des3_ctx), + CMAC64_DIGEST_SIZE, + DES3_KEY_SIZE, + + (nettle_set_key_func*) cmac_des3_set_key, + (nettle_hash_update_func*) cmac_des3_update, + (nettle_hash_digest_func*) cmac_des3_digest +}; + #define test_cmac_aes128(key, msg, ref) \ test_mac(&nettle_cmac_aes128, key, msg, ref)
#define test_cmac_aes256(key, msg, ref) \ test_mac(&nettle_cmac_aes256, key, msg, ref)
+#define test_cmac_des3(key, msg, ref) \ + test_mac(&nettle_cmac_des3, key, msg, ref) + void test_main(void) { @@ -96,4 +111,21 @@ test_main(void) SHEX("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"), SHEX("e1992190549f6ed5696a2c056c315410"));
+ /* CMAC-3DES vectors from NIST SP800-38B examples */ + test_cmac_des3 (SHEX("0123456789abcdef23456789abcdef01456789abcdef0123"), + SDATA(""), + SHEX("7db0d37df936c550")); + + test_cmac_des3 (SHEX("0123456789abcdef23456789abcdef01456789abcdef0123"), + SHEX("6bc1bee22e409f96e93d7e117393172a"), + SHEX("30239cf1f52e6609")); + + test_cmac_des3 (SHEX("0123456789abcdef23456789abcdef01456789abcdef0123"), + SHEX("6bc1bee22e409f96e93d7e117393172aae2d8a57"), + SHEX("6c9f3ee4923f6be2")); + + + test_cmac_des3 (SHEX("0123456789abcdef23456789abcdef01456789abcdef0123"), + SHEX("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"), + SHEX("99429bd0bf7904e5")); }
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- nettle.texinfo | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/nettle.texinfo b/nettle.texinfo index b8579a6ed59b..57e6345f78df 100644 --- a/nettle.texinfo +++ b/nettle.texinfo @@ -3718,14 +3718,21 @@ as described above, the new value is used unless you call the @node CMAC,, UMAC, Keyed hash functions @subsection @acronym{CMAC} @cindex CMAC +@cindex CMAC-128 +@cindex CMAC-64
@acronym{CMAC} is a message authentication code based on CBC encryption mode. It is suitable for systems where block ciphers are preferrable -and perform better than hash functions. @acronym{CMAC} is specified in +and perform better than hash functions. @acronym{CMAC-128} is specified in @cite{RFC4493}. The block size is always 128 bits (16 octets). +@acronym{CMAC-64} is specified by +@uref{https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38B.pdf, +NIST Special Publication 800-38B}. The block size is always 64 bits +(8 octets).
-Nettle provides helper functions for @acronym{CMAC } with -the @acronym{AES} block cipher. +Nettle provides helper functions for @acronym{CMAC-128} with +the @acronym{AES} block cipher and for @acronym{CMAC-64} with +the @acronym{Tripple-DES} block cipher.
Nettle defines @acronym{CMAC} in @file{<nettle/cmac.h>}.
@@ -3734,7 +3741,7 @@ Nettle defines @acronym{CMAC} in @file{<nettle/cmac.h>}. @end deftp
@defvr Constant CMAC128_DIGEST_SIZE -The size of an CMAC digest, 16. +The size of an CMAC-128 digest, 16. @end defvr
@deftypefun void cmac_aes128_set_key (struct cmac_aes128_ctx *@var{ctx}, const uint8_t *@var{key}) @@ -3769,6 +3776,29 @@ provide a smaller value, only the first @var{length} octets of the processing of a new message with the same key. @end deftypefun
+@deftp {Context struct} {struct cmac_des3_ctx} +@end deftp + +@defvr Constant CMAC64_DIGEST_SIZE +The size of an CMAC-64 digest, 8. +@end defvr + +@deftypefun void cmac_des3_set_key (struct cmac_des3_ctx *@var{ctx}, const uint8_t *@var{key}) +This function initializes the @acronym{CMAC} context struct for @acronym{Tripple-DES}. +@end deftypefun + +@deftypefun void cmac_des3_update (struct cmac_des3_ctx *@var{ctx}, size_t @var{length}, const uint8_t *@var{data}) +This function is called zero or more times to process the message. +@end deftypefun + +@deftypefun void cmac_des3_digest (struct cmac_des3_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{digest}) +Extracts the @acronym{MAC} of the message, writing it to @var{digest}. +@var{length} is usually equal to the specified output size, but if you +provide a smaller value, only the first @var{length} octets of the +@acronym{MAC} are written. This function resets the context for +processing of a new message with the same key. +@end deftypefun + @node Poly1305,, CMAC, Keyed hash functions @comment node-name, next, previous, up @subsection Poly1305
Dmitry Eremin-Solenikov dbaryshkov@gmail.com writes:
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com
testsuite/cmac-test.c | 100 +++++++++++------------------------------- testsuite/testutils.c | 64 +++++++++++++++++++++++++++ testsuite/testutils.h | 6 +++ 3 files changed, 96 insertions(+), 74 deletions(-)
diff --git a/testsuite/cmac-test.c b/testsuite/cmac-test.c index 31662d1b6c1b..b1d4aa30dfbe 100644 --- a/testsuite/cmac-test.c +++ b/testsuite/cmac-test.c @@ -2,83 +2,35 @@ #include "nettle-internal.h" #include "cmac.h"
+const struct nettle_mac nettle_cmac_aes128 = +{
- "CMAC-AES128",
Names are usually lowercase, but doesn't really matter for the tests.
I'm merging this patch now, currently on master-updates for testing by the gitlab ci.
I've had a look at also updating the hmac and umac tests, but that wasn't as easy as I hoped. For hmac, the variable key size doesn't fit the struct nettle_mac. For umac, key size is fixed, but one also has a nonce and nonce auto-increment.
Regards, /Niels
nettle-bugs@lists.lysator.liu.se