Index: webrtc/base/sslidentity.cc |
diff --git a/webrtc/base/sslidentity.cc b/webrtc/base/sslidentity.cc |
index 180e60c58bbdeea6f67bab7331d93d6cba88dda6..5f6b6869dd4db39cea25207532b41f6739255864 100644 |
--- a/webrtc/base/sslidentity.cc |
+++ b/webrtc/base/sslidentity.cc |
@@ -15,6 +15,7 @@ |
#include "webrtc/base/sslidentity.h" |
+#include <ctime> |
#include <string> |
#include "webrtc/base/base64.h" |
@@ -177,4 +178,74 @@ SSLIdentity* SSLIdentity::FromPEMStrings(const std::string& private_key, |
#endif // SSL_USE_OPENSSL |
+// Read |n| bytes from ASN1 number string at *|pp| and return the numeric value. |
+// Update *|pp| and *|np| to reflect number of read bytes. |
+static inline int ASN1ReadInt(const unsigned char** pp, size_t* np, size_t n) { |
+ const unsigned char* p = *pp; |
+ int x = 0; |
+ for (size_t i = 0; i < n; i++) |
+ x = 10 * x + p[i] - '0'; |
+ *pp = p + n; |
+ *np = *np - n; |
+ return x; |
+} |
+ |
+int64_t ASN1TimeToSec(const unsigned char* s, size_t length, bool long_format) { |
+ size_t bytes_left = length; |
+ |
+ // Make sure the string ends with Z. Doing it here protects the strspn call |
+ // from running off the end of the string in Z's absense. |
+ if (length == 0 || s[length - 1] != 'Z') |
+ return -1; |
+ |
+ // Make sure we only have ASCII digits so that we don't need to clutter the |
+ // code below and ASN1ReadInt with error checking. |
+ size_t n = strspn(reinterpret_cast<const char*>(s), "0123456789"); |
+ if (n + 1 != length) |
+ return -1; |
+ |
+ int year; |
+ |
+ // Read out ASN1 year, in either 2-char "UTCTIME" or 4-char "GENERALIZEDTIME" |
+ // format. Both format use UTC in this context. |
+ if (long_format) { |
+ // ASN1 format: yyyymmddhh[mm[ss[.fff]]]Z where the Z is literal, but |
+ // RFC 5280 requires us to only support exactly yyyymmddhhmmssZ. |
+ |
+ if (bytes_left < 11) |
+ return -1; |
+ |
+ year = ASN1ReadInt(&s, &bytes_left, 4); |
+ year -= 1900; |
+ } else { |
+ // ASN1 format: yymmddhhmm[ss]Z where the Z is literal, but RFC 5280 |
+ // requires us to only support exactly yymmddhhmmssZ. |
+ |
+ if (bytes_left < 9) |
+ return -1; |
+ |
+ year = ASN1ReadInt(&s, &bytes_left, 2); |
+ if (year < 50) // Per RFC 5280 4.1.2.5.1 |
+ year += 100; |
+ } |
+ |
+ std::tm tm; |
+ tm.tm_year = year; |
+ |
+ // Read out remaining ASN1 time data and store it in |tm| in documented |
+ // std::tm format. |
+ tm.tm_mon = ASN1ReadInt(&s, &bytes_left, 2) - 1; |
+ tm.tm_mday = ASN1ReadInt(&s, &bytes_left, 2); |
+ tm.tm_hour = ASN1ReadInt(&s, &bytes_left, 2); |
+ tm.tm_min = ASN1ReadInt(&s, &bytes_left, 2); |
+ tm.tm_sec = ASN1ReadInt(&s, &bytes_left, 2); |
+ |
+ if (bytes_left != 1) { |
+ // Now just Z should remain. Its existence was asserted above. |
+ return -1; |
+ } |
+ |
+ return TmToSeconds(tm); |
+} |
+ |
} // namespace rtc |