diff options
Diffstat (limited to 'libs/libsodium/src/crypto_sign/ed25519/ref10/open.c')
-rw-r--r-- | libs/libsodium/src/crypto_sign/ed25519/ref10/open.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/libs/libsodium/src/crypto_sign/ed25519/ref10/open.c b/libs/libsodium/src/crypto_sign/ed25519/ref10/open.c new file mode 100644 index 0000000000..c9e8843c1e --- /dev/null +++ b/libs/libsodium/src/crypto_sign/ed25519/ref10/open.c @@ -0,0 +1,93 @@ + +#include <limits.h> +#include <stdint.h> +#include <string.h> + +#include "crypto_hash_sha512.h" +#include "crypto_sign_ed25519.h" +#include "crypto_verify_32.h" +#include "sign_ed25519_ref10.h" +#include "private/ed25519_ref10.h" +#include "utils.h" + +int +_crypto_sign_ed25519_verify_detached(const unsigned char *sig, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *pk, + int prehashed) +{ + crypto_hash_sha512_state hs; + unsigned char h[64]; + unsigned char rcheck[32]; + ge25519_p3 A; + ge25519_p2 R; + +#ifndef ED25519_COMPAT + if (sc25519_is_canonical(sig + 32) == 0 || + ge25519_has_small_order(sig) != 0) { + return -1; + } + if (ge25519_is_canonical(pk) == 0) { + return -1; + } +#else + if (sig[63] & 224) { + return -1; + } +#endif + if (ge25519_has_small_order(pk) != 0 || + ge25519_frombytes_negate_vartime(&A, pk) != 0) { + return -1; + } + _crypto_sign_ed25519_ref10_hinit(&hs, prehashed); + crypto_hash_sha512_update(&hs, sig, 32); + crypto_hash_sha512_update(&hs, pk, 32); + crypto_hash_sha512_update(&hs, m, mlen); + crypto_hash_sha512_final(&hs, h); + sc25519_reduce(h); + + ge25519_double_scalarmult_vartime(&R, h, &A, sig + 32); + ge25519_tobytes(rcheck, &R); + + return crypto_verify_32(rcheck, sig) | (-(rcheck == sig)) | + sodium_memcmp(sig, rcheck, 32); +} + +int +crypto_sign_ed25519_verify_detached(const unsigned char *sig, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *pk) +{ + return _crypto_sign_ed25519_verify_detached(sig, m, mlen, pk, 0); +} + +int +crypto_sign_ed25519_open(unsigned char *m, unsigned long long *mlen_p, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk) +{ + unsigned long long mlen; + + if (smlen < 64 || smlen - 64 > crypto_sign_ed25519_MESSAGEBYTES_MAX) { + goto badsig; + } + mlen = smlen - 64; + if (crypto_sign_ed25519_verify_detached(sm, sm + 64, mlen, pk) != 0) { + memset(m, 0, mlen); + goto badsig; + } + if (mlen_p != NULL) { + *mlen_p = mlen; + } + memmove(m, sm + 64, mlen); + + return 0; + +badsig: + if (mlen_p != NULL) { + *mlen_p = 0; + } + return -1; +} |