1 
2 #include <limits.h>
3 #include <stdint.h>
4 #include <string.h>
5 
6 #include "crypto_hash_sha512.h"
7 #include "crypto_sign_ed25519.h"
8 #include "crypto_verify_32.h"
9 #include "sign_ed25519_ref10.h"
10 #include "private/ed25519_ref10.h"
11 #include "utils.h"
12 
13 int
14 _crypto_sign_ed25519_verify_detached(const unsigned char *sig,
15                                      const unsigned char *m,
16                                      unsigned long long   mlen,
17                                      const unsigned char *pk,
18                                      int prehashed)
19 {
20     crypto_hash_sha512_state hs;
21     unsigned char            h[64];
22     unsigned char            rcheck[32];
23     ge25519_p3               A;
24     ge25519_p2               R;
25 
26 #ifdef ED25519_COMPAT
27     if (sig[63] & 224) {
28         return -1;
29     }
30 #else
31     if (sc25519_is_canonical(sig + 32) == 0 ||
32         ge25519_has_small_order(sig) != 0) {
33         return -1;
34     }
35     if (ge25519_is_canonical(pk) == 0 ||
36         ge25519_has_small_order(pk) != 0) {
37         return -1;
38     }
39 #endif
40     if (ge25519_frombytes_negate_vartime(&A, pk) != 0) {
41         return -1;
42     }
43     _crypto_sign_ed25519_ref10_hinit(&hs, prehashed);
44     crypto_hash_sha512_update(&hs, sig, 32);
45     crypto_hash_sha512_update(&hs, pk, 32);
46     crypto_hash_sha512_update(&hs, m, mlen);
47     crypto_hash_sha512_final(&hs, h);
48     sc25519_reduce(h);
49 
50     ge25519_double_scalarmult_vartime(&R, h, &A, sig + 32);
51     ge25519_tobytes(rcheck, &R);
52 
53     return crypto_verify_32(rcheck, sig) | (-(rcheck == sig)) |
54            sodium_memcmp(sig, rcheck, 32);
55 }
56 
57 int
58 crypto_sign_ed25519_verify_detached(const unsigned char *sig,
59                                     const unsigned char *m,
60                                     unsigned long long   mlen,
61                                     const unsigned char *pk)
62 {
63     return _crypto_sign_ed25519_verify_detached(sig, m, mlen, pk, 0);
64 }
65 
66 int
67 crypto_sign_ed25519_open(unsigned char *m, unsigned long long *mlen_p,
68                          const unsigned char *sm, unsigned long long smlen,
69                          const unsigned char *pk)
70 {
71     unsigned long long mlen;
72 
73     if (smlen < 64 || smlen - 64 > crypto_sign_ed25519_MESSAGEBYTES_MAX) {
74         goto badsig;
75     }
76     mlen = smlen - 64;
77     if (crypto_sign_ed25519_verify_detached(sm, sm + 64, mlen, pk) != 0) {
78         memset(m, 0, mlen);
79         goto badsig;
80     }
81     if (mlen_p != NULL) {
82         *mlen_p = mlen;
83     }
84     memmove(m, sm + 64, mlen);
85 
86     return 0;
87 
88 badsig:
89     if (mlen_p != NULL) {
90         *mlen_p = 0;
91     }
92     return -1;
93 }
94