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