mirror of https://github.com/starwels/secp256k1
Browse Source
This shows a snippet of code to do lax DER parsing, without obeying to any particular standard.master
4 changed files with 222 additions and 2 deletions
@ -0,0 +1,191 @@
@@ -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 |
Loading…
Reference in new issue