From 58a57f4fb312fd2dc0eacb65604b0f4ebb2aa676 Mon Sep 17 00:00:00 2001 From: Loup Vaillant Date: Mon, 9 Oct 2017 00:14:36 +0200 Subject: [PATCH] Streaming interface for crypto_check() --- src/monocypher.c | 52 +++++++++++++++++++++++++++++++++++++++--------- src/monocypher.h | 28 ++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/monocypher.c b/src/monocypher.c index cafaee6..3fa4326 100644 --- a/src/monocypher.c +++ b/src/monocypher.c @@ -1277,7 +1277,7 @@ void crypto_x25519_public_key(u8 public_key[32], // Point in a twisted Edwards curve, // in extended projective coordinates. // x = X/Z, y = Y/Z, T = XY/Z -typedef struct { fe X; fe Y; fe Z; fe T; } ge; +// typedef struct { fe X; fe Y; fe Z; fe T; } ge; static void ge_from_xy(ge *p, const fe x, const fe y) { @@ -1555,23 +1555,57 @@ void crypto_sign(u8 signature[64], modL(signature + 32, s); // second half of the signature = s } -int crypto_check(const u8 signature[64], - const u8 public_key[32], - const u8 *message, size_t message_size) +int crypto_check_init(crypto_check_ctx *ctx, + const u8 signature[64], + const u8 public_key[32]) { - ge A, p, sB, diff; - u8 h_ram[64], R_check[32]; - if (ge_frombytes_neg(&A, public_key)) { // -A + HASH_INIT(&(ctx->hash_ctx)); // some users won't check the return code... + ctx->invalid_pk = 0; + if (ge_frombytes_neg(&(ctx->A), public_key)) { + ctx->invalid_pk = -1; return -1; } - hash_ram(h_ram, signature, public_key, message, message_size); - ge_scalarmult(&p, &A, h_ram); // p = -A*h_ram + HASH_UPDATE(&(ctx->hash_ctx), signature , 32); + HASH_UPDATE(&(ctx->hash_ctx), public_key, 32); + return 0; +} + +void crypto_check_update(crypto_check_ctx *ctx, const u8 *msg, size_t msg_size) +{ + // ... so we'd better init the context before it blows up in their + // face. Now the worst they can do is lose time. + HASH_UPDATE(&(ctx->hash_ctx), msg , msg_size); +} + +int crypto_check_final(crypto_check_ctx *ctx, const u8 signature[64]) +{ + // protect whoever doesn't check the crypto_check_init() return code + if (ctx->invalid_pk != 0) { + return -1; + } + ge p, sB, diff; + u8 h_ram[64], R_check[32]; + HASH_FINAL(&(ctx->hash_ctx), h_ram); + reduce(h_ram); + ge_scalarmult(&p, &(ctx->A), h_ram); // p = -A*h_ram ge_scalarmult_base(&sB, signature + 32); ge_add(&diff, &p, &sB); // diff = s - A*h_ram ge_tobytes(R_check, &diff); return crypto_memcmp(signature, R_check, 32); // R == s - A*h_ram ? OK : fail } +int crypto_check(const u8 signature[64], + const u8 public_key[32], + const u8 *message, size_t message_size) +{ + crypto_check_ctx ctx; + if (crypto_check_init(&ctx, signature, public_key)) { + return -1; + } + crypto_check_update(&ctx, message, message_size); + return crypto_check_final(&ctx, signature); +} + //////////////////// /// Key exchange /// //////////////////// diff --git a/src/monocypher.h b/src/monocypher.h index 9bcce73..df0093f 100644 --- a/src/monocypher.h +++ b/src/monocypher.h @@ -135,6 +135,34 @@ void crypto_sign(uint8_t signature [64], const uint8_t public_key[32], // optional, may be 0 const uint8_t *message, size_t message_size); +#define COMBINE1(x, y) x ## y +#define COMBINE2(x, y) COMBINE1(x, y) +#define HASH_CTX COMBINE2(HASH, _ctx) +#define HASH_INIT COMBINE2(HASH, _init) +#define HASH_UPDATE COMBINE2(HASH, _update) +#define HASH_FINAL COMBINE2(HASH, _final) + +typedef struct { int32_t X[10]; int32_t Y[10]; int32_t Z[10]; int32_t T[10]; +} ge; +typedef struct { +#ifdef ED25519_SHA512 + crypto_sha512_ctx hash_ctx; +#else + crypto_blake2b_ctx hash_ctx; +#endif + ge A; + int invalid_pk; +} crypto_check_ctx; + +int crypto_check_init(crypto_check_ctx *ctx, + const uint8_t signature[64], + const uint8_t public_key[32]); + +void crypto_check_update(crypto_check_ctx *ctx, + const uint8_t *message, size_t message_size); + +int crypto_check_final(crypto_check_ctx *ctx, const uint8_t signature[64]); + int crypto_check(const uint8_t signature [64], const uint8_t public_key[32], const uint8_t *message, size_t message_size); -- 2.47.3