Expose ability to deep-copy a context

This commit is contained in:
Andrew Poelstra 2015-04-11 14:06:54 -05:00
parent 3608c7f2f6
commit d899b5b67c
7 changed files with 91 additions and 0 deletions

View File

@ -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.
*/

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {
@ -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();