Skip to content

Commit

Permalink
Merge pull request bitcoin#347
Browse files Browse the repository at this point in the history
8e48787 Change secp256k1_ec_pubkey_combine's count argument to size_t. (Gregory Maxwell)
c69dea0 Clear output in more cases for pubkey_combine, adds tests. (Gregory Maxwell)
269d422 Comment copyediting. (Gregory Maxwell)
  • Loading branch information
sipa committed Nov 1, 2015
2 parents b4d17da + 8e48787 commit e2100ad
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 30 deletions.
8 changes: 3 additions & 5 deletions include/secp256k1.h
Expand Up @@ -229,7 +229,7 @@ SECP256K1_API void secp256k1_context_set_illegal_callback(
* crashing.
*
* Args: ctx: an existing context object (cannot be NULL)
* In: fun: a pointer to a function to call when an interal error occurs,
* In: fun: a pointer to a function to call when an internal error occurs,
* taking a message and an opaque pointer (NULL restores a default
* handler that calls abort).
* data: the opaque pointer to pass to fun above.
Expand Down Expand Up @@ -562,18 +562,16 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
* Returns: 1: the sum of the public keys is valid.
* 0: the sum of the public keys is not valid.
* Args: ctx: pointer to a context object
* Out: out: pointer to pubkey for placing the resulting public key
* Out: out: pointer to a public key object for placing the resulting public key
* (cannot be NULL)
* In: ins: pointer to array of pointers to public keys (cannot be NULL)
* n: the number of public keys to add together (must be at least 1)
* Use secp256k1_ec_pubkey_compress and secp256k1_ec_pubkey_decompress if the
* uncompressed format is needed.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
const secp256k1_context* ctx,
secp256k1_pubkey *out,
const secp256k1_pubkey * const * ins,
int n
size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

# ifdef __cplusplus
Expand Down
2 changes: 1 addition & 1 deletion include/secp256k1_recovery.h
Expand Up @@ -92,7 +92,7 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
* 0: otherwise.
* Args: ctx: pointer to a context object, initialized for verification (cannot be NULL)
* Out: pubkey: pointer to the recoved public key (cannot be NULL)
* Out: pubkey: pointer to the recovered public key (cannot be NULL)
* In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL)
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
*/
Expand Down
6 changes: 3 additions & 3 deletions include/secp256k1_schnorr.h
Expand Up @@ -99,7 +99,7 @@ SECP256K1_API int secp256k1_schnorr_generate_nonce_pair(
/** Produce a partial Schnorr signature, which can be combined using
* secp256k1_schnorr_partial_combine, to end up with a full signature that is
* verifiable using secp256k1_schnorr_verify.
* Returns: 1: signature created succesfully.
* Returns: 1: signature created successfully.
* 0: no valid signature exists with this combination of keys, nonces
* and message (chance around 1 in 2^128)
* -1: invalid private key, nonce, or public nonces.
Expand Down Expand Up @@ -148,7 +148,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_sign(
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);

/** Combine multiple Schnorr partial signatures.
* Returns: 1: the passed signatures were succesfully combined.
* Returns: 1: the passed signatures were successfully combined.
* 0: the resulting signature is not valid (chance of 1 in 2^256)
* -1: some inputs were invalid, or the signatures were not created
* using the same set of nonces
Expand All @@ -163,7 +163,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_combine
const secp256k1_context* ctx,
unsigned char *sig64,
const unsigned char * const * sig64sin,
int n
size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

# ifdef __cplusplus
Expand Down
13 changes: 9 additions & 4 deletions src/ecdsa_impl.h
Expand Up @@ -75,8 +75,9 @@ static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned cha
return -1;
}
if ((size_t)lenleft > sizeof(size_t)) {
/* The resulthing length would exceed the range of a size_t, so
certainly longer than the passed array size. */
/* The resulting length would exceed the range of a size_t, so
* certainly longer than the passed array size.
*/
return -1;
}
while (lenleft > 0) {
Expand Down Expand Up @@ -267,13 +268,17 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
secp256k1_fe_get_b32(b, &r.x);
secp256k1_scalar_set_b32(sigr, b, &overflow);
if (secp256k1_scalar_is_zero(sigr)) {
/* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. */
/* This branch is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N. */
/* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature.
* This branch is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N.
*/
secp256k1_gej_clear(&rp);
secp256k1_ge_clear(&r);
return 0;
}
if (recid) {
/* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log
* of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria.
*/
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
}
secp256k1_scalar_mul(&n, sigr, seckey);
Expand Down
2 changes: 1 addition & 1 deletion src/field.h
Expand Up @@ -10,7 +10,7 @@
/** Field element module.
*
* Field elements can be represented in several ways, but code accessing
* it (and implementations) need to take certain properaties into account:
* it (and implementations) need to take certain properties into account:
* - Each field element can be normalized or not.
* - Each field element has a magnitude, which represents how far away
* its representation is away from normalization. Normalized elements
Expand Down
2 changes: 1 addition & 1 deletion src/modules/schnorr/main_impl.h
Expand Up @@ -154,7 +154,7 @@ int secp256k1_schnorr_partial_sign(const secp256k1_context* ctx, unsigned char *
return secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64, &sec, &non, &pubnon, secp256k1_schnorr_msghash_sha256, msg32);
}

int secp256k1_schnorr_partial_combine(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char * const *sig64sin, int n) {
int secp256k1_schnorr_partial_combine(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char * const *sig64sin, size_t n) {
ARG_CHECK(sig64 != NULL);
ARG_CHECK(n >= 1);
ARG_CHECK(sig64sin != NULL);
Expand Down
2 changes: 1 addition & 1 deletion src/modules/schnorr/schnorr.h
Expand Up @@ -15,6 +15,6 @@ typedef void (*secp256k1_schnorr_msghash)(unsigned char *h32, const unsigned cha
static int secp256k1_schnorr_sig_sign(const secp256k1_ecmult_gen_context* ctx, unsigned char *sig64, const secp256k1_scalar *key, const secp256k1_scalar *nonce, const secp256k1_ge *pubnonce, secp256k1_schnorr_msghash hash, const unsigned char *msg32);
static int secp256k1_schnorr_sig_verify(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, const secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32);
static int secp256k1_schnorr_sig_recover(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32);
static int secp256k1_schnorr_sig_combine(unsigned char *sig64, int n, const unsigned char * const *sig64ins);
static int secp256k1_schnorr_sig_combine(unsigned char *sig64, size_t n, const unsigned char * const *sig64ins);

#endif
4 changes: 2 additions & 2 deletions src/modules/schnorr/schnorr_impl.h
Expand Up @@ -178,9 +178,9 @@ static int secp256k1_schnorr_sig_recover(const secp256k1_ecmult_context* ctx, co
return 1;
}

static int secp256k1_schnorr_sig_combine(unsigned char *sig64, int n, const unsigned char * const *sig64ins) {
static int secp256k1_schnorr_sig_combine(unsigned char *sig64, size_t n, const unsigned char * const *sig64ins) {
secp256k1_scalar s = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
int i;
size_t i;
for (i = 0; i < n; i++) {
secp256k1_scalar si;
int overflow;
Expand Down
6 changes: 3 additions & 3 deletions src/secp256k1.c
Expand Up @@ -530,12 +530,13 @@ int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *see
return 1;
}

int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, int n) {
int i;
int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) {
size_t i;
secp256k1_gej Qj;
secp256k1_ge Q;

ARG_CHECK(pubnonce != NULL);
memset(pubnonce, 0, sizeof(*pubnonce));
ARG_CHECK(n >= 1);
ARG_CHECK(pubnonces != NULL);

Expand All @@ -546,7 +547,6 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
secp256k1_gej_add_ge(&Qj, &Qj, &Q);
}
if (secp256k1_gej_is_infinity(&Qj)) {
memset(pubnonce, 0, sizeof(*pubnonce));
return 0;
}
secp256k1_ge_set_gej(&Q, &Qj);
Expand Down
88 changes: 79 additions & 9 deletions src/tests.c
Expand Up @@ -594,7 +594,7 @@ void scalar_test(void) {
}

{
/* Test that multipying the scalars is equal to multiplying their numbers modulo the order. */
/* Test that multiplying the scalars is equal to multiplying their numbers modulo the order. */
secp256k1_scalar r;
secp256k1_num r2num;
secp256k1_num rnum;
Expand Down Expand Up @@ -840,7 +840,7 @@ void run_scalar_tests(void) {

{
/* Static test vectors.
* These were reduced from ~10^12 random vectors based on comparision-decision
* These were reduced from ~10^12 random vectors based on comparison-decision
* and edge-case coverage on 32-bit and 64-bit implementations.
* The responses were generated with Sage 5.9.
*/
Expand Down Expand Up @@ -1737,7 +1737,7 @@ void test_ge(void) {
/* Points: (infinity, p1, p1, -p1, -p1, p2, p2, -p2, -p2, p3, p3, -p3, -p3, p4, p4, -p4, -p4).
* The second in each pair of identical points uses a random Z coordinate in the Jacobian form.
* All magnitudes are randomized.
* All 17*17 combinations of points are added to eachother, using all applicable methods.
* All 17*17 combinations of points are added to each other, using all applicable methods.
*
* When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well.
*/
Expand Down Expand Up @@ -2420,7 +2420,7 @@ void run_ecmult_constants(void) {
}

void test_ecmult_gen_blind(void) {
/* Test ecmult_gen() blinding and confirm that the blinding changes, the affline points match, and the z's don't match. */
/* Test ecmult_gen() blinding and confirm that the blinding changes, the affine points match, and the z's don't match. */
secp256k1_scalar key;
secp256k1_scalar b;
unsigned char seed32[32];
Expand Down Expand Up @@ -2902,10 +2902,14 @@ void run_eckey_edge_case_test(void) {
0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41
};
const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00};
unsigned char ctmp[32];
unsigned char ctmp2[32];
unsigned char ctmp[33];
unsigned char ctmp2[33];
secp256k1_pubkey pubkey;
secp256k1_pubkey pubkey2;
secp256k1_pubkey pubkey_one;
secp256k1_pubkey pubkey_negone;
const secp256k1_pubkey *pubkeys[3];
size_t len;
int32_t ecount;
/* Group order is too large, reject. */
CHECK(secp256k1_ec_seckey_verify(ctx, orderc) == 0);
Expand Down Expand Up @@ -2937,6 +2941,7 @@ void run_eckey_edge_case_test(void) {
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
pubkey_one = pubkey;
/* Group order + 1 is too large, reject. */
memcpy(ctmp, orderc, 32);
ctmp[31] = 0x42;
Expand All @@ -2954,6 +2959,7 @@ void run_eckey_edge_case_test(void) {
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
pubkey_negone = pubkey;
/* Tweak of zero leaves the value changed. */
memset(ctmp2, 0, 32);
CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1);
Expand Down Expand Up @@ -3060,6 +3066,67 @@ void run_eckey_edge_case_test(void) {
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0);
CHECK(ecount == 2);
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* secp256k1_ec_pubkey_combine tests. */
ecount = 0;
pubkeys[0] = &pubkey_one;
VG_UNDEF(&pubkeys[0], sizeof(secp256k1_pubkey *));
VG_UNDEF(&pubkeys[1], sizeof(secp256k1_pubkey *));
VG_UNDEF(&pubkeys[2], sizeof(secp256k1_pubkey *));
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0);
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 2);
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 3);
pubkeys[0] = &pubkey_negone;
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
CHECK(ecount == 3);
len = 33;
CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1);
CHECK(memcmp(ctmp, ctmp2, 33) == 0);
/* Result is infinity. */
pubkeys[0] = &pubkey_one;
pubkeys[1] = &pubkey_negone;
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 3);
/* Passes through infinity but comes out one. */
pubkeys[2] = &pubkey_one;
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
CHECK(ecount == 3);
len = 33;
CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1);
CHECK(memcmp(ctmp, ctmp2, 33) == 0);
/* Adds to two. */
pubkeys[1] = &pubkey_one;
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
CHECK(ecount == 3);
secp256k1_context_set_illegal_callback(ctx, NULL, NULL);
}

Expand Down Expand Up @@ -3139,7 +3206,7 @@ static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char
}
return 1;
}
/* Retry rate of 6979 is negligible esp. as we only call this in determinstic tests. */
/* Retry rate of 6979 is negligible esp. as we only call this in deterministic tests. */
/* If someone does fine a case where it retries for secp256k1, we'd like to know. */
if (counter > 5) {
return 0;
Expand Down Expand Up @@ -3933,6 +4000,9 @@ void test_ecdsa_edge_cases(void) {
CHECK(ecount == 5);
CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 1);
CHECK(ecount == 5);
memset(signature, 255, 64);
CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 0);
CHECK(ecount == 5);
secp256k1_context_set_illegal_callback(ctx, NULL, NULL);
}

Expand Down Expand Up @@ -3966,7 +4036,7 @@ void test_ecdsa_edge_cases(void) {
CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, nonce_function_rfc6979, extra) == 1);
CHECK(!is_empty_signature(&sig2));
CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0);
/* The default nonce function is determinstic. */
/* The default nonce function is deterministic. */
CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1);
CHECK(!is_empty_signature(&sig2));
CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0);
Expand Down Expand Up @@ -3998,7 +4068,7 @@ void test_ecdsa_edge_cases(void) {
}

{
/* Check that optional nonce arguments do not have equivilent effect. */
/* Check that optional nonce arguments do not have equivalent effect. */
const unsigned char zeros[32] = {0};
unsigned char nonce[32];
unsigned char nonce2[32];
Expand Down

0 comments on commit e2100ad

Please sign in to comment.