1 #include "internal.h"
2 #include <include/wally_crypto.h>
3 #include "ccan/ccan/build_assert/build_assert.h"
4 #include "ccan/ccan/crypto/ripemd160/ripemd160.h"
5 #include "ccan/ccan/crypto/sha256/sha256.h"
6 #include "ccan/ccan/crypto/sha512/sha512.h"
7 #include "ccan/ccan/endian/endian.h"
8 #include <stdbool.h>
9 
10 #undef malloc
11 #undef free
12 
13 #if defined(_WIN32)
14 #define WIN32_LEAN_AND_MEAN
15 #include <windows.h>
16 #undef WIN32_LEAN_AND_MEAN
17 #endif
18 
19 /* Caller is responsible for thread safety */
20 static secp256k1_context *global_ctx = NULL;
21 
privkey_tweak_add(unsigned char * seckey,const unsigned char * tweak)22 int privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak)
23 {
24     return secp256k1_ec_privkey_tweak_add(secp256k1_context_no_precomp, seckey, tweak);
25 }
26 
pubkey_combine(secp256k1_pubkey * pubnonce,const secp256k1_pubkey * const * pubnonces,size_t n)27 int pubkey_combine(secp256k1_pubkey *pubnonce, const secp256k1_pubkey *const *pubnonces, size_t n)
28 {
29     return secp256k1_ec_pubkey_combine(secp256k1_context_no_precomp, pubnonce, pubnonces, n);
30 }
31 
pubkey_negate(secp256k1_pubkey * pubkey)32 int pubkey_negate(secp256k1_pubkey *pubkey)
33 {
34     return secp256k1_ec_pubkey_negate(secp256k1_context_no_precomp, pubkey);
35 }
36 
pubkey_parse(secp256k1_pubkey * pubkey,const unsigned char * input,size_t inputlen)37 int pubkey_parse(secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen)
38 {
39     return secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, pubkey, input, inputlen);
40 }
41 
pubkey_serialize(unsigned char * output,size_t * outputlen,const secp256k1_pubkey * pubkey,unsigned int flags)42 int pubkey_serialize(unsigned char *output, size_t *outputlen, const secp256k1_pubkey *pubkey, unsigned int flags)
43 {
44     return secp256k1_ec_pubkey_serialize(secp256k1_context_no_precomp, output, outputlen, pubkey, flags);
45 }
46 
seckey_verify(const unsigned char * seckey)47 int seckey_verify(const unsigned char *seckey)
48 {
49     return secp256k1_ec_seckey_verify(secp256k1_context_no_precomp, seckey);
50 }
51 
52 #ifndef SWIG
wally_get_secp_context(void)53 struct secp256k1_context_struct *wally_get_secp_context(void)
54 {
55     return (struct secp256k1_context_struct *)secp_ctx();
56 }
57 #endif
58 
wally_secp_randomize(const unsigned char * bytes,size_t bytes_len)59 int wally_secp_randomize(const unsigned char *bytes, size_t bytes_len)
60 {
61     secp256k1_context *ctx;
62 
63     if (!bytes || bytes_len != WALLY_SECP_RANDOMIZE_LEN)
64         return WALLY_EINVAL;
65 
66     if (!(ctx = (secp256k1_context *)secp_ctx()))
67         return WALLY_ENOMEM;
68 
69     if (!secp256k1_context_randomize(ctx, bytes))
70         return WALLY_ERROR;
71 
72     return WALLY_OK;
73 }
74 
wally_free_string(char * str)75 int wally_free_string(char *str)
76 {
77     if (!str)
78         return WALLY_EINVAL;
79     wally_clear(str, strlen(str));
80     wally_free(str);
81     return WALLY_OK;
82 }
83 
wally_bzero(void * bytes,size_t len)84 int wally_bzero(void *bytes, size_t len)
85 {
86     if (!bytes)
87         return WALLY_EINVAL;
88     wally_clear(bytes, len);
89     return WALLY_OK;
90 }
91 
wally_sha256(const unsigned char * bytes,size_t bytes_len,unsigned char * bytes_out,size_t len)92 int wally_sha256(const unsigned char *bytes, size_t bytes_len,
93                  unsigned char *bytes_out, size_t len)
94 {
95     struct sha256 sha;
96     bool aligned = alignment_ok(bytes_out, sizeof(sha.u.u32));
97 
98     if ((!bytes && bytes_len != 0) || !bytes_out || len != SHA256_LEN)
99         return WALLY_EINVAL;
100 
101     sha256(aligned ? (struct sha256 *)bytes_out : &sha, bytes, bytes_len);
102     if (!aligned) {
103         memcpy(bytes_out, &sha, sizeof(sha));
104         wally_clear(&sha, sizeof(sha));
105     }
106     return WALLY_OK;
107 }
108 
sha256_midstate(struct sha256_ctx * ctx,struct sha256 * res)109 static void sha256_midstate(struct sha256_ctx *ctx, struct sha256 *res)
110 {
111     size_t i;
112 
113     for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++)
114         res->u.u32[i] = cpu_to_be32(ctx->s[i]);
115     ctx->bytes = (size_t)-1;
116 }
117 
wally_sha256_midstate(const unsigned char * bytes,size_t bytes_len,unsigned char * bytes_out,size_t len)118 int wally_sha256_midstate(const unsigned char *bytes, size_t bytes_len,
119                           unsigned char *bytes_out, size_t len)
120 {
121     struct sha256 sha;
122     struct sha256_ctx ctx;
123     bool aligned = alignment_ok(bytes_out, sizeof(sha.u.u32));
124 
125     if ((!bytes && bytes_len != 0) || !bytes_out || len != SHA256_LEN)
126         return WALLY_EINVAL;
127 
128     sha256_init(&ctx);
129     sha256_update(&ctx, bytes, bytes_len);
130     sha256_midstate(&ctx, aligned ? (struct sha256 *)bytes_out : &sha);
131     wally_clear(&ctx, sizeof(ctx));
132 
133     if (!aligned) {
134         memcpy(bytes_out, &sha, sizeof(sha));
135         wally_clear(&sha, sizeof(sha));
136     }
137     return WALLY_OK;
138 }
139 
wally_sha256d(const unsigned char * bytes,size_t bytes_len,unsigned char * bytes_out,size_t len)140 int wally_sha256d(const unsigned char *bytes, size_t bytes_len,
141                   unsigned char *bytes_out, size_t len)
142 {
143     struct sha256 sha_1, sha_2;
144     bool aligned = alignment_ok(bytes_out, sizeof(sha_1.u.u32));
145 
146     if ((!bytes && bytes_len != 0) || !bytes_out || len != SHA256_LEN)
147         return WALLY_EINVAL;
148 
149     sha256(&sha_1, bytes, bytes_len);
150     sha256(aligned ? (struct sha256 *)bytes_out : &sha_2, &sha_1, sizeof(sha_1));
151     if (!aligned) {
152         memcpy(bytes_out, &sha_2, sizeof(sha_2));
153         wally_clear(&sha_2, sizeof(sha_2));
154     }
155     wally_clear(&sha_1, sizeof(sha_1));
156     return WALLY_OK;
157 }
158 
wally_sha512(const unsigned char * bytes,size_t bytes_len,unsigned char * bytes_out,size_t len)159 int wally_sha512(const unsigned char *bytes, size_t bytes_len,
160                  unsigned char *bytes_out, size_t len)
161 {
162     struct sha512 sha;
163     bool aligned = alignment_ok(bytes_out, sizeof(sha.u.u64));
164 
165     if ((!bytes && bytes_len != 0) || !bytes_out || len != SHA512_LEN)
166         return WALLY_EINVAL;
167 
168     sha512(aligned ? (struct sha512 *)bytes_out : &sha, bytes, bytes_len);
169     if (!aligned) {
170         memcpy(bytes_out, &sha, sizeof(sha));
171         wally_clear(&sha, sizeof(sha));
172     }
173     return WALLY_OK;
174 }
175 
wally_hash160(const unsigned char * bytes,size_t bytes_len,unsigned char * bytes_out,size_t len)176 int wally_hash160(const unsigned char *bytes, size_t bytes_len,
177                   unsigned char *bytes_out, size_t len)
178 {
179     unsigned char buff[SHA256_LEN];
180     struct ripemd160 ripemd;
181     const bool aligned = alignment_ok(bytes_out, sizeof(ripemd.u.u32));
182 
183     if (!bytes_out || len != HASH160_LEN)
184         return WALLY_EINVAL;
185 
186     BUILD_ASSERT(sizeof(ripemd) == HASH160_LEN);
187 
188     if (wally_sha256(bytes, bytes_len, buff, sizeof(buff)) != WALLY_OK)
189         return WALLY_EINVAL;
190 
191     ripemd160(aligned ? (struct ripemd160 *)bytes_out : &ripemd, &buff, sizeof(buff));
192     if (!aligned) {
193         memcpy(bytes_out, &ripemd, sizeof(ripemd));
194         wally_clear(&ripemd, sizeof(ripemd));
195     }
196     wally_clear(&buff, sizeof(buff));
197     return WALLY_OK;
198 }
199 
200 /*
201  * For clang 7.0.1 and up it may be useful to disable the memset builtin for this code to not be elided when on -O3.
202  * The following program can be used to check what your compiler is doing.
203  * printf "#include <string.h> \n int main() { unsigned char s[10]; memset(s, 0, sizeof(s)); }" | clang -O3 -fno-builtin-memset -o memset.ll -S -emit-llvm -x c -
204  */
wally_internal_bzero(void * dest,size_t len)205 static void wally_internal_bzero(void *dest, size_t len)
206 {
207 #ifdef _WIN32
208     SecureZeroMemory(dest, len);
209 #elif defined(HAVE_MEMSET_S)
210     memset_s(dest, len, 0, len);
211 #elif defined(HAVE_EXPLICIT_BZERO)
212     explicit_bzero(dest, len);
213 #elif defined(HAVE_EXPLICIT_MEMSET)
214     explicit_memset(dest, 0, len);
215 #else
216     memset(dest, 0, len);
217 #if defined(HAVE_INLINE_ASM)
218     /* This is used by boringssl to prevent memset from being elided. It
219      * works by forcing a memory barrier and so can be slow.
220      */
221     __asm__ __volatile__ ("" : : "r" (dest) : "memory");
222 #endif
223 #endif
224 }
225 
wally_internal_malloc(size_t size)226 static void *wally_internal_malloc(size_t size)
227 {
228     return malloc(size);
229 }
230 
wally_internal_free(void * ptr)231 static void wally_internal_free(void *ptr)
232 {
233     if (ptr)
234         free(ptr);
235 }
236 
wally_internal_ec_nonce_fn(unsigned char * nonce32,const unsigned char * msg32,const unsigned char * key32,const unsigned char * algo16,void * data,unsigned int attempt)237 static int wally_internal_ec_nonce_fn(unsigned char *nonce32,
238                                       const unsigned char *msg32, const unsigned char *key32,
239                                       const unsigned char *algo16, void *data, unsigned int attempt)
240 {
241     return secp256k1_nonce_function_default(nonce32, msg32, key32, algo16, data, attempt);
242 }
243 
wally_get_new_secp_context(void)244 struct secp256k1_context_struct *wally_get_new_secp_context(void)
245 {
246     return secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
247 }
248 
wally_internal_secp_context(void)249 struct secp256k1_context_struct *wally_internal_secp_context(void)
250 {
251     /* Default implementation uses a lazy-initialized global context,
252      * this should be fetched or set by the caller before any threads
253      * are created in order to be thread-safe. */
254     if (!global_ctx)
255         global_ctx = wally_get_new_secp_context();
256 
257     return global_ctx;
258 }
259 
260 static struct wally_operations _ops = {
261     sizeof(struct wally_operations),
262     wally_internal_malloc,
263     wally_internal_free,
264     wally_internal_bzero,
265     wally_internal_ec_nonce_fn,
266     wally_internal_secp_context,
267     NULL,
268     NULL,
269     NULL,
270     NULL
271 };
272 
secp_ctx(void)273 const secp256k1_context *secp_ctx(void)
274 {
275     return (const secp256k1_context *)_ops.secp_context_fn();
276 }
277 
wally_malloc(size_t size)278 void *wally_malloc(size_t size)
279 {
280     return _ops.malloc_fn(size);
281 }
282 
wally_calloc(size_t size)283 void *wally_calloc(size_t size)
284 {
285     void *p = _ops.malloc_fn(size);
286     (void) wally_bzero(p, size);
287     return p;
288 }
289 
wally_free(void * ptr)290 void wally_free(void *ptr)
291 {
292     _ops.free_fn(ptr);
293 }
294 
wally_strdup(const char * str)295 char *wally_strdup(const char *str)
296 {
297     size_t len = strlen(str) + 1;
298     char *new_str = (char *)wally_malloc(len);
299     if (new_str)
300         memcpy(new_str, str, len); /* Copies terminating nul */
301     return new_str;
302 }
303 
wally_ops(void)304 const struct wally_operations *wally_ops(void)
305 {
306     return &_ops;
307 }
308 
wally_get_operations(struct wally_operations * output)309 int wally_get_operations(struct wally_operations *output)
310 {
311     if (!output || output->struct_size != sizeof(struct wally_operations))
312         return WALLY_EINVAL;
313     memcpy(output, &_ops, sizeof(_ops));
314     return WALLY_OK;
315 }
316 
wally_set_operations(const struct wally_operations * ops)317 int wally_set_operations(const struct wally_operations *ops)
318 {
319     if (!ops || ops->struct_size != sizeof(struct wally_operations))
320         return WALLY_EINVAL; /* Null or invalid version of ops */
321     /* Reserved pointers must be null so they can be enabled in the
322      * future without breaking back compatibility */
323     if (ops->reserved_1 || ops->reserved_2 || ops->reserved_3 || ops->reserved_4)
324         return WALLY_EINVAL;
325 
326 #define COPY_FN_PTR(name) if (ops->name) _ops.name = ops->name
327     COPY_FN_PTR(malloc_fn);
328     COPY_FN_PTR(free_fn);
329     COPY_FN_PTR (bzero_fn);
330     COPY_FN_PTR (ec_nonce_fn);
331     COPY_FN_PTR (secp_context_fn);
332 #undef COPY_FN_PTR
333     return WALLY_OK;
334 }
335 
wally_is_elements_build(size_t * written)336 int wally_is_elements_build(size_t *written)
337 {
338     if (!written)
339         return WALLY_EINVAL;
340 #ifdef BUILD_ELEMENTS
341     *written = 1;
342 #else
343     *written = 0;
344 #endif
345     return WALLY_OK;
346 }
347 
wally_clear(void * p,size_t len)348 void wally_clear(void *p, size_t len){
349     _ops.bzero_fn(p, len);
350 }
351 
wally_clear_2(void * p,size_t len,void * p2,size_t len2)352 void wally_clear_2(void *p, size_t len, void *p2, size_t len2){
353     _ops.bzero_fn(p, len);
354     _ops.bzero_fn(p2, len2);
355 }
356 
wally_clear_3(void * p,size_t len,void * p2,size_t len2,void * p3,size_t len3)357 void wally_clear_3(void *p, size_t len, void *p2, size_t len2,
358                    void *p3, size_t len3){
359     _ops.bzero_fn(p, len);
360     _ops.bzero_fn(p2, len2);
361     _ops.bzero_fn(p3, len3);
362 }
363 
wally_clear_4(void * p,size_t len,void * p2,size_t len2,void * p3,size_t len3,void * p4,size_t len4)364 void wally_clear_4(void *p, size_t len, void *p2, size_t len2,
365                    void *p3, size_t len3, void *p4, size_t len4){
366     _ops.bzero_fn(p, len);
367     _ops.bzero_fn(p2, len2);
368     _ops.bzero_fn(p3, len3);
369     _ops.bzero_fn(p4, len4);
370 }
371 
clear_and_free(void * p,size_t len)372 void clear_and_free(void *p, size_t len)
373 {
374     if (p) {
375         wally_clear(p, len);
376         wally_free(p);
377     }
378 }
379 
380 static bool wally_init_done = false;
381 
wally_init(uint32_t flags)382 int wally_init(uint32_t flags)
383 {
384     if (flags)
385         return WALLY_EINVAL;
386 
387     if (!wally_init_done) {
388         sha256_optimize();
389         wally_init_done = true;
390     }
391 
392     return WALLY_OK;
393 }
394 
wally_cleanup(uint32_t flags)395 int wally_cleanup(uint32_t flags)
396 {
397     if (flags)
398         return WALLY_EINVAL;
399     if (global_ctx) {
400         wally_secp_context_free(global_ctx);
401         global_ctx = NULL;
402     }
403     return WALLY_OK;
404 }
405 
wally_secp_context_free(struct secp256k1_context_struct * ctx)406 void wally_secp_context_free(struct secp256k1_context_struct *ctx)
407 {
408 #undef secp256k1_context_destroy
409     if (ctx)
410         secp256k1_context_destroy(ctx);
411 }
412 
413 #ifdef __ANDROID__
414 #define malloc(size) wally_malloc(size)
415 #define free(ptr) wally_free(ptr)
416 #include "cpufeatures/cpu-features.c"
417 #endif
418