| // Copyright 2015 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "net/der/parse_values.h" | 
 |  | 
 | #include <tuple> | 
 |  | 
 | #include "base/logging.h" | 
 |  | 
 | namespace net { | 
 |  | 
 | namespace der { | 
 |  | 
 | namespace { | 
 |  | 
 | bool ParseBoolInternal(const Input& in, bool* out, bool relaxed) { | 
 |   // According to ITU-T X.690 section 8.2, a bool is encoded as a single octet | 
 |   // where the octet of all zeroes is FALSE and a non-zero value for the octet | 
 |   // is TRUE. | 
 |   if (in.Length() != 1) | 
 |     return false; | 
 |   ByteReader data(in); | 
 |   uint8_t byte; | 
 |   if (!data.ReadByte(&byte)) | 
 |     return false; | 
 |   if (byte == 0) { | 
 |     *out = false; | 
 |     return true; | 
 |   } | 
 |   // ITU-T X.690 section 11.1 specifies that for DER, the TRUE value must be | 
 |   // encoded as an octet of all ones. | 
 |   if (byte == 0xff || relaxed) { | 
 |     *out = true; | 
 |     return true; | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | // Reads a positive decimal number with |digits| digits and stores it in | 
 | // |*out|. This function does not check that the type of |*out| is large | 
 | // enough to hold 10^digits - 1; the caller must choose an appropriate type | 
 | // based on the number of digits they wish to parse. | 
 | template <typename UINT> | 
 | bool DecimalStringToUint(ByteReader& in, size_t digits, UINT* out) { | 
 |   UINT value = 0; | 
 |   for (size_t i = 0; i < digits; ++i) { | 
 |     uint8_t digit; | 
 |     if (!in.ReadByte(&digit)) { | 
 |       return false; | 
 |     } | 
 |     if (digit < '0' || digit > '9') { | 
 |       return false; | 
 |     } | 
 |     value = (value * 10) + (digit - '0'); | 
 |   } | 
 |   *out = value; | 
 |   return true; | 
 | } | 
 |  | 
 | // Checks that the values in a GeneralizedTime struct are valid. This involves | 
 | // checking that the year is 4 digits, the month is between 1 and 12, the day | 
 | // is a day that exists in that month (following current leap year rules), | 
 | // hours are between 0 and 23, minutes between 0 and 59, and seconds between | 
 | // 0 and 60 (to allow for leap seconds; no validation is done that a leap | 
 | // second is on a day that could be a leap second). | 
 | bool ValidateGeneralizedTime(const GeneralizedTime& time) { | 
 |   if (time.month < 1 || time.month > 12) | 
 |     return false; | 
 |   if (time.day < 1) | 
 |     return false; | 
 |   if (time.hours < 0 || time.hours > 23) | 
 |     return false; | 
 |   if (time.minutes < 0 || time.minutes > 59) | 
 |     return false; | 
 |   // Leap seconds are allowed. | 
 |   if (time.seconds < 0 || time.seconds > 60) | 
 |     return false; | 
 |  | 
 |   // validate upper bound for day of month | 
 |   switch (time.month) { | 
 |     case 4: | 
 |     case 6: | 
 |     case 9: | 
 |     case 11: | 
 |       if (time.day > 30) | 
 |         return false; | 
 |       break; | 
 |     case 1: | 
 |     case 3: | 
 |     case 5: | 
 |     case 7: | 
 |     case 8: | 
 |     case 10: | 
 |     case 12: | 
 |       if (time.day > 31) | 
 |         return false; | 
 |       break; | 
 |     case 2: | 
 |       if (time.year % 4 == 0 && | 
 |           (time.year % 100 != 0 || time.year % 400 == 0)) { | 
 |         if (time.day > 29) | 
 |           return false; | 
 |       } else { | 
 |         if (time.day > 28) | 
 |           return false; | 
 |       } | 
 |       break; | 
 |     default: | 
 |       NOTREACHED(); | 
 |       return false; | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | // Returns the number of bytes of numeric precision in a DER encoded INTEGER | 
 | // value. |in| must be a valid DER encoding of an INTEGER for this to work. | 
 | // | 
 | // Normally the precision of the number is exactly in.Length(). However when | 
 | // encoding positive numbers using DER it is possible to have a leading zero | 
 | // (to prevent number from being interpreted as negative). | 
 | // | 
 | // For instance a 160-bit positive number might take 21 bytes to encode. This | 
 | // function will return 20 in such a case. | 
 | size_t GetUnsignedIntegerLength(const Input& in) { | 
 |   der::ByteReader reader(in); | 
 |   uint8_t first_byte; | 
 |   if (!reader.ReadByte(&first_byte)) | 
 |     return 0;  // Not valid DER  as |in| was empty. | 
 |  | 
 |   if (first_byte == 0 && in.Length() > 1) | 
 |     return in.Length() - 1; | 
 |   return in.Length(); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | bool ParseBool(const Input& in, bool* out) { | 
 |   return ParseBoolInternal(in, out, false /* relaxed */); | 
 | } | 
 |  | 
 | // BER interprets any non-zero value as true, while DER requires a bool to | 
 | // have either all bits zero (false) or all bits one (true). To support | 
 | // malformed certs, we recognized the BER encoding instead of failing to | 
 | // parse. | 
 | bool ParseBoolRelaxed(const Input& in, bool* out) { | 
 |   return ParseBoolInternal(in, out, true /* relaxed */); | 
 | } | 
 |  | 
 | // ITU-T X.690 section 8.3.2 specifies that an integer value must be encoded | 
 | // in the smallest number of octets. If the encoding consists of more than | 
 | // one octet, then the bits of the first octet and the most significant bit | 
 | // of the second octet must not be all zeroes or all ones. | 
 | bool IsValidInteger(const Input& in, bool* negative) { | 
 |   der::ByteReader reader(in); | 
 |   uint8_t first_byte; | 
 |  | 
 |   if (!reader.ReadByte(&first_byte)) | 
 |     return false;  // Empty inputs are not allowed. | 
 |  | 
 |   uint8_t second_byte; | 
 |   if (reader.ReadByte(&second_byte)) { | 
 |     if ((first_byte == 0x00 || first_byte == 0xFF) && | 
 |         (first_byte & 0x80) == (second_byte & 0x80)) { | 
 |       // Not a minimal encoding. | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   *negative = (first_byte & 0x80) == 0x80; | 
 |   return true; | 
 | } | 
 |  | 
 | bool ParseUint64(const Input& in, uint64_t* out) { | 
 |   // Reject non-minimally encoded numbers and negative numbers. | 
 |   bool negative; | 
 |   if (!IsValidInteger(in, &negative) || negative) | 
 |     return false; | 
 |  | 
 |   // Reject (non-negative) integers whose value would overflow the output type. | 
 |   if (GetUnsignedIntegerLength(in) > sizeof(*out)) | 
 |     return false; | 
 |  | 
 |   ByteReader reader(in); | 
 |   uint8_t data; | 
 |   uint64_t value = 0; | 
 |  | 
 |   while (reader.ReadByte(&data)) { | 
 |     value <<= 8; | 
 |     value |= data; | 
 |   } | 
 |   *out = value; | 
 |   return true; | 
 | } | 
 |  | 
 | bool ParseUint8(const Input& in, uint8_t* out) { | 
 |   // TODO(eroman): Implement this more directly. | 
 |   uint64_t value; | 
 |   if (!ParseUint64(in, &value)) | 
 |     return false; | 
 |  | 
 |   if (value > 0xFF) | 
 |     return false; | 
 |  | 
 |   *out = static_cast<uint8_t>(value); | 
 |   return true; | 
 | } | 
 |  | 
 | BitString::BitString(const Input& bytes, uint8_t unused_bits) | 
 |     : bytes_(bytes), unused_bits_(unused_bits) { | 
 |   DCHECK_LT(unused_bits, 8); | 
 |   DCHECK(unused_bits == 0 || bytes.Length() != 0); | 
 |   // The unused bits must be zero. | 
 |   DCHECK(bytes.Length() == 0 || | 
 |          (bytes.UnsafeData()[bytes.Length() - 1] & ((1u << unused_bits) - 1)) == | 
 |              0); | 
 | } | 
 |  | 
 | bool BitString::AssertsBit(size_t bit_index) const { | 
 |   // Index of the byte that contains the bit. | 
 |   size_t byte_index = bit_index / 8; | 
 |  | 
 |   // If the bit is outside of the bitstring, by definition it is not | 
 |   // asserted. | 
 |   if (byte_index >= bytes_.Length()) | 
 |     return false; | 
 |  | 
 |   // Within a byte, bits are ordered from most significant to least significant. | 
 |   // Convert |bit_index| to an index within the |byte_index| byte, measured from | 
 |   // its least significant bit. | 
 |   uint8_t bit_index_in_byte = 7 - (bit_index - byte_index * 8); | 
 |  | 
 |   // BIT STRING parsing already guarantees that unused bits in a byte are zero | 
 |   // (otherwise it wouldn't be valid DER). Therefore it isn't necessary to check | 
 |   // |unused_bits_| | 
 |   uint8_t byte = bytes_.UnsafeData()[byte_index]; | 
 |   return 0 != (byte & (1 << bit_index_in_byte)); | 
 | } | 
 |  | 
 | bool ParseBitString(const Input& in, BitString* out) { | 
 |   ByteReader reader(in); | 
 |  | 
 |   // From ITU-T X.690, section 8.6.2.2 (applies to BER, CER, DER): | 
 |   // | 
 |   // The initial octet shall encode, as an unsigned binary integer with | 
 |   // bit 1 as the least significant bit, the number of unused bits in the final | 
 |   // subsequent octet. The number shall be in the range zero to seven. | 
 |   uint8_t unused_bits; | 
 |   if (!reader.ReadByte(&unused_bits)) | 
 |     return false; | 
 |   if (unused_bits > 7) | 
 |     return false; | 
 |  | 
 |   Input bytes; | 
 |   if (!reader.ReadBytes(reader.BytesLeft(), &bytes)) | 
 |     return false;  // Not reachable. | 
 |  | 
 |   // Ensure that unused bits in the last byte are set to 0. | 
 |   if (unused_bits > 0) { | 
 |     // From ITU-T X.690, section 8.6.2.3 (applies to BER, CER, DER): | 
 |     // | 
 |     // If the bitstring is empty, there shall be no subsequent octets, | 
 |     // and the initial octet shall be zero. | 
 |     if (bytes.Length() == 0) | 
 |       return false; | 
 |     uint8_t last_byte = bytes.UnsafeData()[bytes.Length() - 1]; | 
 |  | 
 |     // From ITU-T X.690, section 11.2.1 (applies to CER and DER, but not BER): | 
 |     // | 
 |     // Each unused bit in the final octet of the encoding of a bit string value | 
 |     // shall be set to zero. | 
 |     uint8_t mask = 0xFF >> (8 - unused_bits); | 
 |     if ((mask & last_byte) != 0) | 
 |       return false; | 
 |   } | 
 |  | 
 |   *out = BitString(bytes, unused_bits); | 
 |   return true; | 
 | } | 
 |  | 
 | bool GeneralizedTime::InUTCTimeRange() const { | 
 |   return 1950 <= year && year < 2050; | 
 | } | 
 |  | 
 | bool operator<(const GeneralizedTime& lhs, const GeneralizedTime& rhs) { | 
 |   return std::tie(lhs.year, lhs.month, lhs.day, lhs.hours, lhs.minutes, | 
 |                   lhs.seconds) < std::tie(rhs.year, rhs.month, rhs.day, | 
 |                                           rhs.hours, rhs.minutes, rhs.seconds); | 
 | } | 
 |  | 
 | bool operator>(const GeneralizedTime& lhs, const GeneralizedTime& rhs) { | 
 |   return rhs < lhs; | 
 | } | 
 |  | 
 | bool operator<=(const GeneralizedTime& lhs, const GeneralizedTime& rhs) { | 
 |   return !(lhs > rhs); | 
 | } | 
 |  | 
 | bool operator>=(const GeneralizedTime& lhs, const GeneralizedTime& rhs) { | 
 |   return !(lhs < rhs); | 
 | } | 
 |  | 
 | // A UTC Time in DER encoding should be YYMMDDHHMMSSZ, but some CAs encode | 
 | // the time following BER rules, which allows for YYMMDDHHMMZ. If the length | 
 | // is 11, assume it's YYMMDDHHMMZ, and in converting it to a GeneralizedTime, | 
 | // add in the seconds (set to 0). | 
 | bool ParseUTCTimeRelaxed(const Input& in, GeneralizedTime* value) { | 
 |   ByteReader reader(in); | 
 |   GeneralizedTime time; | 
 |   if (!DecimalStringToUint(reader, 2, &time.year) || | 
 |       !DecimalStringToUint(reader, 2, &time.month) || | 
 |       !DecimalStringToUint(reader, 2, &time.day) || | 
 |       !DecimalStringToUint(reader, 2, &time.hours) || | 
 |       !DecimalStringToUint(reader, 2, &time.minutes)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Try to read the 'Z' at the end. If we read something else, then for it to | 
 |   // be valid the next bytes should be seconds (and then followed by 'Z'). | 
 |   uint8_t zulu; | 
 |   ByteReader zulu_reader = reader; | 
 |   if (!zulu_reader.ReadByte(&zulu)) | 
 |     return false; | 
 |   if (zulu == 'Z' && !zulu_reader.HasMore()) { | 
 |     time.seconds = 0; | 
 |     *value = time; | 
 |   } else { | 
 |     if (!DecimalStringToUint(reader, 2, &time.seconds)) | 
 |       return false; | 
 |     if (!reader.ReadByte(&zulu) || zulu != 'Z' || reader.HasMore()) | 
 |       return false; | 
 |   } | 
 |  | 
 |   if (time.year < 50) { | 
 |     time.year += 2000; | 
 |   } else { | 
 |     time.year += 1900; | 
 |   } | 
 |   if (!ValidateGeneralizedTime(time)) | 
 |     return false; | 
 |   *value = time; | 
 |   return true; | 
 | } | 
 |  | 
 | bool ParseUTCTime(const Input& in, GeneralizedTime* value) { | 
 |   ByteReader reader(in); | 
 |   GeneralizedTime time; | 
 |   if (!DecimalStringToUint(reader, 2, &time.year) || | 
 |       !DecimalStringToUint(reader, 2, &time.month) || | 
 |       !DecimalStringToUint(reader, 2, &time.day) || | 
 |       !DecimalStringToUint(reader, 2, &time.hours) || | 
 |       !DecimalStringToUint(reader, 2, &time.minutes) || | 
 |       !DecimalStringToUint(reader, 2, &time.seconds)) { | 
 |     return false; | 
 |   } | 
 |   uint8_t zulu; | 
 |   if (!reader.ReadByte(&zulu) || zulu != 'Z' || reader.HasMore()) | 
 |     return false; | 
 |   if (time.year < 50) { | 
 |     time.year += 2000; | 
 |   } else { | 
 |     time.year += 1900; | 
 |   } | 
 |   if (!ValidateGeneralizedTime(time)) | 
 |     return false; | 
 |   *value = time; | 
 |   return true; | 
 | } | 
 |  | 
 | bool ParseGeneralizedTime(const Input& in, GeneralizedTime* value) { | 
 |   ByteReader reader(in); | 
 |   GeneralizedTime time; | 
 |   if (!DecimalStringToUint(reader, 4, &time.year) || | 
 |       !DecimalStringToUint(reader, 2, &time.month) || | 
 |       !DecimalStringToUint(reader, 2, &time.day) || | 
 |       !DecimalStringToUint(reader, 2, &time.hours) || | 
 |       !DecimalStringToUint(reader, 2, &time.minutes) || | 
 |       !DecimalStringToUint(reader, 2, &time.seconds)) { | 
 |     return false; | 
 |   } | 
 |   uint8_t zulu; | 
 |   if (!reader.ReadByte(&zulu) || zulu != 'Z' || reader.HasMore()) | 
 |     return false; | 
 |   if (!ValidateGeneralizedTime(time)) | 
 |     return false; | 
 |   *value = time; | 
 |   return true; | 
 | } | 
 |  | 
 | }  // namespace der | 
 |  | 
 | }  // namespace net |