• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

libbitcoin / libbitcoin-system / 24331809217

13 Apr 2026 07:45AM UTC coverage: 75.852% (-5.8%) from 81.681%
24331809217

push

github

web-flow
Merge pull request #1811 from pmienk/installer-rewrite

Rewritten build/install scripts.

16733 of 22060 relevant lines covered (75.85%)

2499729.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.5
/src/crypto/der_parser.cpp
1
/**
2
 * Copyright (c) 2011-2026 libbitcoin developers (see AUTHORS)
3
 *
4
 * This file is part of libbitcoin.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <bitcoin/system/crypto/der_parser.hpp>
20

21
#include <secp256k1.h>
22
#include <bitcoin/system/data/data.hpp>
23
#include <bitcoin/system/define.hpp>
24

25
BC_PUSH_WARNING(NO_UNGUARDED_POINTERS)
26
BC_PUSH_WARNING(NO_POINTER_ARITHMETIC)
27
BC_PUSH_WARNING(NO_ARRAY_TO_POINTER_DECAY)
28

29
// Based on example code in bip66, but without signature hash byte.
30
// Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
31
// * total-length: 1-byte length descriptor of everything that follows.
32
// * R-length: 1-byte length descriptor of the R value that follows.
33
// * R: arbitrary-length big-endian encoded R value. Must use shortest.
34
// * S-length: 1-byte length descriptor of the S value that follows.
35
// * S: arbitrary-length big-endian encoded S value. Must use shortest.
36
bool is_valid_signature_encoding(const bc::system::data_slice& sig) NOEXCEPT
3✔
37
{
38
    // Minimum and maximum size constraints (strict DER, no sighash byte).
39
    if (sig.size() < 8u) return false; // Minimum DER size.
3✔
40
    if (sig.size() > 72u) return false; // Maximum DER size.
3✔
41

42
    // A signature is of type 0x30 (compound).
43
    if (sig[0] != 0x30u) return false;
3✔
44

45
    // Make sure the length covers the entire signature (no extra bytes).
46
    if (sig[1] != sig.size() - 2u) return false;
3✔
47

48
    // Extract the length of the R element.
49
    size_t lenR = sig[3];
3✔
50

51
    // Make sure the length of the S element is still inside the signature.
52
    if (5u + lenR >= sig.size()) return false;
3✔
53

54
    // Extract the length of the S element.
55
    size_t lenS = sig[5u + lenR];
3✔
56

57
    // Verify that the entire length is the sum of the sub-lengths.
58
    if (lenR + lenS + 6u != sig.size()) return false;
3✔
59

60
    // Check whether the R element is an integer.
61
    if (sig[2] != 0x02u) return false;
3✔
62

63
    // Zero-length integers are not allowed for R.
64
    if (lenR == 0u) return false;
3✔
65

66
    // Negative numbers are not allowed for R.
67
    if (sig[4u] & 0x80u) return false;
3✔
68

69
    // Null bytes at the start of R are not allowed, unless R would be negative.
70
    if (lenR > 1u && sig[4u] == 0x00u && !(sig[5u] & 0x80u)) return false;
3✔
71

72
    // Check whether the S element is an integer.
73
    if (sig[4u + lenR] != 0x02u) return false;
3✔
74

75
    // Zero-length integers are not allowed for S.
76
    if (lenS == 0u) return false;
3✔
77

78
    // Negative numbers are not allowed for S.
79
    if (sig[6u + lenR] & 0x80u) return false;
3✔
80

81
    // Null bytes at the start of S are not allowed, unless S would be negative.
82
    if (lenS > 1u && sig[6u + lenR] == 0x00u && !(sig[7u + lenR] & 0x80u))
3✔
83
        return false;
×
84

85
    return true;
86
}
87

88
/***********************************************************************
89
 * Copyright (c) 2015 Pieter Wuille                                    *
90
 * Distributed under the MIT software license, see the accompanying    *
91
 * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
92
 ***********************************************************************/
93

94
bool ecdsa_signature_parse_der_lax(const secp256k1_context* ctx,
50✔
95
    secp256k1_ecdsa_signature* sig, const uint8_t* input,
96
    size_t inputlen) NOEXCEPT
97
{
98
    unsigned char tmpsig[64]{};
50✔
99
    size_t rpos, rlen, spos, slen;
50✔
100
    size_t pos = 0;
50✔
101
    size_t lenbyte;
50✔
102

103
    // Hack to initialize sig with a correctly-parsed but invalid signature.
104
    secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
50✔
105

106
    // Sequence tag byte
107
    if (pos == inputlen || input[pos] != 0x30)
50✔
108
        return false;
109

110
    // Sequence length bytes.
111
    if (++pos == inputlen)
50✔
112
        return false;
113

114
    lenbyte = input[pos++];
50✔
115

116
    if (lenbyte & 0x80)
50✔
117
    {
118
        lenbyte -= 0x80;
×
119

120
        if (lenbyte > inputlen - pos)
×
121
            return false;
122

123
        pos += lenbyte;
×
124
    }
125

126
    // Integer tag byte for R.
127
    if (pos == inputlen || input[pos] != 0x02)
50✔
128
        return false;
129

130
    pos++;
50✔
131

132
    // Integer length for R.
133
    if (pos == inputlen)
50✔
134
        return false;
135

136
    lenbyte = input[pos++];
50✔
137

138
    if (lenbyte & 0x80)
50✔
139
    {
140
        lenbyte -= 0x80;
×
141
        if (lenbyte > inputlen - pos)
×
142
            return false;
143

144
        while (lenbyte > 0 && input[pos] == 0)
×
145
        {
146
            pos++;
×
147
            lenbyte--;
×
148
        }
149

150
        if (lenbyte >= sizeof(size_t)) 
×
151
            return false;
152

153
        rlen = 0;
154
        while (lenbyte > 0)
×
155
        {
156
            rlen = (rlen << 8) + input[pos];
×
157
            pos++;
×
158
            lenbyte--;
×
159
        }
160
    }
161
    else
162
    {
163
        rlen = lenbyte;
164
    }
165

166
    if (rlen > inputlen - pos)
50✔
167
        return false;
168

169
    rpos = pos;
50✔
170
    pos += rlen;
50✔
171

172
    // Integer tag byte for S.
173
    if (pos == inputlen || input[pos] != 0x02)
50✔
174
        return false;
175

176
    pos++;
50✔
177

178
    // Integer length for S.
179
    if (pos == inputlen)
50✔
180
        return false;
181

182
    lenbyte = input[pos++];
50✔
183

184
    if (lenbyte & 0x80)
50✔
185
    {
186
        lenbyte -= 0x80;
×
187
        if (lenbyte > inputlen - pos)
×
188
            return false;
189

190
        while (lenbyte > 0 && input[pos] == 0)
×
191
        {
192
            pos++;
×
193
            lenbyte--;
×
194
        }
195

196
        if (lenbyte >= sizeof(size_t))
×
197
            return false;
198

199
        slen = 0;
200
        while (lenbyte > 0)
×
201
        {
202
            slen = (slen << 8) + input[pos];
×
203
            pos++;
×
204
            lenbyte--;
×
205
        }
206
    }
207
    else
208
    {
209
        slen = lenbyte;
210
    }
211

212
    if (slen > (inputlen - pos))
50✔
213
        return false;
214

215
    spos = pos;
216

217
    // Ignore leading zeroes in R.
218
    while (rlen > 0 && input[rpos] == 0)
66✔
219
    {
220
        rlen--;
16✔
221
        rpos++;
16✔
222
    }
223

224
    auto overflow = false;
50✔
225

226
    // Copy R value.
227
    if (rlen > 32)
50✔
228
        overflow = true;
229
    else
230
        std::memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
50✔
231

232
    // Ignore leading zeroes in S.
233
    while (slen > 0 && input[spos] == 0)
55✔
234
    {
235
        slen--;
5✔
236
        spos++;
5✔
237
    }
238

239
    // Copy S value.
240
    if (slen > 32)
50✔
241
        overflow = true;
242
    else
243
        std::memcpy(tmpsig + 64 - slen, input + spos, slen);
50✔
244

245
    overflow |= (secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig) == 0);
50✔
246

247
    if (overflow)
50✔
248
    {
249
        std::memset(tmpsig, 0, 64);
×
250
        secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
×
251
    }
252

253
    return true;
254
}
255

256
BC_POP_WARNING()
257
BC_POP_WARNING()
258
BC_POP_WARNING()
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc