]>
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 | ||
60 | secp256k1_context_t* secp256k1_context_create(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 PW |
87 | void secp256k1_context_destroy(secp256k1_context_t* ctx) { |
88 | secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); | |
89 | secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); | |
90 | ||
91 | free(ctx); | |
254327e4 PW |
92 | } |
93 | ||
995c5487 PW |
94 | void secp256k1_context_set_illegal_callback(secp256k1_context_t* ctx, void (*fun)(const char* message, void* data), void* data) { |
95 | ctx->illegal_callback.fn = fun; | |
96 | ctx->illegal_callback.data = data; | |
97 | } | |
98 | ||
99 | void secp256k1_context_set_error_callback(secp256k1_context_t* ctx, void (*fun)(const char* message, void* data), void* data) { | |
100 | ctx->error_callback.fn = fun; | |
101 | ctx->error_callback.data = data; | |
102 | } | |
103 | ||
104 | static int secp256k1_pubkey_load(const secp256k1_context_t* ctx, secp256k1_ge_t* ge, const secp256k1_pubkey_t* pubkey) { | |
23cfa914 PW |
105 | if (sizeof(secp256k1_ge_storage_t) == 64) { |
106 | /* When the secp256k1_ge_storage_t type is exactly 64 byte, use its | |
107 | * representation inside secp256k1_pubkey_t, as conversion is very fast. | |
108 | * Note that secp256k1_pubkey_save must use the same representation. */ | |
109 | secp256k1_ge_storage_t s; | |
110 | memcpy(&s, &pubkey->data[0], 64); | |
111 | secp256k1_ge_from_storage(ge, &s); | |
23cfa914 PW |
112 | } else { |
113 | /* Otherwise, fall back to 32-byte big endian for X and Y. */ | |
114 | secp256k1_fe_t x, y; | |
115 | secp256k1_fe_set_b32(&x, pubkey->data); | |
23cfa914 PW |
116 | secp256k1_fe_set_b32(&y, pubkey->data + 32); |
117 | secp256k1_ge_set_xy(ge, &x, &y); | |
118 | } | |
995c5487 PW |
119 | ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); |
120 | return 1; | |
23cfa914 PW |
121 | } |
122 | ||
123 | static void secp256k1_pubkey_save(secp256k1_pubkey_t* pubkey, secp256k1_ge_t* ge) { | |
124 | if (sizeof(secp256k1_ge_storage_t) == 64) { | |
125 | secp256k1_ge_storage_t s; | |
126 | secp256k1_ge_to_storage(&s, ge); | |
127 | memcpy(&pubkey->data[0], &s, 64); | |
128 | } else { | |
129 | VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); | |
130 | secp256k1_fe_normalize_var(&ge->x); | |
131 | secp256k1_fe_normalize_var(&ge->y); | |
132 | secp256k1_fe_get_b32(pubkey->data, &ge->x); | |
133 | secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); | |
134 | } | |
135 | } | |
136 | ||
137 | int secp256k1_ec_pubkey_parse(const secp256k1_context_t* ctx, secp256k1_pubkey_t* pubkey, const unsigned char *input, int inputlen) { | |
138 | secp256k1_ge_t Q; | |
139 | ||
140 | (void)ctx; | |
141 | if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { | |
142 | memset(pubkey, 0, sizeof(*pubkey)); | |
143 | return 0; | |
144 | } | |
145 | secp256k1_pubkey_save(pubkey, &Q); | |
146 | secp256k1_ge_clear(&Q); | |
147 | return 1; | |
148 | } | |
149 | ||
150 | int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_pubkey_t* pubkey, int compressed) { | |
151 | secp256k1_ge_t Q; | |
152 | ||
153 | (void)ctx; | |
995c5487 PW |
154 | return (secp256k1_pubkey_load(ctx, &Q, pubkey) && |
155 | secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, compressed)); | |
23cfa914 PW |
156 | } |
157 | ||
995c5487 PW |
158 | static void secp256k1_ecdsa_signature_load(const secp256k1_context_t* ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, int* recid, const secp256k1_ecdsa_signature_t* sig) { |
159 | (void)ctx; | |
74a2acdb PW |
160 | if (sizeof(secp256k1_scalar_t) == 32) { |
161 | /* When the secp256k1_scalar_t type is exactly 32 byte, use its | |
162 | * representation inside secp256k1_ecdsa_signature_t, as conversion is very fast. | |
163 | * Note that secp256k1_ecdsa_signature_save must use the same representation. */ | |
18c329c5 PW |
164 | memcpy(r, &sig->data[0], 32); |
165 | memcpy(s, &sig->data[32], 32); | |
74a2acdb | 166 | } else { |
18c329c5 PW |
167 | secp256k1_scalar_set_b32(r, &sig->data[0], NULL); |
168 | secp256k1_scalar_set_b32(s, &sig->data[32], NULL); | |
74a2acdb PW |
169 | } |
170 | if (recid) { | |
171 | *recid = sig->data[64]; | |
172 | } | |
173 | } | |
174 | ||
18c329c5 | 175 | static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s, int recid) { |
74a2acdb | 176 | if (sizeof(secp256k1_scalar_t) == 32) { |
18c329c5 PW |
177 | memcpy(&sig->data[0], r, 32); |
178 | memcpy(&sig->data[32], s, 32); | |
74a2acdb | 179 | } else { |
18c329c5 PW |
180 | secp256k1_scalar_get_b32(&sig->data[0], r); |
181 | secp256k1_scalar_get_b32(&sig->data[32], s); | |
74a2acdb PW |
182 | } |
183 | sig->data[64] = recid; | |
184 | } | |
185 | ||
186 | int secp256k1_ecdsa_signature_parse_der(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input, int inputlen) { | |
18c329c5 | 187 | secp256k1_scalar_t r, s; |
74a2acdb PW |
188 | |
189 | (void)ctx; | |
995c5487 PW |
190 | ARG_CHECK(sig != NULL); |
191 | ARG_CHECK(input != NULL); | |
74a2acdb | 192 | |
18c329c5 PW |
193 | if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { |
194 | secp256k1_ecdsa_signature_save(sig, &r, &s, -1); | |
74a2acdb PW |
195 | return 1; |
196 | } else { | |
197 | memset(sig, 0, sizeof(*sig)); | |
198 | return 0; | |
199 | } | |
200 | } | |
201 | ||
202 | int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input64, int recid) { | |
18c329c5 | 203 | secp256k1_scalar_t r, s; |
74a2acdb PW |
204 | int ret = 1; |
205 | int overflow = 0; | |
206 | ||
207 | (void)ctx; | |
995c5487 PW |
208 | ARG_CHECK(sig != NULL); |
209 | ARG_CHECK(input64 != NULL); | |
74a2acdb | 210 | |
18c329c5 | 211 | secp256k1_scalar_set_b32(&r, &input64[0], &overflow); |
74a2acdb | 212 | ret &= !overflow; |
18c329c5 | 213 | secp256k1_scalar_set_b32(&s, &input64[32], &overflow); |
74a2acdb PW |
214 | ret &= !overflow; |
215 | ret &= (recid == -1 || (recid >= 0 && recid < 4)); | |
216 | if (ret) { | |
18c329c5 | 217 | secp256k1_ecdsa_signature_save(sig, &r, &s, recid); |
74a2acdb PW |
218 | } else { |
219 | memset(sig, 0, sizeof(*sig)); | |
220 | } | |
221 | return ret; | |
222 | } | |
223 | ||
224 | int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_ecdsa_signature_t* sig) { | |
18c329c5 | 225 | secp256k1_scalar_t r, s; |
74a2acdb PW |
226 | |
227 | (void)ctx; | |
995c5487 PW |
228 | ARG_CHECK(output != NULL); |
229 | ARG_CHECK(outputlen != NULL); | |
230 | ARG_CHECK(sig != NULL); | |
74a2acdb | 231 | |
995c5487 | 232 | secp256k1_ecdsa_signature_load(ctx, &r, &s, NULL, sig); |
18c329c5 | 233 | return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); |
74a2acdb PW |
234 | } |
235 | ||
236 | int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context_t* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_signature_t* sig) { | |
18c329c5 | 237 | secp256k1_scalar_t r, s; |
74a2acdb PW |
238 | int rec; |
239 | ||
240 | (void)ctx; | |
995c5487 PW |
241 | ARG_CHECK(output64 != NULL); |
242 | ARG_CHECK(sig != NULL); | |
74a2acdb | 243 | |
995c5487 | 244 | secp256k1_ecdsa_signature_load(ctx, &r, &s, &rec, sig); |
18c329c5 PW |
245 | secp256k1_scalar_get_b32(&output64[0], &r); |
246 | secp256k1_scalar_get_b32(&output64[32], &s); | |
74a2acdb | 247 | if (recid) { |
995c5487 | 248 | ARG_CHECK(rec >= 0 && rec < 4); |
74a2acdb PW |
249 | *recid = rec; |
250 | } | |
251 | return 1; | |
252 | } | |
253 | ||
254 | int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_signature_t *sig, const secp256k1_pubkey_t *pubkey) { | |
f735446c | 255 | secp256k1_ge_t q; |
18c329c5 | 256 | secp256k1_scalar_t r, s; |
f735446c | 257 | secp256k1_scalar_t m; |
995c5487 PW |
258 | ARG_CHECK(ctx != NULL); |
259 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | |
260 | ARG_CHECK(msg32 != NULL); | |
261 | ARG_CHECK(sig != NULL); | |
262 | ARG_CHECK(pubkey != NULL); | |
1c7fa133 | 263 | |
f24041d6 | 264 | secp256k1_scalar_set_b32(&m, msg32, NULL); |
995c5487 PW |
265 | secp256k1_ecdsa_signature_load(ctx, &r, &s, NULL, sig); |
266 | return (secp256k1_pubkey_load(ctx, &q, pubkey) && | |
267 | secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); | |
607884fc PW |
268 | } |
269 | ||
bbd5ba7c | 270 | static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) { |
3e6f1e20 | 271 | unsigned char keydata[96]; |
bbd5ba7c | 272 | secp256k1_rfc6979_hmac_sha256_t rng; |
f735446c | 273 | unsigned int i; |
3e6f1e20 PW |
274 | /* We feed a byte array to the PRNG as input, consisting of: |
275 | * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. | |
276 | * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. | |
277 | */ | |
278 | memcpy(keydata, key32, 32); | |
279 | memcpy(keydata + 32, msg32, 32); | |
280 | if (data != NULL) { | |
281 | memcpy(keydata + 64, data, 32); | |
282 | } | |
283 | secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, data != NULL ? 96 : 64); | |
284 | memset(keydata, 0, sizeof(keydata)); | |
f735446c | 285 | for (i = 0; i <= counter; i++) { |
bbd5ba7c PW |
286 | secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); |
287 | } | |
288 | secp256k1_rfc6979_hmac_sha256_finalize(&rng); | |
289 | return 1; | |
290 | } | |
291 | ||
292 | const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; | |
293 | const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979; | |
294 | ||
74a2acdb | 295 | int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *msg32, secp256k1_ecdsa_signature_t *signature, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) { |
18c329c5 | 296 | secp256k1_scalar_t r, s; |
f735446c | 297 | secp256k1_scalar_t sec, non, msg; |
74a2acdb | 298 | int recid; |
f735446c GM |
299 | int ret = 0; |
300 | int overflow = 0; | |
301 | unsigned int count = 0; | |
995c5487 PW |
302 | ARG_CHECK(ctx != NULL); |
303 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | |
304 | ARG_CHECK(msg32 != NULL); | |
305 | ARG_CHECK(signature != NULL); | |
306 | ARG_CHECK(seckey != NULL); | |
bbd5ba7c PW |
307 | if (noncefp == NULL) { |
308 | noncefp = secp256k1_nonce_function_default; | |
309 | } | |
1c7fa133 | 310 | |
8030d7c0 | 311 | secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
0065a8fb GM |
312 | /* Fail if the secret key is invalid. */ |
313 | if (!overflow && !secp256k1_scalar_is_zero(&sec)) { | |
314 | secp256k1_scalar_set_b32(&msg, msg32, NULL); | |
315 | while (1) { | |
316 | unsigned char nonce32[32]; | |
317 | ret = noncefp(nonce32, msg32, seckey, count, noncedata); | |
318 | if (!ret) { | |
c6e7f4e8 PW |
319 | break; |
320 | } | |
0065a8fb GM |
321 | secp256k1_scalar_set_b32(&non, nonce32, &overflow); |
322 | memset(nonce32, 0, 32); | |
323 | if (!secp256k1_scalar_is_zero(&non) && !overflow) { | |
18c329c5 | 324 | if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) { |
0065a8fb GM |
325 | break; |
326 | } | |
327 | } | |
328 | count++; | |
c6e7f4e8 | 329 | } |
0065a8fb GM |
330 | secp256k1_scalar_clear(&msg); |
331 | secp256k1_scalar_clear(&non); | |
332 | secp256k1_scalar_clear(&sec); | |
78239167 | 333 | } |
74a2acdb | 334 | if (ret) { |
18c329c5 | 335 | secp256k1_ecdsa_signature_save(signature, &r, &s, recid); |
74a2acdb PW |
336 | } else { |
337 | memset(signature, 0, sizeof(*signature)); | |
8030d7c0 | 338 | } |
50eb498e PW |
339 | return ret; |
340 | } | |
341 | ||
74a2acdb | 342 | int secp256k1_ecdsa_recover(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_signature_t *signature, secp256k1_pubkey_t *pubkey) { |
f735446c | 343 | secp256k1_ge_t q; |
18c329c5 | 344 | secp256k1_scalar_t r, s; |
f735446c | 345 | secp256k1_scalar_t m; |
74a2acdb | 346 | int recid; |
995c5487 PW |
347 | ARG_CHECK(ctx != NULL); |
348 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | |
349 | ARG_CHECK(msg32 != NULL); | |
350 | ARG_CHECK(signature != NULL); | |
351 | ARG_CHECK(pubkey != NULL); | |
352 | ||
353 | secp256k1_ecdsa_signature_load(ctx, &r, &s, &recid, signature); | |
354 | ARG_CHECK(recid >= 0 && recid < 4); | |
74a2acdb | 355 | secp256k1_scalar_set_b32(&m, msg32, NULL); |
18c329c5 | 356 | if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { |
74a2acdb PW |
357 | secp256k1_pubkey_save(pubkey, &q); |
358 | return 1; | |
359 | } else { | |
360 | memset(pubkey, 0, sizeof(*pubkey)); | |
361 | return 0; | |
50eb498e | 362 | } |
50eb498e PW |
363 | } |
364 | ||
a9b6595e | 365 | int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned char *seckey) { |
a9f5c8b8 | 366 | secp256k1_scalar_t sec; |
f735446c | 367 | int ret; |
a9f5c8b8 | 368 | int overflow; |
995c5487 PW |
369 | ARG_CHECK(ctx != NULL); |
370 | ARG_CHECK(seckey != NULL); | |
a9b6595e | 371 | (void)ctx; |
f735446c | 372 | |
eca6cdb1 | 373 | secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
f735446c | 374 | ret = !secp256k1_scalar_is_zero(&sec) && !overflow; |
a9f5c8b8 | 375 | secp256k1_scalar_clear(&sec); |
42cccdaf PW |
376 | return ret; |
377 | } | |
378 | ||
23cfa914 | 379 | int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *seckey) { |
f735446c GM |
380 | secp256k1_gej_t pj; |
381 | secp256k1_ge_t p; | |
382 | secp256k1_scalar_t sec; | |
354ffa33 | 383 | int overflow; |
0065a8fb | 384 | int ret = 0; |
995c5487 PW |
385 | ARG_CHECK(ctx != NULL); |
386 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | |
387 | ARG_CHECK(pubkey != NULL); | |
388 | ARG_CHECK(seckey != NULL); | |
1c7fa133 | 389 | |
354ffa33 | 390 | secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
23cfa914 PW |
391 | ret = !overflow & !secp256k1_scalar_is_zero(&sec); |
392 | secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); | |
393 | secp256k1_ge_set_gej(&p, &pj); | |
394 | secp256k1_pubkey_save(pubkey, &p); | |
395 | secp256k1_scalar_clear(&sec); | |
0065a8fb | 396 | if (!ret) { |
23cfa914 | 397 | memset(pubkey, 0, sizeof(*pubkey)); |
99fd963b | 398 | } |
99fd963b TK |
399 | return ret; |
400 | } | |
401 | ||
a9b6595e | 402 | int secp256k1_ec_privkey_tweak_add(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *tweak) { |
f735446c GM |
403 | secp256k1_scalar_t term; |
404 | secp256k1_scalar_t sec; | |
0065a8fb | 405 | int ret = 0; |
f735446c | 406 | int overflow = 0; |
995c5487 PW |
407 | ARG_CHECK(ctx != NULL); |
408 | ARG_CHECK(seckey != NULL); | |
409 | ARG_CHECK(tweak != NULL); | |
a9b6595e | 410 | (void)ctx; |
1c7fa133 | 411 | |
eca6cdb1 | 412 | secp256k1_scalar_set_b32(&term, tweak, &overflow); |
eca6cdb1 | 413 | secp256k1_scalar_set_b32(&sec, seckey, NULL); |
eb74c36b | 414 | |
f735446c | 415 | ret = secp256k1_eckey_privkey_tweak_add(&sec, &term) && !overflow; |
561b0e10 | 416 | if (ret) { |
eca6cdb1 | 417 | secp256k1_scalar_get_b32(seckey, &sec); |
eb74c36b PW |
418 | } |
419 | ||
a9f5c8b8 PW |
420 | secp256k1_scalar_clear(&sec); |
421 | secp256k1_scalar_clear(&term); | |
561b0e10 PW |
422 | return ret; |
423 | } | |
424 | ||
23cfa914 | 425 | int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) { |
f735446c GM |
426 | secp256k1_ge_t p; |
427 | secp256k1_scalar_t term; | |
0065a8fb | 428 | int ret = 0; |
f735446c | 429 | int overflow = 0; |
995c5487 PW |
430 | ARG_CHECK(ctx != NULL); |
431 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | |
432 | ARG_CHECK(pubkey != NULL); | |
433 | ARG_CHECK(tweak != NULL); | |
1c7fa133 | 434 | |
f24041d6 | 435 | secp256k1_scalar_set_b32(&term, tweak, &overflow); |
995c5487 | 436 | if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) { |
23cfa914 | 437 | ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term); |
0065a8fb | 438 | if (ret) { |
23cfa914 PW |
439 | secp256k1_pubkey_save(pubkey, &p); |
440 | } else { | |
441 | memset(pubkey, 0, sizeof(*pubkey)); | |
0065a8fb | 442 | } |
86d3cce2 | 443 | } |
eb74c36b | 444 | |
86d3cce2 PW |
445 | return ret; |
446 | } | |
447 | ||
a9b6595e | 448 | int secp256k1_ec_privkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *tweak) { |
f735446c GM |
449 | secp256k1_scalar_t factor; |
450 | secp256k1_scalar_t sec; | |
0065a8fb | 451 | int ret = 0; |
f735446c | 452 | int overflow = 0; |
995c5487 PW |
453 | ARG_CHECK(ctx != NULL); |
454 | ARG_CHECK(seckey != NULL); | |
455 | ARG_CHECK(tweak != NULL); | |
a9b6595e | 456 | (void)ctx; |
1c7fa133 | 457 | |
eca6cdb1 | 458 | secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
eca6cdb1 | 459 | secp256k1_scalar_set_b32(&sec, seckey, NULL); |
f735446c | 460 | ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor) && !overflow; |
86d3cce2 | 461 | if (ret) { |
eca6cdb1 | 462 | secp256k1_scalar_get_b32(seckey, &sec); |
eb74c36b PW |
463 | } |
464 | ||
a9f5c8b8 PW |
465 | secp256k1_scalar_clear(&sec); |
466 | secp256k1_scalar_clear(&factor); | |
86d3cce2 PW |
467 | return ret; |
468 | } | |
469 | ||
23cfa914 | 470 | int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) { |
f735446c GM |
471 | secp256k1_ge_t p; |
472 | secp256k1_scalar_t factor; | |
0065a8fb | 473 | int ret = 0; |
f735446c | 474 | int overflow = 0; |
995c5487 PW |
475 | ARG_CHECK(ctx != NULL); |
476 | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | |
477 | ARG_CHECK(pubkey != NULL); | |
478 | ARG_CHECK(tweak != NULL); | |
1c7fa133 | 479 | |
f24041d6 | 480 | secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
995c5487 | 481 | if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) { |
23cfa914 | 482 | ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor); |
0065a8fb | 483 | if (ret) { |
23cfa914 PW |
484 | secp256k1_pubkey_save(pubkey, &p); |
485 | } else { | |
486 | memset(pubkey, 0, sizeof(*pubkey)); | |
0065a8fb | 487 | } |
561b0e10 | 488 | } |
eb74c36b | 489 | |
561b0e10 PW |
490 | return ret; |
491 | } | |
492 | ||
a9b6595e | 493 | int secp256k1_ec_privkey_export(const secp256k1_context_t* ctx, const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) { |
f735446c | 494 | secp256k1_scalar_t key; |
0065a8fb | 495 | int ret = 0; |
995c5487 PW |
496 | ARG_CHECK(seckey != NULL); |
497 | ARG_CHECK(privkey != NULL); | |
498 | ARG_CHECK(privkeylen != NULL); | |
499 | ARG_CHECK(ctx != NULL); | |
500 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | |
1c7fa133 | 501 | |
eca6cdb1 | 502 | secp256k1_scalar_set_b32(&key, seckey, NULL); |
a9b6595e | 503 | ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, compressed); |
a9f5c8b8 | 504 | secp256k1_scalar_clear(&key); |
da3038c7 PW |
505 | return ret; |
506 | } | |
507 | ||
a9b6595e | 508 | int secp256k1_ec_privkey_import(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *privkey, int privkeylen) { |
f735446c | 509 | secp256k1_scalar_t key; |
0065a8fb | 510 | int ret = 0; |
995c5487 PW |
511 | ARG_CHECK(seckey != NULL); |
512 | ARG_CHECK(privkey != NULL); | |
a9b6595e | 513 | (void)ctx; |
1c7fa133 | 514 | |
f735446c | 515 | ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen); |
0065a8fb | 516 | if (ret) { |
eca6cdb1 | 517 | secp256k1_scalar_get_b32(seckey, &key); |
0065a8fb | 518 | } |
a9f5c8b8 | 519 | secp256k1_scalar_clear(&key); |
da3038c7 PW |
520 | return ret; |
521 | } | |
d2275795 GM |
522 | |
523 | int secp256k1_context_randomize(secp256k1_context_t* ctx, const unsigned char *seed32) { | |
995c5487 PW |
524 | ARG_CHECK(ctx != NULL); |
525 | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | |
d2275795 GM |
526 | secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); |
527 | return 1; | |
528 | } |