]> git.codecow.com Git - Monocypher.git/commitdiff
Added HMAC SHA512
authorLoup Vaillant <loup@loup-vaillant.fr>
Sun, 1 Dec 2019 21:36:00 +0000 (22:36 +0100)
committerLoup Vaillant <loup@loup-vaillant.fr>
Sun, 1 Dec 2019 21:36:00 +0000 (22:36 +0100)
EXPERIMENTAL. MAY BE REMOVED.

Monocypher is supposed to be small.  This is why we use Blake2b for both
Argon2 and EdDSA signatures.  Some users however need Ed25519 for
compatibility with other tools.  This means using SHA 512.

We could hide SHA 512 from the public interface entirely, but this seems
like a waste: it could replace Blake2b to make the library smaller. It
will come at a performance loss, but when you verify signatures on a
small device, the hash is rarely the bottleneck.

The main problem with SHA 512 is length extension attacks.  It just
cannot be used as a prefix MAC like Blake2b can.  We need HMAC if we
want SHA 512 to entirely displace Blake2b, so the Monocypher binary
stays small.

Users could use Poly1305 and our version of RFC 8439 of course, but if
they're so tight on space, they're likely to get rid of Poly1305 as
well.  When we have SHA 512 already, HMAC requires much less code.

This is kind of a special corner case. But it could come in handy.

TODO: the tests.

src/optional/ed25519.c
src/optional/ed25519.h

index 1313cf779f2a71776382d35f4789a203de61b560..6818e8c5ecee2189cde3cf7203f1fec46345fe05 100644 (file)
@@ -228,6 +228,53 @@ const crypto_sign_vtable crypto_sha512_vtable = {
     sizeof(crypto_sign_ed25519_ctx),
 };
 
+////////////////////
+/// HMAC SHA 512 ///
+////////////////////
+void crypto_hmac_init(crypto_hmac_ctx *ctx, const u8 *key, size_t key_size)
+{
+    if (key_size <= 64) {
+        FOR (i, 0, key_size)  { ctx->key[i] = key[i]; }
+        FOR (i, key_size, 64) { ctx->key[i] = 0;      }
+    } else {
+        crypto_sha512(ctx->key, key, key_size);
+    }
+    FOR (i, 0, 64) {
+        ctx->key[i] ^= 0x36;
+    }
+    crypto_sha512_init  (&ctx->ctx);
+    crypto_sha512_update(&ctx->ctx, ctx->key, 64);
+}
+
+void crypto_hmac_update(crypto_hmac_ctx *ctx,
+                        const u8 *message, size_t  message_size)
+{
+    crypto_sha512_update(&ctx->ctx, message, message_size);
+}
+
+void crypto_hmac_final(crypto_hmac_ctx *ctx, u8 hmac[64])
+{
+    crypto_sha512_final(&ctx->ctx, hmac);
+    FOR (i, 0, 64) {
+        ctx->key[i] ^= 0x36 ^ 0x5c;
+    }
+    crypto_sha512_init  (&ctx->ctx);
+    crypto_sha512_update(&ctx->ctx, ctx->key , 64);
+    crypto_sha512_update(&ctx->ctx, hmac, 64);
+    crypto_sha512_final (&ctx->ctx, hmac);
+    WIPE_CTX(ctx);
+}
+
+void crypto_hmac(u8 *hmac, const u8 *key, size_t key_size,
+                 const u8 *message, size_t message_size)
+{
+    crypto_hmac_ctx ctx;
+    crypto_hmac_init  (&ctx, key, key_size);
+    crypto_hmac_update(&ctx, message, message_size);
+    crypto_hmac_final (&ctx, hmac);
+}
+
+
 ///////////////
 /// Ed25519 ///
 ///////////////
index e22c86b1fc931eeb14543fa9acead4346560181c..c5e4f726fc4499b9ba15769b516d826bb822331a 100644 (file)
@@ -19,6 +19,11 @@ typedef struct {
     size_t   input_idx;
 } crypto_sha512_ctx;
 
+typedef struct {
+    uint8_t key[64];
+    crypto_sha512_ctx ctx;
+} crypto_hmac_ctx;
+
 typedef struct {
     crypto_sign_ctx_abstract ctx;
     crypto_sha512_ctx        hash;
@@ -31,12 +36,24 @@ void crypto_sha512_init  (crypto_sha512_ctx *ctx);
 void crypto_sha512_update(crypto_sha512_ctx *ctx,
                           const uint8_t *message, size_t  message_size);
 void crypto_sha512_final (crypto_sha512_ctx *ctx, uint8_t hash[64]);
-void crypto_sha512(uint8_t *out,const uint8_t *message, size_t message_size);
+void crypto_sha512(uint8_t *hash, const uint8_t *message, size_t message_size);
 
 // vtable for signatures
 extern const crypto_sign_vtable crypto_sha512_vtable;
 
 
+// HMAC SHA 512
+// ------------
+void crypto_hmac_init(crypto_hmac_ctx *ctx,
+                      const uint8_t *key, size_t key_size);
+void crypto_hmac_update(crypto_hmac_ctx *ctx,
+                        const uint8_t *message, size_t  message_size);
+void crypto_hmac_final(crypto_hmac_ctx *ctx, uint8_t hmac[64]);
+void crypto_hmac(uint8_t *hmac,
+                 const uint8_t *key    , size_t key_size,
+                 const uint8_t *message, size_t message_size);
+
+
 // Ed25519
 // -------