mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 20:03:34 -03:00
Merge pull request #340
96be204
Add additional tests for eckey and arg-checks. (Gregory Maxwell)bb5aa4d
Make the tweak function zeroize-output-on-fail behavior consistent. (Gregory Maxwell)4a243da
Move secp256k1_ec_privkey_import/export to contrib. (Gregory Maxwell)1b3efc1
Move secp256k1_ecdsa_sig_recover into the recovery module. (Gregory Maxwell)e3cd679
Eliminate all side-effects from VERIFY_CHECK() usage. (Gregory Maxwell)b30fc85
Avoid nonce_function_rfc6979 algo16 argument emulation. (Gregory Maxwell)70d4640
Make secp256k1_ec_pubkey_create skip processing invalid secret keys. (Gregory Maxwell)6c476a8
Minor comment improvements. (Gregory Maxwell)
This commit is contained in:
commit
1a3e03a348
12 changed files with 745 additions and 267 deletions
|
@ -41,6 +41,7 @@ noinst_HEADERS += src/field.h
|
|||
noinst_HEADERS += src/field_impl.h
|
||||
noinst_HEADERS += src/bench.h
|
||||
noinst_HEADERS += contrib/lax_der_parsing.h
|
||||
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libsecp256k1.pc
|
||||
|
|
209
contrib/lax_der_privatekey_parsing.h
Normal file
209
contrib/lax_der_privatekey_parsing.h
Normal file
|
@ -0,0 +1,209 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2014, 2015 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
/* This file contains code snippets that parse DER private keys with
|
||||
* various errors and violations. This is not a part of the library
|
||||
* itself, because the allowed violations are chosen arbitrarily and
|
||||
* do not follow or establish any standard.
|
||||
*
|
||||
* It also contains code to serialize private keys in a compatible
|
||||
* manner.
|
||||
*
|
||||
* These functions are meant for compatibility with applications
|
||||
* that require BER encoded keys. When working with secp256k1-specific
|
||||
* code, the simple 32-byte private keys normally used by the
|
||||
* library are sufficient.
|
||||
*/
|
||||
|
||||
#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_
|
||||
#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <secp256k1.h>
|
||||
|
||||
/** Export a private key in DER format.
|
||||
*
|
||||
* Returns: 1 if the private key was valid.
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot
|
||||
* be NULL)
|
||||
* Out: privkey: pointer to an array for storing the private key in BER.
|
||||
* Should have space for 279 bytes, and cannot be NULL.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Import a private key in DER format.
|
||||
* Returns: 1 if a private key was extracted.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL).
|
||||
* Out: seckey: pointer to a 32-byte array for storing the private key.
|
||||
* (cannot be NULL).
|
||||
* In: privkey: pointer to a private key in DER format (cannot be NULL).
|
||||
* privkeylen: length of the DER private key pointed to be privkey.
|
||||
*
|
||||
* This function will accept more than just strict DER, and even allow some BER
|
||||
* violations. The public key stored inside the DER-encoded private key is not
|
||||
* verified for correctness, nor are the curve parameters. Use this function
|
||||
* only if you know in advance it is supposed to contain a secp256k1 private
|
||||
* key.
|
||||
*/
|
||||
static SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import_der(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *seckey,
|
||||
const unsigned char *privkey,
|
||||
size_t privkeylen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
static int secp256k1_eckey_privkey_parse(secp256k1_scalar *key, const unsigned char *privkey, size_t privkeylen) {
|
||||
unsigned char c[32] = {0};
|
||||
const unsigned char *end = privkey + privkeylen;
|
||||
int lenb = 0;
|
||||
int len = 0;
|
||||
int overflow = 0;
|
||||
/* sequence header */
|
||||
if (end < privkey+1 || *privkey != 0x30) {
|
||||
return 0;
|
||||
}
|
||||
privkey++;
|
||||
/* sequence length constructor */
|
||||
if (end < privkey+1 || !(*privkey & 0x80)) {
|
||||
return 0;
|
||||
}
|
||||
lenb = *privkey & ~0x80; privkey++;
|
||||
if (lenb < 1 || lenb > 2) {
|
||||
return 0;
|
||||
}
|
||||
if (end < privkey+lenb) {
|
||||
return 0;
|
||||
}
|
||||
/* sequence length */
|
||||
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0);
|
||||
privkey += lenb;
|
||||
if (end < privkey+len) {
|
||||
return 0;
|
||||
}
|
||||
/* sequence element 0: version number (=1) */
|
||||
if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) {
|
||||
return 0;
|
||||
}
|
||||
privkey += 3;
|
||||
/* sequence element 1: octet string, up to 32 bytes */
|
||||
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(c + 32 - privkey[1], privkey + 2, privkey[1]);
|
||||
secp256k1_scalar_set_b32(key, c, &overflow);
|
||||
memset(c, 0, 32);
|
||||
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) {
|
||||
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) {
|
||||
static const unsigned char begin[] = {
|
||||
0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20
|
||||
};
|
||||
static const unsigned char middle[] = {
|
||||
0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
|
||||
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
|
||||
0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
|
||||
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
|
||||
0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
|
||||
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00
|
||||
};
|
||||
unsigned char *ptr = privkey;
|
||||
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
|
||||
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
|
||||
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
|
||||
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1)) {
|
||||
return 0;
|
||||
}
|
||||
ptr += pubkeylen;
|
||||
*privkeylen = ptr - privkey;
|
||||
} else {
|
||||
static const unsigned char begin[] = {
|
||||
0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20
|
||||
};
|
||||
static const unsigned char middle[] = {
|
||||
0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
|
||||
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
|
||||
0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
|
||||
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
|
||||
0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11,
|
||||
0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10,
|
||||
0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
|
||||
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00
|
||||
};
|
||||
unsigned char *ptr = privkey;
|
||||
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
|
||||
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
|
||||
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
|
||||
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0)) {
|
||||
return 0;
|
||||
}
|
||||
ptr += pubkeylen;
|
||||
*privkeylen = ptr - privkey;
|
||||
}
|
||||
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) {
|
||||
secp256k1_scalar key;
|
||||
int ret = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(seckey != NULL);
|
||||
ARG_CHECK(privkey != NULL);
|
||||
ARG_CHECK(privkeylen != NULL);
|
||||
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);
|
||||
secp256k1_scalar_clear(&key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int secp256k1_ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *privkey, size_t privkeylen) {
|
||||
secp256k1_scalar key;
|
||||
int ret = 0;
|
||||
ARG_CHECK(seckey != NULL);
|
||||
ARG_CHECK(privkey != NULL);
|
||||
(void)ctx;
|
||||
|
||||
ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen);
|
||||
if (ret) {
|
||||
secp256k1_scalar_get_b32(seckey, &key);
|
||||
}
|
||||
secp256k1_scalar_clear(&key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -478,55 +478,6 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
|
|||
const unsigned char *seckey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Export a private key in BER format.
|
||||
*
|
||||
* Returns: 1 if the private key was valid.
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot
|
||||
* be NULL)
|
||||
* Out: privkey: pointer to an array for storing the private key in BER.
|
||||
* Should have space for 279 bytes, and cannot be NULL.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *privkey,
|
||||
size_t *privkeylen,
|
||||
const unsigned char *seckey,
|
||||
unsigned int flags
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Import a private key in DER format.
|
||||
* Returns: 1 if a private key was extracted.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL).
|
||||
* Out: seckey: pointer to a 32-byte array for storing the private key.
|
||||
* (cannot be NULL).
|
||||
* In: privkey: pointer to a private key in DER format (cannot be NULL).
|
||||
* privkeylen: length of the DER private key pointed to be privkey.
|
||||
*
|
||||
* This function will accept more than just strict DER, and even allow some BER
|
||||
* violations. The public key stored inside the DER-encoded private key is not
|
||||
* verified for correctness, nor are the curve parameters. Use this function
|
||||
* only if you know in advance it is supposed to contain a secp256k1 private
|
||||
* key.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *seckey,
|
||||
const unsigned char *privkey,
|
||||
size_t privkeylen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak a private key by adding tweak to it.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||
* uniformly random 32-byte arrays, or if the resulting private key
|
||||
|
|
|
@ -17,6 +17,5 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, c
|
|||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s);
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -238,11 +238,11 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
|
|||
* secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test.
|
||||
*/
|
||||
if (secp256k1_gej_eq_x_var(&xr, &pr)) {
|
||||
/* xr.x == xr * xr.z^2 mod p, so the signature is valid. */
|
||||
/* xr * pr.z^2 mod p == pr.x, so the signature is valid. */
|
||||
return 1;
|
||||
}
|
||||
if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) {
|
||||
/* xr + p >= n, so we can skip testing the second case. */
|
||||
/* xr + n >= p, so we can skip testing the second case. */
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe);
|
||||
|
@ -253,39 +253,6 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {
|
||||
unsigned char brx[32];
|
||||
secp256k1_fe fx;
|
||||
secp256k1_ge x;
|
||||
secp256k1_gej xj;
|
||||
secp256k1_scalar rn, u1, u2;
|
||||
secp256k1_gej qj;
|
||||
|
||||
if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_get_b32(brx, sigr);
|
||||
VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* brx comes from a scalar, so is less than the order; certainly less than p */
|
||||
if (recid & 2) {
|
||||
if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe);
|
||||
}
|
||||
if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_gej_set_ge(&xj, &x);
|
||||
secp256k1_scalar_inverse_var(&rn, sigr);
|
||||
secp256k1_scalar_mul(&u1, &rn, message);
|
||||
secp256k1_scalar_negate(&u1, &u1);
|
||||
secp256k1_scalar_mul(&u2, &rn, sigs);
|
||||
secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);
|
||||
secp256k1_ge_set_gej_var(pubkey, &qj);
|
||||
return !secp256k1_gej_is_infinity(&qj);
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {
|
||||
unsigned char b[32];
|
||||
secp256k1_gej rp;
|
||||
|
@ -301,6 +268,7 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
|
|||
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. */
|
||||
secp256k1_gej_clear(&rp);
|
||||
secp256k1_ge_clear(&r);
|
||||
return 0;
|
||||
|
|
103
src/eckey_impl.h
103
src/eckey_impl.h
|
@ -51,109 +51,6 @@ static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *p
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_privkey_parse(secp256k1_scalar *key, const unsigned char *privkey, size_t privkeylen) {
|
||||
unsigned char c[32] = {0};
|
||||
const unsigned char *end = privkey + privkeylen;
|
||||
int lenb = 0;
|
||||
int len = 0;
|
||||
int overflow = 0;
|
||||
/* sequence header */
|
||||
if (end < privkey+1 || *privkey != 0x30) {
|
||||
return 0;
|
||||
}
|
||||
privkey++;
|
||||
/* sequence length constructor */
|
||||
if (end < privkey+1 || !(*privkey & 0x80)) {
|
||||
return 0;
|
||||
}
|
||||
lenb = *privkey & ~0x80; privkey++;
|
||||
if (lenb < 1 || lenb > 2) {
|
||||
return 0;
|
||||
}
|
||||
if (end < privkey+lenb) {
|
||||
return 0;
|
||||
}
|
||||
/* sequence length */
|
||||
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0);
|
||||
privkey += lenb;
|
||||
if (end < privkey+len) {
|
||||
return 0;
|
||||
}
|
||||
/* sequence element 0: version number (=1) */
|
||||
if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) {
|
||||
return 0;
|
||||
}
|
||||
privkey += 3;
|
||||
/* sequence element 1: octet string, up to 32 bytes */
|
||||
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(c + 32 - privkey[1], privkey + 2, privkey[1]);
|
||||
secp256k1_scalar_set_b32(key, c, &overflow);
|
||||
memset(c, 0, 32);
|
||||
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) {
|
||||
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) {
|
||||
static const unsigned char begin[] = {
|
||||
0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20
|
||||
};
|
||||
static const unsigned char middle[] = {
|
||||
0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
|
||||
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
|
||||
0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
|
||||
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
|
||||
0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
|
||||
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00
|
||||
};
|
||||
unsigned char *ptr = privkey;
|
||||
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
|
||||
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
|
||||
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
|
||||
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1)) {
|
||||
return 0;
|
||||
}
|
||||
ptr += pubkeylen;
|
||||
*privkeylen = ptr - privkey;
|
||||
} else {
|
||||
static const unsigned char begin[] = {
|
||||
0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20
|
||||
};
|
||||
static const unsigned char middle[] = {
|
||||
0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
|
||||
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
|
||||
0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
|
||||
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
|
||||
0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11,
|
||||
0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10,
|
||||
0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
|
||||
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00
|
||||
};
|
||||
unsigned char *ptr = privkey;
|
||||
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
|
||||
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
|
||||
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
|
||||
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0)) {
|
||||
return 0;
|
||||
}
|
||||
ptr += pubkeylen;
|
||||
*privkeylen = ptr - privkey;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
|
||||
secp256k1_scalar_add(key, key, tweak);
|
||||
if (secp256k1_scalar_is_zero(key)) {
|
||||
|
|
|
@ -40,8 +40,13 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx
|
|||
static const unsigned char nums_b32[33] = "The scalar for this x is unknown";
|
||||
secp256k1_fe nums_x;
|
||||
secp256k1_ge nums_ge;
|
||||
VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32));
|
||||
VERIFY_CHECK(secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0));
|
||||
int r;
|
||||
r = secp256k1_fe_set_b32(&nums_x, nums_b32);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
|
||||
/* Add G to make the bits in x uniformly distributed. */
|
||||
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL);
|
||||
|
@ -182,7 +187,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
|
|||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
||||
retry = !secp256k1_fe_set_b32(&s, nonce32);
|
||||
retry |= secp256k1_fe_is_zero(&s);
|
||||
} while (retry);
|
||||
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */
|
||||
/* Randomize the projection to defend against multiplier sidechannels. */
|
||||
secp256k1_gej_rescale(&ctx->initial, &s);
|
||||
secp256k1_fe_clear(&s);
|
||||
|
@ -191,7 +196,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
|
|||
secp256k1_scalar_set_b32(&b, nonce32, &retry);
|
||||
/* A blinding value of 0 works, but would undermine the projection hardening. */
|
||||
retry |= secp256k1_scalar_is_zero(&b);
|
||||
} while (retry);
|
||||
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */
|
||||
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
|
||||
memset(nonce32, 0, 32);
|
||||
secp256k1_ecmult_gen(ctx, &gb, &b);
|
||||
|
|
|
@ -224,6 +224,7 @@ static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) {
|
|||
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
|
||||
};
|
||||
unsigned char b[32];
|
||||
int res;
|
||||
secp256k1_fe c = *a;
|
||||
secp256k1_fe_normalize_var(&c);
|
||||
secp256k1_fe_get_b32(b, &c);
|
||||
|
@ -231,7 +232,9 @@ static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) {
|
|||
secp256k1_num_set_bin(&m, prime, 32);
|
||||
secp256k1_num_mod_inverse(&n, &n, &m);
|
||||
secp256k1_num_get_bin(b, 32, &n);
|
||||
VERIFY_CHECK(secp256k1_fe_set_b32(r, b));
|
||||
res = secp256k1_fe_set_b32(r, b);
|
||||
(void)res;
|
||||
VERIFY_CHECK(res);
|
||||
/* Verify the result is the (unique) valid inverse using non-GMP code. */
|
||||
secp256k1_fe_mul(&c, &c, r);
|
||||
secp256k1_fe_add(&c, &negone);
|
||||
|
|
|
@ -84,6 +84,42 @@ int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {
|
||||
unsigned char brx[32];
|
||||
secp256k1_fe fx;
|
||||
secp256k1_ge x;
|
||||
secp256k1_gej xj;
|
||||
secp256k1_scalar rn, u1, u2;
|
||||
secp256k1_gej qj;
|
||||
int r;
|
||||
|
||||
if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_get_b32(brx, sigr);
|
||||
r = secp256k1_fe_set_b32(&fx, brx);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */
|
||||
if (recid & 2) {
|
||||
if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe);
|
||||
}
|
||||
if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_gej_set_ge(&xj, &x);
|
||||
secp256k1_scalar_inverse_var(&rn, sigr);
|
||||
secp256k1_scalar_mul(&u1, &rn, message);
|
||||
secp256k1_scalar_negate(&u1, &u1);
|
||||
secp256k1_scalar_mul(&u2, &rn, sigs);
|
||||
secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);
|
||||
secp256k1_ge_set_gej_var(pubkey, &qj);
|
||||
return !secp256k1_gej_is_infinity(&qj);
|
||||
}
|
||||
|
||||
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) {
|
||||
secp256k1_scalar r, s;
|
||||
secp256k1_scalar sec, non, msg;
|
||||
|
|
|
@ -70,6 +70,7 @@ static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, cons
|
|||
|
||||
static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
|
||||
mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs);
|
||||
(void)c;
|
||||
VERIFY_CHECK(c == 0);
|
||||
r->limbs = a->limbs;
|
||||
while (r->limbs > 1 && r->data[r->limbs-1]==0) {
|
||||
|
@ -125,6 +126,7 @@ static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a,
|
|||
}
|
||||
sn = NUM_LIMBS+1;
|
||||
gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs);
|
||||
(void)gn;
|
||||
VERIFY_CHECK(gn == 1);
|
||||
VERIFY_CHECK(g[0] == 1);
|
||||
r->neg = a->neg ^ m->neg;
|
||||
|
|
|
@ -300,8 +300,10 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m
|
|||
/* We feed a byte array to the PRNG as input, consisting of:
|
||||
* - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d.
|
||||
* - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data.
|
||||
* - optionally 16 extra bytes with the algorithm name (the extra data bytes
|
||||
* are set to zeroes when not present, while the algorithm name is).
|
||||
* - optionally 16 extra bytes with the algorithm name.
|
||||
* Because the arguments have distinct fixed lengths it is not possible for
|
||||
* different argument mixtures to emulate each other and result in the same
|
||||
* nonces.
|
||||
*/
|
||||
memcpy(keydata, key32, 32);
|
||||
memcpy(keydata + 32, msg32, 32);
|
||||
|
@ -310,9 +312,8 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m
|
|||
keylen = 96;
|
||||
}
|
||||
if (algo16 != NULL) {
|
||||
memset(keydata + keylen, 0, 96 - keylen);
|
||||
memcpy(keydata + 96, algo16, 16);
|
||||
keylen = 112;
|
||||
memcpy(keydata + keylen, algo16, 16);
|
||||
keylen += 16;
|
||||
}
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen);
|
||||
memset(keydata, 0, sizeof(keydata));
|
||||
|
@ -399,13 +400,13 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p
|
|||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
||||
ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec));
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
|
||||
secp256k1_ge_set_gej(&p, &pj);
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
secp256k1_scalar_clear(&sec);
|
||||
if (!ret) {
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
if (ret) {
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
|
||||
secp256k1_ge_set_gej(&p, &pj);
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
}
|
||||
secp256k1_scalar_clear(&sec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -423,6 +424,7 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *
|
|||
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
||||
|
||||
ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term);
|
||||
memset(seckey, 0, 32);
|
||||
if (ret) {
|
||||
secp256k1_scalar_get_b32(seckey, &sec);
|
||||
}
|
||||
|
@ -443,12 +445,13 @@ int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey
|
|||
ARG_CHECK(tweak != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
||||
if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) {
|
||||
ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term);
|
||||
if (ret) {
|
||||
ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
if (ret) {
|
||||
if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) {
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
} else {
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,6 +471,7 @@ int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *
|
|||
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
|
||||
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
||||
ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor);
|
||||
memset(seckey, 0, 32);
|
||||
if (ret) {
|
||||
secp256k1_scalar_get_b32(seckey, &sec);
|
||||
}
|
||||
|
@ -488,48 +492,19 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
|
|||
ARG_CHECK(tweak != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
|
||||
if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) {
|
||||
ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor);
|
||||
if (ret) {
|
||||
ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
if (ret) {
|
||||
if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) {
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
} else {
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_privkey_export(const secp256k1_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, unsigned int flags) {
|
||||
secp256k1_scalar key;
|
||||
int ret = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(seckey != NULL);
|
||||
ARG_CHECK(privkey != NULL);
|
||||
ARG_CHECK(privkeylen != NULL);
|
||||
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);
|
||||
secp256k1_scalar_clear(&key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_privkey_import(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *privkey, size_t privkeylen) {
|
||||
secp256k1_scalar key;
|
||||
int ret = 0;
|
||||
ARG_CHECK(seckey != NULL);
|
||||
ARG_CHECK(privkey != NULL);
|
||||
(void)ctx;
|
||||
|
||||
ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen);
|
||||
if (ret) {
|
||||
secp256k1_scalar_get_b32(seckey, &key);
|
||||
}
|
||||
secp256k1_scalar_clear(&key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) {
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
|
|
482
src/tests.c
482
src/tests.c
|
@ -25,6 +25,7 @@
|
|||
#endif
|
||||
|
||||
#include "contrib/lax_der_parsing.h"
|
||||
#include "contrib/lax_der_privatekey_parsing.h"
|
||||
|
||||
#if !defined(VG_CHECK)
|
||||
# if defined(VALGRIND)
|
||||
|
@ -40,6 +41,22 @@
|
|||
static int count = 64;
|
||||
static secp256k1_context *ctx = NULL;
|
||||
|
||||
static void counting_illegal_callback_fn(const char* str, void* data) {
|
||||
/* Dummy callback function that just counts. */
|
||||
int32_t *p;
|
||||
(void)str;
|
||||
p = data;
|
||||
(*p)++;
|
||||
}
|
||||
|
||||
static void uncounting_illegal_callback_fn(const char* str, void* data) {
|
||||
/* Dummy callback function that just counts (backwards). */
|
||||
int32_t *p;
|
||||
(void)str;
|
||||
p = data;
|
||||
(*p)--;
|
||||
}
|
||||
|
||||
void random_field_element_test(secp256k1_fe *fe) {
|
||||
do {
|
||||
unsigned char b32[32];
|
||||
|
@ -117,6 +134,11 @@ void random_scalar_order(secp256k1_scalar *num) {
|
|||
}
|
||||
|
||||
void run_context_tests(void) {
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
unsigned char ctmp[32];
|
||||
int32_t ecount;
|
||||
int32_t ecount2;
|
||||
secp256k1_context *none = secp256k1_context_create(0);
|
||||
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
|
@ -127,6 +149,13 @@ void run_context_tests(void) {
|
|||
secp256k1_scalar msg, key, nonce;
|
||||
secp256k1_scalar sigr, sigs;
|
||||
|
||||
ecount = 0;
|
||||
ecount2 = 10;
|
||||
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2);
|
||||
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL);
|
||||
CHECK(vrfy->error_callback.fn != sign->error_callback.fn);
|
||||
|
||||
/*** clone and destroy all of them to make sure cloning was complete ***/
|
||||
{
|
||||
secp256k1_context *ctx_tmp;
|
||||
|
@ -137,12 +166,54 @@ void run_context_tests(void) {
|
|||
ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp);
|
||||
}
|
||||
|
||||
/* Verify that the error callback makes it across the clone. */
|
||||
CHECK(vrfy->error_callback.fn != sign->error_callback.fn);
|
||||
/* And that it resets back to default. */
|
||||
secp256k1_context_set_error_callback(sign, NULL, NULL);
|
||||
CHECK(vrfy->error_callback.fn == sign->error_callback.fn);
|
||||
|
||||
/*** attempt to use them ***/
|
||||
random_scalar_order_test(&msg);
|
||||
random_scalar_order_test(&key);
|
||||
secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key);
|
||||
secp256k1_ge_set_gej(&pub, &pubj);
|
||||
|
||||
/* Verify context-type checking illegal-argument errors. */
|
||||
memset(ctmp, 1, 32);
|
||||
CHECK(secp256k1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0);
|
||||
CHECK(ecount == 1);
|
||||
VG_UNDEF(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1);
|
||||
VG_CHECK(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
VG_UNDEF(&sig, sizeof(sig));
|
||||
CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1);
|
||||
VG_CHECK(&sig, sizeof(sig));
|
||||
CHECK(ecount2 == 10);
|
||||
CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0);
|
||||
CHECK(ecount2 == 11);
|
||||
CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0);
|
||||
CHECK(ecount2 == 12);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0);
|
||||
CHECK(ecount2 == 13);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
|
||||
CHECK(ecount2 == 13);
|
||||
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
|
||||
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
|
||||
|
||||
/* This shouldn't leak memory, due to already-set tests. */
|
||||
secp256k1_ecmult_gen_context_build(&sign->ecmult_gen_ctx, NULL);
|
||||
secp256k1_ecmult_context_build(&vrfy->ecmult_ctx, NULL);
|
||||
|
||||
/* obtain a working nonce */
|
||||
do {
|
||||
random_scalar_order_test(&nonce);
|
||||
|
@ -1724,6 +1795,11 @@ void run_wnaf(void) {
|
|||
test_constant_wnaf_negate(&n);
|
||||
test_constant_wnaf(&n, 4 + (i % 10));
|
||||
}
|
||||
secp256k1_scalar_set_int(&n, 0);
|
||||
CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1);
|
||||
CHECK(secp256k1_scalar_is_zero(&n));
|
||||
CHECK(secp256k1_scalar_cond_negate(&n, 0) == 1);
|
||||
CHECK(secp256k1_scalar_is_zero(&n));
|
||||
}
|
||||
|
||||
void test_ecmult_constants(void) {
|
||||
|
@ -1836,22 +1912,6 @@ void run_endomorphism_tests(void) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static void counting_illegal_callback_fn(const char* str, void* data) {
|
||||
/* Dummy callback function that just counts. */
|
||||
int32_t *p;
|
||||
(void)str;
|
||||
p = data;
|
||||
(*p)++;
|
||||
}
|
||||
|
||||
static void uncounting_illegal_callback_fn(const char* str, void* data) {
|
||||
/* Dummy callback function that just counts (backwards). */
|
||||
int32_t *p;
|
||||
(void)str;
|
||||
p = data;
|
||||
(*p)--;
|
||||
}
|
||||
|
||||
void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) {
|
||||
unsigned char pubkeyc[65];
|
||||
secp256k1_pubkey pubkey;
|
||||
|
@ -2228,6 +2288,175 @@ void run_ec_pubkey_parse_test(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void run_eckey_edge_case_test(void) {
|
||||
const unsigned char orderc[32] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
|
||||
0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
|
||||
0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41
|
||||
};
|
||||
const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00};
|
||||
unsigned char ctmp[32];
|
||||
unsigned char ctmp2[32];
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_pubkey pubkey2;
|
||||
int32_t ecount;
|
||||
/* Group order is too large, reject. */
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, orderc) == 0);
|
||||
VG_UNDEF(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0);
|
||||
VG_CHECK(&pubkey, sizeof(pubkey));
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
|
||||
/* Maximum value is too large, reject. */
|
||||
memset(ctmp, 255, 32);
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0);
|
||||
memset(&pubkey, 1, sizeof(pubkey));
|
||||
VG_UNDEF(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0);
|
||||
VG_CHECK(&pubkey, sizeof(pubkey));
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
|
||||
/* Zero is too small, reject. */
|
||||
memset(ctmp, 0, 32);
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0);
|
||||
memset(&pubkey, 1, sizeof(pubkey));
|
||||
VG_UNDEF(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0);
|
||||
VG_CHECK(&pubkey, sizeof(pubkey));
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
|
||||
/* One must be accepted. */
|
||||
ctmp[31] = 0x01;
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1);
|
||||
memset(&pubkey, 0, sizeof(pubkey));
|
||||
VG_UNDEF(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);
|
||||
VG_CHECK(&pubkey, sizeof(pubkey));
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
|
||||
/* Group order + 1 is too large, reject. */
|
||||
memcpy(ctmp, orderc, 32);
|
||||
ctmp[31] = 0x42;
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0);
|
||||
memset(&pubkey, 1, sizeof(pubkey));
|
||||
VG_UNDEF(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0);
|
||||
VG_CHECK(&pubkey, sizeof(pubkey));
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
|
||||
/* -1 must be accepted. */
|
||||
ctmp[31] = 0x40;
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1);
|
||||
memset(&pubkey, 0, sizeof(pubkey));
|
||||
VG_UNDEF(&pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);
|
||||
VG_CHECK(&pubkey, sizeof(pubkey));
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
|
||||
/* Tweak of zero leaves the value changed. */
|
||||
memset(ctmp2, 0, 32);
|
||||
CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1);
|
||||
CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40);
|
||||
memcpy(&pubkey2, &pubkey, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1);
|
||||
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
|
||||
/* Multiply tweak of zero zeroizes the output. */
|
||||
CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, ctmp2) == 0);
|
||||
CHECK(memcmp(zeros, ctmp, 32) == 0);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0);
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);
|
||||
memcpy(&pubkey, &pubkey2, sizeof(pubkey));
|
||||
/* Overflowing key tweak zeroizes. */
|
||||
memcpy(ctmp, orderc, 32);
|
||||
ctmp[31] = 0x40;
|
||||
CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, orderc) == 0);
|
||||
CHECK(memcmp(zeros, ctmp, 32) == 0);
|
||||
memcpy(ctmp, orderc, 32);
|
||||
ctmp[31] = 0x40;
|
||||
CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, orderc) == 0);
|
||||
CHECK(memcmp(zeros, ctmp, 32) == 0);
|
||||
memcpy(ctmp, orderc, 32);
|
||||
ctmp[31] = 0x40;
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0);
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);
|
||||
memcpy(&pubkey, &pubkey2, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0);
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);
|
||||
memcpy(&pubkey, &pubkey2, sizeof(pubkey));
|
||||
/* Private key tweaks results in a key of zero. */
|
||||
ctmp2[31] = 1;
|
||||
CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 0);
|
||||
CHECK(memcmp(zeros, ctmp2, 32) == 0);
|
||||
ctmp2[31] = 1;
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0);
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);
|
||||
memcpy(&pubkey, &pubkey2, sizeof(pubkey));
|
||||
/* Tweak computation wraps and results in a key of 1. */
|
||||
ctmp2[31] = 2;
|
||||
CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 1);
|
||||
CHECK(memcmp(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1);
|
||||
ctmp2[31] = 2;
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1);
|
||||
ctmp2[31] = 1;
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1);
|
||||
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
|
||||
/* Tweak mul * 2 = 1+1. */
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1);
|
||||
ctmp2[31] = 2;
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1);
|
||||
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
|
||||
/* Test argument errors. */
|
||||
ecount = 0;
|
||||
secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
|
||||
CHECK(ecount == 0);
|
||||
/* Zeroize pubkey on parse error. */
|
||||
memset(&pubkey, 0, 32);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0);
|
||||
memcpy(&pubkey, &pubkey2, sizeof(pubkey));
|
||||
memset(&pubkey2, 0, 32);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(memcmp(&pubkey2, zeros, sizeof(pubkey2)) == 0);
|
||||
/* Plain argument errors. */
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, NULL) == 0);
|
||||
CHECK(ecount == 1);
|
||||
ecount = 0;
|
||||
memset(ctmp2, 0, 32);
|
||||
ctmp2[31] = 4;
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, NULL, ctmp2) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
ecount = 0;
|
||||
memset(ctmp2, 0, 32);
|
||||
ctmp2[31] = 4;
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, NULL, ctmp2) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
ecount = 0;
|
||||
memset(ctmp2, 0, 32);
|
||||
CHECK(secp256k1_ec_privkey_tweak_add(ctx, NULL, ctmp2) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
ecount = 0;
|
||||
memset(ctmp2, 0, 32);
|
||||
ctmp2[31] = 1;
|
||||
CHECK(secp256k1_ec_privkey_tweak_mul(ctx, NULL, ctmp2) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
ecount = 0;
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, NULL, ctmp) == 0);
|
||||
CHECK(ecount == 1);
|
||||
memset(&pubkey, 1, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
|
||||
secp256k1_context_set_illegal_callback(ctx, NULL, NULL);
|
||||
}
|
||||
|
||||
void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) {
|
||||
secp256k1_scalar nonce;
|
||||
do {
|
||||
|
@ -2351,8 +2580,8 @@ 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(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1) ? SECP256K1_EC_COMPRESSED : 0);
|
||||
CHECK(secp256k1_ec_privkey_import(ctx, privkey2, seckey, seckeylen) == 1);
|
||||
CHECK(secp256k1_ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1) ? SECP256K1_EC_COMPRESSED : 0);
|
||||
CHECK(secp256k1_ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1);
|
||||
CHECK(memcmp(privkey, privkey2, 32) == 0);
|
||||
|
||||
/* Optionally tweak the keys using addition. */
|
||||
|
@ -2838,7 +3067,6 @@ void run_ecdsa_der_parse(void) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Tests several edge cases. */
|
||||
void test_ecdsa_edge_cases(void) {
|
||||
int t;
|
||||
|
@ -2860,11 +3088,159 @@ void test_ecdsa_edge_cases(void) {
|
|||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
}
|
||||
|
||||
/*Signature where s would be zero.*/
|
||||
/* Verify signature with r of zero fails. */
|
||||
{
|
||||
unsigned char signature[72];
|
||||
const unsigned char pubkey_mods_zero[33] = {
|
||||
0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0,
|
||||
0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41,
|
||||
0x41
|
||||
};
|
||||
secp256k1_ge key;
|
||||
secp256k1_scalar msg;
|
||||
secp256k1_scalar sr, ss;
|
||||
secp256k1_scalar_set_int(&ss, 1);
|
||||
secp256k1_scalar_set_int(&msg, 0);
|
||||
secp256k1_scalar_set_int(&sr, 0);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Verify signature with s of zero fails. */
|
||||
{
|
||||
const unsigned char pubkey[33] = {
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01
|
||||
};
|
||||
secp256k1_ge key;
|
||||
secp256k1_scalar msg;
|
||||
secp256k1_scalar sr, ss;
|
||||
secp256k1_scalar_set_int(&ss, 0);
|
||||
secp256k1_scalar_set_int(&msg, 0);
|
||||
secp256k1_scalar_set_int(&sr, 1);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Verify signature with message 0 passes. */
|
||||
{
|
||||
const unsigned char pubkey[33] = {
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02
|
||||
};
|
||||
const unsigned char pubkey2[33] = {
|
||||
0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0,
|
||||
0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41,
|
||||
0x43
|
||||
};
|
||||
secp256k1_ge key;
|
||||
secp256k1_ge key2;
|
||||
secp256k1_scalar msg;
|
||||
secp256k1_scalar sr, ss;
|
||||
secp256k1_scalar_set_int(&ss, 2);
|
||||
secp256k1_scalar_set_int(&msg, 0);
|
||||
secp256k1_scalar_set_int(&sr, 2);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
|
||||
secp256k1_scalar_negate(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
|
||||
secp256k1_scalar_set_int(&ss, 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Verify signature with message 1 passes. */
|
||||
{
|
||||
const unsigned char pubkey[33] = {
|
||||
0x02, 0x14, 0x4e, 0x5a, 0x58, 0xef, 0x5b, 0x22,
|
||||
0x6f, 0xd2, 0xe2, 0x07, 0x6a, 0x77, 0xcf, 0x05,
|
||||
0xb4, 0x1d, 0xe7, 0x4a, 0x30, 0x98, 0x27, 0x8c,
|
||||
0x93, 0xe6, 0xe6, 0x3c, 0x0b, 0xc4, 0x73, 0x76,
|
||||
0x25
|
||||
};
|
||||
const unsigned char pubkey2[33] = {
|
||||
0x02, 0x8a, 0xd5, 0x37, 0xed, 0x73, 0xd9, 0x40,
|
||||
0x1d, 0xa0, 0x33, 0xd2, 0xdc, 0xf0, 0xaf, 0xae,
|
||||
0x34, 0xcf, 0x5f, 0x96, 0x4c, 0x73, 0x28, 0x0f,
|
||||
0x92, 0xc0, 0xf6, 0x9d, 0xd9, 0xb2, 0x09, 0x10,
|
||||
0x62
|
||||
};
|
||||
const unsigned char csr[32] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4,
|
||||
0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xeb
|
||||
};
|
||||
secp256k1_ge key;
|
||||
secp256k1_ge key2;
|
||||
secp256k1_scalar msg;
|
||||
secp256k1_scalar sr, ss;
|
||||
secp256k1_scalar_set_int(&ss, 1);
|
||||
secp256k1_scalar_set_int(&msg, 1);
|
||||
secp256k1_scalar_set_b32(&sr, csr, NULL);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
|
||||
secp256k1_scalar_negate(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1);
|
||||
secp256k1_scalar_set_int(&ss, 2);
|
||||
secp256k1_scalar_inverse_var(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Verify signature with message -1 passes. */
|
||||
{
|
||||
const unsigned char pubkey[33] = {
|
||||
0x03, 0xaf, 0x97, 0xff, 0x7d, 0x3a, 0xf6, 0xa0,
|
||||
0x02, 0x94, 0xbd, 0x9f, 0x4b, 0x2e, 0xd7, 0x52,
|
||||
0x28, 0xdb, 0x49, 0x2a, 0x65, 0xcb, 0x1e, 0x27,
|
||||
0x57, 0x9c, 0xba, 0x74, 0x20, 0xd5, 0x1d, 0x20,
|
||||
0xf1
|
||||
};
|
||||
const unsigned char csr[32] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4,
|
||||
0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xee
|
||||
};
|
||||
secp256k1_ge key;
|
||||
secp256k1_scalar msg;
|
||||
secp256k1_scalar sr, ss;
|
||||
secp256k1_scalar_set_int(&ss, 1);
|
||||
secp256k1_scalar_set_int(&msg, 1);
|
||||
secp256k1_scalar_negate(&msg, &msg);
|
||||
secp256k1_scalar_set_b32(&sr, csr, NULL);
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
secp256k1_scalar_negate(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1);
|
||||
secp256k1_scalar_set_int(&ss, 3);
|
||||
secp256k1_scalar_inverse_var(&ss, &ss);
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Signature where s would be zero. */
|
||||
{
|
||||
secp256k1_pubkey pubkey;
|
||||
size_t siglen;
|
||||
const unsigned char nonce[32] = {
|
||||
int32_t ecount;
|
||||
unsigned char signature[72];
|
||||
static const unsigned char nonce[32] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
@ -2888,15 +3264,40 @@ void test_ecdsa_edge_cases(void) {
|
|||
0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62,
|
||||
0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9,
|
||||
};
|
||||
ecount = 0;
|
||||
secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 0);
|
||||
msg[31] = 0xaa;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 1);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, NULL, msg, key, precomputed_nonce_function, nonce2) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, &sig, NULL, key, precomputed_nonce_function, nonce2) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, NULL, precomputed_nonce_function, nonce2) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, key) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, NULL, msg, &pubkey) == 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, NULL, &pubkey) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, NULL) == 0);
|
||||
CHECK(ecount == 6);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 1);
|
||||
siglen = 72;
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, NULL, &siglen, &sig) == 0);
|
||||
CHECK(ecount == 7);
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, NULL, &sig) == 0);
|
||||
CHECK(ecount == 8);
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, NULL) == 0);
|
||||
CHECK(ecount == 9);
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1);
|
||||
siglen = 10;
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0);
|
||||
CHECK(ecount == 9);
|
||||
secp256k1_context_set_illegal_callback(ctx, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Nonce function corner cases. */
|
||||
|
@ -2960,6 +3361,34 @@ void test_ecdsa_edge_cases(void) {
|
|||
key[0] = 0;
|
||||
}
|
||||
|
||||
{
|
||||
/* Check that optional nonce arguments do not have equivilent effect. */
|
||||
const unsigned char zeros[32] = {0};
|
||||
unsigned char nonce[32];
|
||||
unsigned char nonce2[32];
|
||||
unsigned char nonce3[32];
|
||||
unsigned char nonce4[32];
|
||||
VG_UNDEF(nonce,32);
|
||||
VG_UNDEF(nonce2,32);
|
||||
VG_UNDEF(nonce3,32);
|
||||
VG_UNDEF(nonce4,32);
|
||||
CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1);
|
||||
VG_CHECK(nonce,32);
|
||||
CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1);
|
||||
VG_CHECK(nonce2,32);
|
||||
CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1);
|
||||
VG_CHECK(nonce3,32);
|
||||
CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1);
|
||||
VG_CHECK(nonce4,32);
|
||||
CHECK(memcmp(nonce, nonce2, 32) != 0);
|
||||
CHECK(memcmp(nonce, nonce3, 32) != 0);
|
||||
CHECK(memcmp(nonce, nonce4, 32) != 0);
|
||||
CHECK(memcmp(nonce2, nonce3, 32) != 0);
|
||||
CHECK(memcmp(nonce2, nonce4, 32) != 0);
|
||||
CHECK(memcmp(nonce3, nonce4, 32) != 0);
|
||||
}
|
||||
|
||||
|
||||
/* Privkey export where pubkey is the point at infinity. */
|
||||
{
|
||||
unsigned char privkey[300];
|
||||
|
@ -2970,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(ctx, privkey, &outlen, seckey, 0));
|
||||
CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, 0));
|
||||
outlen = 300;
|
||||
CHECK(!secp256k1_ec_privkey_export(ctx, privkey, &outlen, seckey, SECP256K1_EC_COMPRESSED));
|
||||
CHECK(!secp256k1_ec_privkey_export_der(ctx, privkey, &outlen, seckey, SECP256K1_EC_COMPRESSED));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3137,9 +3566,12 @@ int main(int argc, char **argv) {
|
|||
run_endomorphism_tests();
|
||||
#endif
|
||||
|
||||
/* EC point parser test*/
|
||||
/* EC point parser test */
|
||||
run_ec_pubkey_parse_test();
|
||||
|
||||
/* EC key edge cases */
|
||||
run_eckey_edge_case_test();
|
||||
|
||||
#ifdef ENABLE_MODULE_ECDH
|
||||
/* ecdh tests */
|
||||
run_ecdh_tests();
|
||||
|
|
Loading…
Reference in a new issue