diff --git a/contrib/lax_der_privatekey_parsing.h b/contrib/lax_der_privatekey_parsing.h index c0639ae..0d3b36a 100644 --- a/contrib/lax_der_privatekey_parsing.h +++ b/contrib/lax_der_privatekey_parsing.h @@ -34,22 +34,22 @@ * privkeylen: Pointer to an int where the length of the private key in * privkey will be stored. * In: seckey: pointer to a 32-byte secret key to export. - * flags: SECP256K1_EC_COMPRESSED if the key should be exported in - * compressed format. + * compressed: 1 if the key should be exported in + * compressed format, 0 otherwise * * This function is purely meant for compatibility with applications that * require BER encoded keys. When working with secp256k1-specific code, the * simple 32-byte private keys are sufficient. * * Note that this function does not guarantee correct DER output. It is - * guaranteed to be parsable by secp256k1_ec_privkey_import. + * guaranteed to be parsable by secp256k1_ec_privkey_import_der */ static SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export_der( const secp256k1_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, - unsigned int flags + int compressed ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Import a private key in DER format. @@ -116,13 +116,13 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar *key, const unsigned c return !overflow; } -static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar *key, unsigned int flags) { +static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar *key, int compressed) { secp256k1_gej rp; secp256k1_ge r; size_t pubkeylen = 0; secp256k1_ecmult_gen(ctx, &rp, key); secp256k1_ge_set_gej(&r, &rp); - if (flags & SECP256K1_EC_COMPRESSED) { + if (compressed) { static const unsigned char begin[] = { 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 }; @@ -176,7 +176,7 @@ static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context return 1; } -static int secp256k1_ec_privkey_export_der(const secp256k1_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, unsigned int flags) { +static int secp256k1_ec_privkey_export_der(const secp256k1_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, int compressed) { secp256k1_scalar key; int ret = 0; VERIFY_CHECK(ctx != NULL); @@ -186,7 +186,7 @@ static int secp256k1_ec_privkey_export_der(const secp256k1_context* ctx, unsigne ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); secp256k1_scalar_set_b32(&key, seckey, NULL); - ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, flags); + ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, compressed); secp256k1_scalar_clear(&key); return ret; } diff --git a/include/secp256k1.h b/include/secp256k1.h index 33bccad..776dc45 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -147,22 +147,24 @@ typedef int (*secp256k1_nonce_function)( # define SECP256K1_ARG_NONNULL(_x) # endif +/** All flags' lower 8 bits indicate what they're for. Do not use directly. */ +#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) +#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) +#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) +/** The higher bits contain the actual data. Do not use directly. */ +#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) +#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) +#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) + /** Flags to pass to secp256k1_context_create. */ -# 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 (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) +#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) +#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) -# 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 (SECP256K1_EC_COMPRESSED_BIT|SECP256K1_EC_CHECK_BIT) -# define SECP256K1_EC_UNCOMPRESSED (SECP256K1_EC_CHECK_BIT) +#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) +#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) -# define SECP256K1_EC_COMPRESSED_BIT (1 << 2) -# define SECP256K1_EC_CHECK_BIT (2) - /** Create a secp256k1 context object. * * Returns: a newly created context object. diff --git a/src/eckey.h b/src/eckey.h index 71c4096..42739a3 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -15,10 +15,7 @@ #include "ecmult_gen.h" static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, unsigned int flags); - -static int secp256k1_eckey_privkey_parse(secp256k1_scalar *key, const unsigned char *privkey, size_t privkeylen); -static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar *key, unsigned int flags); +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); diff --git a/src/eckey_impl.h b/src/eckey_impl.h index 1f71df4..ce38071 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -33,14 +33,14 @@ static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char } } -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, unsigned int flags) { +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { if (secp256k1_ge_is_infinity(elem)) { return 0; } 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_BIT) { + if (compressed) { *size = 33; pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); } else { diff --git a/src/secp256k1.c b/src/secp256k1.c index 90448c3..a4eb345 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -62,7 +62,7 @@ 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)) { + if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { secp256k1_callback_call(&ret->illegal_callback, "Invalid flags"); free(ret); @@ -72,10 +72,10 @@ secp256k1_context* secp256k1_context_create(unsigned int flags) { secp256k1_ecmult_context_init(&ret->ecmult_ctx); secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); - if (flags & SECP256K1_CONTEXT_SIGN_BIT) { + if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); } - if (flags & SECP256K1_CONTEXT_VERIFY_BIT) { + if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); } @@ -173,9 +173,9 @@ 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); + ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); return (secp256k1_pubkey_load(ctx, &Q, pubkey) && - secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, flags)); + secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, flags & SECP256K1_FLAGS_BIT_COMPRESSION)); } static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { diff --git a/src/tests.c b/src/tests.c index d449b93..ce13d03 100644 --- a/src/tests.c +++ b/src/tests.c @@ -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, SECP256K1_EC_UNCOMPRESSED) == 0); + CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); psize = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, SECP256K1_EC_COMPRESSED) == 0); + CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); /* check zero/one edge cases */ secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero); secp256k1_ge_set_gej(&res3, &res1); @@ -2580,7 +2580,7 @@ void test_ecdsa_end_to_end(void) { 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 : SECP256K1_EC_UNCOMPRESSED)); + CHECK(secp256k1_ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); CHECK(secp256k1_ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); CHECK(memcmp(privkey, privkey2, 32) == 0); @@ -2698,7 +2698,7 @@ 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 : SECP256K1_EC_UNCOMPRESSED)); + CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); CHECK(size == len); CHECK(memcmp(&in[1], &out[1], len-1) == 0); /* ... except for the type of hybrid inputs. */ @@ -2706,7 +2706,7 @@ void test_random_pubkeys(void) { CHECK(in[0] == out[0]); } size = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, SECP256K1_EC_UNCOMPRESSED)); + CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0)); CHECK(size == 65); CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); ge_equals_ge(&elem,&elem2); @@ -2722,7 +2722,7 @@ void test_random_pubkeys(void) { } if (res) { ge_equals_ge(&elem,&elem2); - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, SECP256K1_EC_UNCOMPRESSED)); + CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); CHECK(memcmp(&in[1], &out[1], 64) == 0); } } @@ -3399,9 +3399,9 @@ 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, SECP256K1_EC_UNCOMPRESSED)); + CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, 0)); outlen = 300; - CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, SECP256K1_EC_COMPRESSED)); + CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, 1)); } } @@ -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 : SECP256K1_EC_UNCOMPRESSED)); + CHECK(secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, &privkeylen, key, compr)); CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); CHECK(EC_KEY_check_key(ec_key)); return ec_key;