Signed-off-by: Dmitry Eremin-Solenikov <dbarysh...@gmail.com>
---
 cmac.c         | 115 +++++++++++++++++++++++++++++++++++++++++++++++++
 cmac.h         |  58 +++++++++++++++++++++++++
 nettle-types.h |   7 +++
 3 files changed, 180 insertions(+)

diff --git a/cmac.c b/cmac.c
index d08bd8325b16..8a70f595b14b 100644
--- a/cmac.c
+++ b/cmac.c
@@ -64,6 +64,20 @@ block_mulx(union nettle_block16 *dst,
   WRITE_UINT64(dst->b+8, b2);
 }
 
+static void
+block_mulx8(union nettle_block8 *dst,
+           const union nettle_block8 *src)
+{
+  uint64_t b1 = READ_UINT64(src->b);
+
+  b1 <<= 1;
+
+  if (src->b[0] & 0x80)
+    b1 ^= 0x1b;
+
+  WRITE_UINT64(dst->b, b1);
+}
+
 void
 cmac128_set_key(struct cmac128_ctx *ctx, const void *cipher,
                nettle_cipher_func *encrypt)
@@ -167,3 +181,104 @@ cmac128_digest(struct cmac128_ctx *ctx, const void 
*cipher,
   memset(&ctx->X, 0, sizeof(ctx->X));
   ctx->index = 0;
 }
+
+void
+cmac64_set_key(struct cmac64_ctx *ctx, const void *cipher,
+               nettle_cipher_func *encrypt)
+{
+  static const uint8_t const_zero[] = {
+    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+  };
+  union nettle_block8 *L = &ctx->block;
+  memset(ctx, 0, sizeof(*ctx));
+
+  /* step 1 - generate subkeys k1 and k2 */
+  encrypt(cipher, 8, L->b, const_zero);
+
+  block_mulx8(&ctx->K1, L);
+  block_mulx8(&ctx->K2, &ctx->K1);
+}
+
+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 void *cipher,
+              nettle_cipher_func *encrypt,
+              unsigned length,
+              uint8_t *dst)
+{
+  union nettle_block16 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, ctx->K2.b, 8);
+    }
+  else
+    {
+      memxor(ctx->block.b, ctx->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 6d107982273e..ddd0248e5e4f 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_update nettle_cmac128_update
@@ -55,6 +56,10 @@ 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_update nettle_cmac64_update
+#define cmac64_digest nettle_cmac64_digest
+
 struct cmac128_ctx
 {
   /* Key */
@@ -69,6 +74,21 @@ struct cmac128_ctx
   size_t index;
 };
 
+struct cmac64_ctx
+{
+  /* Key */
+  union nettle_block8 K1;
+  union nettle_block8 K2;
+
+  /* MAC state */
+  union nettle_block8 X;
+
+  /* Block buffer */
+  union nettle_block8 block;
+  size_t index;
+};
+
+
 void
 cmac128_set_key(struct cmac128_ctx *ctx, const void *cipher,
                nettle_cipher_func *encrypt);
@@ -107,6 +127,44 @@ cmac128_digest(struct cmac128_ctx *ctx, const void *cipher,
                  (nettle_cipher_func *) (encrypt),             \
                  (length), (digest)))
 
+void
+cmac64_set_key(struct cmac64_ctx *ctx, const void *cipher,
+               nettle_cipher_func *encrypt);
+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 void *cipher,
+              nettle_cipher_func *encrypt,
+              unsigned length,
+              uint8_t *digest);
+
+
+#define CMAC64_CTX(type) \
+  { 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)->ctx, &(self)->cipher,              \
+               (nettle_cipher_func *) (encrypt));              \
+  } while (0)
+
+#define CMAC64_UPDATE(self, encrypt, length, src)              \
+  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)->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 4576b7c7b5b3..84e9706d8364 100644
--- a/nettle-types.h
+++ b/nettle-types.h
@@ -68,6 +68,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);
-- 
2.19.0

_______________________________________________
nettle-bugs mailing list
nettle-bugs@lists.lysator.liu.se
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to