1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/logging.h"
6 #include "base/numerics/safe_math.h"
7 #include "net/der/parse_values.h"
15 bool ParseBoolInternal(const Input
& in
, bool* out
, bool relaxed
) {
16 // According to ITU-T X.690 section 8.2, a bool is encoded as a single octet
17 // where the octet of all zeroes is FALSE and a non-zero value for the octet
23 if (!data
.ReadByte(&byte
))
29 // ITU-T X.690 section 11.1 specifies that for DER, the TRUE value must be
30 // encoded as an octet of all ones.
31 if (byte
== 0xff || relaxed
) {
38 // Reads a positive decimal number with |digits| digits and stores it in
39 // |*out|. This function does not check that the type of |*out| is large
40 // enough to hold 10^digits - 1; the caller must choose an appropriate type
41 // based on the number of digits they wish to parse.
42 template <typename UINT
>
43 bool DecimalStringToUint(ByteReader
& in
, size_t digits
, UINT
* out
) {
45 for (size_t i
= 0; i
< digits
; ++i
) {
47 if (!in
.ReadByte(&digit
)) {
50 if (digit
< '0' || digit
> '9') {
53 value
= (value
* 10) + (digit
- '0');
59 // Checks that the values in a GeneralizedTime struct are valid. This involves
60 // checking that the year is 4 digits, the month is between 1 and 12, the day
61 // is a day that exists in that month (following current leap year rules),
62 // hours are between 0 and 23, minutes between 0 and 59, and seconds between
63 // 0 and 60 (to allow for leap seconds; no validation is done that a leap
64 // second is on a day that could be a leap second).
65 bool ValidateGeneralizedTime(const GeneralizedTime
& time
) {
66 CHECK(time
.year
> 0 && time
.year
< 9999);
67 if (time
.month
< 1 || time
.month
> 12)
71 if (time
.hours
< 0 || time
.hours
> 23)
73 if (time
.minutes
< 0 || time
.minutes
> 59)
75 // Leap seconds are allowed.
76 if (time
.seconds
< 0 || time
.seconds
> 60)
79 // validate upper bound for day of month
99 if (time
.year
% 4 == 0 &&
100 (time
.year
% 100 != 0 || time
.year
% 400 == 0)) {
117 bool ParseBool(const Input
& in
, bool* out
) {
118 return ParseBoolInternal(in
, out
, false /* relaxed */);
121 // BER interprets any non-zero value as true, while DER requires a bool to
122 // have either all bits zero (false) or all bits one (true). To support
123 // malformed certs, we recognized the BER encoding instead of failing to
125 bool ParseBoolRelaxed(const Input
& in
, bool* out
) {
126 return ParseBoolInternal(in
, out
, true /* relaxed */);
129 bool ParseUint64(const Input
& in
, uint64_t* out
) {
130 ByteReader
reader(in
);
131 size_t bytes_read
= 0;
134 // Note that for simplicity, this check only admits integers up to 2^63-1.
135 if (in
.Length() > sizeof(uint64_t) || in
.Length() == 0)
137 while (reader
.ReadByte(&data
)) {
138 if (bytes_read
== 0 && (data
& 0x80)) {
145 // ITU-T X.690 section 8.3.2 specifies that an integer value must be encoded
146 // in the smallest number of octets. If the encoding consists of more than
147 // one octet, then the bits of the first octet and the most significant bit
148 // of the second octet must not be all zeroes or all ones.
149 // Because this function only parses unsigned integers, there's no need to
150 // check for the all ones case.
151 if (bytes_read
> 1) {
152 ByteReader
first_bytes_reader(in
);
155 if (!first_bytes_reader
.ReadByte(&first_byte
) ||
156 !first_bytes_reader
.ReadByte(&second_byte
)) {
159 if (first_byte
== 0 && !(second_byte
& 0x80)) {
167 BitString::BitString(const Input
& bytes
, uint8_t unused_bits
)
168 : bytes_(bytes
), unused_bits_(unused_bits
) {
169 DCHECK_LT(unused_bits
, 8);
170 DCHECK(unused_bits
== 0 || bytes
.Length() != 0);
173 bool ParseBitString(const Input
& in
, BitString
* out
) {
174 ByteReader
reader(in
);
176 // From ITU-T X.690, section 8.6.2.2 (applies to BER, CER, DER):
178 // The initial octet shall encode, as an unsigned binary integer with
179 // bit 1 as the least significant bit, the number of unused bits in the final
180 // subsequent octet. The number shall be in the range zero to seven.
182 if (!reader
.ReadByte(&unused_bits
))
188 if (!reader
.ReadBytes(reader
.BytesLeft(), &bytes
))
189 return false; // Not reachable.
191 // Ensure that unused bits in the last byte are set to 0.
192 if (unused_bits
> 0) {
193 // From ITU-T X.690, section 8.6.2.3 (applies to BER, CER, DER):
195 // If the bitstring is empty, there shall be no subsequent octets,
196 // and the initial octet shall be zero.
197 if (bytes
.Length() == 0)
199 uint8_t last_byte
= bytes
.UnsafeData()[bytes
.Length() - 1];
201 // From ITU-T X.690, section 11.2.1 (applies to CER and DER, but not BER):
203 // Each unused bit in the final octet of the encoding of a bit string value
204 // shall be set to zero.
205 uint8_t mask
= 0xFF >> (8 - unused_bits
);
206 if ((mask
& last_byte
) != 0)
210 *out
= BitString(bytes
, unused_bits
);
214 bool operator<(const GeneralizedTime
& lhs
, const GeneralizedTime
& rhs
) {
215 if (lhs
.year
!= rhs
.year
)
216 return lhs
.year
< rhs
.year
;
217 if (lhs
.month
!= rhs
.month
)
218 return lhs
.month
< rhs
.month
;
219 if (lhs
.day
!= rhs
.day
)
220 return lhs
.day
< rhs
.day
;
221 if (lhs
.hours
!= rhs
.hours
)
222 return lhs
.hours
< rhs
.hours
;
223 if (lhs
.minutes
!= rhs
.minutes
)
224 return lhs
.minutes
< rhs
.minutes
;
225 return lhs
.seconds
< rhs
.seconds
;
228 // A UTC Time in DER encoding should be YYMMDDHHMMSSZ, but some CAs encode
229 // the time following BER rules, which allows for YYMMDDHHMMZ. If the length
230 // is 11, assume it's YYMMDDHHMMZ, and in converting it to a GeneralizedTime,
231 // add in the seconds (set to 0).
232 bool ParseUTCTimeRelaxed(const Input
& in
, GeneralizedTime
* value
) {
233 ByteReader
reader(in
);
234 GeneralizedTime time
;
235 if (!DecimalStringToUint(reader
, 2, &time
.year
) ||
236 !DecimalStringToUint(reader
, 2, &time
.month
) ||
237 !DecimalStringToUint(reader
, 2, &time
.day
) ||
238 !DecimalStringToUint(reader
, 2, &time
.hours
) ||
239 !DecimalStringToUint(reader
, 2, &time
.minutes
)) {
243 // Try to read the 'Z' at the end. If we read something else, then for it to
244 // be valid the next bytes should be seconds (and then followed by 'Z').
246 ByteReader zulu_reader
= reader
;
247 if (!zulu_reader
.ReadByte(&zulu
))
249 if (zulu
== 'Z' && !zulu_reader
.HasMore()) {
254 if (!DecimalStringToUint(reader
, 2, &time
.seconds
))
256 if (!reader
.ReadByte(&zulu
) || zulu
!= 'Z' || reader
.HasMore())
258 if (!ValidateGeneralizedTime(time
))
260 if (time
.year
< 50) {
269 bool ParseUTCTime(const Input
& in
, GeneralizedTime
* value
) {
270 ByteReader
reader(in
);
271 GeneralizedTime time
;
272 if (!DecimalStringToUint(reader
, 2, &time
.year
) ||
273 !DecimalStringToUint(reader
, 2, &time
.month
) ||
274 !DecimalStringToUint(reader
, 2, &time
.day
) ||
275 !DecimalStringToUint(reader
, 2, &time
.hours
) ||
276 !DecimalStringToUint(reader
, 2, &time
.minutes
) ||
277 !DecimalStringToUint(reader
, 2, &time
.seconds
)) {
281 if (!reader
.ReadByte(&zulu
) || zulu
!= 'Z' || reader
.HasMore())
283 if (!ValidateGeneralizedTime(time
))
285 if (time
.year
< 50) {
294 bool ParseGeneralizedTime(const Input
& in
, GeneralizedTime
* value
) {
295 ByteReader
reader(in
);
296 GeneralizedTime time
;
297 if (!DecimalStringToUint(reader
, 4, &time
.year
) ||
298 !DecimalStringToUint(reader
, 2, &time
.month
) ||
299 !DecimalStringToUint(reader
, 2, &time
.day
) ||
300 !DecimalStringToUint(reader
, 2, &time
.hours
) ||
301 !DecimalStringToUint(reader
, 2, &time
.minutes
) ||
302 !DecimalStringToUint(reader
, 2, &time
.seconds
)) {
306 if (!reader
.ReadByte(&zulu
) || zulu
!= 'Z' || reader
.HasMore())
308 if (!ValidateGeneralizedTime(time
))