Index: net/cert/internal/parse_certificate.cc |
diff --git a/net/cert/internal/parse_certificate.cc b/net/cert/internal/parse_certificate.cc |
index 3a04e3ad17977feca5d1756286421d871fb9578b..e790d8a7e043cecfbec838301a549b3d8f95a82a 100644 |
--- a/net/cert/internal/parse_certificate.cc |
+++ b/net/cert/internal/parse_certificate.cc |
@@ -124,6 +124,37 @@ 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; |
+ |
+ // TODO(eroman): Justify using the "relaxed" flavor rather |
+ // than strict. The CT database of certificates do not |
+ // require the relaxed parsing, however certificates in the |
+ // wild may. |
davidben
2015/08/18 17:24:27
Nit: This probably can be word-wrapped more loosel
davidben
2015/08/18 17:24:27
[If we don't have example certs, where did this be
eroman
2015/08/18 17:34:51
I am not sure, I will ask Nick about the history.
|
+ if (tag == der::kUtcTime) |
+ return der::ParseUTCTimeRelaxed(value, out); |
+ |
+ if (tag == der::kGeneralizedTime) |
+ return der::ParseGeneralizedTime(value, out); |
+ |
+ // Unrecognized tag. |
+ return false; |
+} |
+ |
} // namespace |
ParsedTbsCertificate::ParsedTbsCertificate() |
@@ -304,4 +335,43 @@ bool ParseTbsCertificate(const der::Input& tbs_tlv, ParsedTbsCertificate* out) { |
return true; |
} |
+// From RFC 5280: |
+// |
+// Validity ::= SEQUENCE { |
+// notBefore Time, |
+// notAfter Time } |
+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 net |