Skip to content

Commit

Permalink
Merge pull request bitcoin#236
Browse files Browse the repository at this point in the history
d899b5b Expose ability to deep-copy a context (Andrew Poelstra)
  • Loading branch information
sipa committed Apr 12, 2015
2 parents 3608c7f + d899b5b commit 9688030
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 0 deletions.
8 changes: 8 additions & 0 deletions include/secp256k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ secp256k1_context_t* secp256k1_context_create(
int flags
) SECP256K1_WARN_UNUSED_RESULT;

/** Copies a secp256k1 context object.
* Returns: a newly created context object.
* In: ctx: an existing context to copy
*/
secp256k1_context_t* secp256k1_context_clone(
const secp256k1_context_t* ctx
) SECP256K1_WARN_UNUSED_RESULT;

/** Destroy a secp256k1 context object.
* The context pointer may not be used afterwards.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/ecmult.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ typedef struct {

static void secp256k1_ecmult_context_init(secp256k1_ecmult_context_t *ctx);
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx);
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context_t *dst,
const secp256k1_ecmult_context_t *src);
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context_t *ctx);
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context_t *ctx);

Expand Down
2 changes: 2 additions & 0 deletions src/ecmult_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ typedef struct {

static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context_t* ctx);
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t* ctx);
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context_t *dst,
const secp256k1_ecmult_gen_context_t* src);
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t* ctx);
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context_t* ctx);

Expand Down
10 changes: 10 additions & 0 deletions src/ecmult_gen_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_cont
return ctx->prec != NULL;
}

static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context_t *dst,
const secp256k1_ecmult_gen_context_t *src) {
if (src->prec == NULL) {
dst->prec = NULL;
} else {
dst->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(sizeof(*dst->prec));
memcpy(dst->prec, src->prec, sizeof(*dst->prec));
}
}

static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t *ctx) {
free(ctx->prec);
ctx->prec = NULL;
Expand Down
20 changes: 20 additions & 0 deletions src/ecmult_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,26 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx) {
#endif
}

static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context_t *dst,
const secp256k1_ecmult_context_t *src) {
if (src->pre_g == NULL) {
dst->pre_g = NULL;
} else {
size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
dst->pre_g = (secp256k1_ge_storage_t (*)[])checked_malloc(size);
memcpy(dst->pre_g, src->pre_g, size);
}
#ifdef USE_ENDOMORPHISM
if (src->pre_g_128 == NULL) {
dst->pre_g_128 = NULL;
} else {
size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
dst->pre_g_128 = (secp256k1_ge_storage_t (*)[])checked_malloc(size);
memcpy(dst->pre_g_128, src->pre_g_128, size);
}
#endif
}

static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context_t *ctx) {
return ctx->pre_g != NULL;
}
Expand Down
7 changes: 7 additions & 0 deletions src/secp256k1.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ secp256k1_context_t* secp256k1_context_create(int flags) {
return ret;
}

secp256k1_context_t* secp256k1_context_clone(const secp256k1_context_t* ctx) {
secp256k1_context_t* ret = (secp256k1_context_t*)checked_malloc(sizeof(secp256k1_context_t));
secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx);
secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx);
return ret;
}

void secp256k1_context_destroy(secp256k1_context_t* ctx) {
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
Expand Down
42 changes: 42 additions & 0 deletions src/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,47 @@ void random_scalar_order(secp256k1_scalar_t *num) {
} while(1);
}

void run_context_tests(void) {
secp256k1_context_t *none = secp256k1_context_create(0);
secp256k1_context_t *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
secp256k1_context_t *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
secp256k1_context_t *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);

secp256k1_gej_t pubj;
secp256k1_ge_t pub;
secp256k1_scalar_t msg, key, nonce;
secp256k1_ecdsa_sig_t sig;

/*** clone and destroy all of them to make sure cloning was complete ***/
{
secp256k1_context_t *ctx_tmp;

ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_destroy(ctx_tmp);
ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_destroy(ctx_tmp);
ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_destroy(ctx_tmp);
ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp);
}

/*** attempt to use them ***/
random_scalar_order_test(&msg);
random_scalar_order_test(&key);
secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key);
secp256k1_ge_set_gej(&pub, &pubj);

/* obtain a working nonce */
do {
random_scalar_order_test(&nonce);
} while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL));

/* try signing */
CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL));
CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL));

/* try verifying */
CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sig, &pub, &msg));
CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sig, &pub, &msg));
}

/***** HASH TESTS *****/

void run_sha256_tests(void) {
Expand Down Expand Up @@ -1863,6 +1904,7 @@ int main(int argc, char **argv) {
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]);

/* initialize */
run_context_tests();
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);

run_sha256_tests();
Expand Down

0 comments on commit 9688030

Please sign in to comment.