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

Side by Side 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 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #if HAVE_OPENSSL_SSL_H 11 #if HAVE_OPENSSL_SSL_H
12 12
13 #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.
14
13 #include "webrtc/base/opensslidentity.h" 15 #include "webrtc/base/opensslidentity.h"
14 16
15 // Must be included first before openssl headers. 17 // Must be included first before openssl headers.
16 #include "webrtc/base/win32.h" // NOLINT 18 #include "webrtc/base/win32.h" // NOLINT
17 19
18 #include <openssl/bio.h> 20 #include <openssl/bio.h>
19 #include <openssl/err.h> 21 #include <openssl/err.h>
20 #include <openssl/pem.h> 22 #include <openssl/pem.h>
21 #include <openssl/bn.h> 23 #include <openssl/bn.h>
22 #include <openssl/rsa.h> 24 #include <openssl/rsa.h>
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 return pkey; 91 return pkey;
90 } 92 }
91 93
92 // Generate a self-signed certificate, with the public key from the 94 // Generate a self-signed certificate, with the public key from the
93 // given key pair. Caller is responsible for freeing the returned object. 95 // given key pair. Caller is responsible for freeing the returned object.
94 static X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) { 96 static X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) {
95 LOG(LS_INFO) << "Making certificate for " << params.common_name; 97 LOG(LS_INFO) << "Making certificate for " << params.common_name;
96 X509* x509 = NULL; 98 X509* x509 = NULL;
97 BIGNUM* serial_number = NULL; 99 BIGNUM* serial_number = NULL;
98 X509_NAME* name = NULL; 100 X509_NAME* name = NULL;
101 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
99 102
100 if ((x509=X509_new()) == NULL) 103 if ((x509=X509_new()) == NULL)
101 goto error; 104 goto error;
102 105
103 if (!X509_set_pubkey(x509, pkey)) 106 if (!X509_set_pubkey(x509, pkey))
104 goto error; 107 goto error;
105 108
106 // serial number 109 // serial number
107 // temporary reference to serial number inside x509 struct 110 // temporary reference to serial number inside x509 struct
108 ASN1_INTEGER* asn1_serial_number; 111 ASN1_INTEGER* asn1_serial_number;
(...skipping 14 matching lines...) Expand all
123 // clear during SSL negotiation, so there may be a privacy issue in 126 // clear during SSL negotiation, so there may be a privacy issue in
124 // putting anything recognizable here. 127 // putting anything recognizable here.
125 if ((name = X509_NAME_new()) == NULL || 128 if ((name = X509_NAME_new()) == NULL ||
126 !X509_NAME_add_entry_by_NID( 129 !X509_NAME_add_entry_by_NID(
127 name, NID_commonName, MBSTRING_UTF8, 130 name, NID_commonName, MBSTRING_UTF8,
128 (unsigned char*)params.common_name.c_str(), -1, -1, 0) || 131 (unsigned char*)params.common_name.c_str(), -1, -1, 0) ||
129 !X509_set_subject_name(x509, name) || 132 !X509_set_subject_name(x509, name) ||
130 !X509_set_issuer_name(x509, name)) 133 !X509_set_issuer_name(x509, name))
131 goto error; 134 goto error;
132 135
133 if (!X509_gmtime_adj(X509_get_notBefore(x509), params.not_before) || 136 if (!X509_time_adj(X509_get_notBefore(x509), params.not_before, &epoch_off) ||
134 !X509_gmtime_adj(X509_get_notAfter(x509), params.not_after)) 137 !X509_time_adj(X509_get_notAfter(x509), params.not_after, &epoch_off))
135 goto error; 138 goto error;
136 139
137 if (!X509_sign(x509, pkey, EVP_sha256())) 140 if (!X509_sign(x509, pkey, EVP_sha256()))
138 goto error; 141 goto error;
139 142
140 BN_free(serial_number); 143 BN_free(serial_number);
141 X509_NAME_free(name); 144 X509_NAME_free(name);
142 LOG(LS_INFO) << "Returning certificate"; 145 LOG(LS_INFO) << "Returning certificate";
143 return x509; 146 return x509;
144 147
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 369
367 void OpenSSLCertificate::AddReference() const { 370 void OpenSSLCertificate::AddReference() const {
368 ASSERT(x509_ != NULL); 371 ASSERT(x509_ != NULL);
369 #if defined(OPENSSL_IS_BORINGSSL) 372 #if defined(OPENSSL_IS_BORINGSSL)
370 X509_up_ref(x509_); 373 X509_up_ref(x509_);
371 #else 374 #else
372 CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509); 375 CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509);
373 #endif 376 #endif
374 } 377 }
375 378
379 // Convert from std::tm to number of seconds from epoch.
380 // Note that std::tm is relative to 1900-01-01.
381 static int64_t TmToSeconds(const std::tm& tm) {
382 static short int cumul_days[12] = {0, 31, 59, 90, 120, 151,
383 181, 212, 243, 273, 304, 334};
384
385 int year = tm.tm_year + 1900;
386 int month = tm.tm_mon;
387 int day = tm.tm_mday - 1;
388 int hour = tm.tm_hour;
389 int min = tm.tm_min;
390 int sec = tm.tm_sec;
391
392 // If expiration time is in a leap year, number of days depends on exact date.
393 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
394 if (month <= 2 - 1) { // February or earlier (|month| is zero based).
395 day -= 1;
396 }
397 }
398
399 day += cumul_days[month];
400
401 // Add number of leap days between 1970 and the expiration time.
402 day += ((year / 4 - 1970 / 4) - (year / 100 - 1970 / 100) +
403 (year / 400 - 1970 / 400));
404
405 year -= 1970;
406 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.
407 }
408
409 #define ASN1_READ2(x, s, n) \
410 do { \
411 x = 10 * s[0] + s[1] - '0' * 11; \
412 s += 2; \
413 n -= 2; \
414 } while (0)
415 #define ASN1_READ4(x, s, n) \
416 do { \
417 x = 1000 * s[0] + 100 * s[1] + 10 * s[2] + s[3] - '0' * 1111; \
418 s += 4; \
419 n -= 4; \
420 } while (0)
hbos 2015/11/25 15:21:44 Macros are the devil. I think these should be func
421
422 // Convert from ASN1 TIME as restricted by RFC 5280 to milliseconds from epoch.
423 // If the ASN1_TIME cannot be read, return -1. Use std::tm for intermediate
424 // results in the way specified by Unix time functions.
425 static int64_t ASN1TimeToMS(const ASN1_TIME* time) {
426 std::tm tm;
427 int year;
428 int month;
429 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.
430 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
431
432 if (time->type == V_ASN1_UTCTIME) {
433 // ASN1 format: yymmddhhmm[ss]Z where the Z is literal, but RFC 5280
434 // requires us to only support exactly yymmddhhmmssZ.
435
436 if (bytes_left < 9)
437 return -1;
438
439 ASN1_READ2(year, s, bytes_left);
440 if (year < 70)
441 year += 100;
442 } else if (time->type == V_ASN1_GENERALIZEDTIME) {
443 // ASN1 format: yyyymmddhh[mm[ss[.fff]]]Z where the Z is literal, but
444 // RFC 5280 requires us to only support exactly yyyymmddhhmmssZ.
445
446 if (bytes_left < 11)
447 return -1;
448
449 ASN1_READ4(year, s, bytes_left);
450 year -= 1900;
451 } else {
452 return -1;
453 }
454
455 // Zeroing the entire structure helps with the defaulting of the minute and
456 // second fields, as well as a bunch of other (here unused) fields.
457 memset(&tm, 0, sizeof(tm));
458
459 tm.tm_year = year;
460 ASN1_READ2(month, s, bytes_left);
461 tm.tm_mon = month - 1;
462 ASN1_READ2(tm.tm_mday, s, bytes_left);
463 ASN1_READ2(tm.tm_hour, s, bytes_left);
464 ASN1_READ2(tm.tm_min, s, bytes_left);
465 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.
466
467 if (bytes_left != 1 || s[0] != 'Z') {
468 // A final Z means UTC, mandated by RFC 5280, and compatible with OpenSSL.
469 return -1;
470 }
471
472 return 1000 * TmToSeconds(tm);
473 }
474 #undef ASN1_READ4
475 #undef ASN1_READ2
476
477 int64_t OpenSSLCertificate::CertificateExpirationTime() const {
478 ASN1_TIME* exptime = X509_get_notAfter(x509_);
479 return ASN1TimeToMS(exptime);
480 }
481
376 OpenSSLIdentity::OpenSSLIdentity(OpenSSLKeyPair* key_pair, 482 OpenSSLIdentity::OpenSSLIdentity(OpenSSLKeyPair* key_pair,
377 OpenSSLCertificate* certificate) 483 OpenSSLCertificate* certificate)
378 : key_pair_(key_pair), certificate_(certificate) { 484 : key_pair_(key_pair), certificate_(certificate) {
379 ASSERT(key_pair != NULL); 485 ASSERT(key_pair != NULL);
380 ASSERT(certificate != NULL); 486 ASSERT(certificate != NULL);
381 } 487 }
382 488
383 OpenSSLIdentity::~OpenSSLIdentity() = default; 489 OpenSSLIdentity::~OpenSSLIdentity() = default;
384 490
385 OpenSSLIdentity* OpenSSLIdentity::GenerateInternal( 491 OpenSSLIdentity* OpenSSLIdentity::GenerateInternal(
386 const SSLIdentityParams& params) { 492 const SSLIdentityParams& params) {
387 OpenSSLKeyPair* key_pair = OpenSSLKeyPair::Generate(params.key_params); 493 OpenSSLKeyPair* key_pair = OpenSSLKeyPair::Generate(params.key_params);
388 if (key_pair) { 494 if (key_pair) {
389 OpenSSLCertificate* certificate = 495 OpenSSLCertificate* certificate =
390 OpenSSLCertificate::Generate(key_pair, params); 496 OpenSSLCertificate::Generate(key_pair, params);
391 if (certificate) 497 if (certificate)
392 return new OpenSSLIdentity(key_pair, certificate); 498 return new OpenSSLIdentity(key_pair, certificate);
393 delete key_pair; 499 delete key_pair;
394 } 500 }
395 LOG(LS_INFO) << "Identity generation failed"; 501 LOG(LS_INFO) << "Identity generation failed";
396 return NULL; 502 return NULL;
397 } 503 }
398 504
399 OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name, 505 OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name,
400 const KeyParams& key_params) { 506 const KeyParams& key_params) {
401 SSLIdentityParams params; 507 SSLIdentityParams params;
402 params.key_params = key_params; 508 params.key_params = key_params;
403 params.common_name = common_name; 509 params.common_name = common_name;
404 params.not_before = CERTIFICATE_WINDOW; 510 time_t now = time(NULL);
405 params.not_after = CERTIFICATE_LIFETIME; 511 params.not_before = now + CERTIFICATE_WINDOW;
512 params.not_after = now + CERTIFICATE_LIFETIME;
406 return GenerateInternal(params); 513 return GenerateInternal(params);
407 } 514 }
408 515
409 OpenSSLIdentity* OpenSSLIdentity::GenerateForTest( 516 OpenSSLIdentity* OpenSSLIdentity::GenerateForTest(
410 const SSLIdentityParams& params) { 517 const SSLIdentityParams& params) {
411 return GenerateInternal(params); 518 return GenerateInternal(params);
412 } 519 }
413 520
414 SSLIdentity* OpenSSLIdentity::FromPEMStrings( 521 SSLIdentity* OpenSSLIdentity::FromPEMStrings(
415 const std::string& private_key, 522 const std::string& private_key,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) { 562 SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) {
456 LogSSLErrors("Configuring key and certificate"); 563 LogSSLErrors("Configuring key and certificate");
457 return false; 564 return false;
458 } 565 }
459 return true; 566 return true;
460 } 567 }
461 568
462 } // namespace rtc 569 } // namespace rtc
463 570
464 #endif // HAVE_OPENSSL_SSL_H 571 #endif // HAVE_OPENSSL_SSL_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698