Skip to content

Commit d899b5b

Browse files
committed
Expose ability to deep-copy a context
1 parent 3608c7f commit d899b5b

File tree

7 files changed

+91
-0
lines changed

7 files changed

+91
-0
lines changed

include/secp256k1.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ secp256k1_context_t* secp256k1_context_create(
5959
int flags
6060
) SECP256K1_WARN_UNUSED_RESULT;
6161

62+
/** Copies a secp256k1 context object.
63+
* Returns: a newly created context object.
64+
* In: ctx: an existing context to copy
65+
*/
66+
secp256k1_context_t* secp256k1_context_clone(
67+
const secp256k1_context_t* ctx
68+
) SECP256K1_WARN_UNUSED_RESULT;
69+
6270
/** Destroy a secp256k1 context object.
6371
* The context pointer may not be used afterwards.
6472
*/

src/ecmult.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ typedef struct {
2020

2121
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context_t *ctx);
2222
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx);
23+
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context_t *dst,
24+
const secp256k1_ecmult_context_t *src);
2325
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context_t *ctx);
2426
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context_t *ctx);
2527

src/ecmult_gen.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ typedef struct {
2828

2929
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context_t* ctx);
3030
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t* ctx);
31+
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context_t *dst,
32+
const secp256k1_ecmult_gen_context_t* src);
3133
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t* ctx);
3234
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context_t* ctx);
3335

src/ecmult_gen_impl.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_cont
8080
return ctx->prec != NULL;
8181
}
8282

83+
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context_t *dst,
84+
const secp256k1_ecmult_gen_context_t *src) {
85+
if (src->prec == NULL) {
86+
dst->prec = NULL;
87+
} else {
88+
dst->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(sizeof(*dst->prec));
89+
memcpy(dst->prec, src->prec, sizeof(*dst->prec));
90+
}
91+
}
92+
8393
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t *ctx) {
8494
free(ctx->prec);
8595
ctx->prec = NULL;

src/ecmult_impl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,26 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx) {
131131
#endif
132132
}
133133

134+
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context_t *dst,
135+
const secp256k1_ecmult_context_t *src) {
136+
if (src->pre_g == NULL) {
137+
dst->pre_g = NULL;
138+
} else {
139+
size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
140+
dst->pre_g = (secp256k1_ge_storage_t (*)[])checked_malloc(size);
141+
memcpy(dst->pre_g, src->pre_g, size);
142+
}
143+
#ifdef USE_ENDOMORPHISM
144+
if (src->pre_g_128 == NULL) {
145+
dst->pre_g_128 = NULL;
146+
} else {
147+
size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
148+
dst->pre_g_128 = (secp256k1_ge_storage_t (*)[])checked_malloc(size);
149+
memcpy(dst->pre_g_128, src->pre_g_128, size);
150+
}
151+
#endif
152+
}
153+
134154
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context_t *ctx) {
135155
return ctx->pre_g != NULL;
136156
}

src/secp256k1.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ secp256k1_context_t* secp256k1_context_create(int flags) {
4040
return ret;
4141
}
4242

43+
secp256k1_context_t* secp256k1_context_clone(const secp256k1_context_t* ctx) {
44+
secp256k1_context_t* ret = (secp256k1_context_t*)checked_malloc(sizeof(secp256k1_context_t));
45+
secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx);
46+
secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx);
47+
return ret;
48+
}
49+
4350
void secp256k1_context_destroy(secp256k1_context_t* ctx) {
4451
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
4552
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);

src/tests.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,47 @@ void random_scalar_order(secp256k1_scalar_t *num) {
103103
} while(1);
104104
}
105105

106+
void run_context_tests(void) {
107+
secp256k1_context_t *none = secp256k1_context_create(0);
108+
secp256k1_context_t *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
109+
secp256k1_context_t *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
110+
secp256k1_context_t *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
111+
112+
secp256k1_gej_t pubj;
113+
secp256k1_ge_t pub;
114+
secp256k1_scalar_t msg, key, nonce;
115+
secp256k1_ecdsa_sig_t sig;
116+
117+
/*** clone and destroy all of them to make sure cloning was complete ***/
118+
{
119+
secp256k1_context_t *ctx_tmp;
120+
121+
ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_destroy(ctx_tmp);
122+
ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_destroy(ctx_tmp);
123+
ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_destroy(ctx_tmp);
124+
ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp);
125+
}
126+
127+
/*** attempt to use them ***/
128+
random_scalar_order_test(&msg);
129+
random_scalar_order_test(&key);
130+
secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key);
131+
secp256k1_ge_set_gej(&pub, &pubj);
132+
133+
/* obtain a working nonce */
134+
do {
135+
random_scalar_order_test(&nonce);
136+
} while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL));
137+
138+
/* try signing */
139+
CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL));
140+
CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL));
141+
142+
/* try verifying */
143+
CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sig, &pub, &msg));
144+
CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sig, &pub, &msg));
145+
}
146+
106147
/***** HASH TESTS *****/
107148

108149
void run_sha256_tests(void) {
@@ -1863,6 +1904,7 @@ int main(int argc, char **argv) {
18631904
printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]);
18641905

18651906
/* initialize */
1907+
run_context_tests();
18661908
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
18671909

18681910
run_sha256_tests();

0 commit comments

Comments
 (0)