aboutsummaryrefslogtreecommitdiff
path: root/webrtc/base/sslidentity.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/base/sslidentity.cc')
-rw-r--r--webrtc/base/sslidentity.cc71
1 files changed, 71 insertions, 0 deletions
diff --git a/webrtc/base/sslidentity.cc b/webrtc/base/sslidentity.cc
index 180e60c58b..5f6b6869dd 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