Skip to content

Commit 9b3c6e8

Browse files
committed
Split ecdsa_sign logic into a new function and use it from ecdsa_sign and recovery
1 parent 05d315a commit 9b3c6e8

File tree

3 files changed

+38
-46
lines changed

3 files changed

+38
-46
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 & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -467,18 +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-
secp256k1_scalar r, s;
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) {
472471
secp256k1_scalar sec, non, msg;
473472
int ret = 0;
474473
int is_sec_valid;
475474
unsigned char nonce32[32];
476475
unsigned int count = 0;
477-
VERIFY_CHECK(ctx != NULL);
478-
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
479-
ARG_CHECK(msg32 != NULL);
480-
ARG_CHECK(signature != NULL);
481-
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+
}
482482
if (noncefp == NULL) {
483483
noncefp = secp256k1_nonce_function_default;
484484
}
@@ -497,7 +497,7 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
497497
/* The nonce is still secret here, but it being invalid is is less likely than 1:2^255. */
498498
secp256k1_declassify(ctx, &is_nonce_valid, sizeof(is_nonce_valid));
499499
if (is_nonce_valid) {
500-
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);
501501
/* The final signature is no longer a secret, nor is the fact that we were successful or not. */
502502
secp256k1_declassify(ctx, &ret, sizeof(ret));
503503
if (ret) {
@@ -514,8 +514,25 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
514514
secp256k1_scalar_clear(&msg);
515515
secp256k1_scalar_clear(&non);
516516
secp256k1_scalar_clear(&sec);
517-
secp256k1_scalar_cmov(&r, &secp256k1_scalar_zero, !ret);
518-
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);
519536
secp256k1_ecdsa_signature_save(signature, &r, &s);
520537
return ret;
521538
}

src/util.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,12 @@ static SECP256K1_INLINE void memczero(void *s, size_t len, int flag) {
175175
}
176176
}
177177

178+
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
179+
static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) {
180+
uint32_t mask0, mask1;
181+
mask0 = flag + ~((uint32_t)0);
182+
mask1 = ~mask0;
183+
*r = (*r & mask0) | (*a & mask1);
184+
}
185+
178186
#endif /* SECP256K1_UTIL_H */

0 commit comments

Comments
 (0)