OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |