Changeset View
Changeset View
Standalone View
Standalone View
src/secp256k1/src/secp256k1.c
Show First 20 Lines • Show All 465 Lines • ▼ Show 20 Lines | |||||
const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; | const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; | ||||
const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; | const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; | ||||
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) { | 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) { | ||||
secp256k1_scalar r, s; | secp256k1_scalar r, s; | ||||
secp256k1_scalar sec, non, msg; | secp256k1_scalar sec, non, msg; | ||||
int ret = 0; | int ret = 0; | ||||
int overflow = 0; | int is_sec_valid; | ||||
unsigned char nonce32[32]; | unsigned char nonce32[32]; | ||||
unsigned int count = 0; | unsigned int count = 0; | ||||
const unsigned char secp256k1_ecdsa_der_algo16[17] = "ECDSA+DER "; | const unsigned char secp256k1_ecdsa_der_algo16[17] = "ECDSA+DER "; | ||||
VERIFY_CHECK(ctx != NULL); | VERIFY_CHECK(ctx != NULL); | ||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | ||||
ARG_CHECK(msg32 != NULL); | ARG_CHECK(msg32 != NULL); | ||||
ARG_CHECK(signature != NULL); | ARG_CHECK(signature != NULL); | ||||
ARG_CHECK(seckey != NULL); | ARG_CHECK(seckey != NULL); | ||||
if (noncefp == NULL) { | if (noncefp == NULL) { | ||||
noncefp = secp256k1_nonce_function_default; | noncefp = secp256k1_nonce_function_default; | ||||
} | } | ||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); | |||||
/* Fail if the secret key is invalid. */ | /* Fail if the secret key is invalid. */ | ||||
overflow |= secp256k1_scalar_is_zero(&sec); | is_sec_valid = secp256k1_scalar_set_b32_seckey(&sec, seckey); | ||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, overflow); | secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, !is_sec_valid); | ||||
secp256k1_scalar_set_b32(&msg, msg32, NULL); | secp256k1_scalar_set_b32(&msg, msg32, NULL); | ||||
while (1) { | while (1) { | ||||
int koverflow; | int is_nonce_valid; | ||||
ret = noncefp(nonce32, msg32, seckey, secp256k1_ecdsa_der_algo16, (void*)noncedata, count); | ret = !!noncefp(nonce32, msg32, seckey, secp256k1_ecdsa_der_algo16, (void*)noncedata, count); | ||||
if (!ret) { | if (!ret) { | ||||
break; | break; | ||||
} | } | ||||
secp256k1_scalar_set_b32(&non, nonce32, &koverflow); | is_nonce_valid = secp256k1_scalar_set_b32_seckey(&non, nonce32); | ||||
koverflow |= secp256k1_scalar_is_zero(&non); | /* The nonce is still secret here, but it being invalid is is less likely than 1:2^255. */ | ||||
/* The nonce is still secret here, but it overflowing or being zero is is less likely than 1:2^255. */ | secp256k1_declassify(ctx, &is_nonce_valid, sizeof(is_nonce_valid)); | ||||
secp256k1_declassify(ctx, &koverflow, sizeof(koverflow)); | if (is_nonce_valid) { | ||||
if (!koverflow) { | |||||
ret = secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL); | ret = secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL); | ||||
/* The final signature is no longer a secret, nor is the fact that we were successful or not. */ | /* The final signature is no longer a secret, nor is the fact that we were successful or not. */ | ||||
secp256k1_declassify(ctx, &ret, sizeof(ret)); | secp256k1_declassify(ctx, &ret, sizeof(ret)); | ||||
if (ret) { | if (ret) { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
count++; | count++; | ||||
} | } | ||||
/* We don't want to declassify is_sec_valid and therefore the range of | |||||
* seckey. As a result is_sec_valid is included in ret only after ret was | |||||
* used as a branching variable. */ | |||||
ret &= is_sec_valid; | |||||
memset(nonce32, 0, 32); | memset(nonce32, 0, 32); | ||||
secp256k1_scalar_clear(&msg); | secp256k1_scalar_clear(&msg); | ||||
secp256k1_scalar_clear(&non); | secp256k1_scalar_clear(&non); | ||||
secp256k1_scalar_clear(&sec); | secp256k1_scalar_clear(&sec); | ||||
secp256k1_scalar_cmov(&r, &secp256k1_scalar_zero, (!ret) | overflow); | secp256k1_scalar_cmov(&r, &secp256k1_scalar_zero, !ret); | ||||
secp256k1_scalar_cmov(&s, &secp256k1_scalar_zero, (!ret) | overflow); | secp256k1_scalar_cmov(&s, &secp256k1_scalar_zero, !ret); | ||||
secp256k1_ecdsa_signature_save(signature, &r, &s); | secp256k1_ecdsa_signature_save(signature, &r, &s); | ||||
return !!ret & !overflow; | return ret; | ||||
} | } | ||||
int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { | int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { | ||||
secp256k1_scalar sec; | secp256k1_scalar sec; | ||||
int ret; | int ret; | ||||
int overflow; | |||||
VERIFY_CHECK(ctx != NULL); | VERIFY_CHECK(ctx != NULL); | ||||
ARG_CHECK(seckey != NULL); | ARG_CHECK(seckey != NULL); | ||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); | ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); | ||||
ret = !overflow & !secp256k1_scalar_is_zero(&sec); | |||||
secp256k1_scalar_clear(&sec); | secp256k1_scalar_clear(&sec); | ||||
return ret; | return ret; | ||||
} | } | ||||
int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { | int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { | ||||
secp256k1_gej pj; | secp256k1_gej pj; | ||||
secp256k1_ge p; | secp256k1_ge p; | ||||
secp256k1_scalar sec; | secp256k1_scalar sec; | ||||
int overflow; | |||||
int ret = 0; | int ret = 0; | ||||
VERIFY_CHECK(ctx != NULL); | VERIFY_CHECK(ctx != NULL); | ||||
ARG_CHECK(pubkey != NULL); | ARG_CHECK(pubkey != NULL); | ||||
memset(pubkey, 0, sizeof(*pubkey)); | memset(pubkey, 0, sizeof(*pubkey)); | ||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); | ||||
ARG_CHECK(seckey != NULL); | ARG_CHECK(seckey != NULL); | ||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); | ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); | ||||
ret = !overflow & !secp256k1_scalar_is_zero(&sec); | |||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, !ret); | secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, !ret); | ||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); | secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); | ||||
secp256k1_ge_set_gej(&p, &pj); | secp256k1_ge_set_gej(&p, &pj); | ||||
secp256k1_pubkey_save(pubkey, &p); | secp256k1_pubkey_save(pubkey, &p); | ||||
memczero(pubkey, sizeof(*pubkey), !ret); | memczero(pubkey, sizeof(*pubkey), !ret); | ||||
secp256k1_scalar_clear(&sec); | secp256k1_scalar_clear(&sec); | ||||
return ret; | return ret; | ||||
} | } | ||||
int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) { | int secp256k1_ec_seckey_negate(const secp256k1_context* ctx, unsigned char *seckey) { | ||||
secp256k1_scalar sec; | secp256k1_scalar sec; | ||||
int ret = 0; | |||||
VERIFY_CHECK(ctx != NULL); | VERIFY_CHECK(ctx != NULL); | ||||
ARG_CHECK(seckey != NULL); | ARG_CHECK(seckey != NULL); | ||||
secp256k1_scalar_set_b32(&sec, seckey, NULL); | ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); | ||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); | |||||
secp256k1_scalar_negate(&sec, &sec); | secp256k1_scalar_negate(&sec, &sec); | ||||
secp256k1_scalar_get_b32(seckey, &sec); | secp256k1_scalar_get_b32(seckey, &sec); | ||||
secp256k1_scalar_clear(&sec); | secp256k1_scalar_clear(&sec); | ||||
return 1; | return ret; | ||||
} | |||||
int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) { | |||||
return secp256k1_ec_seckey_negate(ctx, seckey); | |||||
} | } | ||||
int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) { | int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) { | ||||
int ret = 0; | int ret = 0; | ||||
secp256k1_ge p; | secp256k1_ge p; | ||||
VERIFY_CHECK(ctx != NULL); | VERIFY_CHECK(ctx != NULL); | ||||
ARG_CHECK(pubkey != NULL); | ARG_CHECK(pubkey != NULL); | ||||
ret = secp256k1_pubkey_load(ctx, &p, pubkey); | ret = secp256k1_pubkey_load(ctx, &p, pubkey); | ||||
memset(pubkey, 0, sizeof(*pubkey)); | memset(pubkey, 0, sizeof(*pubkey)); | ||||
if (ret) { | if (ret) { | ||||
secp256k1_ge_neg(&p, &p); | secp256k1_ge_neg(&p, &p); | ||||
secp256k1_pubkey_save(pubkey, &p); | secp256k1_pubkey_save(pubkey, &p); | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { | int secp256k1_ec_seckey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { | ||||
secp256k1_scalar term; | secp256k1_scalar term; | ||||
secp256k1_scalar sec; | secp256k1_scalar sec; | ||||
int ret = 0; | int ret = 0; | ||||
int overflow = 0; | int overflow = 0; | ||||
VERIFY_CHECK(ctx != NULL); | VERIFY_CHECK(ctx != NULL); | ||||
ARG_CHECK(seckey != NULL); | ARG_CHECK(seckey != NULL); | ||||
ARG_CHECK(tweak != NULL); | ARG_CHECK(tweak != NULL); | ||||
secp256k1_scalar_set_b32(&term, tweak, &overflow); | secp256k1_scalar_set_b32(&term, tweak, &overflow); | ||||
secp256k1_scalar_set_b32(&sec, seckey, NULL); | ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); | ||||
ret = (!overflow) & secp256k1_eckey_privkey_tweak_add(&sec, &term); | ret &= (!overflow) & secp256k1_eckey_privkey_tweak_add(&sec, &term); | ||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); | secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); | ||||
secp256k1_scalar_get_b32(seckey, &sec); | secp256k1_scalar_get_b32(seckey, &sec); | ||||
secp256k1_scalar_clear(&sec); | secp256k1_scalar_clear(&sec); | ||||
secp256k1_scalar_clear(&term); | secp256k1_scalar_clear(&term); | ||||
return ret; | return ret; | ||||
} | } | ||||
int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { | |||||
return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak); | |||||
} | |||||
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { | int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { | ||||
secp256k1_ge p; | secp256k1_ge p; | ||||
secp256k1_scalar term; | secp256k1_scalar term; | ||||
int ret = 0; | int ret = 0; | ||||
int overflow = 0; | int overflow = 0; | ||||
VERIFY_CHECK(ctx != NULL); | VERIFY_CHECK(ctx != NULL); | ||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | ||||
ARG_CHECK(pubkey != NULL); | ARG_CHECK(pubkey != NULL); | ||||
ARG_CHECK(tweak != NULL); | ARG_CHECK(tweak != NULL); | ||||
secp256k1_scalar_set_b32(&term, tweak, &overflow); | secp256k1_scalar_set_b32(&term, tweak, &overflow); | ||||
ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); | ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); | ||||
memset(pubkey, 0, sizeof(*pubkey)); | memset(pubkey, 0, sizeof(*pubkey)); | ||||
if (ret) { | if (ret) { | ||||
if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { | if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { | ||||
secp256k1_pubkey_save(pubkey, &p); | secp256k1_pubkey_save(pubkey, &p); | ||||
} else { | } else { | ||||
ret = 0; | ret = 0; | ||||
} | } | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { | int secp256k1_ec_seckey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { | ||||
secp256k1_scalar factor; | secp256k1_scalar factor; | ||||
secp256k1_scalar sec; | secp256k1_scalar sec; | ||||
int ret = 0; | int ret = 0; | ||||
int overflow = 0; | int overflow = 0; | ||||
VERIFY_CHECK(ctx != NULL); | VERIFY_CHECK(ctx != NULL); | ||||
ARG_CHECK(seckey != NULL); | ARG_CHECK(seckey != NULL); | ||||
ARG_CHECK(tweak != NULL); | ARG_CHECK(tweak != NULL); | ||||
secp256k1_scalar_set_b32(&factor, tweak, &overflow); | secp256k1_scalar_set_b32(&factor, tweak, &overflow); | ||||
secp256k1_scalar_set_b32(&sec, seckey, NULL); | ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); | ||||
ret = (!overflow) & secp256k1_eckey_privkey_tweak_mul(&sec, &factor); | ret &= (!overflow) & secp256k1_eckey_privkey_tweak_mul(&sec, &factor); | ||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); | secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); | ||||
secp256k1_scalar_get_b32(seckey, &sec); | secp256k1_scalar_get_b32(seckey, &sec); | ||||
secp256k1_scalar_clear(&sec); | secp256k1_scalar_clear(&sec); | ||||
secp256k1_scalar_clear(&factor); | secp256k1_scalar_clear(&factor); | ||||
return ret; | return ret; | ||||
} | } | ||||
int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { | |||||
return secp256k1_ec_seckey_tweak_mul(ctx, seckey, tweak); | |||||
} | |||||
int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { | int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { | ||||
secp256k1_ge p; | secp256k1_ge p; | ||||
secp256k1_scalar factor; | secp256k1_scalar factor; | ||||
int ret = 0; | int ret = 0; | ||||
int overflow = 0; | int overflow = 0; | ||||
VERIFY_CHECK(ctx != NULL); | VERIFY_CHECK(ctx != NULL); | ||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); | ||||
ARG_CHECK(pubkey != NULL); | ARG_CHECK(pubkey != NULL); | ||||
▲ Show 20 Lines • Show All 63 Lines • Show Last 20 Lines |