Skip to content

Commit 2876af4

Browse files
committed
Split ecdsa_sign logic into a new function and use it from ecdsa_sign and recovery
1 parent 5e1c885 commit 2876af4

File tree

3 files changed

+44
-47
lines changed

3 files changed

+44
-47
lines changed

src/modules/recovery/main_impl.h

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -122,48 +122,15 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, cons
122122

123123
int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
124124
secp256k1_scalar r, s;
125-
secp256k1_scalar sec, non, msg;
126-
int recid;
127-
int ret = 0;
128-
int overflow = 0;
125+
int ret, recid;
129126
VERIFY_CHECK(ctx != NULL);
130127
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
131128
ARG_CHECK(msg32 != NULL);
132129
ARG_CHECK(signature != NULL);
133130
ARG_CHECK(seckey != NULL);
134-
if (noncefp == NULL) {
135-
noncefp = secp256k1_nonce_function_default;
136-
}
137131

138-
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
139-
/* Fail if the secret key is invalid. */
140-
if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
141-
unsigned char nonce32[32];
142-
unsigned int count = 0;
143-
secp256k1_scalar_set_b32(&msg, msg32, NULL);
144-
while (1) {
145-
ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count);
146-
if (!ret) {
147-
break;
148-
}
149-
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
150-
if (!overflow && !secp256k1_scalar_is_zero(&non)) {
151-
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) {
152-
break;
153-
}
154-
}
155-
count++;
156-
}
157-
memset(nonce32, 0, 32);
158-
secp256k1_scalar_clear(&msg);
159-
secp256k1_scalar_clear(&non);
160-
secp256k1_scalar_clear(&sec);
161-
}
162-
if (ret) {
163-
secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid);
164-
} else {
165-
memset(signature, 0, sizeof(*signature));
166-
}
132+
ret = secp256k1_ecdsa_sign_inner(ctx, &r, &s, &recid, msg32, seckey, noncefp, noncedata);
133+
secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid);
167134
return ret;
168135
}
169136

src/secp256k1.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -467,19 +467,18 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m
467467
const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979;
468468
const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979;
469469

470-
int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
471-
/* Default initialization here is important so we won't pass uninit values to the cmov in the end */
472-
secp256k1_scalar r = secp256k1_scalar_zero, s = secp256k1_scalar_zero;
470+
static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
473471
secp256k1_scalar sec, non, msg;
474472
int ret = 0;
475473
int is_sec_valid;
476474
unsigned char nonce32[32];
477475
unsigned int count = 0;
478-
VERIFY_CHECK(ctx != NULL);
479-
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
480-
ARG_CHECK(msg32 != NULL);
481-
ARG_CHECK(signature != NULL);
482-
ARG_CHECK(seckey != NULL);
476+
/* Default initialization here is important so we won't pass uninit values to the cmov in the end */
477+
*r = secp256k1_scalar_zero;
478+
*s = secp256k1_scalar_zero;
479+
if (recid) {
480+
*recid = 0;
481+
}
483482
if (noncefp == NULL) {
484483
noncefp = secp256k1_nonce_function_default;
485484
}
@@ -498,7 +497,7 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
498497
/* The nonce is still secret here, but it being invalid is is less likely than 1:2^255. */
499498
secp256k1_declassify(ctx, &is_nonce_valid, sizeof(is_nonce_valid));
500499
if (is_nonce_valid) {
501-
ret = secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL);
500+
ret = secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, r, s, &sec, &msg, &non, recid);
502501
/* The final signature is no longer a secret, nor is the fact that we were successful or not. */
503502
secp256k1_declassify(ctx, &ret, sizeof(ret));
504503
if (ret) {
@@ -515,8 +514,25 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
515514
secp256k1_scalar_clear(&msg);
516515
secp256k1_scalar_clear(&non);
517516
secp256k1_scalar_clear(&sec);
518-
secp256k1_scalar_cmov(&r, &secp256k1_scalar_zero, !ret);
519-
secp256k1_scalar_cmov(&s, &secp256k1_scalar_zero, !ret);
517+
secp256k1_scalar_cmov(r, &secp256k1_scalar_zero, !ret);
518+
secp256k1_scalar_cmov(s, &secp256k1_scalar_zero, !ret);
519+
if (recid) {
520+
const int zero = 0;
521+
secp256k1_int_cmov(recid, &zero, !ret);
522+
}
523+
return ret;
524+
}
525+
526+
int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
527+
secp256k1_scalar r, s;
528+
int ret;
529+
VERIFY_CHECK(ctx != NULL);
530+
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
531+
ARG_CHECK(msg32 != NULL);
532+
ARG_CHECK(signature != NULL);
533+
ARG_CHECK(seckey != NULL);
534+
535+
ret = secp256k1_ecdsa_sign_inner(ctx, &r, &s, NULL, msg32, seckey, noncefp, noncedata);
520536
secp256k1_ecdsa_signature_save(signature, &r, &s);
521537
return ret;
522538
}

src/util.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,18 @@ static SECP256K1_INLINE void memczero(void *s, size_t len, int flag) {
194194
}
195195
}
196196

197+
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized and non-negative.*/
198+
static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) {
199+
unsigned int mask0, mask1, r_masked, a_masked;
200+
/* Casting a negative int to unsigned and back to int is implementation defined behavior */
201+
VERIFY_CHECK(*r >= 0 && *a >= 0);
202+
203+
mask0 = (unsigned int)flag + ~0u;
204+
mask1 = ~mask0;
205+
r_masked = ((unsigned int)*r & mask0);
206+
a_masked = ((unsigned int)*a & mask1);
207+
208+
*r = (int)(r_masked | a_masked);
209+
}
210+
197211
#endif /* SECP256K1_UTIL_H */

0 commit comments

Comments
 (0)