Skip to content

Commit

Permalink
Make flags more explicit, add runtime checks.
Browse files Browse the repository at this point in the history
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell authored and sipa committed Oct 24, 2015
1 parent 1a3e03a commit 1a36898
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 19 deletions.
19 changes: 14 additions & 5 deletions include/secp256k1.h
Expand Up @@ -148,12 +148,21 @@ typedef int (*secp256k1_nonce_function)(
# endif

/** Flags to pass to secp256k1_context_create. */
# define SECP256K1_CONTEXT_VERIFY (1 << 0)
# define SECP256K1_CONTEXT_SIGN (1 << 1)

# define SECP256K1_CONTEXT_VERIFY (SECP256K1_CONTEXT_VERIFY_BIT|SECP256K1_CONTEXT_CHECK_BIT)
# define SECP256K1_CONTEXT_SIGN (SECP256K1_CONTEXT_SIGN_BIT|SECP256K1_CONTEXT_CHECK_BIT)
# define SECP256K1_CONTEXT_NONE (SECP256K1_CONTEXT_CHECK_BIT)

# define SECP256K1_CONTEXT_VERIFY_BIT (1 << 2)
# define SECP256K1_CONTEXT_SIGN_BIT (2 << 2)
# define SECP256K1_CONTEXT_CHECK_BIT (1)

/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */
# define SECP256K1_EC_COMPRESSED (1 << 0)
# define SECP256K1_EC_COMPRESSED (SECP256K1_EC_COMPRESSED_BIT|SECP256K1_EC_CHECK_BIT)
# define SECP256K1_EC_UNCOMPRESSED (SECP256K1_EC_CHECK_BIT)

# define SECP256K1_EC_COMPRESSED_BIT (1 << 2)
# define SECP256K1_EC_CHECK_BIT (2)

/** Create a secp256k1 context object.
*
* Returns: a newly created context object.
Expand Down Expand Up @@ -261,7 +270,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(
* In: pubkey: a pointer to a secp256k1_pubkey containing an initialized
* public key.
* flags: SECP256K1_EC_COMPRESSED if serialization should be in
* compressed format.
* compressed format, otherwise SECP256K1_EC_UNCOMPRESSED.
*/
SECP256K1_API int secp256k1_ec_pubkey_serialize(
const secp256k1_context* ctx,
Expand Down
2 changes: 1 addition & 1 deletion src/eckey_impl.h
Expand Up @@ -40,7 +40,7 @@ static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *p
secp256k1_fe_normalize_var(&elem->x);
secp256k1_fe_normalize_var(&elem->y);
secp256k1_fe_get_b32(&pub[1], &elem->x);
if (flags & SECP256K1_EC_COMPRESSED) {
if (flags & SECP256K1_EC_COMPRESSED_BIT) {
*size = 33;
pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00);
} else {
Expand Down
12 changes: 10 additions & 2 deletions src/secp256k1.c
Expand Up @@ -62,13 +62,20 @@ secp256k1_context* secp256k1_context_create(unsigned int flags) {
ret->illegal_callback = default_illegal_callback;
ret->error_callback = default_error_callback;

if (EXPECT(!(flags & SECP256K1_CONTEXT_CHECK_BIT), 0)) {
secp256k1_callback_call(&ret->illegal_callback,
"Invalid flags");
free(ret);
return NULL;
}

secp256k1_ecmult_context_init(&ret->ecmult_ctx);
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);

if (flags & SECP256K1_CONTEXT_SIGN) {
if (flags & SECP256K1_CONTEXT_SIGN_BIT) {
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback);
}
if (flags & SECP256K1_CONTEXT_VERIFY) {
if (flags & SECP256K1_CONTEXT_VERIFY_BIT) {
secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback);
}

Expand Down Expand Up @@ -166,6 +173,7 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *o
ARG_CHECK(output != NULL);
ARG_CHECK(outputlen != NULL);
ARG_CHECK(pubkey != NULL);
ARG_CHECK(flags & SECP256K1_EC_CHECK_BIT);
return (secp256k1_pubkey_load(ctx, &Q, pubkey) &&
secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, flags));
}
Expand Down
22 changes: 11 additions & 11 deletions src/tests.c
Expand Up @@ -139,7 +139,7 @@ void run_context_tests(void) {
unsigned char ctmp[32];
int32_t ecount;
int32_t ecount2;
secp256k1_context *none = secp256k1_context_create(0);
secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
Expand Down Expand Up @@ -1544,9 +1544,9 @@ void test_point_times_order(const secp256k1_gej *point) {
secp256k1_ge_set_gej(&res3, &res1);
CHECK(secp256k1_ge_is_infinity(&res3));
CHECK(secp256k1_ge_is_valid_var(&res3) == 0);
CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0);
CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, SECP256K1_EC_UNCOMPRESSED) == 0);
psize = 65;
CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0);
CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, SECP256K1_EC_COMPRESSED) == 0);
/* check zero/one edge cases */
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero);
secp256k1_ge_set_gej(&res3, &res1);
Expand Down Expand Up @@ -1964,7 +1964,7 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali
VG_CHECK(&pubkey, sizeof(pubkey));
outl = 65;
VG_UNDEF(pubkeyo, 65);
CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, 0) == 1);
CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1);
VG_CHECK(pubkeyo, outl);
CHECK(outl == 65);
CHECK(pubkeyo[0] == 4);
Expand Down Expand Up @@ -2575,12 +2575,12 @@ void test_ecdsa_end_to_end(void) {
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1);

/* Verify exporting and importing public key. */
CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1)) == 1);
CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED));
memset(&pubkey, 0, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1);

/* Verify private key import and export. */
CHECK(secp256k1_ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1) ? SECP256K1_EC_COMPRESSED : 0);
CHECK(secp256k1_ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED));
CHECK(secp256k1_ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1);
CHECK(memcmp(privkey, privkey2, 32) == 0);

Expand Down Expand Up @@ -2698,15 +2698,15 @@ void test_random_pubkeys(void) {
size_t size = len;
firstb = in[0];
/* If the pubkey can be parsed, it should round-trip... */
CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, (len == 33) ? SECP256K1_EC_COMPRESSED : 0));
CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, (len == 33) ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED));
CHECK(size == len);
CHECK(memcmp(&in[1], &out[1], len-1) == 0);
/* ... except for the type of hybrid inputs. */
if ((in[0] != 6) && (in[0] != 7)) {
CHECK(in[0] == out[0]);
}
size = 65;
CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0));
CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, SECP256K1_EC_UNCOMPRESSED));
CHECK(size == 65);
CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size));
ge_equals_ge(&elem,&elem2);
Expand All @@ -2722,7 +2722,7 @@ void test_random_pubkeys(void) {
}
if (res) {
ge_equals_ge(&elem,&elem2);
CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0));
CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, SECP256K1_EC_UNCOMPRESSED));
CHECK(memcmp(&in[1], &out[1], 64) == 0);
}
}
Expand Down Expand Up @@ -3399,7 +3399,7 @@ void test_ecdsa_edge_cases(void) {
0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41,
};
size_t outlen = 300;
CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, 0));
CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, SECP256K1_EC_UNCOMPRESSED));
outlen = 300;
CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, SECP256K1_EC_COMPRESSED));
}
Expand All @@ -3416,7 +3416,7 @@ EC_KEY *get_openssl_key(const secp256k1_scalar *key) {
const unsigned char* pbegin = privkey;
int compr = secp256k1_rand_bits(1);
EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
CHECK(secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, &privkeylen, key, compr ? SECP256K1_EC_COMPRESSED : 0));
CHECK(secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, &privkeylen, key, compr ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED));
CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen));
CHECK(EC_KEY_check_key(ec_key));
return ec_key;
Expand Down

0 comments on commit 1a36898

Please sign in to comment.