mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 10:43:19 -03:00
Merge pull request #334
0c6ab2f
Introduce explicit lower-S normalization (Pieter Wuille)fea19e7
Add contrib/lax_der_parsing.h (Pieter Wuille)3bb9c44
Rewrite ECDSA signature parsing code (Pieter Wuille)fa57f1b
Use secp256k1_rand_int and secp256k1_rand_bits more (Pieter Wuille)49b3749
Add new tests for the extra testrand functions (Pieter Wuille)f684d7d
Faster secp256k1_rand_int implementation (Pieter Wuille)251b1a6
Improve testrand: add extra random functions (Pieter Wuille)
This commit is contained in:
commit
131afe5bf5
12 changed files with 1015 additions and 155 deletions
|
@ -40,6 +40,7 @@ noinst_HEADERS += src/hash_impl.h
|
|||
noinst_HEADERS += src/field.h
|
||||
noinst_HEADERS += src/field_impl.h
|
||||
noinst_HEADERS += src/bench.h
|
||||
noinst_HEADERS += contrib/lax_der_parsing.h
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libsecp256k1.pc
|
||||
|
@ -64,7 +65,7 @@ endif
|
|||
if USE_TESTS
|
||||
noinst_PROGRAMS += tests
|
||||
tests_SOURCES = src/tests.c
|
||||
tests_CPPFLAGS = -DVERIFY -I$(top_srcdir)/src $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
|
||||
tests_CPPFLAGS = -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
|
||||
tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS)
|
||||
tests_LDFLAGS = -static
|
||||
TESTS = tests
|
||||
|
|
191
contrib/lax_der_parsing.h
Normal file
191
contrib/lax_der_parsing.h
Normal file
|
@ -0,0 +1,191 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 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 a code snippet that parses DER 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.
|
||||
*
|
||||
* In many places it matters that different implementations do not only accept
|
||||
* the same set of valid signatures, but also reject the same set of signatures.
|
||||
* The only means to accomplish that is by strictly obeying a standard, and not
|
||||
* accepting anything else.
|
||||
*
|
||||
* Nonetheless, sometimes there is a need for compatibility with systems that
|
||||
* use signatures which do not strictly obey DER. The snippet below shows how
|
||||
* certain violations are easily supported. You may need to adapt it.
|
||||
*
|
||||
* Do not use this for new systems. Use well-defined DER or compact signatures
|
||||
* instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and
|
||||
* secp256k1_ecdsa_signature_parse_compact).
|
||||
*
|
||||
* The supported violations are:
|
||||
* - All numbers are parsed as nonnegative integers, even though X.609-0207
|
||||
* section 8.3.3 specifies that integers are always encoded as two's
|
||||
* complement.
|
||||
* - Integers can have length 0, even though section 8.3.1 says they can't.
|
||||
* - Integers with overly long padding are accepted, violation section
|
||||
* 8.3.2.
|
||||
* - 127-byte long length descriptors are accepted, even though section
|
||||
* 8.1.3.5.c says that they are not.
|
||||
* - Trailing garbage data inside or after the signature is ignored.
|
||||
* - The length descriptor of the sequence is ignored.
|
||||
*
|
||||
* Compared to for example OpenSSL, many violations are NOT supported:
|
||||
* - Using overly long tag descriptors for the sequence or integers inside,
|
||||
* violating section 8.1.2.2.
|
||||
* - Encoding primitive integers as constructed values, violating section
|
||||
* 8.3.1.
|
||||
*/
|
||||
|
||||
#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_
|
||||
#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <secp256k1.h>
|
||||
|
||||
static int secp256k1_ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen);
|
||||
|
||||
static int secp256k1_ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
|
||||
size_t rpos, rlen, spos, slen;
|
||||
size_t pos = 0;
|
||||
size_t lenbyte;
|
||||
unsigned char tmpsig[64] = {0};
|
||||
int overflow = 0;
|
||||
|
||||
/* Hack to initialize sig with a correctly-parsed but invalid signature. */
|
||||
secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
|
||||
|
||||
/* Sequence tag byte */
|
||||
if (pos == inputlen || input[pos] != 0x30) {
|
||||
return 0;
|
||||
}
|
||||
pos++;
|
||||
|
||||
/* Sequence length bytes */
|
||||
if (pos == inputlen) {
|
||||
return 0;
|
||||
}
|
||||
lenbyte = input[pos++];
|
||||
if (lenbyte & 0x80) {
|
||||
lenbyte -= 0x80;
|
||||
if (pos + lenbyte > inputlen) {
|
||||
return 0;
|
||||
}
|
||||
pos += lenbyte;
|
||||
}
|
||||
|
||||
/* Integer tag byte for R */
|
||||
if (pos == inputlen || input[pos] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
pos++;
|
||||
|
||||
/* Integer length for R */
|
||||
if (pos == inputlen) {
|
||||
return 0;
|
||||
}
|
||||
lenbyte = input[pos++];
|
||||
if (lenbyte & 0x80) {
|
||||
lenbyte -= 0x80;
|
||||
if (pos + lenbyte > inputlen) {
|
||||
return 0;
|
||||
}
|
||||
while (lenbyte > 0 && input[pos] == 0) {
|
||||
pos++;
|
||||
lenbyte--;
|
||||
}
|
||||
if (lenbyte >= sizeof(size_t)) {
|
||||
return 0;
|
||||
}
|
||||
rlen = 0;
|
||||
while (lenbyte > 0) {
|
||||
rlen = (rlen << 8) + input[pos];
|
||||
pos++;
|
||||
lenbyte--;
|
||||
}
|
||||
} else {
|
||||
rlen = lenbyte;
|
||||
}
|
||||
if (rlen > inputlen - pos) {
|
||||
return 0;
|
||||
}
|
||||
rpos = pos;
|
||||
pos += rlen;
|
||||
|
||||
/* Integer tag byte for S */
|
||||
if (pos == inputlen || input[pos] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
pos++;
|
||||
|
||||
/* Integer length for S */
|
||||
if (pos == inputlen) {
|
||||
return 0;
|
||||
}
|
||||
lenbyte = input[pos++];
|
||||
if (lenbyte & 0x80) {
|
||||
lenbyte -= 0x80;
|
||||
if (pos + lenbyte > inputlen) {
|
||||
return 0;
|
||||
}
|
||||
while (lenbyte > 0 && input[pos] == 0) {
|
||||
pos++;
|
||||
lenbyte--;
|
||||
}
|
||||
if (lenbyte >= sizeof(size_t)) {
|
||||
return 0;
|
||||
}
|
||||
slen = 0;
|
||||
while (lenbyte > 0) {
|
||||
slen = (slen << 8) + input[pos];
|
||||
pos++;
|
||||
lenbyte--;
|
||||
}
|
||||
} else {
|
||||
slen = lenbyte;
|
||||
}
|
||||
if (slen > inputlen - pos) {
|
||||
return 0;
|
||||
}
|
||||
spos = pos;
|
||||
pos += slen;
|
||||
|
||||
/* Ignore leading zeroes in R */
|
||||
while (rlen > 0 && input[rpos] == 0) {
|
||||
rlen--;
|
||||
rpos++;
|
||||
}
|
||||
/* Copy R value */
|
||||
if (rlen > 32) {
|
||||
overflow = 1;
|
||||
} else {
|
||||
memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
|
||||
}
|
||||
|
||||
/* Ignore leading zeroes in S */
|
||||
while (slen > 0 && input[spos] == 0) {
|
||||
slen--;
|
||||
spos++;
|
||||
}
|
||||
/* Copy S value */
|
||||
if (slen > 32) {
|
||||
overflow = 1;
|
||||
} else {
|
||||
memcpy(tmpsig + 64 - slen, input + spos, slen);
|
||||
}
|
||||
|
||||
if (!overflow) {
|
||||
overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
|
||||
}
|
||||
if (overflow) {
|
||||
memset(tmpsig, 0, 64);
|
||||
secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -271,6 +271,27 @@ SECP256K1_API int secp256k1_ec_pubkey_serialize(
|
|||
unsigned int flags
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Parse an ECDSA signature in compact (64 bytes) format.
|
||||
*
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise.
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sig: a pointer to a signature object
|
||||
* In: input64: a pointer to the 64-byte array to parse
|
||||
*
|
||||
* The signature must consist of a 32-byte big endian R value, followed by a
|
||||
* 32-byte big endian S value. If R or S fall outside of [0..order-1], the
|
||||
* encoding is invalid. R and S with value 0 are allowed in the encoding.
|
||||
*
|
||||
* After the call, sig will always be initialized. If parsing failed or R or
|
||||
* S are zero, the resulting sig value is guaranteed to fail validation for any
|
||||
* message and public key.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature* sig,
|
||||
const unsigned char *input64
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Parse a DER ECDSA signature.
|
||||
*
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise.
|
||||
|
@ -279,7 +300,12 @@ SECP256K1_API int secp256k1_ec_pubkey_serialize(
|
|||
* In: input: a pointer to the signature to be parsed
|
||||
* inputlen: the length of the array pointed to be input
|
||||
*
|
||||
* Note that this function also supports some violations of DER and even BER.
|
||||
* This function will accept any valid DER encoded signature, even if the
|
||||
* encoded numbers are out of range.
|
||||
*
|
||||
* After the call, sig will always be initialized. If parsing failed or the
|
||||
* encoded numbers are out of range, signature validation with it is
|
||||
* guaranteed to fail for every message and public key.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_parse_der(
|
||||
const secp256k1_context* ctx,
|
||||
|
@ -306,6 +332,21 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_der(
|
|||
const secp256k1_ecdsa_signature* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Serialize an ECDSA signature in compact (64 byte) format.
|
||||
*
|
||||
* Returns: 1
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: output64: a pointer to a 64-byte array to store the compact serialization
|
||||
* In: sig: a pointer to an initialized signature object
|
||||
*
|
||||
* See secp256k1_ecdsa_signature_parse_compact for details about the encoding.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output64,
|
||||
const secp256k1_ecdsa_signature* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Verify an ECDSA signature.
|
||||
*
|
||||
* Returns: 1: correct signature
|
||||
|
@ -314,6 +355,15 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_der(
|
|||
* In: sig: the signature being verified (cannot be NULL)
|
||||
* msg32: the 32-byte message hash being verified (cannot be NULL)
|
||||
* pubkey: pointer to an initialized public key to verify with (cannot be NULL)
|
||||
*
|
||||
* To avoid accepting malleable signatures, only ECDSA signatures in lower-S
|
||||
* form are accepted.
|
||||
*
|
||||
* If you need to accept ECDSA signatures from sources that do not obey this
|
||||
* rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to
|
||||
* validation, but be aware that doing so results in malleable signatures.
|
||||
*
|
||||
* For details, see the comments for that function.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
|
||||
const secp256k1_context* ctx,
|
||||
|
@ -322,6 +372,54 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
|
|||
const secp256k1_pubkey *pubkey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Convert a signature to a normalized lower-S form.
|
||||
*
|
||||
* Returns: 1 if sigin was not normalized, 0 if it already was.
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sigout: a pointer to a signature to fill with the normalized form,
|
||||
* or copy if the input was already normalized. (can be NULL if
|
||||
* you're only interested in whether the input was already
|
||||
* normalized).
|
||||
* In: sigin: a pointer to a signature to check/normalize (cannot be NULL,
|
||||
* can be identical to sigout)
|
||||
*
|
||||
* With ECDSA a third-party can forge a second distinct signature of the same
|
||||
* message, given a single initial signature, but without knowing the key. This
|
||||
* is done by negating the S value modulo the order of the curve, 'flipping'
|
||||
* the sign of the random point R which is not included in the signature.
|
||||
*
|
||||
* Forgery of the same message isn't universally problematic, but in systems
|
||||
* where message malleability or uniqueness of signatures is important this can
|
||||
* cause issues. This forgery can be blocked by all verifiers forcing signers
|
||||
* to use a normalized form.
|
||||
*
|
||||
* The lower-S form reduces the size of signatures slightly on average when
|
||||
* variable length encodings (such as DER) are used and is cheap to verify,
|
||||
* making it a good choice. Security of always using lower-S is assured because
|
||||
* anyone can trivially modify a signature after the fact to enforce this
|
||||
* property anyway.
|
||||
*
|
||||
* The lower S value is always between 0x1 and
|
||||
* 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
|
||||
* inclusive.
|
||||
*
|
||||
* No other forms of ECDSA malleability are known and none seem likely, but
|
||||
* there is no formal proof that ECDSA, even with this additional restriction,
|
||||
* is free of other malleability. Commonly used serialization schemes will also
|
||||
* accept various non-unique encodings, so care should be taken when this
|
||||
* property is required for an application.
|
||||
*
|
||||
* The secp256k1_ecdsa_sign function will by default create signatures in the
|
||||
* lower-S form, and secp256k1_ecdsa_verify will not accept others. In case
|
||||
* signatures come from a system that cannot enforce this property,
|
||||
* secp256k1_ecdsa_signature_normalize must be called before verification.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_normalize(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature *sigout,
|
||||
const secp256k1_ecdsa_signature *sigin
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function.
|
||||
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
|
||||
* extra entropy.
|
||||
|
@ -342,32 +440,8 @@ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_def
|
|||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
|
||||
*
|
||||
* The sig always has an s value in the lower half of the range (From 0x1
|
||||
* to 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
|
||||
* inclusive), unlike many other implementations.
|
||||
*
|
||||
* With ECDSA a third-party can can forge a second distinct signature
|
||||
* of the same message given a single initial signature without knowing
|
||||
* the key by setting s to its additive inverse mod-order, 'flipping' the
|
||||
* sign of the random point R which is not included in the signature.
|
||||
* Since the forgery is of the same message this isn't universally
|
||||
* problematic, but in systems where message malleability or uniqueness
|
||||
* of signatures is important this can cause issues. This forgery can be
|
||||
* blocked by all verifiers forcing signers to use a canonical form. The
|
||||
* lower-S form reduces the size of signatures slightly on average when
|
||||
* variable length encodings (such as DER) are used and is cheap to
|
||||
* verify, making it a good choice. Security of always using lower-S is
|
||||
* assured because anyone can trivially modify a signature after the
|
||||
* fact to enforce this property. Adjusting it inside the signing
|
||||
* function avoids the need to re-serialize or have curve specific
|
||||
* constants outside of the library. By always using a canonical form
|
||||
* even in applications where it isn't needed it becomes possible to
|
||||
* impose a requirement later if a need is discovered.
|
||||
* No other forms of ECDSA malleability are known and none seem likely,
|
||||
* but there is no formal proof that ECDSA, even with this additional
|
||||
* restriction, is free of other malleability. Commonly used serialization
|
||||
* schemes will also accept various non-unique encodings, so care should
|
||||
* be taken when this property is required for an application.
|
||||
* The created signature is always in lower-S form. See
|
||||
* secp256k1_ecdsa_signature_normalize for more details.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_sign(
|
||||
const secp256k1_context* ctx,
|
||||
|
|
|
@ -65,7 +65,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
|||
unsigned char *output64,
|
||||
int *recid,
|
||||
const secp256k1_ecdsa_recoverable_signature* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Create a recoverable ECDSA signature.
|
||||
*
|
||||
|
|
162
src/ecdsa_impl.h
162
src/ecdsa_impl.h
|
@ -1,5 +1,5 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Copyright (c) 2013-2015 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
@ -46,66 +46,132 @@ static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CON
|
|||
0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL
|
||||
);
|
||||
|
||||
static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned char *sigend) {
|
||||
int lenleft, b1;
|
||||
size_t ret = 0;
|
||||
if (*sigp >= sigend) {
|
||||
return -1;
|
||||
}
|
||||
b1 = *((*sigp)++);
|
||||
if (b1 == 0xFF) {
|
||||
/* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */
|
||||
return -1;
|
||||
}
|
||||
if ((b1 & 0x80) == 0) {
|
||||
/* X.690-0207 8.1.3.4 short form length octets */
|
||||
return b1;
|
||||
}
|
||||
if (b1 == 0x80) {
|
||||
/* Indefinite length is not allowed in DER. */
|
||||
return -1;
|
||||
}
|
||||
/* X.690-207 8.1.3.5 long form length octets */
|
||||
lenleft = b1 & 0x7F;
|
||||
if (lenleft > sigend - *sigp) {
|
||||
return -1;
|
||||
}
|
||||
if (**sigp == 0) {
|
||||
/* Not the shortest possible length encoding. */
|
||||
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. */
|
||||
return -1;
|
||||
}
|
||||
while (lenleft > 0) {
|
||||
if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) {
|
||||
}
|
||||
ret = (ret << 8) | **sigp;
|
||||
if (ret + lenleft > (size_t)(sigend - *sigp)) {
|
||||
/* Result exceeds the length of the passed array. */
|
||||
return -1;
|
||||
}
|
||||
(*sigp)++;
|
||||
lenleft--;
|
||||
}
|
||||
if (ret < 128) {
|
||||
/* Not the shortest possible length encoding. */
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) {
|
||||
int overflow = 0;
|
||||
unsigned char ra[32] = {0};
|
||||
int rlen;
|
||||
|
||||
if (*sig == sigend || **sig != 0x02) {
|
||||
/* Not a primitive integer (X.690-0207 8.3.1). */
|
||||
return 0;
|
||||
}
|
||||
(*sig)++;
|
||||
rlen = secp256k1_der_read_len(sig, sigend);
|
||||
if (rlen <= 0 || (*sig) + rlen > sigend) {
|
||||
/* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */
|
||||
return 0;
|
||||
}
|
||||
if (**sig == 0x00 && rlen > 1 && (((*sig)[1]) & 0x80) == 0x00) {
|
||||
/* Excessive 0x00 padding. */
|
||||
return 0;
|
||||
}
|
||||
if (**sig == 0xFF && rlen > 1 && (((*sig)[1]) & 0x80) == 0x80) {
|
||||
/* Excessive 0xFF padding. */
|
||||
return 0;
|
||||
}
|
||||
if ((**sig & 0x80) == 0x80) {
|
||||
/* Negative. */
|
||||
overflow = 1;
|
||||
}
|
||||
while (rlen > 0 && **sig == 0) {
|
||||
/* Skip leading zero bytes */
|
||||
rlen--;
|
||||
(*sig)++;
|
||||
}
|
||||
if (rlen > 32) {
|
||||
overflow = 1;
|
||||
}
|
||||
if (!overflow) {
|
||||
memcpy(ra + 32 - rlen, *sig, rlen);
|
||||
secp256k1_scalar_set_b32(r, ra, &overflow);
|
||||
}
|
||||
if (overflow) {
|
||||
secp256k1_scalar_set_int(r, 0);
|
||||
}
|
||||
(*sig) += rlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, const unsigned char *sig, size_t size) {
|
||||
unsigned char ra[32] = {0}, sa[32] = {0};
|
||||
const unsigned char *rp;
|
||||
const unsigned char *sp;
|
||||
size_t lenr;
|
||||
size_t lens;
|
||||
int overflow;
|
||||
if (sig[0] != 0x30) {
|
||||
const unsigned char *sigend = sig + size;
|
||||
int rlen;
|
||||
if (sig == sigend || *(sig++) != 0x30) {
|
||||
/* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */
|
||||
return 0;
|
||||
}
|
||||
lenr = sig[3];
|
||||
if (5+lenr >= size) {
|
||||
rlen = secp256k1_der_read_len(&sig, sigend);
|
||||
if (rlen < 0 || sig + rlen > sigend) {
|
||||
/* Tuple exceeds bounds */
|
||||
return 0;
|
||||
}
|
||||
lens = sig[lenr+5];
|
||||
if (sig[1] != lenr+lens+4) {
|
||||
if (sig + rlen != sigend) {
|
||||
/* Garbage after tuple. */
|
||||
return 0;
|
||||
}
|
||||
if (lenr+lens+6 > size) {
|
||||
|
||||
if (!secp256k1_der_parse_integer(rr, &sig, sigend)) {
|
||||
return 0;
|
||||
}
|
||||
if (sig[2] != 0x02) {
|
||||
if (!secp256k1_der_parse_integer(rs, &sig, sigend)) {
|
||||
return 0;
|
||||
}
|
||||
if (lenr == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (sig[lenr+4] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
if (lens == 0) {
|
||||
return 0;
|
||||
}
|
||||
sp = sig + 6 + lenr;
|
||||
while (lens > 0 && sp[0] == 0) {
|
||||
lens--;
|
||||
sp++;
|
||||
}
|
||||
if (lens > 32) {
|
||||
return 0;
|
||||
}
|
||||
rp = sig + 4;
|
||||
while (lenr > 0 && rp[0] == 0) {
|
||||
lenr--;
|
||||
rp++;
|
||||
}
|
||||
if (lenr > 32) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(ra + 32 - lenr, rp, lenr);
|
||||
memcpy(sa + 32 - lens, sp, lens);
|
||||
overflow = 0;
|
||||
secp256k1_scalar_set_b32(rr, ra, &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_set_b32(rs, sa, &overflow);
|
||||
if (overflow) {
|
||||
|
||||
if (sig != sigend) {
|
||||
/* Trailing garbage inside tuple. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_cont
|
|||
(void)ctx;
|
||||
ARG_CHECK(output64 != NULL);
|
||||
ARG_CHECK(sig != NULL);
|
||||
ARG_CHECK(recid != NULL);
|
||||
|
||||
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig);
|
||||
secp256k1_scalar_get_b32(&output64[0], &r);
|
||||
|
|
|
@ -56,7 +56,7 @@ void test_ecdsa_recovery_end_to_end(void) {
|
|||
CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0);
|
||||
/* Serialize/destroy/parse signature and verify again. */
|
||||
CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1);
|
||||
sig[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255);
|
||||
sig[secp256k1_rand_bits(6)] += 1 + secp256k1_rand_int(255);
|
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1);
|
||||
CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0);
|
||||
|
@ -163,25 +163,24 @@ void test_ecdsa_recovery_edge_cases(void) {
|
|||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid2) == 1);
|
||||
CHECK(secp256k1_ecdsa_recover(ctx, &pubkey2b, &rsig, msg32) == 1);
|
||||
/* Verifying with (order + r,4) should always fail. */
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0);
|
||||
}
|
||||
/* DER parsing tests. */
|
||||
/* Zero length r/s. */
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0);
|
||||
/* Leading zeros. */
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1);
|
||||
sigbderalt3[4] = 1;
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0);
|
||||
sigbderalt4[7] = 1;
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0);
|
||||
sigbderalt3[4] = 1;
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0);
|
||||
sigbderalt4[7] = 1;
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0);
|
||||
/* Damage signature. */
|
||||
sigbder[7]++;
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1);
|
||||
|
|
|
@ -33,7 +33,7 @@ void test_schnorr_end_to_end(void) {
|
|||
CHECK(secp256k1_schnorr_recover(ctx, &recpubkey, schnorr_signature, message) == 1);
|
||||
CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0);
|
||||
/* Destroy signature and verify again. */
|
||||
schnorr_signature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255);
|
||||
schnorr_signature[secp256k1_rand_bits(6)] += 1 + secp256k1_rand_int(255);
|
||||
CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 0);
|
||||
CHECK(secp256k1_schnorr_recover(ctx, &recpubkey, schnorr_signature, message) != 1 ||
|
||||
memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0);
|
||||
|
@ -73,8 +73,8 @@ void test_schnorr_sign_verify(void) {
|
|||
CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[k], &pubkey[k], &test_schnorr_hash, msg32));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
int pos = secp256k1_rand32() % 64;
|
||||
int mod = 1 + (secp256k1_rand32() % 255);
|
||||
int pos = secp256k1_rand_bits(6);
|
||||
int mod = 1 + secp256k1_rand_int(255);
|
||||
sig64[k][pos] ^= mod;
|
||||
CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[k], &pubkey[k], &test_schnorr_hash, msg32) == 0);
|
||||
sig64[k][pos] ^= mod;
|
||||
|
@ -97,9 +97,9 @@ void test_schnorr_threshold(void) {
|
|||
int damage;
|
||||
int ret = 0;
|
||||
|
||||
damage = (secp256k1_rand32() % 2) ? (1 + (secp256k1_rand32() % 4)) : 0;
|
||||
damage = secp256k1_rand_bits(1) ? (1 + secp256k1_rand_int(4)) : 0;
|
||||
secp256k1_rand256_test(msg);
|
||||
n = 2 + (secp256k1_rand32() % 4);
|
||||
n = 2 + secp256k1_rand_int(4);
|
||||
for (i = 0; i < n; i++) {
|
||||
do {
|
||||
secp256k1_rand256_test(sec[i]);
|
||||
|
@ -109,9 +109,9 @@ void test_schnorr_threshold(void) {
|
|||
pubs[i] = &pub[i];
|
||||
}
|
||||
if (damage == 1) {
|
||||
nonce[secp256k1_rand32() % n][secp256k1_rand32() % 32] ^= 1 + (secp256k1_rand32() % 255);
|
||||
nonce[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
|
||||
} else if (damage == 2) {
|
||||
sec[secp256k1_rand32() % n][secp256k1_rand32() % 32] ^= 1 + (secp256k1_rand32() % 255);
|
||||
sec[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_pubkey allpubnonce;
|
||||
|
@ -128,14 +128,14 @@ void test_schnorr_threshold(void) {
|
|||
sigs[i] = sig[i];
|
||||
}
|
||||
if (damage == 3) {
|
||||
sig[secp256k1_rand32() % n][secp256k1_rand32() % 64] ^= 1 + (secp256k1_rand32() % 255);
|
||||
sig[secp256k1_rand_int(n)][secp256k1_rand_bits(6)] ^= 1 + secp256k1_rand_int(255);
|
||||
}
|
||||
ret |= (secp256k1_ec_pubkey_combine(ctx, &allpub, pubs, n) != 1) * 2;
|
||||
if ((ret & 1) == 0) {
|
||||
ret |= (secp256k1_schnorr_partial_combine(ctx, allsig, sigs, n) != 1) * 4;
|
||||
}
|
||||
if (damage == 4) {
|
||||
allsig[secp256k1_rand32() % 32] ^= 1 + (secp256k1_rand32() % 255);
|
||||
allsig[secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
|
||||
}
|
||||
if ((ret & 7) == 0) {
|
||||
ret |= (secp256k1_schnorr_verify(ctx, allsig, msg, &allpub) != 1) * 8;
|
||||
|
|
|
@ -210,6 +210,27 @@ int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_
|
|||
}
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64) {
|
||||
secp256k1_scalar r, s;
|
||||
int ret = 1;
|
||||
int overflow = 0;
|
||||
|
||||
(void)ctx;
|
||||
ARG_CHECK(sig != NULL);
|
||||
ARG_CHECK(input64 != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&r, &input64[0], &overflow);
|
||||
ret &= !overflow;
|
||||
secp256k1_scalar_set_b32(&s, &input64[32], &overflow);
|
||||
ret &= !overflow;
|
||||
if (ret) {
|
||||
secp256k1_ecdsa_signature_save(sig, &r, &s);
|
||||
} else {
|
||||
memset(sig, 0, sizeof(*sig));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) {
|
||||
secp256k1_scalar r, s;
|
||||
|
||||
|
@ -222,6 +243,38 @@ int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsign
|
|||
return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s);
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) {
|
||||
secp256k1_scalar r, s;
|
||||
|
||||
(void)ctx;
|
||||
ARG_CHECK(output64 != NULL);
|
||||
ARG_CHECK(sig != NULL);
|
||||
|
||||
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
|
||||
secp256k1_scalar_get_b32(&output64[0], &r);
|
||||
secp256k1_scalar_get_b32(&output64[32], &s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) {
|
||||
secp256k1_scalar r, s;
|
||||
int ret = 0;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(sigin != NULL);
|
||||
|
||||
secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin);
|
||||
ret = secp256k1_scalar_is_high(&s);
|
||||
if (sigout != NULL) {
|
||||
if (ret) {
|
||||
secp256k1_scalar_negate(&s, &s);
|
||||
}
|
||||
secp256k1_ecdsa_signature_save(sigout, &r, &s);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) {
|
||||
secp256k1_ge q;
|
||||
secp256k1_scalar r, s;
|
||||
|
@ -234,7 +287,8 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s
|
|||
|
||||
secp256k1_scalar_set_b32(&m, msg32, NULL);
|
||||
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
|
||||
return (secp256k1_pubkey_load(ctx, &q, pubkey) &&
|
||||
return (!secp256k1_scalar_is_high(&s) &&
|
||||
secp256k1_pubkey_load(ctx, &q, pubkey) &&
|
||||
secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m));
|
||||
}
|
||||
|
||||
|
|
|
@ -16,13 +16,23 @@
|
|||
/** Seed the pseudorandom number generator for testing. */
|
||||
SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16);
|
||||
|
||||
/** Generate a pseudorandom 32-bit number. */
|
||||
/** Generate a pseudorandom number in the range [0..2**32-1]. */
|
||||
static uint32_t secp256k1_rand32(void);
|
||||
|
||||
/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or
|
||||
* more. */
|
||||
static uint32_t secp256k1_rand_bits(int bits);
|
||||
|
||||
/** Generate a pseudorandom number in the range [0..range-1]. */
|
||||
static uint32_t secp256k1_rand_int(uint32_t range);
|
||||
|
||||
/** Generate a pseudorandom 32-byte array. */
|
||||
static void secp256k1_rand256(unsigned char *b32);
|
||||
|
||||
/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */
|
||||
static void secp256k1_rand256_test(unsigned char *b32);
|
||||
|
||||
/** Generate pseudorandom bytes with long sequences of zero and one bits. */
|
||||
static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Copyright (c) 2013-2015 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
@ -16,6 +16,8 @@
|
|||
static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng;
|
||||
static uint32_t secp256k1_test_rng_precomputed[8];
|
||||
static int secp256k1_test_rng_precomputed_used = 8;
|
||||
static uint64_t secp256k1_test_rng_integer;
|
||||
static int secp256k1_test_rng_integer_bits_left = 0;
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16) {
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16);
|
||||
|
@ -29,32 +31,80 @@ SECP256K1_INLINE static uint32_t secp256k1_rand32(void) {
|
|||
return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++];
|
||||
}
|
||||
|
||||
static uint32_t secp256k1_rand_bits(int bits) {
|
||||
uint32_t ret;
|
||||
if (secp256k1_test_rng_integer_bits_left < bits) {
|
||||
secp256k1_test_rng_integer |= (((uint64_t)secp256k1_rand32()) << secp256k1_test_rng_integer_bits_left);
|
||||
secp256k1_test_rng_integer_bits_left += 32;
|
||||
}
|
||||
ret = secp256k1_test_rng_integer;
|
||||
secp256k1_test_rng_integer >>= bits;
|
||||
secp256k1_test_rng_integer_bits_left -= bits;
|
||||
ret &= ((~((uint32_t)0)) >> (32 - bits));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t secp256k1_rand_int(uint32_t range) {
|
||||
/* We want a uniform integer between 0 and range-1, inclusive.
|
||||
* B is the smallest number such that range <= 2**B.
|
||||
* two mechanisms implemented here:
|
||||
* - generate B bits numbers until one below range is found, and return it
|
||||
* - find the largest multiple M of range that is <= 2**(B+A), generate B+A
|
||||
* bits numbers until one below M is found, and return it modulo range
|
||||
* The second mechanism consumes A more bits of entropy in every iteration,
|
||||
* but may need fewer iterations due to M being closer to 2**(B+A) then
|
||||
* range is to 2**B. The array below (indexed by B) contains a 0 when the
|
||||
* first mechanism is to be used, and the number A otherwise.
|
||||
*/
|
||||
static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0};
|
||||
uint32_t trange, mult;
|
||||
int bits = 0;
|
||||
if (range <= 1) {
|
||||
return 0;
|
||||
}
|
||||
trange = range - 1;
|
||||
while (trange > 0) {
|
||||
trange >>= 1;
|
||||
bits++;
|
||||
}
|
||||
if (addbits[bits]) {
|
||||
bits = bits + addbits[bits];
|
||||
mult = ((~((uint32_t)0)) >> (32 - bits)) / range;
|
||||
trange = range * mult;
|
||||
} else {
|
||||
trange = range;
|
||||
mult = 1;
|
||||
}
|
||||
while(1) {
|
||||
uint32_t x = secp256k1_rand_bits(bits);
|
||||
if (x < trange) {
|
||||
return (mult == 1) ? x : (x % range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_rand256(unsigned char *b32) {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32);
|
||||
}
|
||||
|
||||
static void secp256k1_rand256_test(unsigned char *b32) {
|
||||
int bits=0;
|
||||
uint64_t ent = 0;
|
||||
int entleft = 0;
|
||||
memset(b32, 0, 32);
|
||||
while (bits < 256) {
|
||||
static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len) {
|
||||
size_t bits = 0;
|
||||
memset(bytes, 0, len);
|
||||
while (bits < len * 8) {
|
||||
int now;
|
||||
uint32_t val;
|
||||
if (entleft < 12) {
|
||||
ent |= ((uint64_t)secp256k1_rand32()) << entleft;
|
||||
entleft += 32;
|
||||
}
|
||||
now = 1 + ((ent % 64)*((ent >> 6) % 32)+16)/31;
|
||||
val = 1 & (ent >> 11);
|
||||
ent >>= 12;
|
||||
entleft -= 12;
|
||||
while (now > 0 && bits < 256) {
|
||||
b32[bits / 8] |= val << (bits % 8);
|
||||
now = 1 + (secp256k1_rand_bits(6) * secp256k1_rand_bits(5) + 16) / 31;
|
||||
val = secp256k1_rand_bits(1);
|
||||
while (now > 0 && bits < len * 8) {
|
||||
bytes[bits / 8] |= val << (bits % 8);
|
||||
now--;
|
||||
bits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_rand256_test(unsigned char *b32) {
|
||||
secp256k1_rand_bytes_test(b32, 32);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
490
src/tests.c
490
src/tests.c
|
@ -24,6 +24,8 @@
|
|||
#include "openssl/obj_mac.h"
|
||||
#endif
|
||||
|
||||
#include "contrib/lax_der_parsing.h"
|
||||
|
||||
#if !defined(VG_CHECK)
|
||||
# if defined(VALGRIND)
|
||||
# include <valgrind/memcheck.h>
|
||||
|
@ -50,7 +52,7 @@ void random_field_element_test(secp256k1_fe *fe) {
|
|||
|
||||
void random_field_element_magnitude(secp256k1_fe *fe) {
|
||||
secp256k1_fe zero;
|
||||
int n = secp256k1_rand32() % 9;
|
||||
int n = secp256k1_rand_int(9);
|
||||
secp256k1_fe_normalize(fe);
|
||||
if (n == 0) {
|
||||
return;
|
||||
|
@ -66,7 +68,7 @@ void random_group_element_test(secp256k1_ge *ge) {
|
|||
secp256k1_fe fe;
|
||||
do {
|
||||
random_field_element_test(&fe);
|
||||
if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_rand32() & 1)) {
|
||||
if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_rand_bits(1))) {
|
||||
secp256k1_fe_normalize(&ge->y);
|
||||
break;
|
||||
}
|
||||
|
@ -189,7 +191,7 @@ void run_sha256_tests(void) {
|
|||
secp256k1_sha256_finalize(&hasher, out);
|
||||
CHECK(memcmp(out, outputs[i], 32) == 0);
|
||||
if (strlen(inputs[i]) > 0) {
|
||||
int split = secp256k1_rand32() % strlen(inputs[i]);
|
||||
int split = secp256k1_rand_int(strlen(inputs[i]));
|
||||
secp256k1_sha256_initialize(&hasher);
|
||||
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
|
||||
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
|
||||
|
@ -233,7 +235,7 @@ void run_hmac_sha256_tests(void) {
|
|||
secp256k1_hmac_sha256_finalize(&hasher, out);
|
||||
CHECK(memcmp(out, outputs[i], 32) == 0);
|
||||
if (strlen(inputs[i]) > 0) {
|
||||
int split = secp256k1_rand32() % strlen(inputs[i]);
|
||||
int split = secp256k1_rand_int(strlen(inputs[i]));
|
||||
secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
|
||||
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
|
||||
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
|
||||
|
@ -284,11 +286,83 @@ void run_rfc6979_hmac_sha256_tests(void) {
|
|||
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
|
||||
}
|
||||
|
||||
/***** RANDOM TESTS *****/
|
||||
|
||||
void test_rand_bits(int rand32, int bits) {
|
||||
/* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to
|
||||
* get a false negative chance below once in a billion */
|
||||
static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316};
|
||||
/* We try multiplying the results with various odd numbers, which shouldn't
|
||||
* influence the uniform distribution modulo a power of 2. */
|
||||
static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011};
|
||||
/* We only select up to 6 bits from the output to analyse */
|
||||
unsigned int usebits = bits > 6 ? 6 : bits;
|
||||
unsigned int maxshift = bits - usebits;
|
||||
/* For each of the maxshift+1 usebits-bit sequences inside a bits-bit
|
||||
number, track all observed outcomes, one per bit in a uint64_t. */
|
||||
uint64_t x[6][27] = {{0}};
|
||||
unsigned int i, shift, m;
|
||||
/* Multiply the output of all rand calls with the odd number m, which
|
||||
should not change the uniformity of its distribution. */
|
||||
for (i = 0; i < rounds[usebits]; i++) {
|
||||
uint32_t r = (rand32 ? secp256k1_rand32() : secp256k1_rand_bits(bits));
|
||||
CHECK((((uint64_t)r) >> bits) == 0);
|
||||
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
|
||||
uint32_t rm = r * mults[m];
|
||||
for (shift = 0; shift <= maxshift; shift++) {
|
||||
x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
|
||||
for (shift = 0; shift <= maxshift; shift++) {
|
||||
/* Test that the lower usebits bits of x[shift] are 1 */
|
||||
CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Subrange must be a whole divisor of range, and at most 64 */
|
||||
void test_rand_int(uint32_t range, uint32_t subrange) {
|
||||
/* (1-1/subrange)^rounds < 1/10^9 */
|
||||
int rounds = (subrange * 2073) / 100;
|
||||
int i;
|
||||
uint64_t x = 0;
|
||||
CHECK((range % subrange) == 0);
|
||||
for (i = 0; i < rounds; i++) {
|
||||
uint32_t r = secp256k1_rand_int(range);
|
||||
CHECK(r < range);
|
||||
r = r % subrange;
|
||||
x |= (((uint64_t)1) << r);
|
||||
}
|
||||
/* Test that the lower subrange bits of x are 1. */
|
||||
CHECK(((~x) << (64 - subrange)) == 0);
|
||||
}
|
||||
|
||||
void run_rand_bits(void) {
|
||||
size_t b;
|
||||
test_rand_bits(1, 32);
|
||||
for (b = 1; b <= 32; b++) {
|
||||
test_rand_bits(0, b);
|
||||
}
|
||||
}
|
||||
|
||||
void run_rand_int(void) {
|
||||
static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432};
|
||||
static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64};
|
||||
unsigned int m, s;
|
||||
for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) {
|
||||
for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) {
|
||||
test_rand_int(ms[m] * ss[s], ss[s]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***** NUM TESTS *****/
|
||||
|
||||
#ifndef USE_NUM_NONE
|
||||
void random_num_negate(secp256k1_num *num) {
|
||||
if (secp256k1_rand32() & 1) {
|
||||
if (secp256k1_rand_bits(1)) {
|
||||
secp256k1_num_negate(num);
|
||||
}
|
||||
}
|
||||
|
@ -329,13 +403,12 @@ void test_num_add_sub(void) {
|
|||
secp256k1_num n1;
|
||||
secp256k1_num n2;
|
||||
secp256k1_num n1p2, n2p1, n1m2, n2m1;
|
||||
int r = secp256k1_rand32();
|
||||
random_num_order_test(&n1); /* n1 = R1 */
|
||||
if (r & 1) {
|
||||
if (secp256k1_rand_bits(1)) {
|
||||
random_num_negate(&n1);
|
||||
}
|
||||
random_num_order_test(&n2); /* n2 = R2 */
|
||||
if (r & 2) {
|
||||
if (secp256k1_rand_bits(1)) {
|
||||
random_num_negate(&n2);
|
||||
}
|
||||
secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */
|
||||
|
@ -420,7 +493,7 @@ void scalar_test(void) {
|
|||
while (i < 256) {
|
||||
secp256k1_scalar t;
|
||||
int j;
|
||||
int now = (secp256k1_rand32() % 15) + 1;
|
||||
int now = secp256k1_rand_int(15) + 1;
|
||||
if (now + i > 256) {
|
||||
now = 256 - i;
|
||||
}
|
||||
|
@ -497,7 +570,7 @@ void scalar_test(void) {
|
|||
secp256k1_num rnum;
|
||||
secp256k1_num rnum2;
|
||||
unsigned char cone[1] = {0x01};
|
||||
unsigned int shift = 256 + (secp256k1_rand32() % 257);
|
||||
unsigned int shift = 256 + secp256k1_rand_int(257);
|
||||
secp256k1_scalar_mul_shift_var(&r, &s1, &s2, shift);
|
||||
secp256k1_num_mul(&rnum, &s1num, &s2num);
|
||||
secp256k1_num_shift(&rnum, shift - 1);
|
||||
|
@ -515,7 +588,7 @@ void scalar_test(void) {
|
|||
random_scalar_order_test(&r);
|
||||
for (i = 0; i < 100; ++i) {
|
||||
int low;
|
||||
int shift = 1 + (secp256k1_rand32() % 15);
|
||||
int shift = 1 + secp256k1_rand_int(15);
|
||||
int expected = r.d[0] % (1 << shift);
|
||||
low = secp256k1_scalar_shr_int(&r, shift);
|
||||
CHECK(expected == low);
|
||||
|
@ -559,7 +632,7 @@ void scalar_test(void) {
|
|||
secp256k1_scalar b;
|
||||
int i;
|
||||
/* Test add_bit. */
|
||||
int bit = secp256k1_rand32() % 256;
|
||||
int bit = secp256k1_rand_bits(8);
|
||||
secp256k1_scalar_set_int(&b, 1);
|
||||
CHECK(secp256k1_scalar_is_one(&b));
|
||||
for (i = 0; i < bit; i++) {
|
||||
|
@ -874,7 +947,7 @@ void run_field_inv_all_var(void) {
|
|||
secp256k1_fe_inv_all_var(0, xi, x);
|
||||
for (i = 0; i < count; i++) {
|
||||
size_t j;
|
||||
size_t len = (secp256k1_rand32() & 15) + 1;
|
||||
size_t len = secp256k1_rand_int(15) + 1;
|
||||
for (j = 0; j < len; j++) {
|
||||
random_fe_non_zero(&x[j]);
|
||||
}
|
||||
|
@ -1163,7 +1236,7 @@ void test_ge(void) {
|
|||
gej_shuffled[i] = gej[i];
|
||||
}
|
||||
for (i = 0; i < 4 * runs + 1; i++) {
|
||||
int swap = i + secp256k1_rand32() % (4 * runs + 1 - i);
|
||||
int swap = i + secp256k1_rand_int(4 * runs + 1 - i);
|
||||
if (swap != i) {
|
||||
secp256k1_gej t = gej_shuffled[i];
|
||||
gej_shuffled[i] = gej_shuffled[swap];
|
||||
|
@ -2174,7 +2247,7 @@ void test_ecdsa_sign_verify(void) {
|
|||
random_scalar_order_test(&key);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key);
|
||||
secp256k1_ge_set_gej(&pub, &pubj);
|
||||
getrec = secp256k1_rand32()&1;
|
||||
getrec = secp256k1_rand_bits(1);
|
||||
random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL);
|
||||
if (getrec) {
|
||||
CHECK(recid >= 0 && recid < 4);
|
||||
|
@ -2249,7 +2322,8 @@ void test_ecdsa_end_to_end(void) {
|
|||
unsigned char privkey[32];
|
||||
unsigned char message[32];
|
||||
unsigned char privkey2[32];
|
||||
secp256k1_ecdsa_signature signature[5];
|
||||
secp256k1_ecdsa_signature signature[6];
|
||||
secp256k1_scalar r, s;
|
||||
unsigned char sig[74];
|
||||
size_t siglen = 74;
|
||||
unsigned char pubkeyc[65];
|
||||
|
@ -2272,17 +2346,17 @@ void test_ecdsa_end_to_end(void) {
|
|||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1);
|
||||
|
||||
/* Verify exporting and importing public key. */
|
||||
CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand32() % 2) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1)) == 1);
|
||||
memset(&pubkey, 0, sizeof(pubkey));
|
||||
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_rand32() % 2) == 1) ? SECP256K1_EC_COMPRESSED : 0);
|
||||
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(memcmp(privkey, privkey2, 32) == 0);
|
||||
|
||||
/* Optionally tweak the keys using addition. */
|
||||
if (secp256k1_rand32() % 3 == 0) {
|
||||
if (secp256k1_rand_int(3) == 0) {
|
||||
int ret1;
|
||||
int ret2;
|
||||
unsigned char rnd[32];
|
||||
|
@ -2299,7 +2373,7 @@ void test_ecdsa_end_to_end(void) {
|
|||
}
|
||||
|
||||
/* Optionally tweak the keys using multiplication. */
|
||||
if (secp256k1_rand32() % 3 == 0) {
|
||||
if (secp256k1_rand_int(3) == 0) {
|
||||
int ret1;
|
||||
int ret2;
|
||||
unsigned char rnd[32];
|
||||
|
@ -2336,6 +2410,21 @@ void test_ecdsa_end_to_end(void) {
|
|||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[2], message, &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[3], message, &pubkey) == 1);
|
||||
/* Test lower-S form, malleate, verify and fail, test again, malleate again */
|
||||
CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[0]));
|
||||
secp256k1_ecdsa_signature_load(ctx, &r, &s, &signature[0]);
|
||||
secp256k1_scalar_negate(&s, &s);
|
||||
secp256k1_ecdsa_signature_save(&signature[5], &r, &s);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5]));
|
||||
CHECK(secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5]));
|
||||
CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5]));
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1);
|
||||
secp256k1_scalar_negate(&s, &s);
|
||||
secp256k1_ecdsa_signature_save(&signature[5], &r, &s);
|
||||
CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5]));
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1);
|
||||
CHECK(memcmp(&signature[5], &signature[0], 64) == 0);
|
||||
|
||||
/* Serialize/parse DER and verify again */
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1);
|
||||
|
@ -2345,7 +2434,7 @@ void test_ecdsa_end_to_end(void) {
|
|||
/* Serialize/destroy/parse DER and verify again. */
|
||||
siglen = 74;
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1);
|
||||
sig[secp256k1_rand32() % siglen] += 1 + (secp256k1_rand32() % 255);
|
||||
sig[secp256k1_rand_int(siglen)] += 1 + secp256k1_rand_int(255);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 ||
|
||||
secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 0);
|
||||
}
|
||||
|
@ -2355,23 +2444,18 @@ void test_random_pubkeys(void) {
|
|||
secp256k1_ge elem2;
|
||||
unsigned char in[65];
|
||||
/* Generate some randomly sized pubkeys. */
|
||||
uint32_t r = secp256k1_rand32();
|
||||
size_t len = (r & 3) == 0 ? 65 : 33;
|
||||
r>>=2;
|
||||
if ((r & 3) == 0) {
|
||||
len = (r & 252) >> 3;
|
||||
size_t len = secp256k1_rand_bits(2) == 0 ? 65 : 33;
|
||||
if (secp256k1_rand_bits(2) == 0) {
|
||||
len = secp256k1_rand_bits(6);
|
||||
}
|
||||
r>>=8;
|
||||
if (len == 65) {
|
||||
in[0] = (r & 2) ? 4 : ((r & 1)? 6 : 7);
|
||||
in[0] = secp256k1_rand_bits(1) ? 4 : (secp256k1_rand_bits(1) ? 6 : 7);
|
||||
} else {
|
||||
in[0] = (r & 1) ? 2 : 3;
|
||||
in[0] = secp256k1_rand_bits(1) ? 2 : 3;
|
||||
}
|
||||
r>>=2;
|
||||
if ((r & 7) == 0) {
|
||||
in[0] = (r & 2040) >> 3;
|
||||
if (secp256k1_rand_bits(3) == 0) {
|
||||
in[0] = secp256k1_rand_bits(8);
|
||||
}
|
||||
r>>=11;
|
||||
if (len > 1) {
|
||||
secp256k1_rand256(&in[1]);
|
||||
}
|
||||
|
@ -2398,7 +2482,7 @@ void test_random_pubkeys(void) {
|
|||
CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size));
|
||||
ge_equals_ge(&elem,&elem2);
|
||||
/* Check that the X9.62 hybrid type is checked. */
|
||||
in[0] = (r & 1) ? 6 : 7;
|
||||
in[0] = secp256k1_rand_bits(1) ? 6 : 7;
|
||||
res = secp256k1_eckey_pubkey_parse(&elem2, in, size);
|
||||
if (firstb == 2 || firstb == 3) {
|
||||
if (in[0] == firstb + 4) {
|
||||
|
@ -2429,6 +2513,332 @@ void run_ecdsa_end_to_end(void) {
|
|||
}
|
||||
}
|
||||
|
||||
int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_der, int certainly_not_der) {
|
||||
static const unsigned char zeroes[32] = {0};
|
||||
static const unsigned char max_scalar[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, 0x40
|
||||
};
|
||||
|
||||
int ret = 0;
|
||||
|
||||
secp256k1_ecdsa_signature sig_der;
|
||||
unsigned char roundtrip_der[2048];
|
||||
unsigned char compact_der[64];
|
||||
size_t len_der = 2048;
|
||||
int parsed_der = 0, valid_der = 0, roundtrips_der = 0;
|
||||
|
||||
secp256k1_ecdsa_signature sig_der_lax;
|
||||
unsigned char roundtrip_der_lax[2048];
|
||||
unsigned char compact_der_lax[64];
|
||||
size_t len_der_lax = 2048;
|
||||
int parsed_der_lax = 0, valid_der_lax = 0, roundtrips_der_lax = 0;
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
ECDSA_SIG *sig_openssl;
|
||||
const unsigned char *sigptr;
|
||||
unsigned char roundtrip_openssl[2048];
|
||||
int len_openssl = 2048;
|
||||
int parsed_openssl, valid_openssl = 0, roundtrips_openssl = 0;
|
||||
#endif
|
||||
|
||||
parsed_der = secp256k1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen);
|
||||
if (parsed_der) {
|
||||
ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0;
|
||||
valid_der = (memcmp(compact_der, zeroes, 32) != 0) && (memcmp(compact_der + 32, zeroes, 32) != 0);
|
||||
}
|
||||
if (valid_der) {
|
||||
ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1;
|
||||
roundtrips_der = (len_der == siglen) && memcmp(roundtrip_der, sig, siglen) == 0;
|
||||
}
|
||||
|
||||
parsed_der_lax = secp256k1_ecdsa_signature_parse_der_lax(ctx, &sig_der_lax, sig, siglen);
|
||||
if (parsed_der_lax) {
|
||||
ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der_lax, &sig_der_lax)) << 10;
|
||||
valid_der_lax = (memcmp(compact_der_lax, zeroes, 32) != 0) && (memcmp(compact_der_lax + 32, zeroes, 32) != 0);
|
||||
}
|
||||
if (valid_der_lax) {
|
||||
ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11;
|
||||
roundtrips_der_lax = (len_der_lax == siglen) && memcmp(roundtrip_der_lax, sig, siglen) == 0;
|
||||
}
|
||||
|
||||
if (certainly_der) {
|
||||
ret |= (!parsed_der) << 2;
|
||||
}
|
||||
if (certainly_not_der) {
|
||||
ret |= (parsed_der) << 17;
|
||||
}
|
||||
if (valid_der) {
|
||||
ret |= (!roundtrips_der) << 3;
|
||||
}
|
||||
|
||||
if (valid_der) {
|
||||
ret |= (!roundtrips_der_lax) << 12;
|
||||
ret |= (len_der != len_der_lax) << 13;
|
||||
ret |= (memcmp(roundtrip_der_lax, roundtrip_der, len_der) != 0) << 14;
|
||||
}
|
||||
ret |= (roundtrips_der != roundtrips_der_lax) << 15;
|
||||
if (parsed_der) {
|
||||
ret |= (!parsed_der_lax) << 16;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPENSSL_TESTS
|
||||
sig_openssl = ECDSA_SIG_new();
|
||||
sigptr = sig;
|
||||
parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL);
|
||||
if (parsed_openssl) {
|
||||
valid_openssl = !BN_is_negative(sig_openssl->r) && !BN_is_negative(sig_openssl->s) && BN_num_bits(sig_openssl->r) > 0 && BN_num_bits(sig_openssl->r) <= 256 && BN_num_bits(sig_openssl->s) > 0 && BN_num_bits(sig_openssl->s) <= 256;
|
||||
if (valid_openssl) {
|
||||
unsigned char tmp[32] = {0};
|
||||
BN_bn2bin(sig_openssl->r, tmp + 32 - BN_num_bytes(sig_openssl->r));
|
||||
valid_openssl = memcmp(tmp, max_scalar, 32) < 0;
|
||||
}
|
||||
if (valid_openssl) {
|
||||
unsigned char tmp[32] = {0};
|
||||
BN_bn2bin(sig_openssl->s, tmp + 32 - BN_num_bytes(sig_openssl->s));
|
||||
valid_openssl = memcmp(tmp, max_scalar, 32) < 0;
|
||||
}
|
||||
}
|
||||
len_openssl = i2d_ECDSA_SIG(sig_openssl, NULL);
|
||||
if (len_openssl <= 2048) {
|
||||
unsigned char *ptr = roundtrip_openssl;
|
||||
CHECK(i2d_ECDSA_SIG(sig_openssl, &ptr) == len_openssl);
|
||||
roundtrips_openssl = valid_openssl && ((size_t)len_openssl == siglen) && (memcmp(roundtrip_openssl, sig, siglen) == 0);
|
||||
} else {
|
||||
len_openssl = 0;
|
||||
}
|
||||
ECDSA_SIG_free(sig_openssl);
|
||||
|
||||
ret |= (parsed_der && !parsed_openssl) << 4;
|
||||
ret |= (valid_der && !valid_openssl) << 5;
|
||||
ret |= (roundtrips_openssl && !parsed_der) << 6;
|
||||
ret |= (roundtrips_der != roundtrips_openssl) << 7;
|
||||
if (roundtrips_openssl) {
|
||||
ret |= (len_der != (size_t)len_openssl) << 8;
|
||||
ret |= (memcmp(roundtrip_der, roundtrip_openssl, len_der) != 0) << 9;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) {
|
||||
size_t i;
|
||||
for (i = 0; i < ptrlen; i++) {
|
||||
int shift = ptrlen - 1 - i;
|
||||
if (shift >= 4) {
|
||||
ptr[i] = 0;
|
||||
} else {
|
||||
ptr[i] = (val >> shift) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void damage_array(unsigned char *sig, size_t *len) {
|
||||
int pos;
|
||||
int action = secp256k1_rand_bits(3);
|
||||
if (action < 1) {
|
||||
/* Delete a byte. */
|
||||
pos = secp256k1_rand_int(*len);
|
||||
memmove(sig + pos, sig + pos + 1, *len - pos - 1);
|
||||
(*len)--;
|
||||
return;
|
||||
} else if (action < 2) {
|
||||
/* Insert a byte. */
|
||||
pos = secp256k1_rand_int(1 + *len);
|
||||
memmove(sig + pos + 1, sig + pos, *len - pos);
|
||||
sig[pos] = secp256k1_rand_bits(8);
|
||||
(*len)++;
|
||||
return;
|
||||
} else if (action < 4) {
|
||||
/* Modify a byte. */
|
||||
sig[secp256k1_rand_int(*len)] += 1 + secp256k1_rand_int(255);
|
||||
return;
|
||||
} else { /* action < 8 */
|
||||
/* Modify a bit. */
|
||||
sig[secp256k1_rand_int(*len)] ^= 1 << secp256k1_rand_bits(3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly_der, int* certainly_not_der) {
|
||||
int der;
|
||||
int nlow[2], nlen[2], nlenlen[2], nhbit[2], nhbyte[2], nzlen[2];
|
||||
size_t tlen, elen, glen;
|
||||
int indet;
|
||||
int n;
|
||||
|
||||
*len = 0;
|
||||
der = secp256k1_rand_bits(2) == 0;
|
||||
*certainly_der = der;
|
||||
*certainly_not_der = 0;
|
||||
indet = der ? 0 : secp256k1_rand_int(10) == 0;
|
||||
|
||||
for (n = 0; n < 2; n++) {
|
||||
/* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */
|
||||
nlow[n] = der ? 1 : (secp256k1_rand_bits(3) != 0);
|
||||
/* The length of the number in bytes (the first byte of which will always be nonzero) */
|
||||
nlen[n] = nlow[n] ? secp256k1_rand_int(33) : 32 + secp256k1_rand_int(200) * secp256k1_rand_int(8) / 8;
|
||||
CHECK(nlen[n] <= 232);
|
||||
/* The top bit of the number. */
|
||||
nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_rand_bits(1));
|
||||
/* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */
|
||||
nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_rand_bits(7) : 1 + secp256k1_rand_int(127));
|
||||
/* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */
|
||||
nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_rand_int(3) : secp256k1_rand_int(300 - nlen[n]) * secp256k1_rand_int(8) / 8);
|
||||
if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) {
|
||||
*certainly_not_der = 1;
|
||||
}
|
||||
CHECK(nlen[n] + nzlen[n] <= 300);
|
||||
/* The length of the length descriptor for the number. 0 means short encoding, anything else is long encoding. */
|
||||
nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2);
|
||||
if (!der) {
|
||||
/* nlenlen[n] max 127 bytes */
|
||||
int add = secp256k1_rand_int(127 - nlenlen[n]) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256;
|
||||
nlenlen[n] += add;
|
||||
if (add != 0) {
|
||||
*certainly_not_der = 1;
|
||||
}
|
||||
}
|
||||
CHECK(nlen[n] + nzlen[n] + nlenlen[n] <= 427);
|
||||
}
|
||||
|
||||
/* The total length of the data to go, so far */
|
||||
tlen = 2 + nlenlen[0] + nlen[0] + nzlen[0] + 2 + nlenlen[1] + nlen[1] + nzlen[1];
|
||||
CHECK(tlen <= 856);
|
||||
|
||||
/* The length of the garbage inside the tuple. */
|
||||
elen = (der || indet) ? 0 : secp256k1_rand_int(980 - tlen) * secp256k1_rand_int(8) / 8;
|
||||
if (elen != 0) {
|
||||
*certainly_not_der = 1;
|
||||
}
|
||||
tlen += elen;
|
||||
CHECK(tlen <= 980);
|
||||
|
||||
/* The length of the garbage after the end of the tuple. */
|
||||
glen = der ? 0 : secp256k1_rand_int(990 - tlen) * secp256k1_rand_int(8) / 8;
|
||||
if (glen != 0) {
|
||||
*certainly_not_der = 1;
|
||||
}
|
||||
CHECK(tlen + glen <= 990);
|
||||
|
||||
/* Write the tuple header. */
|
||||
sig[(*len)++] = 0x30;
|
||||
if (indet) {
|
||||
/* Indeterminate length */
|
||||
sig[(*len)++] = 0x80;
|
||||
*certainly_not_der = 1;
|
||||
} else {
|
||||
int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2);
|
||||
if (!der) {
|
||||
int add = secp256k1_rand_int(127 - tlenlen) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256;
|
||||
tlenlen += add;
|
||||
if (add != 0) {
|
||||
*certainly_not_der = 1;
|
||||
}
|
||||
}
|
||||
if (tlenlen == 0) {
|
||||
/* Short length notation */
|
||||
sig[(*len)++] = tlen;
|
||||
} else {
|
||||
/* Long length notation */
|
||||
sig[(*len)++] = 128 + tlenlen;
|
||||
assign_big_endian(sig + *len, tlenlen, tlen);
|
||||
*len += tlenlen;
|
||||
}
|
||||
tlen += tlenlen;
|
||||
}
|
||||
tlen += 2;
|
||||
CHECK(tlen + glen <= 1119);
|
||||
|
||||
for (n = 0; n < 2; n++) {
|
||||
/* Write the integer header. */
|
||||
sig[(*len)++] = 0x02;
|
||||
if (nlenlen[n] == 0) {
|
||||
/* Short length notation */
|
||||
sig[(*len)++] = nlen[n] + nzlen[n];
|
||||
} else {
|
||||
/* Long length notation. */
|
||||
sig[(*len)++] = 128 + nlenlen[n];
|
||||
assign_big_endian(sig + *len, nlenlen[n], nlen[n] + nzlen[n]);
|
||||
*len += nlenlen[n];
|
||||
}
|
||||
/* Write zero padding */
|
||||
while (nzlen[n] > 0) {
|
||||
sig[(*len)++] = 0x00;
|
||||
nzlen[n]--;
|
||||
}
|
||||
if (nlen[n] == 32 && !nlow[n]) {
|
||||
/* Special extra 16 0xFF bytes in "high" 32-byte numbers */
|
||||
int i;
|
||||
for (i = 0; i < 16; i++) {
|
||||
sig[(*len)++] = 0xFF;
|
||||
}
|
||||
nlen[n] -= 16;
|
||||
}
|
||||
/* Write first byte of number */
|
||||
if (nlen[n] > 0) {
|
||||
sig[(*len)++] = nhbyte[n];
|
||||
nlen[n]--;
|
||||
}
|
||||
/* Generate remaining random bytes of number */
|
||||
secp256k1_rand_bytes_test(sig + *len, nlen[n]);
|
||||
*len += nlen[n];
|
||||
nlen[n] = 0;
|
||||
}
|
||||
|
||||
/* Generate random garbage inside tuple. */
|
||||
secp256k1_rand_bytes_test(sig + *len, elen);
|
||||
*len += elen;
|
||||
|
||||
/* Generate end-of-contents bytes. */
|
||||
if (indet) {
|
||||
sig[(*len)++] = 0;
|
||||
sig[(*len)++] = 0;
|
||||
tlen += 2;
|
||||
}
|
||||
CHECK(tlen + glen <= 1121);
|
||||
|
||||
/* Generate random garbage outside tuple. */
|
||||
secp256k1_rand_bytes_test(sig + *len, glen);
|
||||
*len += glen;
|
||||
tlen += glen;
|
||||
CHECK(tlen <= 1121);
|
||||
CHECK(tlen == *len);
|
||||
}
|
||||
|
||||
void run_ecdsa_der_parse(void) {
|
||||
int i,j;
|
||||
for (i = 0; i < 200 * count; i++) {
|
||||
unsigned char buffer[2048];
|
||||
size_t buflen = 0;
|
||||
int certainly_der = 0;
|
||||
int certainly_not_der = 0;
|
||||
random_ber_signature(buffer, &buflen, &certainly_der, &certainly_not_der);
|
||||
for (j = 0; j < 16; j++) {
|
||||
int ret = 0;
|
||||
if (j > 0) {
|
||||
damage_array(buffer, &buflen);
|
||||
/* We don't know anything anymore about the DERness of the result */
|
||||
certainly_der = 0;
|
||||
certainly_not_der = 0;
|
||||
}
|
||||
ret = test_ecdsa_der_parse(buffer, buflen, certainly_der, certainly_not_der);
|
||||
if (ret != 0) {
|
||||
size_t k;
|
||||
fprintf(stderr, "Failure %x on ", ret);
|
||||
for (k = 0; k < buflen; k++) {
|
||||
fprintf(stderr, "%02x ", buffer[k]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
CHECK(ret == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Tests several edge cases. */
|
||||
void test_ecdsa_edge_cases(void) {
|
||||
int t;
|
||||
|
@ -2575,7 +2985,7 @@ EC_KEY *get_openssl_key(const secp256k1_scalar *key) {
|
|||
unsigned char privkey[300];
|
||||
size_t privkeylen;
|
||||
const unsigned char* pbegin = privkey;
|
||||
int compr = secp256k1_rand32() & 1;
|
||||
int compr = secp256k1_rand_bits(1);
|
||||
EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
CHECK(secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, &privkeylen, key, compr ? SECP256K1_EC_COMPRESSED : 0));
|
||||
CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen));
|
||||
|
@ -2681,11 +3091,14 @@ int main(int argc, char **argv) {
|
|||
/* initialize */
|
||||
run_context_tests();
|
||||
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
if (secp256k1_rand32() & 1) {
|
||||
if (secp256k1_rand_bits(1)) {
|
||||
secp256k1_rand256(run32);
|
||||
CHECK(secp256k1_context_randomize(ctx, (secp256k1_rand32() & 1) ? run32 : NULL));
|
||||
CHECK(secp256k1_context_randomize(ctx, secp256k1_rand_bits(1) ? run32 : NULL));
|
||||
}
|
||||
|
||||
run_rand_bits();
|
||||
run_rand_int();
|
||||
|
||||
run_sha256_tests();
|
||||
run_hmac_sha256_tests();
|
||||
run_rfc6979_hmac_sha256_tests();
|
||||
|
@ -2734,6 +3147,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
/* ecdsa tests */
|
||||
run_random_pubkeys();
|
||||
run_ecdsa_der_parse();
|
||||
run_ecdsa_sign_verify();
|
||||
run_ecdsa_end_to_end();
|
||||
run_ecdsa_edge_cases();
|
||||
|
|
Loading…
Add table
Reference in a new issue