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

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 fixes. 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..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);

Powered by Google App Engine
This is Rietveld 408576698