Index: net/cert/internal/parse_certificate.cc |
diff --git a/net/cert/internal/parse_certificate.cc b/net/cert/internal/parse_certificate.cc |
index e04adb89d48640716b0d7c1002b71bbb0a8fdf9f..9535459bb8ad27ccb39b0807e24d210d4c5212ff 100644 |
--- a/net/cert/internal/parse_certificate.cc |
+++ b/net/cert/internal/parse_certificate.cc |
@@ -103,6 +103,75 @@ WARN_UNUSED_RESULT bool VerifySerialNumber(const der::Input& value) { |
return true; |
} |
+// Consumes a "Time" value (as defined by RFC 5280) from |parser|. On success |
+// writes the result to |*out| and returns true. On failure no guarantees are |
+// made about the state of |parser|. |
+// |
+// From RFC 5280: |
+// |
+// Time ::= CHOICE { |
+// utcTime UTCTime, |
+// generalTime GeneralizedTime } |
+WARN_UNUSED_RESULT bool ReadTime(der::Parser* parser, |
+ der::GeneralizedTime* out) { |
+ der::Input value; |
+ der::Tag tag; |
+ |
+ if (!parser->ReadTagAndValue(&tag, &value)) |
+ return false; |
+ |
+ if (tag == der::kUtcTime) |
+ return der::ParseUTCTime(value, out); |
+ |
+ if (tag == der::kGeneralizedTime) |
+ return der::ParseGeneralizedTime(value, out); |
+ |
+ // Unrecognized tag. |
+ return false; |
+} |
+ |
+// Parses a DER-encoded "Validity" as specified by RFC 5280. Returns true on |
+// success and sets the results in |not_before| and |not_after|: |
+// |
+// Validity ::= SEQUENCE { |
+// notBefore Time, |
+// notAfter Time } |
+// |
+// Note that upon success it is NOT guaranteed that |*not_before <= *not_after|. |
+bool ParseValidity(const der::Input& validity_tlv, |
+ der::GeneralizedTime* not_before, |
+ der::GeneralizedTime* not_after) { |
+ der::Parser parser(validity_tlv); |
+ |
+ // Validity ::= SEQUENCE { |
+ der::Parser validity_parser; |
+ if (!parser.ReadSequence(&validity_parser)) |
+ return false; |
+ |
+ // notBefore Time, |
+ if (!ReadTime(&validity_parser, not_before)) |
+ return false; |
+ |
+ // notAfter Time } |
+ if (!ReadTime(&validity_parser, not_after)) |
+ return false; |
+ |
+ // By definition the input was a single Validity sequence, so there shouldn't |
+ // be unconsumed data. |
+ if (parser.HasMore()) |
+ return false; |
+ |
+ // The Validity type does not have an extension point. |
+ if (validity_parser.HasMore()) |
+ return false; |
+ |
+ // Note that RFC 5280 doesn't require notBefore to be <= |
+ // notAfter, so that will not be considered a "parsing" error here. Instead it |
+ // will be considered an expired certificate later when testing against the |
+ // current timestamp. |
+ return true; |
+} |
+ |
} // namespace |
ParsedTbsCertificate::ParsedTbsCertificate() {} |
@@ -201,8 +270,13 @@ bool ParseTbsCertificate(const der::Input& tbs_tlv, ParsedTbsCertificate* out) { |
return false; |
// validity Validity, |
- if (!ReadSequenceTLV(&tbs_parser, &out->validity_tlv)) |
+ der::Input validity_tlv; |
+ if (!tbs_parser.ReadRawTLV(&validity_tlv)) |
+ return false; |
+ if (!ParseValidity(validity_tlv, &out->validity_not_before, |
+ &out->validity_not_after)) { |
return false; |
+ } |
// subject Name, |
if (!ReadSequenceTLV(&tbs_parser, &out->subject_tlv)) |