Index: webrtc/base/opensslidentity.cc |
diff --git a/webrtc/base/opensslidentity.cc b/webrtc/base/opensslidentity.cc |
index 7894b4887cd1e58d52ac0ea7e6324122358f4b56..9373309550b0cd096f7f63811e3eb872f0dd8110 100644 |
--- a/webrtc/base/opensslidentity.cc |
+++ b/webrtc/base/opensslidentity.cc |
@@ -10,6 +10,8 @@ |
#if HAVE_OPENSSL_SSL_H |
+#include <ctime> |
hbos
2015/11/25 15:21:44
The first include should be opensslidentity.h. I w
torbjorng (webrtc)
2015/11/25 19:14:09
Done.
|
+ |
#include "webrtc/base/opensslidentity.h" |
// Must be included first before openssl headers. |
@@ -96,6 +98,7 @@ static X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) { |
X509* x509 = NULL; |
BIGNUM* serial_number = NULL; |
X509_NAME* name = NULL; |
+ time_t epoch_off = 0; // Time offset since epoch. |
hbos
2015/11/25 15:21:44
nit/optional: Is it a style in this file or person
torbjorng (webrtc)
2015/11/25 19:14:09
Since it sets a value and since the function is fu
|
if ((x509=X509_new()) == NULL) |
goto error; |
@@ -130,8 +133,8 @@ 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 (!X509_time_adj(X509_get_notBefore(x509), params.not_before, &epoch_off) || |
+ !X509_time_adj(X509_get_notAfter(x509), params.not_after, &epoch_off)) |
goto error; |
if (!X509_sign(x509, pkey, EVP_sha256())) |
@@ -373,6 +376,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 TmToSeconds(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; |
hbos
2015/11/25 15:21:44
I think style guide says static_cast<int64_t> inst
torbjorng (webrtc)
2015/11/25 19:14:09
Done.
|
+} |
+ |
+#define ASN1_READ2(x, s, n) \ |
+ do { \ |
+ x = 10 * s[0] + s[1] - '0' * 11; \ |
+ s += 2; \ |
+ n -= 2; \ |
+ } while (0) |
+#define ASN1_READ4(x, s, n) \ |
+ do { \ |
+ x = 1000 * s[0] + 100 * s[1] + 10 * s[2] + s[3] - '0' * 1111; \ |
+ s += 4; \ |
+ n -= 4; \ |
+ } while (0) |
hbos
2015/11/25 15:21:44
Macros are the devil. I think these should be func
|
+ |
+// 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 ASN1TimeToMS(const ASN1_TIME* time) { |
+ std::tm tm; |
+ int year; |
+ int month; |
+ const unsigned char* s = (const unsigned char*)time->data; |
hbos
2015/11/25 15:21:44
Style guide: use static_cast. Wait, isn't this an
torbjorng (webrtc)
2015/11/25 19:14:09
Done.
|
+ size_t bytes_left = time->length; |
hbos
2015/11/25 15:21:44
size_t is what should be used for stuff like this
torbjorng (webrtc)
2015/11/25 19:14:09
OpenSSL uses 'int' for sizes. I expect that to ge
|
+ |
+ if (time->type == V_ASN1_UTCTIME) { |
+ // 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; |
+ |
+ ASN1_READ2(year, s, bytes_left); |
+ 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 requires us to only support exactly yyyymmddhhmmssZ. |
+ |
+ if (bytes_left < 11) |
+ return -1; |
+ |
+ ASN1_READ4(year, s, bytes_left); |
+ 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, s, bytes_left); |
+ tm.tm_mon = month - 1; |
+ ASN1_READ2(tm.tm_mday, s, bytes_left); |
+ ASN1_READ2(tm.tm_hour, s, bytes_left); |
+ ASN1_READ2(tm.tm_min, s, bytes_left); |
+ ASN1_READ2(tm.tm_sec, s, bytes_left); |
hbos
2015/11/25 15:21:44
A short comment here and/or at the function defini
torbjorng (webrtc)
2015/11/25 19:14:09
Done.
|
+ |
+ if (bytes_left != 1 || s[0] != 'Z') { |
+ // A final Z means UTC, mandated by RFC 5280, and compatible with OpenSSL. |
+ return -1; |
+ } |
+ |
+ return 1000 * TmToSeconds(tm); |
+} |
+#undef ASN1_READ4 |
+#undef ASN1_READ2 |
+ |
+int64_t OpenSSLCertificate::CertificateExpirationTime() const { |
+ ASN1_TIME* exptime = X509_get_notAfter(x509_); |
+ return ASN1TimeToMS(exptime); |
+} |
+ |
OpenSSLIdentity::OpenSSLIdentity(OpenSSLKeyPair* key_pair, |
OpenSSLCertificate* certificate) |
: key_pair_(key_pair), certificate_(certificate) { |
@@ -401,8 +507,9 @@ OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name, |
SSLIdentityParams params; |
params.key_params = key_params; |
params.common_name = common_name; |
- params.not_before = CERTIFICATE_WINDOW; |
- params.not_after = CERTIFICATE_LIFETIME; |
+ time_t now = time(NULL); |
+ params.not_before = now + CERTIFICATE_WINDOW; |
+ params.not_after = now + CERTIFICATE_LIFETIME; |
return GenerateInternal(params); |
} |