]>
Commit | Line | Data |
---|---|---|
07aa4c70 DA |
1 | /*********************************************************************** |
2 | * Copyright (c) 2020 Jonas Nick * | |
3 | * Distributed under the MIT software license, see the accompanying * | |
4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* | |
5 | ***********************************************************************/ | |
47e6618e | 6 | |
fb390c52 RC |
7 | #ifndef SECP256K1_MODULE_EXTRAKEYS_MAIN_H |
8 | #define SECP256K1_MODULE_EXTRAKEYS_MAIN_H | |
47e6618e JN |
9 | |
10 | #include "include/secp256k1.h" | |
11 | #include "include/secp256k1_extrakeys.h" | |
12 | ||
4cd2ee47 JN |
13 | static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) { |
14 | return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey); | |
15 | } | |
16 | ||
17 | static SECP256K1_INLINE void secp256k1_xonly_pubkey_save(secp256k1_xonly_pubkey *pubkey, secp256k1_ge *ge) { | |
18 | secp256k1_pubkey_save((secp256k1_pubkey *) pubkey, ge); | |
19 | } | |
20 | ||
21 | int secp256k1_xonly_pubkey_parse(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, const unsigned char *input32) { | |
22 | secp256k1_ge pk; | |
23 | secp256k1_fe x; | |
24 | ||
25 | VERIFY_CHECK(ctx != NULL); | |
26 | ARG_CHECK(pubkey != NULL); | |
27 | memset(pubkey, 0, sizeof(*pubkey)); | |
28 | ARG_CHECK(input32 != NULL); | |
29 | ||
30 | if (!secp256k1_fe_set_b32(&x, input32)) { | |
31 | return 0; | |
32 | } | |
33 | if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) { | |
34 | return 0; | |
08d7d892 PW |
35 | } |
36 | if (!secp256k1_ge_is_in_correct_subgroup(&pk)) { | |
37 | return 0; | |
4cd2ee47 JN |
38 | } |
39 | secp256k1_xonly_pubkey_save(pubkey, &pk); | |
40 | return 1; | |
41 | } | |
42 | ||
43 | int secp256k1_xonly_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output32, const secp256k1_xonly_pubkey *pubkey) { | |
44 | secp256k1_ge pk; | |
45 | ||
46 | VERIFY_CHECK(ctx != NULL); | |
47 | ARG_CHECK(output32 != NULL); | |
48 | memset(output32, 0, 32); | |
49 | ARG_CHECK(pubkey != NULL); | |
50 | ||
51 | if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) { | |
52 | return 0; | |
53 | } | |
54 | secp256k1_fe_get_b32(output32, &pk.x); | |
55 | return 1; | |
56 | } | |
57 | ||
6eceec6d AP |
58 | int secp256k1_xonly_pubkey_cmp(const secp256k1_context* ctx, const secp256k1_xonly_pubkey* pk0, const secp256k1_xonly_pubkey* pk1) { |
59 | unsigned char out[2][32]; | |
60 | const secp256k1_xonly_pubkey* pk[2]; | |
61 | int i; | |
62 | ||
63 | VERIFY_CHECK(ctx != NULL); | |
64 | pk[0] = pk0; pk[1] = pk1; | |
65 | for (i = 0; i < 2; i++) { | |
66 | /* If the public key is NULL or invalid, xonly_pubkey_serialize will | |
67 | * call the illegal_callback and return 0. In that case we will | |
68 | * serialize the key as all zeros which is less than any valid public | |
69 | * key. This results in consistent comparisons even if NULL or invalid | |
70 | * pubkeys are involved and prevents edge cases such as sorting | |
71 | * algorithms that use this function and do not terminate as a | |
72 | * result. */ | |
73 | if (!secp256k1_xonly_pubkey_serialize(ctx, out[i], pk[i])) { | |
74 | /* Note that xonly_pubkey_serialize should already set the output to | |
75 | * zero in that case, but it's not guaranteed by the API, we can't | |
76 | * test it and writing a VERIFY_CHECK is more complex than | |
77 | * explicitly memsetting (again). */ | |
78 | memset(out[i], 0, sizeof(out[i])); | |
79 | } | |
80 | } | |
81 | return secp256k1_memcmp_var(out[0], out[1], sizeof(out[1])); | |
82 | } | |
83 | ||
4cd2ee47 JN |
84 | /** Keeps a group element as is if it has an even Y and otherwise negates it. |
85 | * y_parity is set to 0 in the former case and to 1 in the latter case. | |
86 | * Requires that the coordinates of r are normalized. */ | |
87 | static int secp256k1_extrakeys_ge_even_y(secp256k1_ge *r) { | |
88 | int y_parity = 0; | |
89 | VERIFY_CHECK(!secp256k1_ge_is_infinity(r)); | |
90 | ||
91 | if (secp256k1_fe_is_odd(&r->y)) { | |
92 | secp256k1_fe_negate(&r->y, &r->y, 1); | |
93 | y_parity = 1; | |
94 | } | |
95 | return y_parity; | |
96 | } | |
97 | ||
98 | int secp256k1_xonly_pubkey_from_pubkey(const secp256k1_context* ctx, secp256k1_xonly_pubkey *xonly_pubkey, int *pk_parity, const secp256k1_pubkey *pubkey) { | |
99 | secp256k1_ge pk; | |
100 | int tmp; | |
101 | ||
102 | VERIFY_CHECK(ctx != NULL); | |
103 | ARG_CHECK(xonly_pubkey != NULL); | |
104 | ARG_CHECK(pubkey != NULL); | |
105 | ||
106 | if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) { | |
107 | return 0; | |
108 | } | |
109 | tmp = secp256k1_extrakeys_ge_even_y(&pk); | |
110 | if (pk_parity != NULL) { | |
111 | *pk_parity = tmp; | |
112 | } | |
113 | secp256k1_xonly_pubkey_save(xonly_pubkey, &pk); | |
114 | return 1; | |
115 | } | |
116 | ||
910d9c28 JN |
117 | int secp256k1_xonly_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { |
118 | secp256k1_ge pk; | |
119 | ||
120 | VERIFY_CHECK(ctx != NULL); | |
121 | ARG_CHECK(output_pubkey != NULL); | |
122 | memset(output_pubkey, 0, sizeof(*output_pubkey)); | |
123 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | |
124 | ARG_CHECK(internal_pubkey != NULL); | |
125 | ARG_CHECK(tweak32 != NULL); | |
126 | ||
127 | if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) | |
128 | || !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) { | |
129 | return 0; | |
130 | } | |
131 | secp256k1_pubkey_save(output_pubkey, &pk); | |
132 | return 1; | |
133 | } | |
134 | ||
135 | int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { | |
136 | secp256k1_ge pk; | |
137 | unsigned char pk_expected32[32]; | |
138 | ||
139 | VERIFY_CHECK(ctx != NULL); | |
140 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | |
141 | ARG_CHECK(internal_pubkey != NULL); | |
142 | ARG_CHECK(tweaked_pubkey32 != NULL); | |
143 | ARG_CHECK(tweak32 != NULL); | |
144 | ||
145 | if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) | |
146 | || !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) { | |
147 | return 0; | |
148 | } | |
149 | secp256k1_fe_normalize_var(&pk.x); | |
150 | secp256k1_fe_normalize_var(&pk.y); | |
151 | secp256k1_fe_get_b32(pk_expected32, &pk.x); | |
152 | ||
6173839c | 153 | return secp256k1_memcmp_var(&pk_expected32, tweaked_pubkey32, 32) == 0 |
910d9c28 JN |
154 | && secp256k1_fe_is_odd(&pk.y) == tweaked_pk_parity; |
155 | } | |
156 | ||
58254463 JN |
157 | static void secp256k1_keypair_save(secp256k1_keypair *keypair, const secp256k1_scalar *sk, secp256k1_ge *pk) { |
158 | secp256k1_scalar_get_b32(&keypair->data[0], sk); | |
159 | secp256k1_pubkey_save((secp256k1_pubkey *)&keypair->data[32], pk); | |
160 | } | |
161 | ||
162 | ||
163 | static int secp256k1_keypair_seckey_load(const secp256k1_context* ctx, secp256k1_scalar *sk, const secp256k1_keypair *keypair) { | |
164 | int ret; | |
165 | ||
166 | ret = secp256k1_scalar_set_b32_seckey(sk, &keypair->data[0]); | |
167 | /* We can declassify ret here because sk is only zero if a keypair function | |
168 | * failed (which zeroes the keypair) and its return value is ignored. */ | |
169 | secp256k1_declassify(ctx, &ret, sizeof(ret)); | |
170 | ARG_CHECK(ret); | |
171 | return ret; | |
172 | } | |
173 | ||
174 | /* Load a keypair into pk and sk (if non-NULL). This function declassifies pk | |
175 | * and ARG_CHECKs that the keypair is not invalid. It always initializes sk and | |
176 | * pk with dummy values. */ | |
177 | static int secp256k1_keypair_load(const secp256k1_context* ctx, secp256k1_scalar *sk, secp256k1_ge *pk, const secp256k1_keypair *keypair) { | |
178 | int ret; | |
179 | const secp256k1_pubkey *pubkey = (const secp256k1_pubkey *)&keypair->data[32]; | |
180 | ||
181 | /* Need to declassify the pubkey because pubkey_load ARG_CHECKs if it's | |
182 | * invalid. */ | |
183 | secp256k1_declassify(ctx, pubkey, sizeof(*pubkey)); | |
184 | ret = secp256k1_pubkey_load(ctx, pk, pubkey); | |
185 | if (sk != NULL) { | |
186 | ret = ret && secp256k1_keypair_seckey_load(ctx, sk, keypair); | |
187 | } | |
188 | if (!ret) { | |
189 | *pk = secp256k1_ge_const_g; | |
190 | if (sk != NULL) { | |
191 | *sk = secp256k1_scalar_one; | |
192 | } | |
193 | } | |
194 | return ret; | |
195 | } | |
196 | ||
197 | int secp256k1_keypair_create(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *seckey32) { | |
198 | secp256k1_scalar sk; | |
199 | secp256k1_ge pk; | |
200 | int ret = 0; | |
201 | VERIFY_CHECK(ctx != NULL); | |
202 | ARG_CHECK(keypair != NULL); | |
203 | memset(keypair, 0, sizeof(*keypair)); | |
204 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | |
205 | ARG_CHECK(seckey32 != NULL); | |
206 | ||
207 | ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &sk, &pk, seckey32); | |
208 | secp256k1_keypair_save(keypair, &sk, &pk); | |
e89278f2 | 209 | secp256k1_memczero(keypair, sizeof(*keypair), !ret); |
58254463 JN |
210 | |
211 | secp256k1_scalar_clear(&sk); | |
212 | return ret; | |
213 | } | |
214 | ||
fc96aa73 ET |
215 | int secp256k1_keypair_sec(const secp256k1_context* ctx, unsigned char *seckey, const secp256k1_keypair *keypair) { |
216 | VERIFY_CHECK(ctx != NULL); | |
217 | ARG_CHECK(seckey != NULL); | |
218 | memset(seckey, 0, 32); | |
219 | ARG_CHECK(keypair != NULL); | |
220 | ||
221 | memcpy(seckey, &keypair->data[0], 32); | |
222 | return 1; | |
223 | } | |
224 | ||
58254463 JN |
225 | int secp256k1_keypair_pub(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_keypair *keypair) { |
226 | VERIFY_CHECK(ctx != NULL); | |
227 | ARG_CHECK(pubkey != NULL); | |
228 | memset(pubkey, 0, sizeof(*pubkey)); | |
229 | ARG_CHECK(keypair != NULL); | |
230 | ||
231 | memcpy(pubkey->data, &keypair->data[32], sizeof(*pubkey)); | |
232 | return 1; | |
233 | } | |
234 | ||
235 | int secp256k1_keypair_xonly_pub(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, const secp256k1_keypair *keypair) { | |
236 | secp256k1_ge pk; | |
237 | int tmp; | |
238 | ||
239 | VERIFY_CHECK(ctx != NULL); | |
240 | ARG_CHECK(pubkey != NULL); | |
241 | memset(pubkey, 0, sizeof(*pubkey)); | |
242 | ARG_CHECK(keypair != NULL); | |
243 | ||
244 | if (!secp256k1_keypair_load(ctx, NULL, &pk, keypair)) { | |
245 | return 0; | |
246 | } | |
247 | tmp = secp256k1_extrakeys_ge_even_y(&pk); | |
248 | if (pk_parity != NULL) { | |
249 | *pk_parity = tmp; | |
250 | } | |
251 | secp256k1_xonly_pubkey_save(pubkey, &pk); | |
252 | ||
253 | return 1; | |
254 | } | |
255 | ||
6fcb5b84 JN |
256 | int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *tweak32) { |
257 | secp256k1_ge pk; | |
258 | secp256k1_scalar sk; | |
259 | int y_parity; | |
260 | int ret; | |
261 | ||
262 | VERIFY_CHECK(ctx != NULL); | |
263 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | |
264 | ARG_CHECK(keypair != NULL); | |
265 | ARG_CHECK(tweak32 != NULL); | |
266 | ||
267 | ret = secp256k1_keypair_load(ctx, &sk, &pk, keypair); | |
268 | memset(keypair, 0, sizeof(*keypair)); | |
269 | ||
270 | y_parity = secp256k1_extrakeys_ge_even_y(&pk); | |
271 | if (y_parity == 1) { | |
272 | secp256k1_scalar_negate(&sk, &sk); | |
273 | } | |
274 | ||
275 | ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32); | |
276 | ret &= secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32); | |
277 | ||
278 | secp256k1_declassify(ctx, &ret, sizeof(ret)); | |
279 | if (ret) { | |
280 | secp256k1_keypair_save(keypair, &sk, &pk); | |
281 | } | |
282 | ||
283 | secp256k1_scalar_clear(&sk); | |
284 | return ret; | |
285 | } | |
286 | ||
47e6618e | 287 | #endif |