From 1ca3dce7e74c72a323bed8d05c9379d110fa7d49 Mon Sep 17 00:00:00 2001 From: Loup Vaillant Date: Sun, 1 Dec 2019 22:36:00 +0100 Subject: [PATCH] Added HMAC SHA512 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 | 47 ++++++++++++++++++++++++++++++++++++++++++ src/optional/ed25519.h | 19 ++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/optional/ed25519.c b/src/optional/ed25519.c index 1313cf7..6818e8c 100644 --- a/src/optional/ed25519.c +++ b/src/optional/ed25519.c @@ -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 /// /////////////// diff --git a/src/optional/ed25519.h b/src/optional/ed25519.h index e22c86b..c5e4f72 100644 --- a/src/optional/ed25519.h +++ b/src/optional/ed25519.h @@ -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 // ------- -- 2.47.3