Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(380)

Unified Diff: webrtc/base/opensslidentity.cc

Issue 1468273004: Provide method for returning certificate expiration timestamp. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Misc CL cleanups Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
}

Powered by Google App Engine
This is Rietveld 408576698