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 if (time
.month
< 1 || time
.month
> 12)
70 if (time
.hours
< 0 || time
.hours
> 23)
72 if (time
.minutes
< 0 || time
.minutes
> 59)
74 // Leap seconds are allowed.
75 if (time
.seconds
< 0 || time
.seconds
> 60)
78 // validate upper bound for day of month
98 if (time
.year
% 4 == 0 &&
99 (time
.year
% 100 != 0 || time
.year
% 400 == 0)) {
114 // Returns the number of bytes of numeric precision in a DER encoded INTEGER
115 // value. |in| must be a valid DER encoding of an INTEGER for this to work.
117 // Normally the precision of the number is exactly in.Length(). However when
118 // encoding positive numbers using DER it is possible to have a leading zero
119 // (to prevent number from being interpreted as negative).
121 // For instance a 160-bit positive number might take 21 bytes to encode. This
122 // function will return 20 in such a case.
123 size_t GetUnsignedIntegerLength(const Input
& in
) {
124 der::ByteReader
reader(in
);
126 if (!reader
.ReadByte(&first_byte
))
127 return 0; // Not valid DER as |in| was empty.
129 if (first_byte
== 0 && in
.Length() > 1)
130 return in
.Length() - 1;
136 bool ParseBool(const Input
& in
, bool* out
) {
137 return ParseBoolInternal(in
, out
, false /* relaxed */);
140 // BER interprets any non-zero value as true, while DER requires a bool to
141 // have either all bits zero (false) or all bits one (true). To support
142 // malformed certs, we recognized the BER encoding instead of failing to
144 bool ParseBoolRelaxed(const Input
& in
, bool* out
) {
145 return ParseBoolInternal(in
, out
, true /* relaxed */);
148 // ITU-T X.690 section 8.3.2 specifies that an integer value must be encoded
149 // in the smallest number of octets. If the encoding consists of more than
150 // one octet, then the bits of the first octet and the most significant bit
151 // of the second octet must not be all zeroes or all ones.
152 bool IsValidInteger(const Input
& in
, bool* negative
) {
153 der::ByteReader
reader(in
);
156 if (!reader
.ReadByte(&first_byte
))
157 return false; // Empty inputs are not allowed.
160 if (reader
.ReadByte(&second_byte
)) {
161 if ((first_byte
== 0x00 || first_byte
== 0xFF) &&
162 (first_byte
& 0x80) == (second_byte
& 0x80)) {
163 // Not a minimal encoding.
168 *negative
= (first_byte
& 0x80) == 0x80;
172 bool ParseUint64(const Input
& in
, uint64_t* out
) {
173 // Reject non-minimally encoded numbers and negative numbers.
175 if (!IsValidInteger(in
, &negative
) || negative
)
178 // Reject (non-negative) integers whose value would overflow the output type.
179 if (GetUnsignedIntegerLength(in
) > sizeof(*out
))
182 ByteReader
reader(in
);
186 while (reader
.ReadByte(&data
)) {
194 BitString::BitString(const Input
& bytes
, uint8_t unused_bits
)
195 : bytes_(bytes
), unused_bits_(unused_bits
) {
196 DCHECK_LT(unused_bits
, 8);
197 DCHECK(unused_bits
== 0 || bytes
.Length() != 0);
200 bool ParseBitString(const Input
& in
, BitString
* out
) {
201 ByteReader
reader(in
);
203 // From ITU-T X.690, section 8.6.2.2 (applies to BER, CER, DER):
205 // The initial octet shall encode, as an unsigned binary integer with
206 // bit 1 as the least significant bit, the number of unused bits in the final
207 // subsequent octet. The number shall be in the range zero to seven.
209 if (!reader
.ReadByte(&unused_bits
))
215 if (!reader
.ReadBytes(reader
.BytesLeft(), &bytes
))
216 return false; // Not reachable.
218 // Ensure that unused bits in the last byte are set to 0.
219 if (unused_bits
> 0) {
220 // From ITU-T X.690, section 8.6.2.3 (applies to BER, CER, DER):
222 // If the bitstring is empty, there shall be no subsequent octets,
223 // and the initial octet shall be zero.
224 if (bytes
.Length() == 0)
226 uint8_t last_byte
= bytes
.UnsafeData()[bytes
.Length() - 1];
228 // From ITU-T X.690, section 11.2.1 (applies to CER and DER, but not BER):
230 // Each unused bit in the final octet of the encoding of a bit string value
231 // shall be set to zero.
232 uint8_t mask
= 0xFF >> (8 - unused_bits
);
233 if ((mask
& last_byte
) != 0)
237 *out
= BitString(bytes
, unused_bits
);
241 bool operator<(const GeneralizedTime
& lhs
, const GeneralizedTime
& rhs
) {
242 if (lhs
.year
!= rhs
.year
)
243 return lhs
.year
< rhs
.year
;
244 if (lhs
.month
!= rhs
.month
)
245 return lhs
.month
< rhs
.month
;
246 if (lhs
.day
!= rhs
.day
)
247 return lhs
.day
< rhs
.day
;
248 if (lhs
.hours
!= rhs
.hours
)
249 return lhs
.hours
< rhs
.hours
;
250 if (lhs
.minutes
!= rhs
.minutes
)
251 return lhs
.minutes
< rhs
.minutes
;
252 return lhs
.seconds
< rhs
.seconds
;
255 // A UTC Time in DER encoding should be YYMMDDHHMMSSZ, but some CAs encode
256 // the time following BER rules, which allows for YYMMDDHHMMZ. If the length
257 // is 11, assume it's YYMMDDHHMMZ, and in converting it to a GeneralizedTime,
258 // add in the seconds (set to 0).
259 bool ParseUTCTimeRelaxed(const Input
& in
, GeneralizedTime
* value
) {
260 ByteReader
reader(in
);
261 GeneralizedTime time
;
262 if (!DecimalStringToUint(reader
, 2, &time
.year
) ||
263 !DecimalStringToUint(reader
, 2, &time
.month
) ||
264 !DecimalStringToUint(reader
, 2, &time
.day
) ||
265 !DecimalStringToUint(reader
, 2, &time
.hours
) ||
266 !DecimalStringToUint(reader
, 2, &time
.minutes
)) {
270 // Try to read the 'Z' at the end. If we read something else, then for it to
271 // be valid the next bytes should be seconds (and then followed by 'Z').
273 ByteReader zulu_reader
= reader
;
274 if (!zulu_reader
.ReadByte(&zulu
))
276 if (zulu
== 'Z' && !zulu_reader
.HasMore()) {
280 if (!DecimalStringToUint(reader
, 2, &time
.seconds
))
282 if (!reader
.ReadByte(&zulu
) || zulu
!= 'Z' || reader
.HasMore())
286 if (time
.year
< 50) {
291 if (!ValidateGeneralizedTime(time
))
297 bool ParseUTCTime(const Input
& in
, GeneralizedTime
* value
) {
298 ByteReader
reader(in
);
299 GeneralizedTime time
;
300 if (!DecimalStringToUint(reader
, 2, &time
.year
) ||
301 !DecimalStringToUint(reader
, 2, &time
.month
) ||
302 !DecimalStringToUint(reader
, 2, &time
.day
) ||
303 !DecimalStringToUint(reader
, 2, &time
.hours
) ||
304 !DecimalStringToUint(reader
, 2, &time
.minutes
) ||
305 !DecimalStringToUint(reader
, 2, &time
.seconds
)) {
309 if (!reader
.ReadByte(&zulu
) || zulu
!= 'Z' || reader
.HasMore())
311 if (time
.year
< 50) {
316 if (!ValidateGeneralizedTime(time
))
322 bool ParseGeneralizedTime(const Input
& in
, GeneralizedTime
* value
) {
323 ByteReader
reader(in
);
324 GeneralizedTime time
;
325 if (!DecimalStringToUint(reader
, 4, &time
.year
) ||
326 !DecimalStringToUint(reader
, 2, &time
.month
) ||
327 !DecimalStringToUint(reader
, 2, &time
.day
) ||
328 !DecimalStringToUint(reader
, 2, &time
.hours
) ||
329 !DecimalStringToUint(reader
, 2, &time
.minutes
) ||
330 !DecimalStringToUint(reader
, 2, &time
.seconds
)) {
334 if (!reader
.ReadByte(&zulu
) || zulu
!= 'Z' || reader
.HasMore())
336 if (!ValidateGeneralizedTime(time
))