Index: webrtc/base/opensslidentity.cc |
diff --git a/webrtc/base/opensslidentity.cc b/webrtc/base/opensslidentity.cc |
index 7894b4887cd1e58d52ac0ea7e6324122358f4b56..658e1930c4d0eb28b6bbdf50ad7e9b166e3e0aad 100644 |
--- a/webrtc/base/opensslidentity.cc |
+++ b/webrtc/base/opensslidentity.cc |
@@ -8,6 +8,8 @@ |
* be found in the AUTHORS file in the root of the source tree. |
*/ |
+#include <ctime> |
hbos
2015/11/25 11:18:31
Move this to the other includes, everything else i
torbjorng (webrtc)
2015/11/25 14:27:11
Done.
|
+ |
#if HAVE_OPENSSL_SSL_H |
#include "webrtc/base/opensslidentity.h" |
@@ -130,9 +132,18 @@ static X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) { |
!X509_set_issuer_name(x509, name)) |
goto error; |
- if (!X509_gmtime_adj(X509_get_notBefore(x509), params.not_before) || |
- !X509_gmtime_adj(X509_get_notAfter(x509), params.not_after)) |
+ if (params.absolute_time) { |
+ time_t zero = 0; // Make time epoch based. |
+ if (!X509_time_adj_ex(X509_get_notBefore(x509), 0, params.not_before, |
+ &zero) || |
+ !X509_time_adj_ex(X509_get_notAfter(x509), 0, params.not_after, &zero)) |
+ goto error; |
+ } else { |
+ if (!X509_time_adj_ex(X509_get_notBefore(x509), 0, params.not_before, |
+ NULL) || |
+ !X509_time_adj_ex(X509_get_notAfter(x509), 0, params.not_after, NULL)) |
goto error; |
+ } |
if (!X509_sign(x509, pkey, EVP_sha256())) |
goto error; |
@@ -373,6 +384,109 @@ void OpenSSLCertificate::AddReference() const { |
#endif |
} |
+// Convert from std::tm to number of seconds from epoch. |
+// Note that std::tm is relative to 1900-01-01. |
+static int64_t tm_to_seconds(const std::tm& tm) { |
+ static short int cumul_days[12] = {0, 31, 59, 90, 120, 151, |
+ 181, 212, 243, 273, 304, 334}; |
+ |
+ int year = tm.tm_year + 1900; |
+ int month = tm.tm_mon; |
+ int day = tm.tm_mday - 1; |
+ int hour = tm.tm_hour; |
+ int min = tm.tm_min; |
+ int sec = tm.tm_sec; |
+ |
+ // If expiration time is in a leap year, number of days depends on exact date. |
+ if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) { |
+ if (month <= 2 - 1) { // February or earlier (|month| is zero based). |
+ day -= 1; |
+ } |
+ } |
+ |
+ day += cumul_days[month]; |
+ |
+ // Add number of leap days between 1970 and the expiration time. |
+ day += ((year / 4 - 1970 / 4) - (year / 100 - 1970 / 100) + |
+ (year / 400 - 1970 / 400)); |
+ |
+ year -= 1970; |
+ return ((((int64_t)year * 365 + day) * 24 + hour) * 60 + min) * 60 + sec; |
+} |
+ |
+#define ASN1_READ2(x) \ |
+ do { \ |
+ x = 10 * s[0] + s[1] - '0' * 11; \ |
+ s += 2; \ |
+ bytes_left -= 2; \ |
+ } while (0) |
+#define ASN1_READ4(x) \ |
+ do { \ |
+ x = 1000 * s[0] + 100 * s[1] + 10 * s[2] + s[3] - '0' * 1111; \ |
+ s += 4; \ |
+ bytes_left -= 4; \ |
+ } while (0) |
+ |
+// Convert from ASN1 TIME as restricted by RFC 5280 to milliseconds from epoch. |
+// If the ASN1_TIME cannot be read, return -1. Use std::tm for intermediate |
+// results in the way specified by Unix time functions. |
+static int64_t asn1_time_to_time_t(const ASN1_TIME* time) { |
+ std::tm tm; |
+ int year; |
+ int month; |
+ const unsigned char* s = (const unsigned char*)time->data; |
+ size_t bytes_left = time->length; |
+ |
+ if (time->type == V_ASN1_UTCTIME) { |
+ // ASN1 format: yymmddhhmm[ss]Z where the Z is literal, but RFC 5280 only |
+ // requires us to support exactly yymmddhhmmssZ. |
+ |
+ if (bytes_left < 9) |
+ return -1; |
+ |
+ ASN1_READ2(year); |
+ if (year < 70) |
+ year += 100; |
+ } else if (time->type == V_ASN1_GENERALIZEDTIME) { |
+ // ASN1 format: yyyymmddhh[mm[ss[.fff]]]Z where the Z is literal. but |
+ // RFC 5280 only requires us to support exactly yyyymmddhhmmssZ. |
+ |
+ if (bytes_left < 11) |
+ return -1; |
+ |
+ ASN1_READ4(year); |
+ year -= 1900; |
+ } else { |
+ return -1; |
+ } |
+ |
+ // Zeroing the entire structure helps with the defaulting of the minute and |
+ // second fields, as well as a bunch of other (here unused) fields. |
+ memset(&tm, 0, sizeof(tm)); |
+ |
+ tm.tm_year = year; |
+ ASN1_READ2(month); |
+ tm.tm_mon = month - 1; |
+ ASN1_READ2(tm.tm_mday); |
+ ASN1_READ2(tm.tm_hour); |
+ ASN1_READ2(tm.tm_min); |
+ ASN1_READ2(tm.tm_sec); |
+ |
+ if (bytes_left != 1 || s[0] != 'Z') { |
+ // A final Z means UTC, mandated by RFC 5280, and compatible with OpenSSL. |
+ return -1; |
+ } |
+ |
+ return 1000 * tm_to_seconds(tm); |
+} |
+#undef ASN1_READ4 |
+#undef ASN1_READ2 |
+ |
+int64_t OpenSSLCertificate::CertificateExpirationTime() const { |
+ ASN1_TIME* exptime = X509_get_notAfter(x509_); |
+ return asn1_time_to_time_t(exptime); |
+} |
+ |
OpenSSLIdentity::OpenSSLIdentity(OpenSSLKeyPair* key_pair, |
OpenSSLCertificate* certificate) |
: key_pair_(key_pair), certificate_(certificate) { |
@@ -401,6 +515,7 @@ OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name, |
SSLIdentityParams params; |
params.key_params = key_params; |
params.common_name = common_name; |
+ params.absolute_time = false; |
params.not_before = CERTIFICATE_WINDOW; |
params.not_after = CERTIFICATE_LIFETIME; |
return GenerateInternal(params); |