Skip to content

Commit a3603ac

Browse files
committed
Fix potential overflows in ECDSA DER parsers
1 parent 0b01935 commit a3603ac

File tree

2 files changed

+28
-19
lines changed

2 files changed

+28
-19
lines changed

src/key.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Copyright (c) 2009-2016 The Bitcoin Core developers
2+
// Copyright (c) 2017 The Zcash developers
23
// Distributed under the MIT software license, see the accompanying
34
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
45

@@ -18,41 +19,46 @@ static secp256k1_context* secp256k1_context_sign = NULL;
1819
/** These functions are taken from the libsecp256k1 distribution and are very ugly. */
1920
static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) {
2021
const unsigned char *end = privkey + privkeylen;
21-
int lenb = 0;
22-
int len = 0;
22+
size_t lenb = 0;
23+
size_t len = 0;
2324
memset(out32, 0, 32);
2425
/* sequence header */
25-
if (end < privkey+1 || *privkey != 0x30) {
26+
if (end - privkey < 1 || *privkey != 0x30u) {
2627
return 0;
2728
}
2829
privkey++;
2930
/* sequence length constructor */
30-
if (end < privkey+1 || !(*privkey & 0x80)) {
31+
if (end - privkey < 1 || !(*privkey & 0x80u)) {
3132
return 0;
3233
}
33-
lenb = *privkey & ~0x80; privkey++;
34+
lenb = *privkey & ~0x80u; privkey++;
3435
if (lenb < 1 || lenb > 2) {
3536
return 0;
3637
}
37-
if (end < privkey+lenb) {
38+
if (end - privkey < lenb) {
3839
return 0;
3940
}
4041
/* sequence length */
41-
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0);
42+
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0u);
4243
privkey += lenb;
43-
if (end < privkey+len) {
44+
if (end - privkey < len) {
4445
return 0;
4546
}
4647
/* sequence element 0: version number (=1) */
47-
if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) {
48+
if (end - privkey < 3 || privkey[0] != 0x02u || privkey[1] != 0x01u || privkey[2] != 0x01u) {
4849
return 0;
4950
}
5051
privkey += 3;
5152
/* sequence element 1: octet string, up to 32 bytes */
52-
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) {
53+
if (end - privkey < 2 || privkey[0] != 0x04u) {
5354
return 0;
5455
}
55-
memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]);
56+
size_t oslen = privkey[1];
57+
privkey += 2;
58+
if (oslen > 32 || end - privkey < oslen) {
59+
return 0;
60+
}
61+
memcpy(out32 + (32 - oslen), privkey, oslen);
5662
if (!secp256k1_ec_seckey_verify(ctx, out32)) {
5763
memset(out32, 0, 32);
5864
return 0;
@@ -219,10 +225,10 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const
219225
std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);
220226
if ((nChild >> 31) == 0) {
221227
CPubKey pubkey = GetPubKey();
222-
assert(pubkey.begin() + 33 == pubkey.end());
228+
assert(pubkey.size() == 33);
223229
BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, vout.data());
224230
} else {
225-
assert(begin() + 32 == end());
231+
assert(size() == 32);
226232
BIP32Hash(cc, nChild, 0, begin(), vout.data());
227233
}
228234
memcpy(ccChild.begin(), vout.data()+32, 32);

src/pubkey.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Copyright (c) 2009-2016 The Bitcoin Core developers
2+
// Copyright (c) 2017 The Zcash developers
23
// Distributed under the MIT software license, see the accompanying
34
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
45

@@ -46,7 +47,7 @@ static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1
4647
lenbyte = input[pos++];
4748
if (lenbyte & 0x80) {
4849
lenbyte -= 0x80;
49-
if (pos + lenbyte > inputlen) {
50+
if (lenbyte > inputlen - pos) {
5051
return 0;
5152
}
5253
pos += lenbyte;
@@ -65,14 +66,15 @@ static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1
6566
lenbyte = input[pos++];
6667
if (lenbyte & 0x80) {
6768
lenbyte -= 0x80;
68-
if (pos + lenbyte > inputlen) {
69+
if (lenbyte > inputlen - pos) {
6970
return 0;
7071
}
7172
while (lenbyte > 0 && input[pos] == 0) {
7273
pos++;
7374
lenbyte--;
7475
}
75-
if (lenbyte >= sizeof(size_t)) {
76+
static_assert(sizeof(size_t) >= 4, "size_t too small");
77+
if (lenbyte >= 4) {
7678
return 0;
7779
}
7880
rlen = 0;
@@ -103,14 +105,15 @@ static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1
103105
lenbyte = input[pos++];
104106
if (lenbyte & 0x80) {
105107
lenbyte -= 0x80;
106-
if (pos + lenbyte > inputlen) {
108+
if (lenbyte > inputlen - pos) {
107109
return 0;
108110
}
109111
while (lenbyte > 0 && input[pos] == 0) {
110112
pos++;
111113
lenbyte--;
112114
}
113-
if (lenbyte >= sizeof(size_t)) {
115+
static_assert(sizeof(size_t) >= 4, "size_t too small");
116+
if (lenbyte >= 4) {
114117
return 0;
115118
}
116119
slen = 0;
@@ -225,7 +228,7 @@ bool CPubKey::Decompress() {
225228
bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {
226229
assert(IsValid());
227230
assert((nChild >> 31) == 0);
228-
assert(begin() + 33 == end());
231+
assert(size() == 33);
229232
unsigned char out[64];
230233
BIP32Hash(cc, nChild, *begin(), begin()+1, out);
231234
memcpy(ccChild.begin(), out+32, 32);

0 commit comments

Comments
 (0)