Coverage Report

Created: 2026-10-27 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/pki/parse_values.cc
Line
Count
Source
1
// Copyright 2015 The Chromium Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "parse_values.h"
16
17
#include <stdlib.h>
18
19
#include <tuple>
20
21
#include <openssl/base.h>
22
#include <openssl/bytestring.h>
23
#include <openssl/mem.h>
24
25
BSSL_NAMESPACE_BEGIN
26
namespace der {
27
28
namespace {
29
30
2.02k
bool ParseBoolInternal(Input in, bool *out, bool relaxed) {
31
  // According to ITU-T X.690 section 8.2, a bool is encoded as a single octet
32
  // where the octet of all zeroes is FALSE and a non-zero value for the octet
33
  // is TRUE.
34
2.02k
  if (in.size() != 1) {
35
47
    return false;
36
47
  }
37
1.97k
  ByteReader data(in);
38
1.97k
  uint8_t byte;
39
1.97k
  if (!data.ReadByte(&byte)) {
40
0
    return false;
41
0
  }
42
1.97k
  if (byte == 0) {
43
14
    *out = false;
44
14
    return true;
45
14
  }
46
  // ITU-T X.690 section 11.1 specifies that for DER, the TRUE value must be
47
  // encoded as an octet of all ones.
48
1.96k
  if (byte == 0xff || relaxed) {
49
1.92k
    *out = true;
50
1.92k
    return true;
51
1.92k
  }
52
37
  return false;
53
1.96k
}
54
55
// Reads a positive decimal number with `digits` digits and stores it in
56
// `*out`. This function does not check that the type of `*out` is large
57
// enough to hold 10^digits - 1; the caller must choose an appropriate type
58
// based on the number of digits they wish to parse.
59
template <typename UINT>
60
80.7k
bool DecimalStringToUint(ByteReader &in, size_t digits, UINT *out) {
61
80.7k
  UINT value = 0;
62
249k
  for (size_t i = 0; i < digits; ++i) {
63
169k
    uint8_t digit;
64
169k
    if (!in.ReadByte(&digit)) {
65
343
      return false;
66
343
    }
67
169k
    if (digit < '0' || digit > '9') {
68
500
      return false;
69
500
    }
70
168k
    value = (value * 10) + (digit - '0');
71
168k
  }
72
79.8k
  *out = value;
73
79.8k
  return true;
74
80.7k
}
parse_values.cc:bool bssl::der::(anonymous namespace)::DecimalStringToUint<unsigned short>(bssl::der::ByteReader&, unsigned long, unsigned short*)
Line
Count
Source
60
13.8k
bool DecimalStringToUint(ByteReader &in, size_t digits, UINT *out) {
61
13.8k
  UINT value = 0;
62
49.9k
  for (size_t i = 0; i < digits; ++i) {
63
36.2k
    uint8_t digit;
64
36.2k
    if (!in.ReadByte(&digit)) {
65
76
      return false;
66
76
    }
67
36.1k
    if (digit < '0' || digit > '9') {
68
104
      return false;
69
104
    }
70
36.0k
    value = (value * 10) + (digit - '0');
71
36.0k
  }
72
13.6k
  *out = value;
73
13.6k
  return true;
74
13.8k
}
parse_values.cc:bool bssl::der::(anonymous namespace)::DecimalStringToUint<unsigned char>(bssl::der::ByteReader&, unsigned long, unsigned char*)
Line
Count
Source
60
66.9k
bool DecimalStringToUint(ByteReader &in, size_t digits, UINT *out) {
61
66.9k
  UINT value = 0;
62
199k
  for (size_t i = 0; i < digits; ++i) {
63
133k
    uint8_t digit;
64
133k
    if (!in.ReadByte(&digit)) {
65
267
      return false;
66
267
    }
67
133k
    if (digit < '0' || digit > '9') {
68
396
      return false;
69
396
    }
70
132k
    value = (value * 10) + (digit - '0');
71
132k
  }
72
66.2k
  *out = value;
73
66.2k
  return true;
74
66.9k
}
75
76
// Checks that the values in a GeneralizedTime struct are valid. This involves
77
// checking that the year is 4 digits, the month is between 1 and 12, the day
78
// is a day that exists in that month (following current leap year rules),
79
// hours are between 0 and 23, minutes between 0 and 59, and seconds between
80
// 0 and 60 (to allow for leap seconds; no validation is done that a leap
81
// second is on a day that could be a leap second).
82
12.8k
bool ValidateGeneralizedTime(const GeneralizedTime &time) {
83
12.8k
  if (time.month < 1 || time.month > 12) {
84
32
    return false;
85
32
  }
86
12.7k
  if (time.day < 1) {
87
7
    return false;
88
7
  }
89
12.7k
  if (time.hours > 23) {
90
11
    return false;
91
11
  }
92
12.7k
  if (time.minutes > 59) {
93
13
    return false;
94
13
  }
95
  // Leap seconds are allowed.
96
12.7k
  if (time.seconds > 60) {
97
8
    return false;
98
8
  }
99
100
  // validate upper bound for day of month
101
12.7k
  switch (time.month) {
102
1.62k
    case 4:
103
2.68k
    case 6:
104
3.38k
    case 9:
105
4.21k
    case 11:
106
4.21k
      if (time.day > 30) {
107
31
        return false;
108
31
      }
109
4.18k
      break;
110
4.18k
    case 1:
111
1.61k
    case 3:
112
2.28k
    case 5:
113
3.35k
    case 7:
114
4.44k
    case 8:
115
5.09k
    case 10:
116
5.74k
    case 12:
117
5.74k
      if (time.day > 31) {
118
39
        return false;
119
39
      }
120
5.70k
      break;
121
5.70k
    case 2:
122
2.79k
      if (time.year % 4 == 0 &&
123
1.80k
          (time.year % 100 != 0 || time.year % 400 == 0)) {
124
1.18k
        if (time.day > 29) {
125
23
          return false;
126
23
        }
127
1.61k
      } else {
128
1.61k
        if (time.day > 28) {
129
28
          return false;
130
28
        }
131
1.61k
      }
132
2.74k
      break;
133
2.74k
    default:
134
0
      abort();
135
12.7k
  }
136
12.6k
  return true;
137
12.7k
}
138
139
// Returns the number of bytes of numeric precision in a DER encoded INTEGER
140
// value. `in` must be a valid DER encoding of an INTEGER for this to work.
141
//
142
// Normally the precision of the number is exactly in.size(). However when
143
// encoding positive numbers using DER it is possible to have a leading zero
144
// (to prevent number from being interpreted as negative).
145
//
146
// For instance a 160-bit positive number might take 21 bytes to encode. This
147
// function will return 20 in such a case.
148
3.19k
size_t GetUnsignedIntegerLength(Input in) {
149
3.19k
  der::ByteReader reader(in);
150
3.19k
  uint8_t first_byte;
151
3.19k
  if (!reader.ReadByte(&first_byte)) {
152
0
    return 0;  // Not valid DER  as `in` was empty.
153
0
  }
154
155
3.19k
  if (first_byte == 0 && in.size() > 1) {
156
459
    return in.size() - 1;
157
459
  }
158
2.73k
  return in.size();
159
3.19k
}
160
161
}  // namespace
162
163
2.02k
bool ParseBool(Input in, bool *out) {
164
2.02k
  return ParseBoolInternal(in, out, false /* relaxed */);
165
2.02k
}
166
167
// BER interprets any non-zero value as true, while DER requires a bool to
168
// have either all bits zero (false) or all bits one (true). To support
169
// malformed certs, we recognized the BER encoding instead of failing to
170
// parse.
171
0
bool ParseBoolRelaxed(Input in, bool *out) {
172
0
  return ParseBoolInternal(in, out, true /* relaxed */);
173
0
}
174
175
// ITU-T X.690 section 8.3.2 specifies that an integer value must be encoded
176
// in the smallest number of octets. If the encoding consists of more than
177
// one octet, then the bits of the first octet and the most significant bit
178
// of the second octet must not be all zeroes or all ones.
179
5.90k
bool IsValidInteger(Input in, bool *negative) {
180
5.90k
  CBS cbs;
181
5.90k
  CBS_init(&cbs, in.data(), in.size());
182
5.90k
  int negative_int;
183
5.90k
  if (!CBS_is_valid_asn1_integer(&cbs, &negative_int)) {
184
42
    return false;
185
42
  }
186
187
5.85k
  *negative = !!negative_int;
188
5.85k
  return true;
189
5.90k
}
190
191
3.27k
bool ParseUint64(Input in, uint64_t *out) {
192
  // Reject non-minimally encoded numbers and negative numbers.
193
3.27k
  bool negative;
194
3.27k
  if (!IsValidInteger(in, &negative) || negative) {
195
83
    return false;
196
83
  }
197
198
  // Reject (non-negative) integers whose value would overflow the output type.
199
3.19k
  if (GetUnsignedIntegerLength(in) > sizeof(*out)) {
200
135
    return false;
201
135
  }
202
203
3.05k
  ByteReader reader(in);
204
3.05k
  uint8_t data;
205
3.05k
  uint64_t value = 0;
206
207
10.0k
  while (reader.ReadByte(&data)) {
208
7.00k
    value <<= 8;
209
7.00k
    value |= data;
210
7.00k
  }
211
3.05k
  *out = value;
212
3.05k
  return true;
213
3.19k
}
214
215
1.16k
bool ParseUint8(Input in, uint8_t *out) {
216
  // TODO(eroman): Implement this more directly.
217
1.16k
  uint64_t value;
218
1.16k
  if (!ParseUint64(in, &value)) {
219
124
    return false;
220
124
  }
221
222
1.04k
  if (value > 0xFF) {
223
390
    return false;
224
390
  }
225
226
652
  *out = static_cast<uint8_t>(value);
227
652
  return true;
228
1.04k
}
229
230
BitString::BitString(Input bytes, uint8_t unused_bits)
231
3.37k
    : bytes_(bytes), unused_bits_(unused_bits) {
232
3.37k
  BSSL_CHECK(unused_bits < 8);
233
3.37k
  BSSL_CHECK(unused_bits == 0 || !bytes.empty());
234
  // The unused bits must be zero.
235
3.37k
  BSSL_CHECK(bytes.empty() || (bytes.back() & ((1u << unused_bits) - 1)) == 0);
236
3.37k
}
237
238
0
bool BitString::AssertsBit(size_t bit_index) const {
239
  // Index of the byte that contains the bit.
240
0
  size_t byte_index = bit_index / 8;
241
242
  // If the bit is outside of the bitstring, by definition it is not
243
  // asserted.
244
0
  if (byte_index >= bytes_.size()) {
245
0
    return false;
246
0
  }
247
248
  // Within a byte, bits are ordered from most significant to least significant.
249
  // Convert `bit_index` to an index within the `byte_index` byte, measured from
250
  // its least significant bit.
251
0
  uint8_t bit_index_in_byte = 7 - (bit_index - byte_index * 8);
252
253
  // BIT STRING parsing already guarantees that unused bits in a byte are zero
254
  // (otherwise it wouldn't be valid DER). Therefore it isn't necessary to check
255
  // `unused_bits_`
256
0
  uint8_t byte = bytes_[byte_index];
257
0
  return 0 != (byte & (1 << bit_index_in_byte));
258
0
}
259
260
3.44k
std::optional<BitString> ParseBitString(Input in) {
261
3.44k
  ByteReader reader(in);
262
263
  // From ITU-T X.690, section 8.6.2.2 (applies to BER, CER, DER):
264
  //
265
  // The initial octet shall encode, as an unsigned binary integer with
266
  // bit 1 as the least significant bit, the number of unused bits in the final
267
  // subsequent octet. The number shall be in the range zero to seven.
268
3.44k
  uint8_t unused_bits;
269
3.44k
  if (!reader.ReadByte(&unused_bits)) {
270
7
    return std::nullopt;
271
7
  }
272
3.44k
  if (unused_bits > 7) {
273
25
    return std::nullopt;
274
25
  }
275
276
3.41k
  Input bytes;
277
3.41k
  if (!reader.ReadBytes(reader.BytesLeft(), &bytes)) {
278
0
    return std::nullopt;  // Not reachable.
279
0
  }
280
281
  // Ensure that unused bits in the last byte are set to 0.
282
3.41k
  if (unused_bits > 0) {
283
    // From ITU-T X.690, section 8.6.2.3 (applies to BER, CER, DER):
284
    //
285
    // If the bitstring is empty, there shall be no subsequent octets,
286
    // and the initial octet shall be zero.
287
501
    if (bytes.empty()) {
288
8
      return std::nullopt;
289
8
    }
290
493
    uint8_t last_byte = bytes.back();
291
292
    // From ITU-T X.690, section 11.2.1 (applies to CER and DER, but not BER):
293
    //
294
    // Each unused bit in the final octet of the encoding of a bit string value
295
    // shall be set to zero.
296
493
    uint8_t mask = 0xFF >> (8 - unused_bits);
297
493
    if ((mask & last_byte) != 0) {
298
30
      return std::nullopt;
299
30
    }
300
493
  }
301
302
3.37k
  return BitString(bytes, unused_bits);
303
3.41k
}
304
305
0
bool GeneralizedTime::InUTCTimeRange() const {
306
0
  return 1950 <= year && year < 2050;
307
0
}
308
309
0
bool operator<(const GeneralizedTime &lhs, const GeneralizedTime &rhs) {
310
0
  return std::tie(lhs.year, lhs.month, lhs.day, lhs.hours, lhs.minutes,
311
0
                  lhs.seconds) < std::tie(rhs.year, rhs.month, rhs.day,
312
0
                                          rhs.hours, rhs.minutes, rhs.seconds);
313
0
}
314
315
0
bool operator>(const GeneralizedTime &lhs, const GeneralizedTime &rhs) {
316
0
  return rhs < lhs;
317
0
}
318
319
0
bool operator<=(const GeneralizedTime &lhs, const GeneralizedTime &rhs) {
320
0
  return !(lhs > rhs);
321
0
}
322
323
0
bool operator>=(const GeneralizedTime &lhs, const GeneralizedTime &rhs) {
324
0
  return !(lhs < rhs);
325
0
}
326
327
9.39k
bool ParseUTCTime(Input in, GeneralizedTime *value) {
328
9.39k
  ByteReader reader(in);
329
9.39k
  GeneralizedTime time;
330
9.39k
  if (!DecimalStringToUint(reader, 2, &time.year) ||
331
9.33k
      !DecimalStringToUint(reader, 2, &time.month) ||
332
9.27k
      !DecimalStringToUint(reader, 2, &time.day) ||
333
9.21k
      !DecimalStringToUint(reader, 2, &time.hours) ||
334
9.16k
      !DecimalStringToUint(reader, 2, &time.minutes) ||
335
9.10k
      !DecimalStringToUint(reader, 2, &time.seconds)) {
336
338
    return false;
337
338
  }
338
9.05k
  uint8_t zulu;
339
9.05k
  if (!reader.ReadByte(&zulu) || zulu != 'Z' || reader.HasMore()) {
340
66
    return false;
341
66
  }
342
8.99k
  if (time.year < 50) {
343
5.87k
    time.year += 2000;
344
5.87k
  } else {
345
3.11k
    time.year += 1900;
346
3.11k
  }
347
8.99k
  if (!ValidateGeneralizedTime(time)) {
348
96
    return false;
349
96
  }
350
8.89k
  *value = time;
351
8.89k
  return true;
352
8.99k
}
353
354
4.44k
bool ParseGeneralizedTime(Input in, GeneralizedTime *value) {
355
4.44k
  ByteReader reader(in);
356
4.44k
  GeneralizedTime time;
357
4.44k
  if (!DecimalStringToUint(reader, 4, &time.year) ||
358
4.32k
      !DecimalStringToUint(reader, 2, &time.month) ||
359
4.23k
      !DecimalStringToUint(reader, 2, &time.day) ||
360
4.15k
      !DecimalStringToUint(reader, 2, &time.hours) ||
361
4.08k
      !DecimalStringToUint(reader, 2, &time.minutes) ||
362
4.01k
      !DecimalStringToUint(reader, 2, &time.seconds)) {
363
505
    return false;
364
505
  }
365
3.94k
  uint8_t zulu;
366
3.94k
  if (!reader.ReadByte(&zulu) || zulu != 'Z' || reader.HasMore()) {
367
103
    return false;
368
103
  }
369
3.83k
  if (!ValidateGeneralizedTime(time)) {
370
96
    return false;
371
96
  }
372
3.74k
  *value = time;
373
3.74k
  return true;
374
3.83k
}
375
376
0
bool ParseIA5String(Input in, std::string *out) {
377
0
  for (uint8_t c : in) {
378
0
    if (c > 127) {
379
0
      return false;
380
0
    }
381
0
  }
382
0
  *out = BytesAsStringView(in);
383
0
  return true;
384
0
}
385
386
0
bool ParseVisibleString(Input in, std::string *out) {
387
  // ITU-T X.680:
388
  // VisibleString : "Defining registration number 6" + SPACE
389
  // 6 includes all the characters from '!' .. '~' (33 .. 126), space is 32.
390
  // Also ITU-T X.691 says it much more clearly:
391
  // "for VisibleString [the range] is 32 to 126 ... For VisibleString .. all
392
  // the values in the range are present."
393
0
  for (uint8_t c : in) {
394
0
    if (c < 32 || c > 126) {
395
0
      return false;
396
0
    }
397
0
  }
398
0
  *out = BytesAsStringView(in);
399
0
  return true;
400
0
}
401
402
0
bool ParsePrintableString(Input in, std::string *out) {
403
0
  for (uint8_t c : in) {
404
0
    if (!(OPENSSL_isalpha(c) || c == ' ' || (c >= '\'' && c <= ':') ||
405
0
          c == '=' || c == '?')) {
406
0
      return false;
407
0
    }
408
0
  }
409
0
  *out = BytesAsStringView(in);
410
0
  return true;
411
0
}
412
413
0
bool ParseTeletexStringAsLatin1(Input in, std::string *out) {
414
0
  out->clear();
415
  // Convert from Latin-1 to UTF-8.
416
0
  size_t utf8_length = in.size();
417
0
  for (size_t i = 0; i < in.size(); i++) {
418
0
    if (in[i] > 0x7f) {
419
0
      utf8_length++;
420
0
    }
421
0
  }
422
0
  out->reserve(utf8_length);
423
0
  for (size_t i = 0; i < in.size(); i++) {
424
0
    uint8_t u = in[i];
425
0
    if (u <= 0x7f) {
426
0
      out->push_back(u);
427
0
    } else {
428
0
      out->push_back(0xc0 | (u >> 6));
429
0
      out->push_back(0x80 | (u & 0x3f));
430
0
    }
431
0
  }
432
0
  BSSL_CHECK(utf8_length == out->size());
433
0
  return true;
434
0
}
435
436
57.1k
bool ParseUniversalString(Input in, std::string *out) {
437
57.1k
  if (in.size() % 4 != 0) {
438
199
    return false;
439
199
  }
440
441
56.9k
  CBS cbs;
442
56.9k
  CBS_init(&cbs, in.data(), in.size());
443
56.9k
  bssl::ScopedCBB cbb;
444
56.9k
  if (!CBB_init(cbb.get(), in.size())) {
445
0
    return false;
446
0
  }
447
448
66.6k
  while (CBS_len(&cbs) != 0) {
449
10.5k
    uint32_t c;
450
10.5k
    if (!CBS_get_utf32_be(&cbs, &c) ||  //
451
9.73k
        !CBB_add_utf8(cbb.get(), c)) {
452
818
      return false;
453
818
    }
454
10.5k
  }
455
456
56.0k
  out->assign(CBB_data(cbb.get()), CBB_data(cbb.get()) + CBB_len(cbb.get()));
457
56.0k
  return true;
458
56.9k
}
459
460
184k
bool ParseBmpString(Input in, std::string *out) {
461
184k
  if (in.size() % 2 != 0) {
462
171
    return false;
463
171
  }
464
465
184k
  CBS cbs;
466
184k
  CBS_init(&cbs, in.data(), in.size());
467
184k
  bssl::ScopedCBB cbb;
468
184k
  if (!CBB_init(cbb.get(), in.size())) {
469
0
    return false;
470
0
  }
471
472
6.25M
  while (CBS_len(&cbs) != 0) {
473
6.07M
    uint32_t c;
474
6.07M
    if (!CBS_get_ucs2_be(&cbs, &c) ||  //
475
6.06M
        !CBB_add_utf8(cbb.get(), c)) {
476
553
      return false;
477
553
    }
478
6.07M
  }
479
480
183k
  out->assign(CBB_data(cbb.get()), CBB_data(cbb.get()) + CBB_len(cbb.get()));
481
183k
  return true;
482
184k
}
483
484
}  // namespace der
485
BSSL_NAMESPACE_END