From 593166287167f179cb164873a0d94e541241cc00 Mon Sep 17 00:00:00 2001 From: Ricky Cormier Date: Mon, 24 Aug 2015 17:55:47 +0100 Subject: [PATCH] Add support for large messages Rather than having to verify a whole memory buffer in one go, allow chunks of memory to be processed using begin, update and end verify functions. The begin function starts a new verify process, returning an opaque context handle. The update function can then be called multiple times with this context and blocks of memory to process memory in chuncks. Finally the end function is called with the context to end the verify process and get the result. --- src/ed25519.h | 4 ++++ src/verify.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/ed25519.h b/src/ed25519.h index 8924659..ec27282 100644 --- a/src/ed25519.h +++ b/src/ed25519.h @@ -30,6 +30,10 @@ int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsign void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); +void * ED25519_DECLSPEC ed25519_verify_begin(const unsigned char *signature, const unsigned char *public_key); +void ED25519_DECLSPEC ed25519_verify_update(void * hash, const unsigned char *message, size_t message_len); +int ED25519_DECLSPEC ed25519_verify_end(void * hash, const unsigned char *signature); + #ifdef __cplusplus } diff --git a/src/verify.c b/src/verify.c index 32f988e..d1b1ad8 100644 --- a/src/verify.c +++ b/src/verify.c @@ -1,3 +1,6 @@ +#include +#include + #include "ed25519.h" #include "sha512.h" #include "ge.h" @@ -64,7 +67,7 @@ int ed25519_verify(const unsigned char *signature, const unsigned char *message, sha512_update(&hash, public_key, 32); sha512_update(&hash, message, message_len); sha512_final(&hash, h); - + sc_reduce(h); ge_double_scalarmult_vartime(&R, h, &A, signature + 32); ge_tobytes(checker, &R); @@ -75,3 +78,55 @@ int ed25519_verify(const unsigned char *signature, const unsigned char *message, return 1; } + +typedef struct context_ +{ + sha512_context hash; + ge_p3 A; +} context; + +void * ed25519_verify_begin(const unsigned char *signature, const unsigned char *public_key) { + ge_p3 A; + + if (signature[63] & 224) { + return NULL; + } + + if (ge_frombytes_negate_vartime(&A, public_key) != 0) { + return NULL; + } + + context * ctx = (context*) malloc(sizeof(context)); + + memcpy(&ctx->A, &A, sizeof(A)); + + sha512_init(&ctx->hash); + sha512_update(&ctx->hash, signature, 32); + sha512_update(&ctx->hash, public_key, 32); + + return ctx; +} + +void ed25519_verify_update(void * ctx, const unsigned char *message, size_t message_len) { + sha512_update(&((context*)ctx)->hash, message, message_len); +} + +int ed25519_verify_end(void * ctx, const unsigned char *signature) { + unsigned char h[64]; + unsigned char checker[32]; + ge_p2 R; + + sha512_final(&((context*)ctx)->hash, h); + + sc_reduce(h); + ge_double_scalarmult_vartime(&R, h, &((context*)ctx)->A, signature + 32); + ge_tobytes(checker, &R); + + free(ctx); + + if (!consttime_equal(checker, signature)) { + return 0; + } + + return 1; +}