1 
2 #include <limits.h>
3 #include <stdint.h>
4 #include <string.h>
5 
6 #include "crypto_hash_sha512.h"
7 #include "crypto_sign_edwards25519sha512batch.h"
8 #include "crypto_verify_32.h"
9 #include "private/ed25519_ref10.h"
10 #include "randombytes.h"
11 #include "utils.h"
12 
13 int
14 crypto_sign_edwards25519sha512batch_keypair(unsigned char *pk,
15                                             unsigned char *sk)
16 {
17     ge25519_p3 A;
18 
19     randombytes_buf(sk, 32);
20     crypto_hash_sha512(sk, sk, 32);
21     sk[0] &= 248;
22     sk[31] &= 127;
23     sk[31] |= 64;
24     ge25519_scalarmult_base(&A, sk);
25     ge25519_p3_tobytes(pk, &A);
26 
27     return 0;
28 }
29 
30 int
31 crypto_sign_edwards25519sha512batch(unsigned char       *sm,
32                                     unsigned long long  *smlen_p,
33                                     const unsigned char *m,
34                                     unsigned long long   mlen,
35                                     const unsigned char *sk)
36 {
37     crypto_hash_sha512_state hs;
38     unsigned char            nonce[64];
39     unsigned char            hram[64];
40     unsigned char            sig[64];
41     ge25519_p3               A;
42     ge25519_p3               R;
43 
44     crypto_hash_sha512_init(&hs);
45     crypto_hash_sha512_update(&hs, sk + 32, 32);
46     crypto_hash_sha512_update(&hs, m, mlen);
47     crypto_hash_sha512_final(&hs, nonce);
48     ge25519_scalarmult_base(&A, sk);
49     ge25519_p3_tobytes(sig + 32, &A);
50     sc25519_reduce(nonce);
51     ge25519_scalarmult_base(&R, nonce);
52     ge25519_p3_tobytes(sig, &R);
53     crypto_hash_sha512_init(&hs);
54     crypto_hash_sha512_update(&hs, sig, 32);
55     crypto_hash_sha512_update(&hs, m, mlen);
56     crypto_hash_sha512_final(&hs, hram);
57     sc25519_reduce(hram);
58     sc25519_muladd(sig + 32, hram, nonce, sk);
59     sodium_memzero(hram, sizeof hram);
60     memmove(sm + 32, m, (size_t) mlen);
61     memcpy(sm, sig, 32);
62     memcpy(sm + 32 + mlen, sig + 32, 32);
63     *smlen_p = mlen + 64U;
64 
65     return 0;
66 }
67 
68 int
69 crypto_sign_edwards25519sha512batch_open(unsigned char       *m,
70                                          unsigned long long  *mlen_p,
71                                          const unsigned char *sm,
72                                          unsigned long long   smlen,
73                                          const unsigned char *pk)
74 {
75     unsigned char      h[64];
76     unsigned char      t1[32], t2[32];
77     unsigned long long mlen;
78     ge25519_cached     Ai;
79     ge25519_p1p1       csa;
80     ge25519_p2         cs;
81     ge25519_p3         A;
82     ge25519_p3         R;
83     ge25519_p3         cs3;
84 
85     *mlen_p = 0;
86     if (smlen < 64 || smlen - 64 > crypto_sign_edwards25519sha512batch_MESSAGEBYTES_MAX) {
87         return -1;
88     }
89     mlen = smlen - 64;
90     if (sm[smlen - 1] & 224) {
91         return -1;
92     }
93     if (ge25519_has_small_order(pk) != 0 ||
94         ge25519_frombytes_negate_vartime(&A, pk) != 0 ||
95         ge25519_has_small_order(sm) != 0 ||
96         ge25519_frombytes_negate_vartime(&R, sm) != 0) {
97         return -1;
98     }
99     ge25519_p3_to_cached(&Ai, &A);
100     crypto_hash_sha512(h, sm, mlen + 32);
101     sc25519_reduce(h);
102     ge25519_scalarmult(&cs3, h, &R);
103     ge25519_add(&csa, &cs3, &Ai);
104     ge25519_p1p1_to_p2(&cs, &csa);
105     ge25519_tobytes(t1, &cs);
106     t1[31] ^= 1 << 7;
107     ge25519_scalarmult_base(&R, sm + 32 + mlen);
108     ge25519_p3_tobytes(t2, &R);
109     if (crypto_verify_32(t1, t2) != 0) {
110         return -1;
111     }
112     *mlen_p = mlen;
113     memmove(m, sm + 32, mlen);
114 
115     return 0;
116 }
117