Skip to content

Commit eed87af

Browse files
committed
Change contrib/laxder from headers-only to files compilable as standalone C
Verified that both programs compile with gcc -I. -I../include -lsecp256k1 -c -W -Wextra -Wall -Werror -ansi -pedantic lax_der_privatekey_parsing.c gcc -I. -I../include -lsecp256k1 -c -W -Wextra -Wall -Werror -ansi -pedantic lax_der_parsing.c
1 parent d7eb1ae commit eed87af

File tree

6 files changed

+327
-250
lines changed

6 files changed

+327
-250
lines changed

Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ noinst_HEADERS += src/field.h
4141
noinst_HEADERS += src/field_impl.h
4242
noinst_HEADERS += src/bench.h
4343
noinst_HEADERS += contrib/lax_der_parsing.h
44+
noinst_HEADERS += contrib/lax_der_parsing.c
4445
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
46+
noinst_HEADERS += contrib/lax_der_privatekey_parsing.c
4547

4648
pkgconfigdir = $(libdir)/pkgconfig
4749
pkgconfig_DATA = libsecp256k1.pc

contrib/lax_der_parsing.c

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/**********************************************************************
2+
* Copyright (c) 2015 Pieter Wuille *
3+
* Distributed under the MIT software license, see the accompanying *
4+
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5+
**********************************************************************/
6+
7+
#include <string.h>
8+
#include <secp256k1.h>
9+
10+
#include "lax_der_parsing.h"
11+
12+
int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
13+
size_t rpos, rlen, spos, slen;
14+
size_t pos = 0;
15+
size_t lenbyte;
16+
unsigned char tmpsig[64] = {0};
17+
int overflow = 0;
18+
19+
/* Hack to initialize sig with a correctly-parsed but invalid signature. */
20+
secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
21+
22+
/* Sequence tag byte */
23+
if (pos == inputlen || input[pos] != 0x30) {
24+
return 0;
25+
}
26+
pos++;
27+
28+
/* Sequence length bytes */
29+
if (pos == inputlen) {
30+
return 0;
31+
}
32+
lenbyte = input[pos++];
33+
if (lenbyte & 0x80) {
34+
lenbyte -= 0x80;
35+
if (pos + lenbyte > inputlen) {
36+
return 0;
37+
}
38+
pos += lenbyte;
39+
}
40+
41+
/* Integer tag byte for R */
42+
if (pos == inputlen || input[pos] != 0x02) {
43+
return 0;
44+
}
45+
pos++;
46+
47+
/* Integer length for R */
48+
if (pos == inputlen) {
49+
return 0;
50+
}
51+
lenbyte = input[pos++];
52+
if (lenbyte & 0x80) {
53+
lenbyte -= 0x80;
54+
if (pos + lenbyte > inputlen) {
55+
return 0;
56+
}
57+
while (lenbyte > 0 && input[pos] == 0) {
58+
pos++;
59+
lenbyte--;
60+
}
61+
if (lenbyte >= sizeof(size_t)) {
62+
return 0;
63+
}
64+
rlen = 0;
65+
while (lenbyte > 0) {
66+
rlen = (rlen << 8) + input[pos];
67+
pos++;
68+
lenbyte--;
69+
}
70+
} else {
71+
rlen = lenbyte;
72+
}
73+
if (rlen > inputlen - pos) {
74+
return 0;
75+
}
76+
rpos = pos;
77+
pos += rlen;
78+
79+
/* Integer tag byte for S */
80+
if (pos == inputlen || input[pos] != 0x02) {
81+
return 0;
82+
}
83+
pos++;
84+
85+
/* Integer length for S */
86+
if (pos == inputlen) {
87+
return 0;
88+
}
89+
lenbyte = input[pos++];
90+
if (lenbyte & 0x80) {
91+
lenbyte -= 0x80;
92+
if (pos + lenbyte > inputlen) {
93+
return 0;
94+
}
95+
while (lenbyte > 0 && input[pos] == 0) {
96+
pos++;
97+
lenbyte--;
98+
}
99+
if (lenbyte >= sizeof(size_t)) {
100+
return 0;
101+
}
102+
slen = 0;
103+
while (lenbyte > 0) {
104+
slen = (slen << 8) + input[pos];
105+
pos++;
106+
lenbyte--;
107+
}
108+
} else {
109+
slen = lenbyte;
110+
}
111+
if (slen > inputlen - pos) {
112+
return 0;
113+
}
114+
spos = pos;
115+
pos += slen;
116+
117+
/* Ignore leading zeroes in R */
118+
while (rlen > 0 && input[rpos] == 0) {
119+
rlen--;
120+
rpos++;
121+
}
122+
/* Copy R value */
123+
if (rlen > 32) {
124+
overflow = 1;
125+
} else {
126+
memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
127+
}
128+
129+
/* Ignore leading zeroes in S */
130+
while (slen > 0 && input[spos] == 0) {
131+
slen--;
132+
spos++;
133+
}
134+
/* Copy S value */
135+
if (slen > 32) {
136+
overflow = 1;
137+
} else {
138+
memcpy(tmpsig + 64 - slen, input + spos, slen);
139+
}
140+
141+
if (!overflow) {
142+
overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
143+
}
144+
if (overflow) {
145+
memset(tmpsig, 0, 64);
146+
secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
147+
}
148+
return 1;
149+
}
150+

contrib/lax_der_parsing.h

Lines changed: 40 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@
44
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
55
**********************************************************************/
66

7-
/* This file contains a code snippet that parses DER with various errors and
7+
/****
8+
* Please do not link this file directly. It is not part of the libsecp256k1
9+
* project and does not promise any stability in its API, functionality or
10+
* presence. Projects which use this code should instead copy this header
11+
* and its accompanying .c file directly into their codebase.
12+
****/
13+
14+
/* This file defines a function that parses DER with various errors and
815
* violations. This is not a part of the library itself, because the allowed
916
* violations are chosen arbitrarily and do not follow or establish any
1017
* standard.
@@ -44,148 +51,41 @@
4451
#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_
4552
#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_
4653

47-
#include <string.h>
4854
#include <secp256k1.h>
4955

50-
static int secp256k1_ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen);
56+
# ifdef __cplusplus
57+
extern "C" {
58+
# endif
5159

52-
static int secp256k1_ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
53-
size_t rpos, rlen, spos, slen;
54-
size_t pos = 0;
55-
size_t lenbyte;
56-
unsigned char tmpsig[64] = {0};
57-
int overflow = 0;
58-
59-
/* Hack to initialize sig with a correctly-parsed but invalid signature. */
60-
secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
61-
62-
/* Sequence tag byte */
63-
if (pos == inputlen || input[pos] != 0x30) {
64-
return 0;
65-
}
66-
pos++;
67-
68-
/* Sequence length bytes */
69-
if (pos == inputlen) {
70-
return 0;
71-
}
72-
lenbyte = input[pos++];
73-
if (lenbyte & 0x80) {
74-
lenbyte -= 0x80;
75-
if (pos + lenbyte > inputlen) {
76-
return 0;
77-
}
78-
pos += lenbyte;
79-
}
80-
81-
/* Integer tag byte for R */
82-
if (pos == inputlen || input[pos] != 0x02) {
83-
return 0;
84-
}
85-
pos++;
86-
87-
/* Integer length for R */
88-
if (pos == inputlen) {
89-
return 0;
90-
}
91-
lenbyte = input[pos++];
92-
if (lenbyte & 0x80) {
93-
lenbyte -= 0x80;
94-
if (pos + lenbyte > inputlen) {
95-
return 0;
96-
}
97-
while (lenbyte > 0 && input[pos] == 0) {
98-
pos++;
99-
lenbyte--;
100-
}
101-
if (lenbyte >= sizeof(size_t)) {
102-
return 0;
103-
}
104-
rlen = 0;
105-
while (lenbyte > 0) {
106-
rlen = (rlen << 8) + input[pos];
107-
pos++;
108-
lenbyte--;
109-
}
110-
} else {
111-
rlen = lenbyte;
112-
}
113-
if (rlen > inputlen - pos) {
114-
return 0;
115-
}
116-
rpos = pos;
117-
pos += rlen;
118-
119-
/* Integer tag byte for S */
120-
if (pos == inputlen || input[pos] != 0x02) {
121-
return 0;
122-
}
123-
pos++;
124-
125-
/* Integer length for S */
126-
if (pos == inputlen) {
127-
return 0;
128-
}
129-
lenbyte = input[pos++];
130-
if (lenbyte & 0x80) {
131-
lenbyte -= 0x80;
132-
if (pos + lenbyte > inputlen) {
133-
return 0;
134-
}
135-
while (lenbyte > 0 && input[pos] == 0) {
136-
pos++;
137-
lenbyte--;
138-
}
139-
if (lenbyte >= sizeof(size_t)) {
140-
return 0;
141-
}
142-
slen = 0;
143-
while (lenbyte > 0) {
144-
slen = (slen << 8) + input[pos];
145-
pos++;
146-
lenbyte--;
147-
}
148-
} else {
149-
slen = lenbyte;
150-
}
151-
if (slen > inputlen - pos) {
152-
return 0;
153-
}
154-
spos = pos;
155-
pos += slen;
156-
157-
/* Ignore leading zeroes in R */
158-
while (rlen > 0 && input[rpos] == 0) {
159-
rlen--;
160-
rpos++;
161-
}
162-
/* Copy R value */
163-
if (rlen > 32) {
164-
overflow = 1;
165-
} else {
166-
memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
167-
}
168-
169-
/* Ignore leading zeroes in S */
170-
while (slen > 0 && input[spos] == 0) {
171-
slen--;
172-
spos++;
173-
}
174-
/* Copy S value */
175-
if (slen > 32) {
176-
overflow = 1;
177-
} else {
178-
memcpy(tmpsig + 64 - slen, input + spos, slen);
179-
}
180-
181-
if (!overflow) {
182-
overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
183-
}
184-
if (overflow) {
185-
memset(tmpsig, 0, 64);
186-
secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
187-
}
188-
return 1;
60+
/** Parse a signature in "lax DER" format
61+
*
62+
* Returns: 1 when the signature could be parsed, 0 otherwise.
63+
* Args: ctx: a secp256k1 context object
64+
* Out: sig: a pointer to a signature object
65+
* In: input: a pointer to the signature to be parsed
66+
* inputlen: the length of the array pointed to be input
67+
*
68+
* This function will accept any valid DER encoded signature, even if the
69+
* encoded numbers are out of range. In addition, it will accept signatures
70+
* which violate the DER spec in various ways. Its purpose is to allow
71+
* validation of the Bitcoin blockchain, which includes non-DER signatures
72+
* from before the network rules were updated to enforce DER. Note that
73+
* the set of supported violations is a strict subset of what OpenSSL will
74+
* accept.
75+
*
76+
* After the call, sig will always be initialized. If parsing failed or the
77+
* encoded numbers are out of range, signature validation with it is
78+
* guaranteed to fail for every message and public key.
79+
*/
80+
int ecdsa_signature_parse_der_lax(
81+
const secp256k1_context* ctx,
82+
secp256k1_ecdsa_signature* sig,
83+
const unsigned char *input,
84+
size_t inputlen
85+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
86+
87+
#ifdef __cplusplus
18988
}
89+
#endif
19090

19191
#endif

0 commit comments

Comments
 (0)