Browse Source

BLAKE2 based MACs

Karel Miko 8 years ago
parent
commit
0d585958c1

+ 10 - 0
src/headers/tomcrypt_custom.h

@@ -260,6 +260,8 @@
 #define LTC_F9_MODE
 #define LTC_F9_MODE
 #define LTC_PELICAN
 #define LTC_PELICAN
 #define LTC_POLY1305
 #define LTC_POLY1305
+#define LTC_BLAKE2SMAC
+#define LTC_BLAKE2BMAC
 
 
 /* ---> Encrypt + Authenticate Modes <--- */
 /* ---> Encrypt + Authenticate Modes <--- */
 
 
@@ -521,6 +523,14 @@
    #error LTC_CHACHA20_PRNG requires LTC_CHACHA
    #error LTC_CHACHA20_PRNG requires LTC_CHACHA
 #endif
 #endif
 
 
+#if defined(LTC_BLAKE2SMAC) && !defined(LTC_BLAKE2S)
+   #error LTC_BLAKE2SMAC requires LTC_BLAKE2S
+#endif
+
+#if defined(LTC_BLAKE2BMAC) && !defined(LTC_BLAKE2B)
+   #error LTC_BLAKE2BMAC requires LTC_BLAKE2B
+#endif
+
 /* THREAD management */
 /* THREAD management */
 #ifdef LTC_PTHREAD
 #ifdef LTC_PTHREAD
 
 

+ 24 - 0
src/headers/tomcrypt_mac.h

@@ -116,6 +116,30 @@ int poly1305_file(const char *fname, const unsigned char *key, unsigned long key
 int poly1305_test(void);
 int poly1305_test(void);
 #endif /* LTC_POLY1305 */
 #endif /* LTC_POLY1305 */
 
 
+#ifdef LTC_BLAKE2SMAC
+typedef hash_state blake2smac_state;
+int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen);
+int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen);
+int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen);
+int blake2smac_test(void);
+int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen);
+int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in,  unsigned long inlen, ...);
+int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen);
+int blake2smac_test(void);
+#endif /* LTC_BLAKE2SMAC */
+
+#ifdef LTC_BLAKE2BMAC
+typedef hash_state blake2bmac_state;
+int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen);
+int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen);
+int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen);
+int blake2bmac_test(void);
+int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen);
+int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in,  unsigned long inlen, ...);
+int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen);
+int blake2bmac_test(void);
+#endif /* LTC_BLAKE2BMAC */
+
 #ifdef LTC_EAX_MODE
 #ifdef LTC_EAX_MODE
 
 
 #if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE))
 #if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE))

+ 61 - 0
src/mac/blake2/blake2bmac.c

@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_BLAKE2BMAC
+
+/**
+   Initialize an BLAKE2B MAC context.
+   @param st       The BLAKE2B MAC state
+   @param key      The secret key
+   @param keylen   The length of the secret key (octets)
+   @return CRYPT_OK if successful
+*/
+int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen)
+{
+   LTC_ARGCHK(st  != NULL);
+   LTC_ARGCHK(key != NULL);
+   return blake2b_init(st, outlen, key, keylen);
+}
+
+/**
+  Process data through BLAKE2B MAC
+  @param st      The BLAKE2B MAC state
+  @param in      The data to send through HMAC
+  @param inlen   The length of the data to HMAC (octets)
+  @return CRYPT_OK if successful
+*/
+int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen)
+{
+   if (inlen == 0) return CRYPT_OK; /* nothing to do */
+   LTC_ARGCHK(st != NULL);
+   LTC_ARGCHK(in != NULL);
+   return blake2b_process(st, in, inlen);
+}
+
+/**
+   Terminate a BLAKE2B MAC session
+   @param st      The BLAKE2B MAC state
+   @param mac     [out] The destination of the BLAKE2B MAC authentication tag
+   @param maclen  [in/out]  The max size and resulting size of the BLAKE2B MAC authentication tag
+   @return CRYPT_OK if successful
+*/
+int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen)
+{
+   LTC_ARGCHK(st     != NULL);
+   LTC_ARGCHK(mac    != NULL);
+   LTC_ARGCHK(maclen != NULL);
+   LTC_ARGCHK(*maclen >= st->blake2b.outlen);
+
+   *maclen = st->blake2b.outlen;
+   return blake2b_done(st, mac);
+}
+
+#endif

+ 79 - 0
src/mac/blake2/blake2bmac_file.c

@@ -0,0 +1,79 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_BLAKE2BMAC
+
+/**
+  BLAKE2B MAC a file
+  @param fname    The name of the file you wish to BLAKE2B MAC
+  @param key      The secret key
+  @param keylen   The length of the secret key
+  @param mac      [out] The BLAKE2B MAC authentication tag
+  @param maclen   [in/out]  The max size and resulting size of the authentication tag
+  @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen)
+{
+        #ifdef LTC_NO_FILE
+   return CRYPT_NOP;
+#else
+   blake2bmac_state st;
+   FILE *in;
+   unsigned char *buf;
+   size_t x;
+   int err;
+
+   LTC_ARGCHK(fname  != NULL);
+   LTC_ARGCHK(key    != NULL);
+   LTC_ARGCHK(mac    != NULL);
+   LTC_ARGCHK(maclen != NULL);
+
+   if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+      return CRYPT_MEM;
+   }
+
+   if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) {
+      goto LBL_ERR;
+   }
+
+   in = fopen(fname, "rb");
+   if (in == NULL) {
+      err = CRYPT_FILE_NOTFOUND;
+      goto LBL_ERR;
+   }
+
+   do {
+      x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+      if ((err = blake2bmac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) {
+         fclose(in);
+         goto LBL_CLEANBUF;
+      }
+   } while (x == LTC_FILE_READ_BUFSIZE);
+
+   if (fclose(in) != 0) {
+      err = CRYPT_ERROR;
+      goto LBL_CLEANBUF;
+   }
+
+   err = blake2bmac_done(&st, mac, maclen);
+
+LBL_CLEANBUF:
+   zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+   zeromem(&st, sizeof(blake2bmac_state));
+#endif
+   XFREE(buf);
+   return err;
+#endif
+}
+
+#endif

+ 44 - 0
src/mac/blake2/blake2bmac_memory.c

@@ -0,0 +1,44 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_BLAKE2BMAC
+
+/**
+   BLAKE2B MAC a block of memory to produce the authentication tag
+   @param key       The secret key
+   @param keylen    The length of the secret key (octets)
+   @param in        The data to BLAKE2B MAC
+   @param inlen     The length of the data to BLAKE2B MAC (octets)
+   @param mac       [out] Destination of the authentication tag
+   @param maclen    [in/out] Max size and resulting size of authentication tag
+   @return CRYPT_OK if successful
+*/
+int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen)
+{
+   blake2bmac_state st;
+   int err;
+
+   LTC_ARGCHK(key    != NULL);
+   LTC_ARGCHK(in     != NULL);
+   LTC_ARGCHK(mac    != NULL);
+   LTC_ARGCHK(maclen != NULL);
+
+   if ((err = blake2bmac_init(&st, *maclen, key, keylen))  != CRYPT_OK) { goto LBL_ERR; }
+   if ((err = blake2bmac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
+   err = blake2bmac_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+   zeromem(&st, sizeof(blake2bmac_state));
+#endif
+   return err;
+}
+
+#endif

+ 58 - 0
src/mac/blake2/blake2bmac_memory_multi.c

@@ -0,0 +1,58 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+#include <stdarg.h>
+
+#ifdef LTC_BLAKE2BMAC
+
+/**
+   BLAKE2B MAC multiple blocks of memory to produce the authentication tag
+   @param key       The secret key
+   @param keylen    The length of the secret key (octets)
+   @param out       [out] Destination of the authentication tag
+   @param outlen    [in/out] Max size and resulting size of authentication tag
+   @param in        The data to BLAKE2B MAC
+   @param inlen     The length of the data to BLAKE2B MAC (octets)
+   @param ...       tuples of (data,len) pairs to BLAKE2B MAC, terminated with a (NULL,x) (x=don't care)
+   @return CRYPT_OK if successful
+*/
+int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in,  unsigned long inlen, ...)
+{
+   blake2bmac_state st;
+   int err;
+   va_list args;
+   const unsigned char *curptr;
+   unsigned long curlen;
+
+   LTC_ARGCHK(key    != NULL);
+   LTC_ARGCHK(in     != NULL);
+   LTC_ARGCHK(mac    != NULL);
+   LTC_ARGCHK(maclen != NULL);
+
+   va_start(args, inlen);
+   curptr = in;
+   curlen = inlen;
+   if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK)          { goto LBL_ERR; }
+   for (;;) {
+      if ((err = blake2bmac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; }
+      curptr = va_arg(args, const unsigned char*);
+      if (curptr == NULL) break;
+      curlen = va_arg(args, unsigned long);
+   }
+   err = blake2bmac_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+   zeromem(&st, sizeof(blake2bmac_state));
+#endif
+   va_end(args);
+   return err;
+}
+
+#endif

+ 44 - 0
src/mac/blake2/blake2bmac_test.c

@@ -0,0 +1,44 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_BLAKE2BMAC
+
+int blake2bmac_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   unsigned char k[]   = { 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b };
+   unsigned char tag[] = { 0x3d, 0xd6, 0x35, 0x81, 0x32, 0xb5, 0x3c, 0xc8, 0x0a, 0x8c, 0x33, 0x91, 0x93, 0x5d, 0x30, 0x1b };
+   char m[] = "Cryptographic Forum Research Group";
+   unsigned long len = 16, mlen = strlen(m);
+   unsigned char out[1000];
+   blake2bmac_state st;
+   /* process piece by piece */
+   blake2bmac_init(&st, 16, k, 32);
+   blake2bmac_process(&st, (unsigned char*)m,      5);
+   blake2bmac_process(&st, (unsigned char*)m + 5,  4);
+   blake2bmac_process(&st, (unsigned char*)m + 9,  3);
+   blake2bmac_process(&st, (unsigned char*)m + 12, 2);
+   blake2bmac_process(&st, (unsigned char*)m + 14, 1);
+   blake2bmac_process(&st, (unsigned char*)m + 15, mlen - 15);
+   blake2bmac_done(&st, out, &len);
+   if (compare_testvector(out, len, tag, sizeof(tag), "BLAKE2B MAC-TV1", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+   /* process in one go */
+   blake2bmac_init(&st, 16, k, 32);
+   blake2bmac_process(&st, (unsigned char*)m, mlen);
+   blake2bmac_done(&st, out, &len);
+   if (compare_testvector(out, len, tag, sizeof(tag), "BLAKE2B MAC-TV2", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+   return CRYPT_OK;
+#endif
+}
+
+#endif

+ 61 - 0
src/mac/blake2/blake2smac.c

@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_BLAKE2SMAC
+
+/**
+   Initialize an BLAKE2S MAC context.
+   @param st       The BLAKE2S MAC state
+   @param key      The secret key
+   @param keylen   The length of the secret key (octets)
+   @return CRYPT_OK if successful
+*/
+int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen)
+{
+   LTC_ARGCHK(st  != NULL);
+   LTC_ARGCHK(key != NULL);
+   return blake2s_init(st, outlen, key, keylen);
+}
+
+/**
+  Process data through BLAKE2S MAC
+  @param st      The BLAKE2S MAC state
+  @param in      The data to send through HMAC
+  @param inlen   The length of the data to HMAC (octets)
+  @return CRYPT_OK if successful
+*/
+int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen)
+{
+   if (inlen == 0) return CRYPT_OK; /* nothing to do */
+   LTC_ARGCHK(st != NULL);
+   LTC_ARGCHK(in != NULL);
+   return blake2s_process(st, in, inlen);
+}
+
+/**
+   Terminate a BLAKE2S MAC session
+   @param st      The BLAKE2S MAC state
+   @param mac     [out] The destination of the BLAKE2S MAC authentication tag
+   @param maclen  [in/out]  The max size and resulting size of the BLAKE2S MAC authentication tag
+   @return CRYPT_OK if successful
+*/
+int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen)
+{
+   LTC_ARGCHK(st     != NULL);
+   LTC_ARGCHK(mac    != NULL);
+   LTC_ARGCHK(maclen != NULL);
+   LTC_ARGCHK(*maclen >= st->blake2s.outlen);
+
+   *maclen = st->blake2s.outlen;
+   return blake2s_done(st, mac);
+}
+
+#endif

+ 79 - 0
src/mac/blake2/blake2smac_file.c

@@ -0,0 +1,79 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_BLAKE2SMAC
+
+/**
+  BLAKE2S MAC a file
+  @param fname    The name of the file you wish to BLAKE2S MAC
+  @param key      The secret key
+  @param keylen   The length of the secret key
+  @param mac      [out] The BLAKE2S MAC authentication tag
+  @param maclen   [in/out]  The max size and resulting size of the authentication tag
+  @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled
+*/
+int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen)
+{
+#ifdef LTC_NO_FILE
+   return CRYPT_NOP;
+#else
+   blake2smac_state st;
+   FILE *in;
+   unsigned char *buf;
+   size_t x;
+   int err;
+
+   LTC_ARGCHK(fname  != NULL);
+   LTC_ARGCHK(key    != NULL);
+   LTC_ARGCHK(mac    != NULL);
+   LTC_ARGCHK(maclen != NULL);
+
+   if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
+      return CRYPT_MEM;
+   }
+
+   if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) {
+      goto LBL_ERR;
+   }
+
+   in = fopen(fname, "rb");
+   if (in == NULL) {
+      err = CRYPT_FILE_NOTFOUND;
+      goto LBL_ERR;
+   }
+
+   do {
+      x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in);
+      if ((err = blake2smac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) {
+         fclose(in);
+         goto LBL_CLEANBUF;
+      }
+   } while (x == LTC_FILE_READ_BUFSIZE);
+
+   if (fclose(in) != 0) {
+      err = CRYPT_ERROR;
+      goto LBL_CLEANBUF;
+   }
+
+   err = blake2smac_done(&st, mac, maclen);
+
+LBL_CLEANBUF:
+   zeromem(buf, LTC_FILE_READ_BUFSIZE);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+   zeromem(&st, sizeof(blake2smac_state));
+#endif
+   XFREE(buf);
+   return err;
+#endif
+}
+
+#endif

+ 44 - 0
src/mac/blake2/blake2smac_memory.c

@@ -0,0 +1,44 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_BLAKE2SMAC
+
+/**
+   BLAKE2S MAC a block of memory to produce the authentication tag
+   @param key       The secret key
+   @param keylen    The length of the secret key (octets)
+   @param in        The data to BLAKE2S MAC
+   @param inlen     The length of the data to BLAKE2S MAC (octets)
+   @param mac       [out] Destination of the authentication tag
+   @param maclen    [in/out] Max size and resulting size of authentication tag
+   @return CRYPT_OK if successful
+*/
+int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen)
+{
+   blake2smac_state st;
+   int err;
+
+   LTC_ARGCHK(key    != NULL);
+   LTC_ARGCHK(in     != NULL);
+   LTC_ARGCHK(mac    != NULL);
+   LTC_ARGCHK(maclen != NULL);
+
+   if ((err = blake2smac_init(&st, *maclen, key, keylen))  != CRYPT_OK) { goto LBL_ERR; }
+   if ((err = blake2smac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
+   err = blake2smac_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+   zeromem(&st, sizeof(blake2smac_state));
+#endif
+   return err;
+}
+
+#endif

+ 58 - 0
src/mac/blake2/blake2smac_memory_multi.c

@@ -0,0 +1,58 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+#include <stdarg.h>
+
+#ifdef LTC_BLAKE2SMAC
+
+/**
+   BLAKE2S MAC multiple blocks of memory to produce the authentication tag
+   @param key       The secret key
+   @param keylen    The length of the secret key (octets)
+   @param out       [out] Destination of the authentication tag
+   @param outlen    [in/out] Max size and resulting size of authentication tag
+   @param in        The data to BLAKE2S MAC
+   @param inlen     The length of the data to BLAKE2S MAC (octets)
+   @param ...       tuples of (data,len) pairs to BLAKE2S MAC, terminated with a (NULL,x) (x=don't care)
+   @return CRYPT_OK if successful
+*/
+int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in,  unsigned long inlen, ...)
+{
+   blake2smac_state st;
+   int err;
+   va_list args;
+   const unsigned char *curptr;
+   unsigned long curlen;
+
+   LTC_ARGCHK(key    != NULL);
+   LTC_ARGCHK(in     != NULL);
+   LTC_ARGCHK(mac    != NULL);
+   LTC_ARGCHK(maclen != NULL);
+
+   va_start(args, inlen);
+   curptr = in;
+   curlen = inlen;
+   if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK)          { goto LBL_ERR; }
+   for (;;) {
+      if ((err = blake2smac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; }
+      curptr = va_arg(args, const unsigned char*);
+      if (curptr == NULL) break;
+      curlen = va_arg(args, unsigned long);
+   }
+   err = blake2smac_done(&st, mac, maclen);
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+   zeromem(&st, sizeof(blake2smac_state));
+#endif
+   va_end(args);
+   return err;
+}
+
+#endif

+ 44 - 0
src/mac/blake2/blake2smac_test.c

@@ -0,0 +1,44 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_BLAKE2SMAC
+
+int blake2smac_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   unsigned char k[]   = { 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b };
+   unsigned char tag[] = { 0x96, 0x32, 0xf9, 0x85, 0xf3, 0x30, 0xd6, 0x8c, 0x21, 0x78, 0x6e, 0xae, 0xb4, 0x99, 0xba, 0xbb };
+   char m[] = "Cryptographic Forum Research Group";
+   unsigned long len = 16, mlen = strlen(m);
+   unsigned char out[1000];
+   blake2smac_state st;
+   /* process piece by piece */
+   blake2smac_init(&st,16,  k, 32);
+   blake2smac_process(&st, (unsigned char*)m,      5);
+   blake2smac_process(&st, (unsigned char*)m + 5,  4);
+   blake2smac_process(&st, (unsigned char*)m + 9,  3);
+   blake2smac_process(&st, (unsigned char*)m + 12, 2);
+   blake2smac_process(&st, (unsigned char*)m + 14, 1);
+   blake2smac_process(&st, (unsigned char*)m + 15, mlen - 15);
+   blake2smac_done(&st, out, &len);
+   if (compare_testvector(out, len, tag, sizeof(tag), "BLAKE2S MAC-TV1", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+   /* process in one go */
+   blake2smac_init(&st, 16, k, 32);
+   blake2smac_process(&st, (unsigned char*)m, mlen);
+   blake2smac_done(&st, out, &len);
+   if (compare_testvector(out, len, tag, sizeof(tag), "BLAKE2S MAC-TV2", 1) != 0) return CRYPT_FAIL_TESTVECTOR;
+   return CRYPT_OK;
+#endif
+}
+
+#endif

+ 6 - 0
src/misc/crypt/crypt.c

@@ -242,6 +242,12 @@ const char *crypt_build_settings =
 #if defined(LTC_POLY1305)
 #if defined(LTC_POLY1305)
     "   POLY1305\n"
     "   POLY1305\n"
 #endif
 #endif
+#if defined(LTC_BLAKE2SMAC)
+    "   BLAKE2S MAC\n"
+#endif
+#if defined(LTC_BLAKE2BMAC)
+    "   BLAKE2B MAC\n"
+#endif
 
 
     "\nENC + AUTH modes:\n"
     "\nENC + AUTH modes:\n"
 #if defined(LTC_EAX_MODE)
 #if defined(LTC_EAX_MODE)

+ 6 - 0
testprof/mac_test.c

@@ -41,6 +41,12 @@ int mac_test(void)
 #endif
 #endif
 #ifdef LTC_CHACHA20POLY1305_MODE
 #ifdef LTC_CHACHA20POLY1305_MODE
    DO(chacha20poly1305_test());
    DO(chacha20poly1305_test());
+#endif
+#ifdef LTC_BLAKE2SMAC
+   DO(blake2smac_test());
+#endif
+#ifdef LTC_BLAKE2BMAC
+   DO(blake2bmac_test());
 #endif
 #endif
    return 0;
    return 0;
 }
 }