]>
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 | |
8563713a GM |
7 | #define SECP256K1_BUILD (1) |
8 | ||
04e34d18 PW |
9 | #include "include/secp256k1.h" |
10 | ||
1c7fa133 | 11 | #include "util.h" |
11ab5622 PW |
12 | #include "num_impl.h" |
13 | #include "field_impl.h" | |
a9f5c8b8 | 14 | #include "scalar_impl.h" |
11ab5622 PW |
15 | #include "group_impl.h" |
16 | #include "ecmult_impl.h" | |
44015000 | 17 | #include "ecmult_const_impl.h" |
949c1ebb | 18 | #include "ecmult_gen_impl.h" |
11ab5622 | 19 | #include "ecdsa_impl.h" |
e2f71f1e | 20 | #include "eckey_impl.h" |
b37fbc28 | 21 | #include "hash_impl.h" |
254327e4 | 22 | |
995c5487 PW |
23 | #define ARG_CHECK(cond) do { \ |
24 | if (EXPECT(!(cond), 0)) { \ | |
25 | ctx->illegal_callback.fn(#cond, ctx->illegal_callback.data); \ | |
26 | return 0; \ | |
27 | } \ | |
28 | } while(0) | |
29 | ||
30 | static void default_illegal_callback_fn(const char* str, void* data) { | |
31 | (void)data; | |
32 | fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); | |
33 | abort(); | |
34 | } | |
35 | ||
36 | static const callback_t default_illegal_callback = { | |
37 | default_illegal_callback_fn, | |
38 | NULL | |
39 | }; | |
40 | ||
41 | static void default_error_callback_fn(const char* str, void* data) { | |
42 | (void)data; | |
43 | fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); | |
44 | abort(); | |
45 | } | |
46 | ||
47 | static const callback_t default_error_callback = { | |
48 | default_error_callback_fn, | |
49 | NULL | |
50 | }; | |
51 | ||
52 | ||
a9b6595e PW |
53 | struct secp256k1_context_struct { |
54 | secp256k1_ecmult_context_t ecmult_ctx; | |
55 | secp256k1_ecmult_gen_context_t ecmult_gen_ctx; | |
995c5487 PW |
56 | callback_t illegal_callback; |
57 | callback_t error_callback; | |
a9b6595e PW |
58 | }; |
59 | ||
64b730bc | 60 | secp256k1_context_t* secp256k1_context_create(unsigned int flags) { |
995c5487 PW |
61 | secp256k1_context_t* ret = (secp256k1_context_t*)checked_malloc(&default_error_callback, sizeof(secp256k1_context_t)); |
62 | ret->illegal_callback = default_illegal_callback; | |
63 | ret->error_callback = default_error_callback; | |
a9b6595e PW |
64 | |
65 | secp256k1_ecmult_context_init(&ret->ecmult_ctx); | |
66 | secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); | |
67 | ||
68 | if (flags & SECP256K1_CONTEXT_SIGN) { | |
995c5487 | 69 | secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); |
04e34d18 | 70 | } |
a9b6595e | 71 | if (flags & SECP256K1_CONTEXT_VERIFY) { |
995c5487 | 72 | secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); |
04e34d18 | 73 | } |
a9b6595e PW |
74 | |
75 | return ret; | |
254327e4 PW |
76 | } |
77 | ||
d899b5b6 | 78 | secp256k1_context_t* secp256k1_context_clone(const secp256k1_context_t* ctx) { |
995c5487 PW |
79 | secp256k1_context_t* ret = (secp256k1_context_t*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context_t)); |
80 | ret->illegal_callback = ctx->illegal_callback; | |
81 | ret->error_callback = ctx->error_callback; | |
82 | secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); | |
83 | secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); | |
d899b5b6 AP |
84 | return ret; |
85 | } | |
86 | ||
a9b6595e | 87 | void secp256k1_context_destroy(secp256k1_context_t* ctx) { |
9aac0080 LD |
88 | if (!ctx) |
89 | return; | |
90 | ||
a9b6595e PW |
91 | secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); |
92 | secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); | |
93 | ||
94 | free(ctx); | |
254327e4 PW |
95 | } |
96 | ||
995c5487 PW |
97 | void secp256k1_context_set_illegal_callback(secp256k1_context_t* ctx, void (*fun)(const char* message, void* data), void* data) { |
98 | ctx->illegal_callback.fn = fun; | |
99 | ctx->illegal_callback.data = data; | |
100 | } | |
101 | ||
102 | void secp256k1_context_set_error_callback(secp256k1_context_t* ctx, void (*fun)(const char* message, void* data), void* data) { | |
103 | ctx->error_callback.fn = fun; | |
104 | ctx->error_callback.data = data; | |
105 | } | |
106 | ||
107 | static int secp256k1_pubkey_load(const secp256k1_context_t* ctx, secp256k1_ge_t* ge, const secp256k1_pubkey_t* pubkey) { | |
23cfa914 PW |
108 | if (sizeof(secp256k1_ge_storage_t) == 64) { |
109 | /* When the secp256k1_ge_storage_t type is exactly 64 byte, use its | |
110 | * representation inside secp256k1_pubkey_t, as conversion is very fast. | |
111 | * Note that secp256k1_pubkey_save must use the same representation. */ | |
112 | secp256k1_ge_storage_t s; | |
113 | memcpy(&s, &pubkey->data[0], 64); | |
114 | secp256k1_ge_from_storage(ge, &s); | |
23cfa914 PW |
115 | } else { |
116 | /* Otherwise, fall back to 32-byte big endian for X and Y. */ | |
117 | secp256k1_fe_t x, y; | |
118 | secp256k1_fe_set_b32(&x, pubkey->data); | |
23cfa914 PW |
119 | secp256k1_fe_set_b32(&y, pubkey->data + 32); |
120 | secp256k1_ge_set_xy(ge, &x, &y); | |
121 | } | |
995c5487 PW |
122 | ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); |
123 | return 1; | |
23cfa914 PW |
124 | } |
125 | ||
126 | static void secp256k1_pubkey_save(secp256k1_pubkey_t* pubkey, secp256k1_ge_t* ge) { | |
127 | if (sizeof(secp256k1_ge_storage_t) == 64) { | |
128 | secp256k1_ge_storage_t s; | |
129 | secp256k1_ge_to_storage(&s, ge); | |
130 | memcpy(&pubkey->data[0], &s, 64); | |
131 | } else { | |
132 | VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); | |
133 | secp256k1_fe_normalize_var(&ge->x); | |
134 | secp256k1_fe_normalize_var(&ge->y); | |
135 | secp256k1_fe_get_b32(pubkey->data, &ge->x); | |
136 | secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); | |
137 | } | |
138 | } | |
139 | ||
140 | int secp256k1_ec_pubkey_parse(const secp256k1_context_t* ctx, secp256k1_pubkey_t* pubkey, const unsigned char *input, int inputlen) { | |
141 | secp256k1_ge_t Q; | |
142 | ||
143 | (void)ctx; | |
144 | if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { | |
145 | memset(pubkey, 0, sizeof(*pubkey)); | |
146 | return 0; | |
147 | } | |
148 | secp256k1_pubkey_save(pubkey, &Q); | |
149 | secp256k1_ge_clear(&Q); | |
150 | return 1; | |
151 | } | |
152 | ||
153 | int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_pubkey_t* pubkey, int compressed) { | |
154 | secp256k1_ge_t Q; | |
155 | ||
156 | (void)ctx; | |
995c5487 PW |
157 | return (secp256k1_pubkey_load(ctx, &Q, pubkey) && |
158 | secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, compressed)); | |
23cfa914 PW |
159 | } |
160 | ||
439d34ad PW |
161 | static void secp256k1_ecdsa_signature_load(const secp256k1_context_t* ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, const secp256k1_ecdsa_signature_t* sig) { |
162 | (void)ctx; | |
163 | if (sizeof(secp256k1_scalar_t) == 32) { | |
164 | /* When the secp256k1_scalar_t type is exactly 32 byte, use its | |
165 | * representation inside secp256k1_ecdsa_signature_t, as conversion is very fast. | |
166 | * Note that secp256k1_ecdsa_signature_save must use the same representation. */ | |
167 | memcpy(r, &sig->data[0], 32); | |
168 | memcpy(s, &sig->data[32], 32); | |
169 | } else { | |
170 | secp256k1_scalar_set_b32(r, &sig->data[0], NULL); | |
171 | secp256k1_scalar_set_b32(s, &sig->data[32], NULL); | |
172 | } | |
173 | } | |
174 | ||
175 | static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s) { | |
176 | if (sizeof(secp256k1_scalar_t) == 32) { | |
177 | memcpy(&sig->data[0], r, 32); | |
178 | memcpy(&sig->data[32], s, 32); | |
179 | } else { | |
180 | secp256k1_scalar_get_b32(&sig->data[0], r); | |
181 | secp256k1_scalar_get_b32(&sig->data[32], s); | |
182 | } | |
183 | } | |
184 | ||
74a2acdb | 185 | int secp256k1_ecdsa_signature_parse_der(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input, int inputlen) { |
18c329c5 | 186 | secp256k1_scalar_t r, s; |
74a2acdb PW |
187 | |
188 | (void)ctx; | |
995c5487 PW |
189 | ARG_CHECK(sig != NULL); |
190 | ARG_CHECK(input != NULL); | |
74a2acdb | 191 | |
18c329c5 | 192 | if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { |
439d34ad | 193 | secp256k1_ecdsa_signature_save(sig, &r, &s); |
74a2acdb PW |
194 | return 1; |
195 | } else { | |
196 | memset(sig, 0, sizeof(*sig)); | |
197 | return 0; | |
198 | } | |
199 | } | |
200 | ||
74a2acdb | 201 | int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_ecdsa_signature_t* sig) { |
18c329c5 | 202 | secp256k1_scalar_t r, s; |
74a2acdb PW |
203 | |
204 | (void)ctx; | |
995c5487 PW |
205 | ARG_CHECK(output != NULL); |
206 | ARG_CHECK(outputlen != NULL); | |
207 | ARG_CHECK(sig != NULL); | |
74a2acdb | 208 | |
439d34ad | 209 | secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); |
18c329c5 | 210 | return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); |
74a2acdb PW |
211 | } |
212 | ||
dc0ce9fc | 213 | int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const secp256k1_ecdsa_signature_t *sig, const unsigned char *msg32, const secp256k1_pubkey_t *pubkey) { |
f735446c | 214 | secp256k1_ge_t q; |
18c329c5 | 215 | secp256k1_scalar_t r, s; |
f735446c | 216 | secp256k1_scalar_t m; |
b183b411 | 217 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
218 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
219 | ARG_CHECK(msg32 != NULL); | |
220 | ARG_CHECK(sig != NULL); | |
221 | ARG_CHECK(pubkey != NULL); | |
1c7fa133 | 222 | |
f24041d6 | 223 | secp256k1_scalar_set_b32(&m, msg32, NULL); |
439d34ad | 224 | secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); |
995c5487 PW |
225 | return (secp256k1_pubkey_load(ctx, &q, pubkey) && |
226 | secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); | |
607884fc PW |
227 | } |
228 | ||
dc0ce9fc | 229 | static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, const void *data, unsigned int counter) { |
a5a66c70 PW |
230 | unsigned char keydata[112]; |
231 | int keylen = 64; | |
bbd5ba7c | 232 | secp256k1_rfc6979_hmac_sha256_t rng; |
f735446c | 233 | unsigned int i; |
3e6f1e20 PW |
234 | /* We feed a byte array to the PRNG as input, consisting of: |
235 | * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. | |
236 | * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. | |
a5a66c70 PW |
237 | * - optionally 16 extra bytes with the algorithm name (the extra data bytes |
238 | * are set to zeroes when not present, while the algorithm name is). | |
3e6f1e20 PW |
239 | */ |
240 | memcpy(keydata, key32, 32); | |
241 | memcpy(keydata + 32, msg32, 32); | |
242 | if (data != NULL) { | |
243 | memcpy(keydata + 64, data, 32); | |
a5a66c70 | 244 | keylen = 96; |
3e6f1e20 | 245 | } |
a5a66c70 PW |
246 | if (algo16 != NULL) { |
247 | memset(keydata + keylen, 0, 96 - keylen); | |
248 | memcpy(keydata + 96, algo16, 16); | |
249 | keylen = 112; | |
250 | } | |
251 | secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); | |
3e6f1e20 | 252 | memset(keydata, 0, sizeof(keydata)); |
f735446c | 253 | for (i = 0; i <= counter; i++) { |
bbd5ba7c PW |
254 | secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); |
255 | } | |
256 | secp256k1_rfc6979_hmac_sha256_finalize(&rng); | |
257 | return 1; | |
258 | } | |
259 | ||
260 | const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; | |
261 | const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979; | |
262 | ||
dc0ce9fc | 263 | int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) { |
439d34ad PW |
264 | secp256k1_scalar_t r, s; |
265 | secp256k1_scalar_t sec, non, msg; | |
266 | int ret = 0; | |
267 | int overflow = 0; | |
268 | unsigned int count = 0; | |
b183b411 | 269 | VERIFY_CHECK(ctx != NULL); |
439d34ad PW |
270 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
271 | ARG_CHECK(msg32 != NULL); | |
272 | ARG_CHECK(signature != NULL); | |
273 | ARG_CHECK(seckey != NULL); | |
274 | if (noncefp == NULL) { | |
275 | noncefp = secp256k1_nonce_function_default; | |
276 | } | |
277 | ||
278 | secp256k1_scalar_set_b32(&sec, seckey, &overflow); | |
279 | /* Fail if the secret key is invalid. */ | |
280 | if (!overflow && !secp256k1_scalar_is_zero(&sec)) { | |
281 | secp256k1_scalar_set_b32(&msg, msg32, NULL); | |
282 | while (1) { | |
283 | unsigned char nonce32[32]; | |
dc0ce9fc | 284 | ret = noncefp(nonce32, msg32, seckey, NULL, noncedata, count); |
439d34ad PW |
285 | if (!ret) { |
286 | break; | |
287 | } | |
288 | secp256k1_scalar_set_b32(&non, nonce32, &overflow); | |
289 | memset(nonce32, 0, 32); | |
290 | if (!secp256k1_scalar_is_zero(&non) && !overflow) { | |
291 | if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { | |
292 | break; | |
293 | } | |
294 | } | |
295 | count++; | |
296 | } | |
297 | secp256k1_scalar_clear(&msg); | |
298 | secp256k1_scalar_clear(&non); | |
299 | secp256k1_scalar_clear(&sec); | |
300 | } | |
301 | if (ret) { | |
302 | secp256k1_ecdsa_signature_save(signature, &r, &s); | |
303 | } else { | |
304 | memset(signature, 0, sizeof(*signature)); | |
305 | } | |
306 | return ret; | |
307 | } | |
308 | ||
a9b6595e | 309 | int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned char *seckey) { |
a9f5c8b8 | 310 | secp256k1_scalar_t sec; |
f735446c | 311 | int ret; |
a9f5c8b8 | 312 | int overflow; |
b183b411 | 313 | VERIFY_CHECK(ctx != NULL); |
995c5487 | 314 | ARG_CHECK(seckey != NULL); |
a9b6595e | 315 | (void)ctx; |
f735446c | 316 | |
eca6cdb1 | 317 | secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
f735446c | 318 | ret = !secp256k1_scalar_is_zero(&sec) && !overflow; |
a9f5c8b8 | 319 | secp256k1_scalar_clear(&sec); |
42cccdaf PW |
320 | return ret; |
321 | } | |
322 | ||
23cfa914 | 323 | int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *seckey) { |
f735446c GM |
324 | secp256k1_gej_t pj; |
325 | secp256k1_ge_t p; | |
326 | secp256k1_scalar_t sec; | |
354ffa33 | 327 | int overflow; |
0065a8fb | 328 | int ret = 0; |
b183b411 | 329 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
330 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
331 | ARG_CHECK(pubkey != NULL); | |
332 | ARG_CHECK(seckey != NULL); | |
1c7fa133 | 333 | |
354ffa33 | 334 | secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
23cfa914 PW |
335 | ret = !overflow & !secp256k1_scalar_is_zero(&sec); |
336 | secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); | |
337 | secp256k1_ge_set_gej(&p, &pj); | |
338 | secp256k1_pubkey_save(pubkey, &p); | |
339 | secp256k1_scalar_clear(&sec); | |
0065a8fb | 340 | if (!ret) { |
23cfa914 | 341 | memset(pubkey, 0, sizeof(*pubkey)); |
99fd963b | 342 | } |
99fd963b TK |
343 | return ret; |
344 | } | |
345 | ||
a9b6595e | 346 | int secp256k1_ec_privkey_tweak_add(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *tweak) { |
f735446c GM |
347 | secp256k1_scalar_t term; |
348 | secp256k1_scalar_t sec; | |
0065a8fb | 349 | int ret = 0; |
f735446c | 350 | int overflow = 0; |
b183b411 | 351 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
352 | ARG_CHECK(seckey != NULL); |
353 | ARG_CHECK(tweak != NULL); | |
a9b6595e | 354 | (void)ctx; |
1c7fa133 | 355 | |
eca6cdb1 | 356 | secp256k1_scalar_set_b32(&term, tweak, &overflow); |
eca6cdb1 | 357 | secp256k1_scalar_set_b32(&sec, seckey, NULL); |
eb74c36b | 358 | |
f735446c | 359 | ret = secp256k1_eckey_privkey_tweak_add(&sec, &term) && !overflow; |
561b0e10 | 360 | if (ret) { |
eca6cdb1 | 361 | secp256k1_scalar_get_b32(seckey, &sec); |
eb74c36b PW |
362 | } |
363 | ||
a9f5c8b8 PW |
364 | secp256k1_scalar_clear(&sec); |
365 | secp256k1_scalar_clear(&term); | |
561b0e10 PW |
366 | return ret; |
367 | } | |
368 | ||
23cfa914 | 369 | int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) { |
f735446c GM |
370 | secp256k1_ge_t p; |
371 | secp256k1_scalar_t term; | |
0065a8fb | 372 | int ret = 0; |
f735446c | 373 | int overflow = 0; |
b183b411 | 374 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
375 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
376 | ARG_CHECK(pubkey != NULL); | |
377 | ARG_CHECK(tweak != NULL); | |
1c7fa133 | 378 | |
f24041d6 | 379 | secp256k1_scalar_set_b32(&term, tweak, &overflow); |
995c5487 | 380 | if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) { |
23cfa914 | 381 | ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term); |
0065a8fb | 382 | if (ret) { |
23cfa914 PW |
383 | secp256k1_pubkey_save(pubkey, &p); |
384 | } else { | |
385 | memset(pubkey, 0, sizeof(*pubkey)); | |
0065a8fb | 386 | } |
86d3cce2 | 387 | } |
eb74c36b | 388 | |
86d3cce2 PW |
389 | return ret; |
390 | } | |
391 | ||
a9b6595e | 392 | int secp256k1_ec_privkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *tweak) { |
f735446c GM |
393 | secp256k1_scalar_t factor; |
394 | secp256k1_scalar_t sec; | |
0065a8fb | 395 | int ret = 0; |
f735446c | 396 | int overflow = 0; |
b183b411 | 397 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
398 | ARG_CHECK(seckey != NULL); |
399 | ARG_CHECK(tweak != NULL); | |
a9b6595e | 400 | (void)ctx; |
1c7fa133 | 401 | |
eca6cdb1 | 402 | secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
eca6cdb1 | 403 | secp256k1_scalar_set_b32(&sec, seckey, NULL); |
f735446c | 404 | ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor) && !overflow; |
86d3cce2 | 405 | if (ret) { |
eca6cdb1 | 406 | secp256k1_scalar_get_b32(seckey, &sec); |
eb74c36b PW |
407 | } |
408 | ||
a9f5c8b8 PW |
409 | secp256k1_scalar_clear(&sec); |
410 | secp256k1_scalar_clear(&factor); | |
86d3cce2 PW |
411 | return ret; |
412 | } | |
413 | ||
23cfa914 | 414 | int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) { |
f735446c GM |
415 | secp256k1_ge_t p; |
416 | secp256k1_scalar_t factor; | |
0065a8fb | 417 | int ret = 0; |
f735446c | 418 | int overflow = 0; |
b183b411 | 419 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
420 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
421 | ARG_CHECK(pubkey != NULL); | |
422 | ARG_CHECK(tweak != NULL); | |
1c7fa133 | 423 | |
f24041d6 | 424 | secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
995c5487 | 425 | if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) { |
23cfa914 | 426 | ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor); |
0065a8fb | 427 | if (ret) { |
23cfa914 PW |
428 | secp256k1_pubkey_save(pubkey, &p); |
429 | } else { | |
430 | memset(pubkey, 0, sizeof(*pubkey)); | |
0065a8fb | 431 | } |
561b0e10 | 432 | } |
eb74c36b | 433 | |
561b0e10 PW |
434 | return ret; |
435 | } | |
436 | ||
dc0ce9fc | 437 | int secp256k1_ec_privkey_export(const secp256k1_context_t* ctx, unsigned char *privkey, int *privkeylen, const unsigned char *seckey, int compressed) { |
f735446c | 438 | secp256k1_scalar_t key; |
0065a8fb | 439 | int ret = 0; |
b183b411 | 440 | VERIFY_CHECK(ctx != NULL); |
995c5487 PW |
441 | ARG_CHECK(seckey != NULL); |
442 | ARG_CHECK(privkey != NULL); | |
443 | ARG_CHECK(privkeylen != NULL); | |
995c5487 | 444 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
1c7fa133 | 445 | |
eca6cdb1 | 446 | secp256k1_scalar_set_b32(&key, seckey, NULL); |
a9b6595e | 447 | ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, compressed); |
a9f5c8b8 | 448 | secp256k1_scalar_clear(&key); |
da3038c7 PW |
449 | return ret; |
450 | } | |
451 | ||
a9b6595e | 452 | int secp256k1_ec_privkey_import(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *privkey, int privkeylen) { |
f735446c | 453 | secp256k1_scalar_t key; |
0065a8fb | 454 | int ret = 0; |
995c5487 PW |
455 | ARG_CHECK(seckey != NULL); |
456 | ARG_CHECK(privkey != NULL); | |
a9b6595e | 457 | (void)ctx; |
1c7fa133 | 458 | |
f735446c | 459 | ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen); |
0065a8fb | 460 | if (ret) { |
eca6cdb1 | 461 | secp256k1_scalar_get_b32(seckey, &key); |
0065a8fb | 462 | } |
a9f5c8b8 | 463 | secp256k1_scalar_clear(&key); |
da3038c7 PW |
464 | return ret; |
465 | } | |
d2275795 GM |
466 | |
467 | int secp256k1_context_randomize(secp256k1_context_t* ctx, const unsigned char *seed32) { | |
b183b411 | 468 | VERIFY_CHECK(ctx != NULL); |
995c5487 | 469 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
d2275795 GM |
470 | secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); |
471 | return 1; | |
472 | } | |
0739bbb6 | 473 | |
dc0ce9fc | 474 | int secp256k1_ec_pubkey_combine(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubnonce, const secp256k1_pubkey_t * const *pubnonces, int n) { |
a5a66c70 PW |
475 | int i; |
476 | secp256k1_gej_t Qj; | |
477 | secp256k1_ge_t Q; | |
478 | ||
479 | ARG_CHECK(pubnonce != NULL); | |
480 | ARG_CHECK(n >= 1); | |
481 | ARG_CHECK(pubnonces != NULL); | |
482 | ||
483 | secp256k1_gej_set_infinity(&Qj); | |
484 | ||
485 | for (i = 0; i < n; i++) { | |
486 | secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); | |
487 | secp256k1_gej_add_ge(&Qj, &Qj, &Q); | |
488 | } | |
489 | if (secp256k1_gej_is_infinity(&Qj)) { | |
490 | memset(pubnonce, 0, sizeof(*pubnonce)); | |
491 | return 0; | |
492 | } | |
493 | secp256k1_ge_set_gej(&Q, &Qj); | |
494 | secp256k1_pubkey_save(pubnonce, &Q); | |
495 | return 1; | |
496 | } | |
497 | ||
0739bbb6 AP |
498 | #ifdef ENABLE_MODULE_ECDH |
499 | # include "modules/ecdh/main_impl.h" | |
500 | #endif | |
a5a66c70 PW |
501 | |
502 | #ifdef ENABLE_MODULE_SCHNORR | |
503 | # include "modules/schnorr/main_impl.h" | |
504 | #endif | |
9f443be0 PW |
505 | |
506 | #ifdef ENABLE_MODULE_RECOVERY | |
507 | # include "modules/recovery/main_impl.h" | |
508 | #endif |