]> Git Repo - VerusCoin.git/blame - src/pubkey.cpp
Fix potential overflows in ECDSA DER parsers
[VerusCoin.git] / src / pubkey.cpp
CommitLineData
f914f1a7 1// Copyright (c) 2009-2014 The Bitcoin Core developers
50fa0797 2// Copyright (c) 2017 The Zcash developers
b4347f60 3// Distributed under the MIT software license, see the accompanying
d2e74c55
CF
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include "pubkey.h"
7
3d02d0f6
PW
8#include <secp256k1.h>
9#include <secp256k1_recovery.h>
d2e74c55 10
3d02d0f6
PW
11namespace
12{
13/* Global secp256k1_context object used for verification. */
14secp256k1_context* secp256k1_context_verify = NULL;
15}
16
17/** This function is taken from the libsecp256k1 distribution and implements
18 * DER parsing for ECDSA signatures, while supporting an arbitrary subset of
19 * format violations.
20 *
21 * Supported violations include negative integers, excessive padding, garbage
22 * at the end, and overly long length descriptors. This is safe to use in
23 * Bitcoin because since the activation of BIP66, signatures are verified to be
24 * strict DER before being passed to this module, and we know it supports all
25 * violations present in the blockchain before that point.
26 */
27static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
28 size_t rpos, rlen, spos, slen;
29 size_t pos = 0;
30 size_t lenbyte;
31 unsigned char tmpsig[64] = {0};
32 int overflow = 0;
33
34 /* Hack to initialize sig with a correctly-parsed but invalid signature. */
35 secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
36
37 /* Sequence tag byte */
38 if (pos == inputlen || input[pos] != 0x30) {
39 return 0;
40 }
41 pos++;
42
43 /* Sequence length bytes */
44 if (pos == inputlen) {
45 return 0;
46 }
47 lenbyte = input[pos++];
48 if (lenbyte & 0x80) {
49 lenbyte -= 0x80;
50fa0797 50 if (lenbyte > inputlen - pos) {
3d02d0f6
PW
51 return 0;
52 }
53 pos += lenbyte;
54 }
55
56 /* Integer tag byte for R */
57 if (pos == inputlen || input[pos] != 0x02) {
58 return 0;
59 }
60 pos++;
61
62 /* Integer length for R */
63 if (pos == inputlen) {
64 return 0;
65 }
66 lenbyte = input[pos++];
67 if (lenbyte & 0x80) {
68 lenbyte -= 0x80;
50fa0797 69 if (lenbyte > inputlen - pos) {
3d02d0f6
PW
70 return 0;
71 }
72 while (lenbyte > 0 && input[pos] == 0) {
73 pos++;
74 lenbyte--;
75 }
50fa0797
JG
76 static_assert(sizeof(size_t) >= 4, "size_t too small");
77 if (lenbyte >= 4) {
3d02d0f6
PW
78 return 0;
79 }
80 rlen = 0;
81 while (lenbyte > 0) {
82 rlen = (rlen << 8) + input[pos];
83 pos++;
84 lenbyte--;
85 }
86 } else {
87 rlen = lenbyte;
88 }
89 if (rlen > inputlen - pos) {
90 return 0;
91 }
92 rpos = pos;
93 pos += rlen;
94
95 /* Integer tag byte for S */
96 if (pos == inputlen || input[pos] != 0x02) {
97 return 0;
98 }
99 pos++;
100
101 /* Integer length for S */
102 if (pos == inputlen) {
103 return 0;
104 }
105 lenbyte = input[pos++];
106 if (lenbyte & 0x80) {
107 lenbyte -= 0x80;
50fa0797 108 if (lenbyte > inputlen - pos) {
3d02d0f6
PW
109 return 0;
110 }
111 while (lenbyte > 0 && input[pos] == 0) {
112 pos++;
113 lenbyte--;
114 }
50fa0797
JG
115 static_assert(sizeof(size_t) >= 4, "size_t too small");
116 if (lenbyte >= 4) {
3d02d0f6
PW
117 return 0;
118 }
119 slen = 0;
120 while (lenbyte > 0) {
121 slen = (slen << 8) + input[pos];
122 pos++;
123 lenbyte--;
124 }
125 } else {
126 slen = lenbyte;
127 }
128 if (slen > inputlen - pos) {
129 return 0;
130 }
131 spos = pos;
132 pos += slen;
133
134 /* Ignore leading zeroes in R */
135 while (rlen > 0 && input[rpos] == 0) {
136 rlen--;
137 rpos++;
138 }
139 /* Copy R value */
140 if (rlen > 32) {
141 overflow = 1;
142 } else {
143 memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
144 }
145
146 /* Ignore leading zeroes in S */
147 while (slen > 0 && input[spos] == 0) {
148 slen--;
149 spos++;
150 }
151 /* Copy S value */
152 if (slen > 32) {
153 overflow = 1;
154 } else {
155 memcpy(tmpsig + 64 - slen, input + spos, slen);
156 }
157
158 if (!overflow) {
159 overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
160 }
161 if (overflow) {
162 /* Overwrite the result again with a correctly-parsed but invalid
163 signature if parsing failed. */
164 memset(tmpsig, 0, 64);
165 secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
166 }
167 return 1;
168}
d2e74c55
CF
169
170bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
171 if (!IsValid())
172 return false;
3d02d0f6
PW
173 secp256k1_pubkey pubkey;
174 secp256k1_ecdsa_signature sig;
175 if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
d2e74c55 176 return false;
3d02d0f6
PW
177 }
178 if (vchSig.size() == 0) {
d2e74c55 179 return false;
3d02d0f6
PW
180 }
181 if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
182 return false;
183 }
184 /* libsecp256k1's ECDSA verification requires lower-S signatures, which have
185 * not historically been enforced in Bitcoin, so normalize them first. */
186 secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, &sig, &sig);
187 return secp256k1_ecdsa_verify(secp256k1_context_verify, &sig, hash.begin(), &pubkey);
d2e74c55
CF
188}
189
190bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
191 if (vchSig.size() != 65)
192 return false;
193 int recid = (vchSig[0] - 27) & 3;
194 bool fComp = ((vchSig[0] - 27) & 4) != 0;
3d02d0f6
PW
195 secp256k1_pubkey pubkey;
196 secp256k1_ecdsa_recoverable_signature sig;
197 if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_verify, &sig, &vchSig[1], recid)) {
d2e74c55 198 return false;
3d02d0f6
PW
199 }
200 if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, hash.begin())) {
201 return false;
202 }
203 unsigned char pub[65];
204 size_t publen = 65;
205 secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
206 Set(pub, pub + publen);
d2e74c55
CF
207 return true;
208}
209
210bool CPubKey::IsFullyValid() const {
211 if (!IsValid())
212 return false;
3d02d0f6
PW
213 secp256k1_pubkey pubkey;
214 return secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size());
d2e74c55
CF
215}
216
217bool CPubKey::Decompress() {
218 if (!IsValid())
219 return false;
3d02d0f6
PW
220 secp256k1_pubkey pubkey;
221 if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
d2e74c55 222 return false;
3d02d0f6
PW
223 }
224 unsigned char pub[65];
225 size_t publen = 65;
226 secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
227 Set(pub, pub + publen);
d2e74c55
CF
228 return true;
229}
230
a5748996 231bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {
d2e74c55
CF
232 assert(IsValid());
233 assert((nChild >> 31) == 0);
50fa0797 234 assert(size() == 33);
d2e74c55
CF
235 unsigned char out[64];
236 BIP32Hash(cc, nChild, *begin(), begin()+1, out);
a5748996 237 memcpy(ccChild.begin(), out+32, 32);
3d02d0f6
PW
238 secp256k1_pubkey pubkey;
239 if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
240 return false;
241 }
242 if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) {
243 return false;
244 }
245 unsigned char pub[33];
246 size_t publen = 33;
247 secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED);
248 pubkeyChild.Set(pub, pub + publen);
249 return true;
d2e74c55
CF
250}
251
252void CExtPubKey::Encode(unsigned char code[74]) const {
253 code[0] = nDepth;
254 memcpy(code+1, vchFingerprint, 4);
255 code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
256 code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
a5748996 257 memcpy(code+9, chaincode.begin(), 32);
d2e74c55
CF
258 assert(pubkey.size() == 33);
259 memcpy(code+41, pubkey.begin(), 33);
260}
261
262void CExtPubKey::Decode(const unsigned char code[74]) {
263 nDepth = code[0];
264 memcpy(vchFingerprint, code+1, 4);
265 nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
a5748996 266 memcpy(chaincode.begin(), code+9, 32);
d2e74c55
CF
267 pubkey.Set(code+41, code+74);
268}
269
270bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
271 out.nDepth = nDepth + 1;
272 CKeyID id = pubkey.GetID();
273 memcpy(&out.vchFingerprint[0], &id, 4);
274 out.nChild = nChild;
a5748996 275 return pubkey.Derive(out.pubkey, out.chaincode, nChild, chaincode);
d2e74c55 276}
3d02d0f6
PW
277
278/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
279 secp256k1_ecdsa_signature sig;
280 if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
281 return false;
282 }
283 return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig));
284}
285
286/* static */ int ECCVerifyHandle::refcount = 0;
287
288ECCVerifyHandle::ECCVerifyHandle()
289{
290 if (refcount == 0) {
291 assert(secp256k1_context_verify == NULL);
292 secp256k1_context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
293 assert(secp256k1_context_verify != NULL);
294 }
295 refcount++;
296}
297
298ECCVerifyHandle::~ECCVerifyHandle()
299{
300 refcount--;
301 if (refcount == 0) {
302 assert(secp256k1_context_verify != NULL);
303 secp256k1_context_destroy(secp256k1_context_verify);
304 secp256k1_context_verify = NULL;
305 }
306}
This page took 0.140539 seconds and 4 git commands to generate.