Branch data Line data Source code
1 : : /* Edwards curve signature system
2 : : * Daniel Beer <dlbeer@gmail.com>, 22 Apr 2014
3 : : *
4 : : * This file is in the public domain.
5 : : */
6 : :
7 : : #include "ed25519.h"
8 : :
9 : : #ifndef COMPACT_DISABLE_ED25519
10 : : #include "sha512.h"
11 : : #include "fprime.h"
12 : : #include "edsign.h"
13 : :
14 : : #define EXPANDED_SIZE 64
15 : :
16 : : static const uint8_t ed25519_order[FPRIME_SIZE] = {
17 : : 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
18 : : 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
19 : : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20 : : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
21 : : };
22 : :
23 : 2 : static void expand_key(uint8_t *expanded, const uint8_t *secret)
24 : : {
25 : 2 : struct sha512_state s;
26 : :
27 : 2 : sha512_init(&s);
28 : 2 : sha512_final(&s, secret, EDSIGN_SECRET_KEY_SIZE);
29 : 2 : sha512_get(&s, expanded, 0, EXPANDED_SIZE);
30 : 2 : ed25519_prepare(expanded);
31 : 2 : }
32 : :
33 : 4 : static uint8_t upp(struct ed25519_pt *p, const uint8_t *packed)
34 : : {
35 : 4 : uint8_t x[F25519_SIZE];
36 : 4 : uint8_t y[F25519_SIZE];
37 : 4 : uint8_t ok = ed25519_try_unpack(x, y, packed);
38 : :
39 : 4 : ed25519_project(p, x, y);
40 : 4 : return ok;
41 : : }
42 : :
43 : 6 : static void pp(uint8_t *packed, const struct ed25519_pt *p)
44 : : {
45 : 6 : uint8_t x[F25519_SIZE];
46 : 6 : uint8_t y[F25519_SIZE];
47 : :
48 : 6 : ed25519_unproject(x, y, p);
49 : 6 : ed25519_pack(packed, x, y);
50 : 6 : }
51 : :
52 : 4 : static void sm_pack(uint8_t *r, const uint8_t *k)
53 : : {
54 : 4 : struct ed25519_pt p;
55 : :
56 : 4 : ed25519_smult(&p, &ed25519_base, k);
57 : 4 : pp(r, &p);
58 : 4 : }
59 : :
60 : 0 : void edsign_sec_to_pub(uint8_t *pub, const uint8_t *secret)
61 : : {
62 : 0 : uint8_t expanded[EXPANDED_SIZE];
63 : :
64 : 0 : expand_key(expanded, secret);
65 : 0 : sm_pack(pub, expanded);
66 : 0 : }
67 : :
68 : 6 : static void hash_with_prefix(uint8_t *out_fp,
69 : : uint8_t *init_block, unsigned int prefix_size,
70 : : const uint8_t *message, size_t len)
71 : : {
72 : 6 : struct sha512_state s;
73 : :
74 : 6 : sha512_init(&s);
75 : :
76 [ - + - - ]: 6 : if (len < SHA512_BLOCK_SIZE && len + prefix_size < SHA512_BLOCK_SIZE) {
77 : 0 : memcpy(init_block + prefix_size, message, len);
78 : 0 : sha512_final(&s, init_block, len + prefix_size);
79 : : } else {
80 : 6 : size_t i;
81 : :
82 : 6 : memcpy(init_block + prefix_size, message,
83 : : SHA512_BLOCK_SIZE - prefix_size);
84 : 6 : sha512_block(&s, init_block);
85 : :
86 : 6 : for (i = SHA512_BLOCK_SIZE - prefix_size;
87 [ + + ]: 16 : i + SHA512_BLOCK_SIZE <= len;
88 : 10 : i += SHA512_BLOCK_SIZE)
89 : 10 : sha512_block(&s, message + i);
90 : :
91 : 6 : sha512_final(&s, message + i, len + prefix_size);
92 : : }
93 : :
94 : 6 : sha512_get(&s, init_block, 0, SHA512_HASH_SIZE);
95 : 6 : fprime_from_bytes(out_fp, init_block, SHA512_HASH_SIZE, ed25519_order);
96 : 6 : }
97 : :
98 : 2 : static void generate_k(uint8_t *k, const uint8_t *kgen_key,
99 : : const uint8_t *message, size_t len)
100 : : {
101 : 2 : uint8_t block[SHA512_BLOCK_SIZE];
102 : :
103 : 2 : memcpy(block, kgen_key, 32);
104 : 2 : hash_with_prefix(k, block, 32, message, len);
105 : 2 : }
106 : :
107 : 4 : static void hash_message(uint8_t *z, const uint8_t *r, const uint8_t *a,
108 : : const uint8_t *m, size_t len)
109 : : {
110 : 4 : uint8_t block[SHA512_BLOCK_SIZE];
111 : :
112 : 4 : memcpy(block, r, 32);
113 : 4 : memcpy(block + 32, a, 32);
114 : 4 : hash_with_prefix(z, block, 64, m, len);
115 : 4 : }
116 : :
117 : 2 : void edsign_sign(uint8_t *signature, const uint8_t *pub,
118 : : const uint8_t *secret,
119 : : const uint8_t *message, size_t len)
120 : : {
121 : 2 : uint8_t expanded[EXPANDED_SIZE];
122 : 2 : uint8_t e[FPRIME_SIZE];
123 : 2 : uint8_t s[FPRIME_SIZE];
124 : 2 : uint8_t k[FPRIME_SIZE];
125 : 2 : uint8_t z[FPRIME_SIZE];
126 : :
127 : 2 : expand_key(expanded, secret);
128 : :
129 : : /* Generate k and R = kB */
130 : 2 : generate_k(k, expanded + 32, message, len);
131 : 2 : sm_pack(signature, k);
132 : :
133 : : /* Compute z = H(R, A, M) */
134 : 2 : hash_message(z, signature, pub, message, len);
135 : :
136 : : /* Obtain e */
137 : 2 : fprime_from_bytes(e, expanded, 32, ed25519_order);
138 : :
139 : : /* Compute s = ze + k */
140 : 2 : fprime_mul(s, z, e, ed25519_order);
141 : 2 : fprime_add(s, k, ed25519_order);
142 : 2 : memcpy(signature + 32, s, 32);
143 : 2 : }
144 : :
145 : 2 : uint8_t edsign_verify(const uint8_t *signature, const uint8_t *pub,
146 : : const uint8_t *message, size_t len)
147 : : {
148 : 2 : struct ed25519_pt p;
149 : 2 : struct ed25519_pt q;
150 : 2 : uint8_t lhs[F25519_SIZE];
151 : 2 : uint8_t rhs[F25519_SIZE];
152 : 2 : uint8_t z[FPRIME_SIZE];
153 : 2 : uint8_t ok = 1;
154 : :
155 : : /* Compute z = H(R, A, M) */
156 : 2 : hash_message(z, signature, pub, message, len);
157 : :
158 : : /* sB = (ze + k)B = ... */
159 : 2 : sm_pack(lhs, signature + 32);
160 : :
161 : : /* ... = zA + R */
162 : 2 : ok &= upp(&p, pub);
163 : 2 : ed25519_smult(&p, &p, z);
164 : 2 : ok &= upp(&q, signature);
165 : 2 : ed25519_add(&p, &p, &q);
166 : 2 : pp(rhs, &p);
167 : :
168 : : /* Equal? */
169 : 2 : return ok & f25519_eq(lhs, rhs);
170 : : }
171 : : #endif
|