]>
Commit | Line | Data |
---|---|---|
71712b27 | 1 | /********************************************************************** |
a9b6595e | 2 | * Copyright (c) 2013-2015 Pieter Wuille * |
71712b27 GM |
3 | * Distributed under the MIT software license, see the accompanying * |
4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* | |
5 | **********************************************************************/ | |
0a433ea2 | 6 | |
04e34d18 PW |
7 | #include "include/secp256k1.h" |
8 | ||
1c7fa133 | 9 | #include "util.h" |
11ab5622 PW |
10 | #include "num_impl.h" |
11 | #include "field_impl.h" | |
a9f5c8b8 | 12 | #include "scalar_impl.h" |
11ab5622 PW |
13 | #include "group_impl.h" |
14 | #include "ecmult_impl.h" | |
44015000 | 15 | #include "ecmult_const_impl.h" |
949c1ebb | 16 | #include "ecmult_gen_impl.h" |
11ab5622 | 17 | #include "ecdsa_impl.h" |
e2f71f1e | 18 | #include "eckey_impl.h" |
b37fbc28 | 19 | #include "hash_impl.h" |
548de42e | 20 | #include "scratch_impl.h" |
254327e4 | 21 | |
995c5487 PW |
22 | #define ARG_CHECK(cond) do { \ |
23 | if (EXPECT(!(cond), 0)) { \ | |
dd891e0e | 24 | secp256k1_callback_call(&ctx->illegal_callback, #cond); \ |
995c5487 PW |
25 | return 0; \ |
26 | } \ | |
27 | } while(0) | |
28 | ||
29 | static void default_illegal_callback_fn(const char* str, void* data) { | |
30 | (void)data; | |
31 | fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); | |
32 | abort(); | |
33 | } | |
34 | ||
dd891e0e | 35 | static const secp256k1_callback default_illegal_callback = { |
995c5487 PW |
36 | default_illegal_callback_fn, |
37 | NULL | |
38 | }; | |
39 | ||
40 | static void default_error_callback_fn(const char* str, void* data) { | |
41 | (void)data; | |
42 | fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); | |
43 | abort(); | |
44 | } | |
45 | ||
dd891e0e | 46 | static const secp256k1_callback default_error_callback = { |
995c5487 PW |
47 | default_error_callback_fn, |
48 | NULL | |
49 | }; | |
50 | ||
51 | ||
a9b6595e | 52 | struct secp256k1_context_struct { |
dd891e0e PW |
53 | secp256k1_ecmult_context ecmult_ctx; |
54 | secp256k1_ecmult_gen_context ecmult_gen_ctx; | |
55 | secp256k1_callback illegal_callback; | |
56 | secp256k1_callback error_callback; | |
a9b6595e PW |
57 | }; |
58 | ||
dd891e0e PW |
59 | secp256k1_context* secp256k1_context_create(unsigned int flags) { |
60 | secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context)); | |
995c5487 PW |
61 | ret->illegal_callback = default_illegal_callback; |
62 | ret->error_callback = default_error_callback; | |
a9b6595e | 63 | |
9234391e | 64 | if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { |
1a368980 RR |
65 | secp256k1_callback_call(&ret->illegal_callback, |
66 | "Invalid flags"); | |
67 | free(ret); | |
68 | return NULL; | |
69 | } | |
70 | ||
a9b6595e PW |
71 | secp256k1_ecmult_context_init(&ret->ecmult_ctx); |
72 | secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); | |
73 | ||
9234391e | 74 | if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { |
995c5487 | 75 | secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); |
04e34d18 | 76 | } |
9234391e | 77 | if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { |
995c5487 | 78 | secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); |
04e34d18 | 79 | } |
a9b6595e PW |
80 | |
81 | return ret; | |
254327e4 PW |
82 | } |
83 | ||
dd891e0e PW |
84 | secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { |
85 | secp256k1_context* ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context)); | |
995c5487 PW |
86 | ret->illegal_callback = ctx->illegal_callback; |
87 | ret->error_callback = ctx->error_callback; | |
88 | secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); | |
89 | secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); | |
d899b5b6 AP |
90 | return ret; |
91 | } | |
92 | ||
dd891e0e | 93 | void secp256k1_context_destroy(secp256k1_context* ctx) { |
2b199de8 | 94 | if (ctx != NULL) { |
912f203f GM |
95 | secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); |
96 | secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); | |
9aac0080 | 97 | |
912f203f GM |
98 | free(ctx); |
99 | } | |
254327e4 PW |
100 | } |
101 | ||
dd891e0e | 102 | void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { |
2b199de8 | 103 | if (fun == NULL) { |
c9d7c2a4 | 104 | fun = default_illegal_callback_fn; |
912f203f | 105 | } |
995c5487 PW |
106 | ctx->illegal_callback.fn = fun; |
107 | ctx->illegal_callback.data = data; | |
108 | } | |
109 | ||
dd891e0e | 110 | void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { |
2b199de8 | 111 | if (fun == NULL) { |
c9d7c2a4 | 112 | fun = default_error_callback_fn; |
912f203f | 113 | } |
995c5487 PW |
114 | ctx->error_callback.fn = fun; |
115 | ctx->error_callback.data = data; | |
116 | } | |
117 | ||
6fe50439 | 118 | secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) { |
548de42e | 119 | VERIFY_CHECK(ctx != NULL); |
6fe50439 | 120 | return secp256k1_scratch_create(&ctx->error_callback, max_size); |
548de42e AP |
121 | } |
122 | ||
123 | void secp256k1_scratch_space_destroy(secp256k1_scratch_space* scratch) { | |
124 | secp256k1_scratch_destroy(scratch); | |
125 | } | |
126 | ||
dd891e0e PW |
127 | static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { |
128 | if (sizeof(secp256k1_ge_storage) == 64) { | |
129 | /* When the secp256k1_ge_storage type is exactly 64 byte, use its | |
130 | * representation inside secp256k1_pubkey, as conversion is very fast. | |
23cfa914 | 131 | * Note that secp256k1_pubkey_save must use the same representation. */ |
dd891e0e | 132 | secp256k1_ge_storage s; |
c7680e57 | 133 | memcpy(&s, &pubkey->data[0], sizeof(s)); |
23cfa914 | 134 | secp256k1_ge_from_storage(ge, &s); |
23cfa914 PW |
135 | } else { |
136 | /* Otherwise, fall back to 32-byte big endian for X and Y. */ | |
dd891e0e | 137 | secp256k1_fe x, y; |
23cfa914 | 138 | secp256k1_fe_set_b32(&x, pubkey->data); |
23cfa914 PW |
139 | secp256k1_fe_set_b32(&y, pubkey->data + 32); |
140 | secp256k1_ge_set_xy(ge, &x, &y); | |
141 | } | |
995c5487 PW |
142 | ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); |
143 | return 1; | |
23cfa914 PW |
144 | } |
145 | ||
dd891e0e PW |
146 | static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { |
147 | if (sizeof(secp256k1_ge_storage) == 64) { | |
148 | secp256k1_ge_storage s; | |
23cfa914 | 149 | secp256k1_ge_to_storage(&s, ge); |
c7680e57 | 150 | memcpy(&pubkey->data[0], &s, sizeof(s)); |
23cfa914 PW |
151 | } else { |
152 | VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); | |
153 | secp256k1_fe_normalize_var(&ge->x); | |
154 | secp256k1_fe_normalize_var(&ge->y); | |
155 | secp256k1_fe_get_b32(pubkey->data, &ge->x); | |
156 | secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); | |
157 | } | |
158 | } | |
159 | ||
dd891e0e PW |
160 | int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { |
161 | secp256k1_ge Q; | |
23cfa914 | 162 | |
ee2cb400 GM |
163 | VERIFY_CHECK(ctx != NULL); |
164 | ARG_CHECK(pubkey != NULL); | |
165 | memset(pubkey, 0, sizeof(*pubkey)); | |
166 | ARG_CHECK(input != NULL); | |
23cfa914 | 167 | if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { |
23cfa914 PW |
168 | return 0; |
169 | } | |
170 | secp256k1_pubkey_save(pubkey, &Q); | |
171 | secp256k1_ge_clear(&Q); | |
172 | return 1; | |
173 | } | |
174 | ||
dd891e0e PW |
175 | int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { |
176 | secp256k1_ge Q; | |
5b71a3f4 GM |
177 | size_t len; |
178 | int ret = 0; | |
23cfa914 | 179 | |
ee2cb400 | 180 | VERIFY_CHECK(ctx != NULL); |
ee2cb400 | 181 | ARG_CHECK(outputlen != NULL); |
06aeea55 | 182 | ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65)); |
5b71a3f4 GM |
183 | len = *outputlen; |
184 | *outputlen = 0; | |
185 | ARG_CHECK(output != NULL); | |
186 | memset(output, 0, len); | |
ee2cb400 | 187 | ARG_CHECK(pubkey != NULL); |
9234391e | 188 | ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); |
5b71a3f4 GM |
189 | if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { |
190 | ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); | |
191 | if (ret) { | |
192 | *outputlen = len; | |
193 | } | |
194 | } | |
195 | return ret; | |
23cfa914 PW |
196 | } |
197 | ||
dd891e0e | 198 | static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { |
439d34ad | 199 | (void)ctx; |
dd891e0e PW |
200 | if (sizeof(secp256k1_scalar) == 32) { |
201 | /* When the secp256k1_scalar type is exactly 32 byte, use its | |
202 | * representation inside secp256k1_ecdsa_signature, as conversion is very fast. | |
439d34ad PW |
203 | * Note that secp256k1_ecdsa_signature_save must use the same representation. */ |
204 | memcpy(r, &sig->data[0], 32); | |
205 | memcpy(s, &sig->data[32], 32); | |
206 | } else { | |
207 | secp256k1_scalar_set_b32(r, &sig->data[0], NULL); | |
208 | secp256k1_scalar_set_b32(s, &sig->data[32], NULL); | |
209 | } | |
210 | } | |
211 | ||
dd891e0e PW |
212 | static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) { |
213 | if (sizeof(secp256k1_scalar) == 32) { | |
439d34ad PW |
214 | memcpy(&sig->data[0], r, 32); |
215 | memcpy(&sig->data[32], s, 32); | |
216 | } else { | |
217 | secp256k1_scalar_get_b32(&sig->data[0], r); | |
218 | secp256k1_scalar_get_b32(&sig->data[32], s); | |
219 | } | |
220 | } | |
221 | ||
dd891e0e PW |
222 | int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { |
223 | secp256k1_scalar r, s; | |
74a2acdb | 224 | |
bcc4881d | 225 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
226 | ARG_CHECK(sig != NULL); |
227 | ARG_CHECK(input != NULL); | |
74a2acdb | 228 | |
18c329c5 | 229 | if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { |
439d34ad | 230 | secp256k1_ecdsa_signature_save(sig, &r, &s); |
74a2acdb PW |
231 | return 1; |
232 | } else { | |
233 | memset(sig, 0, sizeof(*sig)); | |
234 | return 0; | |
235 | } | |
236 | } | |
237 | ||
3bb9c447 PW |
238 | int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64) { |
239 | secp256k1_scalar r, s; | |
240 | int ret = 1; | |
241 | int overflow = 0; | |
242 | ||
bcc4881d | 243 | VERIFY_CHECK(ctx != NULL); |
3bb9c447 PW |
244 | ARG_CHECK(sig != NULL); |
245 | ARG_CHECK(input64 != NULL); | |
246 | ||
247 | secp256k1_scalar_set_b32(&r, &input64[0], &overflow); | |
248 | ret &= !overflow; | |
249 | secp256k1_scalar_set_b32(&s, &input64[32], &overflow); | |
250 | ret &= !overflow; | |
251 | if (ret) { | |
252 | secp256k1_ecdsa_signature_save(sig, &r, &s); | |
253 | } else { | |
254 | memset(sig, 0, sizeof(*sig)); | |
255 | } | |
256 | return ret; | |
257 | } | |
258 | ||
dd891e0e PW |
259 | int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) { |
260 | secp256k1_scalar r, s; | |
74a2acdb | 261 | |
bcc4881d | 262 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
263 | ARG_CHECK(output != NULL); |
264 | ARG_CHECK(outputlen != NULL); | |
265 | ARG_CHECK(sig != NULL); | |
74a2acdb | 266 | |
439d34ad | 267 | secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); |
18c329c5 | 268 | return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); |
74a2acdb PW |
269 | } |
270 | ||
3bb9c447 PW |
271 | int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) { |
272 | secp256k1_scalar r, s; | |
273 | ||
bcc4881d | 274 | VERIFY_CHECK(ctx != NULL); |
3bb9c447 PW |
275 | ARG_CHECK(output64 != NULL); |
276 | ARG_CHECK(sig != NULL); | |
277 | ||
278 | secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); | |
279 | secp256k1_scalar_get_b32(&output64[0], &r); | |
280 | secp256k1_scalar_get_b32(&output64[32], &s); | |
281 | return 1; | |
282 | } | |
283 | ||
0c6ab2ff PW |
284 | int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) { |
285 | secp256k1_scalar r, s; | |
286 | int ret = 0; | |
287 | ||
288 | VERIFY_CHECK(ctx != NULL); | |
289 | ARG_CHECK(sigin != NULL); | |
290 | ||
291 | secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin); | |
292 | ret = secp256k1_scalar_is_high(&s); | |
293 | if (sigout != NULL) { | |
294 | if (ret) { | |
295 | secp256k1_scalar_negate(&s, &s); | |
296 | } | |
297 | secp256k1_ecdsa_signature_save(sigout, &r, &s); | |
298 | } | |
299 | ||
300 | return ret; | |
301 | } | |
302 | ||
dd891e0e PW |
303 | int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { |
304 | secp256k1_ge q; | |
305 | secp256k1_scalar r, s; | |
306 | secp256k1_scalar m; | |
b183b411 | 307 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
308 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
309 | ARG_CHECK(msg32 != NULL); | |
310 | ARG_CHECK(sig != NULL); | |
311 | ARG_CHECK(pubkey != NULL); | |
1c7fa133 | 312 | |
f24041d6 | 313 | secp256k1_scalar_set_b32(&m, msg32, NULL); |
439d34ad | 314 | secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); |
0c6ab2ff PW |
315 | return (!secp256k1_scalar_is_high(&s) && |
316 | secp256k1_pubkey_load(ctx, &q, pubkey) && | |
995c5487 | 317 | secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); |
607884fc PW |
318 | } |
319 | ||
c7680e57 TS |
320 | static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) { |
321 | memcpy(buf + *offset, data, len); | |
322 | *offset += len; | |
323 | } | |
324 | ||
05732c5a | 325 | static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { |
a5a66c70 | 326 | unsigned char keydata[112]; |
c7680e57 | 327 | unsigned int offset = 0; |
d1dc9dfc | 328 | secp256k1_rfc6979_hmac_sha256 rng; |
f735446c | 329 | unsigned int i; |
3e6f1e20 PW |
330 | /* We feed a byte array to the PRNG as input, consisting of: |
331 | * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. | |
332 | * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. | |
b30fc85c GM |
333 | * - optionally 16 extra bytes with the algorithm name. |
334 | * Because the arguments have distinct fixed lengths it is not possible for | |
335 | * different argument mixtures to emulate each other and result in the same | |
336 | * nonces. | |
3e6f1e20 | 337 | */ |
c7680e57 TS |
338 | buffer_append(keydata, &offset, key32, 32); |
339 | buffer_append(keydata, &offset, msg32, 32); | |
3e6f1e20 | 340 | if (data != NULL) { |
c7680e57 | 341 | buffer_append(keydata, &offset, data, 32); |
3e6f1e20 | 342 | } |
a5a66c70 | 343 | if (algo16 != NULL) { |
c7680e57 | 344 | buffer_append(keydata, &offset, algo16, 16); |
a5a66c70 | 345 | } |
c7680e57 | 346 | secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); |
3e6f1e20 | 347 | memset(keydata, 0, sizeof(keydata)); |
f735446c | 348 | for (i = 0; i <= counter; i++) { |
bbd5ba7c PW |
349 | secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); |
350 | } | |
351 | secp256k1_rfc6979_hmac_sha256_finalize(&rng); | |
352 | return 1; | |
353 | } | |
354 | ||
dd891e0e PW |
355 | const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; |
356 | const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; | |
bbd5ba7c | 357 | |
dd891e0e PW |
358 | int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { |
359 | secp256k1_scalar r, s; | |
360 | secp256k1_scalar sec, non, msg; | |
439d34ad PW |
361 | int ret = 0; |
362 | int overflow = 0; | |
b183b411 | 363 | VERIFY_CHECK(ctx != NULL); |
439d34ad PW |
364 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
365 | ARG_CHECK(msg32 != NULL); | |
366 | ARG_CHECK(signature != NULL); | |
367 | ARG_CHECK(seckey != NULL); | |
368 | if (noncefp == NULL) { | |
369 | noncefp = secp256k1_nonce_function_default; | |
370 | } | |
371 | ||
372 | secp256k1_scalar_set_b32(&sec, seckey, &overflow); | |
373 | /* Fail if the secret key is invalid. */ | |
374 | if (!overflow && !secp256k1_scalar_is_zero(&sec)) { | |
0f9e69db | 375 | unsigned char nonce32[32]; |
cfe0ed91 | 376 | unsigned int count = 0; |
439d34ad PW |
377 | secp256k1_scalar_set_b32(&msg, msg32, NULL); |
378 | while (1) { | |
05732c5a | 379 | ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); |
439d34ad PW |
380 | if (!ret) { |
381 | break; | |
382 | } | |
383 | secp256k1_scalar_set_b32(&non, nonce32, &overflow); | |
cfe0ed91 | 384 | if (!overflow && !secp256k1_scalar_is_zero(&non)) { |
439d34ad PW |
385 | if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { |
386 | break; | |
387 | } | |
388 | } | |
389 | count++; | |
390 | } | |
0f9e69db | 391 | memset(nonce32, 0, 32); |
439d34ad PW |
392 | secp256k1_scalar_clear(&msg); |
393 | secp256k1_scalar_clear(&non); | |
394 | secp256k1_scalar_clear(&sec); | |
395 | } | |
396 | if (ret) { | |
397 | secp256k1_ecdsa_signature_save(signature, &r, &s); | |
398 | } else { | |
399 | memset(signature, 0, sizeof(*signature)); | |
400 | } | |
401 | return ret; | |
402 | } | |
403 | ||
dd891e0e PW |
404 | int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { |
405 | secp256k1_scalar sec; | |
f735446c | 406 | int ret; |
a9f5c8b8 | 407 | int overflow; |
b183b411 | 408 | VERIFY_CHECK(ctx != NULL); |
995c5487 | 409 | ARG_CHECK(seckey != NULL); |
f735446c | 410 | |
eca6cdb1 | 411 | secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
cfe0ed91 | 412 | ret = !overflow && !secp256k1_scalar_is_zero(&sec); |
a9f5c8b8 | 413 | secp256k1_scalar_clear(&sec); |
42cccdaf PW |
414 | return ret; |
415 | } | |
416 | ||
dd891e0e PW |
417 | int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { |
418 | secp256k1_gej pj; | |
419 | secp256k1_ge p; | |
420 | secp256k1_scalar sec; | |
354ffa33 | 421 | int overflow; |
0065a8fb | 422 | int ret = 0; |
b183b411 | 423 | VERIFY_CHECK(ctx != NULL); |
995c5487 | 424 | ARG_CHECK(pubkey != NULL); |
5b71a3f4 GM |
425 | memset(pubkey, 0, sizeof(*pubkey)); |
426 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | |
995c5487 | 427 | ARG_CHECK(seckey != NULL); |
1c7fa133 | 428 | |
354ffa33 | 429 | secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
cfe0ed91 | 430 | ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec)); |
70d46401 GM |
431 | if (ret) { |
432 | secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); | |
433 | secp256k1_ge_set_gej(&p, &pj); | |
434 | secp256k1_pubkey_save(pubkey, &p); | |
99fd963b | 435 | } |
70d46401 | 436 | secp256k1_scalar_clear(&sec); |
99fd963b TK |
437 | return ret; |
438 | } | |
439 | ||
8e48aa60 AP |
440 | int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) { |
441 | secp256k1_scalar sec; | |
442 | VERIFY_CHECK(ctx != NULL); | |
443 | ARG_CHECK(seckey != NULL); | |
444 | ||
445 | secp256k1_scalar_set_b32(&sec, seckey, NULL); | |
446 | secp256k1_scalar_negate(&sec, &sec); | |
447 | secp256k1_scalar_get_b32(seckey, &sec); | |
448 | ||
449 | return 1; | |
450 | } | |
451 | ||
452 | int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) { | |
453 | int ret = 0; | |
454 | secp256k1_ge p; | |
455 | VERIFY_CHECK(ctx != NULL); | |
456 | ARG_CHECK(pubkey != NULL); | |
457 | ||
458 | ret = secp256k1_pubkey_load(ctx, &p, pubkey); | |
459 | memset(pubkey, 0, sizeof(*pubkey)); | |
460 | if (ret) { | |
461 | secp256k1_ge_neg(&p, &p); | |
462 | secp256k1_pubkey_save(pubkey, &p); | |
463 | } | |
464 | return ret; | |
465 | } | |
466 | ||
dd891e0e PW |
467 | int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { |
468 | secp256k1_scalar term; | |
469 | secp256k1_scalar sec; | |
0065a8fb | 470 | int ret = 0; |
f735446c | 471 | int overflow = 0; |
b183b411 | 472 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
473 | ARG_CHECK(seckey != NULL); |
474 | ARG_CHECK(tweak != NULL); | |
1c7fa133 | 475 | |
eca6cdb1 | 476 | secp256k1_scalar_set_b32(&term, tweak, &overflow); |
eca6cdb1 | 477 | secp256k1_scalar_set_b32(&sec, seckey, NULL); |
eb74c36b | 478 | |
cfe0ed91 | 479 | ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term); |
bb5aa4df | 480 | memset(seckey, 0, 32); |
561b0e10 | 481 | if (ret) { |
eca6cdb1 | 482 | secp256k1_scalar_get_b32(seckey, &sec); |
eb74c36b PW |
483 | } |
484 | ||
a9f5c8b8 PW |
485 | secp256k1_scalar_clear(&sec); |
486 | secp256k1_scalar_clear(&term); | |
561b0e10 PW |
487 | return ret; |
488 | } | |
489 | ||
dd891e0e PW |
490 | int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { |
491 | secp256k1_ge p; | |
492 | secp256k1_scalar term; | |
0065a8fb | 493 | int ret = 0; |
f735446c | 494 | int overflow = 0; |
b183b411 | 495 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
496 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
497 | ARG_CHECK(pubkey != NULL); | |
498 | ARG_CHECK(tweak != NULL); | |
1c7fa133 | 499 | |
f24041d6 | 500 | secp256k1_scalar_set_b32(&term, tweak, &overflow); |
bb5aa4df GM |
501 | ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); |
502 | memset(pubkey, 0, sizeof(*pubkey)); | |
503 | if (ret) { | |
504 | if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { | |
23cfa914 PW |
505 | secp256k1_pubkey_save(pubkey, &p); |
506 | } else { | |
bb5aa4df | 507 | ret = 0; |
0065a8fb | 508 | } |
86d3cce2 | 509 | } |
eb74c36b | 510 | |
86d3cce2 PW |
511 | return ret; |
512 | } | |
513 | ||
dd891e0e PW |
514 | int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { |
515 | secp256k1_scalar factor; | |
516 | secp256k1_scalar sec; | |
0065a8fb | 517 | int ret = 0; |
f735446c | 518 | int overflow = 0; |
b183b411 | 519 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
520 | ARG_CHECK(seckey != NULL); |
521 | ARG_CHECK(tweak != NULL); | |
1c7fa133 | 522 | |
eca6cdb1 | 523 | secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
eca6cdb1 | 524 | secp256k1_scalar_set_b32(&sec, seckey, NULL); |
cfe0ed91 | 525 | ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor); |
bb5aa4df | 526 | memset(seckey, 0, 32); |
86d3cce2 | 527 | if (ret) { |
eca6cdb1 | 528 | secp256k1_scalar_get_b32(seckey, &sec); |
eb74c36b PW |
529 | } |
530 | ||
a9f5c8b8 PW |
531 | secp256k1_scalar_clear(&sec); |
532 | secp256k1_scalar_clear(&factor); | |
86d3cce2 PW |
533 | return ret; |
534 | } | |
535 | ||
dd891e0e PW |
536 | int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { |
537 | secp256k1_ge p; | |
538 | secp256k1_scalar factor; | |
0065a8fb | 539 | int ret = 0; |
f735446c | 540 | int overflow = 0; |
b183b411 | 541 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
542 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
543 | ARG_CHECK(pubkey != NULL); | |
544 | ARG_CHECK(tweak != NULL); | |
1c7fa133 | 545 | |
f24041d6 | 546 | secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
bb5aa4df GM |
547 | ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); |
548 | memset(pubkey, 0, sizeof(*pubkey)); | |
549 | if (ret) { | |
550 | if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) { | |
23cfa914 PW |
551 | secp256k1_pubkey_save(pubkey, &p); |
552 | } else { | |
bb5aa4df | 553 | ret = 0; |
0065a8fb | 554 | } |
561b0e10 | 555 | } |
eb74c36b | 556 | |
561b0e10 PW |
557 | return ret; |
558 | } | |
559 | ||
dd891e0e | 560 | int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { |
b183b411 | 561 | VERIFY_CHECK(ctx != NULL); |
995c5487 | 562 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
d2275795 GM |
563 | secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); |
564 | return 1; | |
565 | } | |
0739bbb6 | 566 | |
8e48787d GM |
567 | int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { |
568 | size_t i; | |
dd891e0e PW |
569 | secp256k1_gej Qj; |
570 | secp256k1_ge Q; | |
a5a66c70 PW |
571 | |
572 | ARG_CHECK(pubnonce != NULL); | |
c69dea02 | 573 | memset(pubnonce, 0, sizeof(*pubnonce)); |
a5a66c70 PW |
574 | ARG_CHECK(n >= 1); |
575 | ARG_CHECK(pubnonces != NULL); | |
576 | ||
577 | secp256k1_gej_set_infinity(&Qj); | |
578 | ||
579 | for (i = 0; i < n; i++) { | |
580 | secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); | |
581 | secp256k1_gej_add_ge(&Qj, &Qj, &Q); | |
582 | } | |
583 | if (secp256k1_gej_is_infinity(&Qj)) { | |
a5a66c70 PW |
584 | return 0; |
585 | } | |
586 | secp256k1_ge_set_gej(&Q, &Qj); | |
587 | secp256k1_pubkey_save(pubnonce, &Q); | |
588 | return 1; | |
589 | } | |
590 | ||
0739bbb6 AP |
591 | #ifdef ENABLE_MODULE_ECDH |
592 | # include "modules/ecdh/main_impl.h" | |
593 | #endif | |
a5a66c70 | 594 | |
9f443be0 PW |
595 | #ifdef ENABLE_MODULE_RECOVERY |
596 | # include "modules/recovery/main_impl.h" | |
597 | #endif |