| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
| 3 * | |
| 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 | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include "webrtc/base/opensslidentity.h" | |
| 12 | |
| 13 #include <memory> | |
| 14 | |
| 15 // Must be included first before openssl headers. | |
| 16 #include "webrtc/base/win32.h" // NOLINT | |
| 17 | |
| 18 #include <openssl/bio.h> | |
| 19 #include <openssl/err.h> | |
| 20 #include <openssl/pem.h> | |
| 21 #include <openssl/bn.h> | |
| 22 #include <openssl/rsa.h> | |
| 23 #include <openssl/crypto.h> | |
| 24 | |
| 25 #include "webrtc/base/checks.h" | |
| 26 #include "webrtc/base/helpers.h" | |
| 27 #include "webrtc/base/logging.h" | |
| 28 #include "webrtc/base/openssl.h" | |
| 29 #include "webrtc/base/openssldigest.h" | |
| 30 | |
| 31 namespace rtc { | |
| 32 | |
| 33 // We could have exposed a myriad of parameters for the crypto stuff, | |
| 34 // but keeping it simple seems best. | |
| 35 | |
| 36 // Random bits for certificate serial number | |
| 37 static const int SERIAL_RAND_BITS = 64; | |
| 38 | |
| 39 // Generate a key pair. Caller is responsible for freeing the returned object. | |
| 40 static EVP_PKEY* MakeKey(const KeyParams& key_params) { | |
| 41 LOG(LS_INFO) << "Making key pair"; | |
| 42 EVP_PKEY* pkey = EVP_PKEY_new(); | |
| 43 if (key_params.type() == KT_RSA) { | |
| 44 int key_length = key_params.rsa_params().mod_size; | |
| 45 BIGNUM* exponent = BN_new(); | |
| 46 RSA* rsa = RSA_new(); | |
| 47 if (!pkey || !exponent || !rsa || | |
| 48 !BN_set_word(exponent, key_params.rsa_params().pub_exp) || | |
| 49 !RSA_generate_key_ex(rsa, key_length, exponent, nullptr) || | |
| 50 !EVP_PKEY_assign_RSA(pkey, rsa)) { | |
| 51 EVP_PKEY_free(pkey); | |
| 52 BN_free(exponent); | |
| 53 RSA_free(rsa); | |
| 54 LOG(LS_ERROR) << "Failed to make RSA key pair"; | |
| 55 return nullptr; | |
| 56 } | |
| 57 // ownership of rsa struct was assigned, don't free it. | |
| 58 BN_free(exponent); | |
| 59 } else if (key_params.type() == KT_ECDSA) { | |
| 60 if (key_params.ec_curve() == EC_NIST_P256) { | |
| 61 EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); | |
| 62 | |
| 63 // Ensure curve name is included when EC key is serialized. | |
| 64 // Without this call, OpenSSL versions before 1.1.0 will create | |
| 65 // certificates that don't work for TLS. | |
| 66 // This is a no-op for BoringSSL and OpenSSL 1.1.0+ | |
| 67 EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE); | |
| 68 | |
| 69 if (!pkey || !ec_key || !EC_KEY_generate_key(ec_key) || | |
| 70 !EVP_PKEY_assign_EC_KEY(pkey, ec_key)) { | |
| 71 EVP_PKEY_free(pkey); | |
| 72 EC_KEY_free(ec_key); | |
| 73 LOG(LS_ERROR) << "Failed to make EC key pair"; | |
| 74 return nullptr; | |
| 75 } | |
| 76 // ownership of ec_key struct was assigned, don't free it. | |
| 77 } else { | |
| 78 // Add generation of any other curves here. | |
| 79 EVP_PKEY_free(pkey); | |
| 80 LOG(LS_ERROR) << "ECDSA key requested for unknown curve"; | |
| 81 return nullptr; | |
| 82 } | |
| 83 } else { | |
| 84 EVP_PKEY_free(pkey); | |
| 85 LOG(LS_ERROR) << "Key type requested not understood"; | |
| 86 return nullptr; | |
| 87 } | |
| 88 | |
| 89 LOG(LS_INFO) << "Returning key pair"; | |
| 90 return pkey; | |
| 91 } | |
| 92 | |
| 93 // Generate a self-signed certificate, with the public key from the | |
| 94 // given key pair. Caller is responsible for freeing the returned object. | |
| 95 static X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) { | |
| 96 LOG(LS_INFO) << "Making certificate for " << params.common_name; | |
| 97 X509* x509 = nullptr; | |
| 98 BIGNUM* serial_number = nullptr; | |
| 99 X509_NAME* name = nullptr; | |
| 100 time_t epoch_off = 0; // Time offset since epoch. | |
| 101 | |
| 102 if ((x509 = X509_new()) == nullptr) | |
| 103 goto error; | |
| 104 | |
| 105 if (!X509_set_pubkey(x509, pkey)) | |
| 106 goto error; | |
| 107 | |
| 108 // serial number | |
| 109 // temporary reference to serial number inside x509 struct | |
| 110 ASN1_INTEGER* asn1_serial_number; | |
| 111 if ((serial_number = BN_new()) == nullptr || | |
| 112 !BN_pseudo_rand(serial_number, SERIAL_RAND_BITS, 0, 0) || | |
| 113 (asn1_serial_number = X509_get_serialNumber(x509)) == nullptr || | |
| 114 !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)) | |
| 115 goto error; | |
| 116 | |
| 117 if (!X509_set_version(x509, 2L)) // version 3 | |
| 118 goto error; | |
| 119 | |
| 120 // There are a lot of possible components for the name entries. In | |
| 121 // our P2P SSL mode however, the certificates are pre-exchanged | |
| 122 // (through the secure XMPP channel), and so the certificate | |
| 123 // identification is arbitrary. It can't be empty, so we set some | |
| 124 // arbitrary common_name. Note that this certificate goes out in | |
| 125 // clear during SSL negotiation, so there may be a privacy issue in | |
| 126 // putting anything recognizable here. | |
| 127 if ((name = X509_NAME_new()) == nullptr || | |
| 128 !X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8, | |
| 129 (unsigned char*)params.common_name.c_str(), | |
| 130 -1, -1, 0) || | |
| 131 !X509_set_subject_name(x509, name) || !X509_set_issuer_name(x509, name)) | |
| 132 goto error; | |
| 133 | |
| 134 if (!X509_time_adj(X509_get_notBefore(x509), params.not_before, &epoch_off) || | |
| 135 !X509_time_adj(X509_get_notAfter(x509), params.not_after, &epoch_off)) | |
| 136 goto error; | |
| 137 | |
| 138 if (!X509_sign(x509, pkey, EVP_sha256())) | |
| 139 goto error; | |
| 140 | |
| 141 BN_free(serial_number); | |
| 142 X509_NAME_free(name); | |
| 143 LOG(LS_INFO) << "Returning certificate"; | |
| 144 return x509; | |
| 145 | |
| 146 error: | |
| 147 BN_free(serial_number); | |
| 148 X509_NAME_free(name); | |
| 149 X509_free(x509); | |
| 150 return nullptr; | |
| 151 } | |
| 152 | |
| 153 // This dumps the SSL error stack to the log. | |
| 154 static void LogSSLErrors(const std::string& prefix) { | |
| 155 char error_buf[200]; | |
| 156 unsigned long err; | |
| 157 | |
| 158 while ((err = ERR_get_error()) != 0) { | |
| 159 ERR_error_string_n(err, error_buf, sizeof(error_buf)); | |
| 160 LOG(LS_ERROR) << prefix << ": " << error_buf << "\n"; | |
| 161 } | |
| 162 } | |
| 163 | |
| 164 OpenSSLKeyPair* OpenSSLKeyPair::Generate(const KeyParams& key_params) { | |
| 165 EVP_PKEY* pkey = MakeKey(key_params); | |
| 166 if (!pkey) { | |
| 167 LogSSLErrors("Generating key pair"); | |
| 168 return nullptr; | |
| 169 } | |
| 170 return new OpenSSLKeyPair(pkey); | |
| 171 } | |
| 172 | |
| 173 OpenSSLKeyPair* OpenSSLKeyPair::FromPrivateKeyPEMString( | |
| 174 const std::string& pem_string) { | |
| 175 BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1); | |
| 176 if (!bio) { | |
| 177 LOG(LS_ERROR) << "Failed to create a new BIO buffer."; | |
| 178 return nullptr; | |
| 179 } | |
| 180 BIO_set_mem_eof_return(bio, 0); | |
| 181 EVP_PKEY* pkey = | |
| 182 PEM_read_bio_PrivateKey(bio, nullptr, nullptr, const_cast<char*>("\0")); | |
| 183 BIO_free(bio); // Frees the BIO, but not the pointed-to string. | |
| 184 if (!pkey) { | |
| 185 LOG(LS_ERROR) << "Failed to create the private key from PEM string."; | |
| 186 return nullptr; | |
| 187 } | |
| 188 if (EVP_PKEY_missing_parameters(pkey) != 0) { | |
| 189 LOG(LS_ERROR) << "The resulting key pair is missing public key parameters."; | |
| 190 EVP_PKEY_free(pkey); | |
| 191 return nullptr; | |
| 192 } | |
| 193 return new OpenSSLKeyPair(pkey); | |
| 194 } | |
| 195 | |
| 196 OpenSSLKeyPair::~OpenSSLKeyPair() { | |
| 197 EVP_PKEY_free(pkey_); | |
| 198 } | |
| 199 | |
| 200 OpenSSLKeyPair* OpenSSLKeyPair::GetReference() { | |
| 201 AddReference(); | |
| 202 return new OpenSSLKeyPair(pkey_); | |
| 203 } | |
| 204 | |
| 205 void OpenSSLKeyPair::AddReference() { | |
| 206 #if defined(OPENSSL_IS_BORINGSSL) | |
| 207 EVP_PKEY_up_ref(pkey_); | |
| 208 #else | |
| 209 CRYPTO_add(&pkey_->references, 1, CRYPTO_LOCK_EVP_PKEY); | |
| 210 #endif | |
| 211 } | |
| 212 | |
| 213 std::string OpenSSLKeyPair::PrivateKeyToPEMString() const { | |
| 214 BIO* temp_memory_bio = BIO_new(BIO_s_mem()); | |
| 215 if (!temp_memory_bio) { | |
| 216 LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; | |
| 217 RTC_NOTREACHED(); | |
| 218 return ""; | |
| 219 } | |
| 220 if (!PEM_write_bio_PrivateKey( | |
| 221 temp_memory_bio, pkey_, nullptr, nullptr, 0, nullptr, nullptr)) { | |
| 222 LOG_F(LS_ERROR) << "Failed to write private key"; | |
| 223 BIO_free(temp_memory_bio); | |
| 224 RTC_NOTREACHED(); | |
| 225 return ""; | |
| 226 } | |
| 227 BIO_write(temp_memory_bio, "\0", 1); | |
| 228 char* buffer; | |
| 229 BIO_get_mem_data(temp_memory_bio, &buffer); | |
| 230 std::string priv_key_str = buffer; | |
| 231 BIO_free(temp_memory_bio); | |
| 232 return priv_key_str; | |
| 233 } | |
| 234 | |
| 235 std::string OpenSSLKeyPair::PublicKeyToPEMString() const { | |
| 236 BIO* temp_memory_bio = BIO_new(BIO_s_mem()); | |
| 237 if (!temp_memory_bio) { | |
| 238 LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; | |
| 239 RTC_NOTREACHED(); | |
| 240 return ""; | |
| 241 } | |
| 242 if (!PEM_write_bio_PUBKEY(temp_memory_bio, pkey_)) { | |
| 243 LOG_F(LS_ERROR) << "Failed to write public key"; | |
| 244 BIO_free(temp_memory_bio); | |
| 245 RTC_NOTREACHED(); | |
| 246 return ""; | |
| 247 } | |
| 248 BIO_write(temp_memory_bio, "\0", 1); | |
| 249 char* buffer; | |
| 250 BIO_get_mem_data(temp_memory_bio, &buffer); | |
| 251 std::string pub_key_str = buffer; | |
| 252 BIO_free(temp_memory_bio); | |
| 253 return pub_key_str; | |
| 254 } | |
| 255 | |
| 256 bool OpenSSLKeyPair::operator==(const OpenSSLKeyPair& other) const { | |
| 257 return EVP_PKEY_cmp(this->pkey_, other.pkey_) == 1; | |
| 258 } | |
| 259 | |
| 260 bool OpenSSLKeyPair::operator!=(const OpenSSLKeyPair& other) const { | |
| 261 return !(*this == other); | |
| 262 } | |
| 263 | |
| 264 #if !defined(NDEBUG) | |
| 265 // Print a certificate to the log, for debugging. | |
| 266 static void PrintCert(X509* x509) { | |
| 267 BIO* temp_memory_bio = BIO_new(BIO_s_mem()); | |
| 268 if (!temp_memory_bio) { | |
| 269 LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; | |
| 270 return; | |
| 271 } | |
| 272 X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0); | |
| 273 BIO_write(temp_memory_bio, "\0", 1); | |
| 274 char* buffer; | |
| 275 BIO_get_mem_data(temp_memory_bio, &buffer); | |
| 276 LOG(LS_VERBOSE) << buffer; | |
| 277 BIO_free(temp_memory_bio); | |
| 278 } | |
| 279 #endif | |
| 280 | |
| 281 OpenSSLCertificate* OpenSSLCertificate::Generate( | |
| 282 OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) { | |
| 283 SSLIdentityParams actual_params(params); | |
| 284 if (actual_params.common_name.empty()) { | |
| 285 // Use a random string, arbitrarily 8chars long. | |
| 286 actual_params.common_name = CreateRandomString(8); | |
| 287 } | |
| 288 X509* x509 = MakeCertificate(key_pair->pkey(), actual_params); | |
| 289 if (!x509) { | |
| 290 LogSSLErrors("Generating certificate"); | |
| 291 return nullptr; | |
| 292 } | |
| 293 #if !defined(NDEBUG) | |
| 294 PrintCert(x509); | |
| 295 #endif | |
| 296 OpenSSLCertificate* ret = new OpenSSLCertificate(x509); | |
| 297 X509_free(x509); | |
| 298 return ret; | |
| 299 } | |
| 300 | |
| 301 OpenSSLCertificate* OpenSSLCertificate::FromPEMString( | |
| 302 const std::string& pem_string) { | |
| 303 BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1); | |
| 304 if (!bio) | |
| 305 return nullptr; | |
| 306 BIO_set_mem_eof_return(bio, 0); | |
| 307 X509* x509 = | |
| 308 PEM_read_bio_X509(bio, nullptr, nullptr, const_cast<char*>("\0")); | |
| 309 BIO_free(bio); // Frees the BIO, but not the pointed-to string. | |
| 310 | |
| 311 if (!x509) | |
| 312 return nullptr; | |
| 313 | |
| 314 OpenSSLCertificate* ret = new OpenSSLCertificate(x509); | |
| 315 X509_free(x509); | |
| 316 return ret; | |
| 317 } | |
| 318 | |
| 319 // NOTE: This implementation only functions correctly after InitializeSSL | |
| 320 // and before CleanupSSL. | |
| 321 bool OpenSSLCertificate::GetSignatureDigestAlgorithm( | |
| 322 std::string* algorithm) const { | |
| 323 int nid = OBJ_obj2nid(x509_->sig_alg->algorithm); | |
| 324 switch (nid) { | |
| 325 case NID_md5WithRSA: | |
| 326 case NID_md5WithRSAEncryption: | |
| 327 *algorithm = DIGEST_MD5; | |
| 328 break; | |
| 329 case NID_ecdsa_with_SHA1: | |
| 330 case NID_dsaWithSHA1: | |
| 331 case NID_dsaWithSHA1_2: | |
| 332 case NID_sha1WithRSA: | |
| 333 case NID_sha1WithRSAEncryption: | |
| 334 *algorithm = DIGEST_SHA_1; | |
| 335 break; | |
| 336 case NID_ecdsa_with_SHA224: | |
| 337 case NID_sha224WithRSAEncryption: | |
| 338 case NID_dsa_with_SHA224: | |
| 339 *algorithm = DIGEST_SHA_224; | |
| 340 break; | |
| 341 case NID_ecdsa_with_SHA256: | |
| 342 case NID_sha256WithRSAEncryption: | |
| 343 case NID_dsa_with_SHA256: | |
| 344 *algorithm = DIGEST_SHA_256; | |
| 345 break; | |
| 346 case NID_ecdsa_with_SHA384: | |
| 347 case NID_sha384WithRSAEncryption: | |
| 348 *algorithm = DIGEST_SHA_384; | |
| 349 break; | |
| 350 case NID_ecdsa_with_SHA512: | |
| 351 case NID_sha512WithRSAEncryption: | |
| 352 *algorithm = DIGEST_SHA_512; | |
| 353 break; | |
| 354 default: | |
| 355 // Unknown algorithm. There are several unhandled options that are less | |
| 356 // common and more complex. | |
| 357 LOG(LS_ERROR) << "Unknown signature algorithm NID: " << nid; | |
| 358 algorithm->clear(); | |
| 359 return false; | |
| 360 } | |
| 361 return true; | |
| 362 } | |
| 363 | |
| 364 std::unique_ptr<SSLCertChain> OpenSSLCertificate::GetChain() const { | |
| 365 // Chains are not yet supported when using OpenSSL. | |
| 366 // OpenSSLStreamAdapter::SSLVerifyCallback currently requires the remote | |
| 367 // certificate to be self-signed. | |
| 368 return nullptr; | |
| 369 } | |
| 370 | |
| 371 bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm, | |
| 372 unsigned char* digest, | |
| 373 size_t size, | |
| 374 size_t* length) const { | |
| 375 return ComputeDigest(x509_, algorithm, digest, size, length); | |
| 376 } | |
| 377 | |
| 378 bool OpenSSLCertificate::ComputeDigest(const X509* x509, | |
| 379 const std::string& algorithm, | |
| 380 unsigned char* digest, | |
| 381 size_t size, | |
| 382 size_t* length) { | |
| 383 const EVP_MD* md; | |
| 384 unsigned int n; | |
| 385 | |
| 386 if (!OpenSSLDigest::GetDigestEVP(algorithm, &md)) | |
| 387 return false; | |
| 388 | |
| 389 if (size < static_cast<size_t>(EVP_MD_size(md))) | |
| 390 return false; | |
| 391 | |
| 392 X509_digest(x509, md, digest, &n); | |
| 393 | |
| 394 *length = n; | |
| 395 | |
| 396 return true; | |
| 397 } | |
| 398 | |
| 399 OpenSSLCertificate::~OpenSSLCertificate() { | |
| 400 X509_free(x509_); | |
| 401 } | |
| 402 | |
| 403 OpenSSLCertificate* OpenSSLCertificate::GetReference() const { | |
| 404 return new OpenSSLCertificate(x509_); | |
| 405 } | |
| 406 | |
| 407 std::string OpenSSLCertificate::ToPEMString() const { | |
| 408 BIO* bio = BIO_new(BIO_s_mem()); | |
| 409 if (!bio) { | |
| 410 FATAL() << "unreachable code"; | |
| 411 } | |
| 412 if (!PEM_write_bio_X509(bio, x509_)) { | |
| 413 BIO_free(bio); | |
| 414 FATAL() << "unreachable code"; | |
| 415 } | |
| 416 BIO_write(bio, "\0", 1); | |
| 417 char* buffer; | |
| 418 BIO_get_mem_data(bio, &buffer); | |
| 419 std::string ret(buffer); | |
| 420 BIO_free(bio); | |
| 421 return ret; | |
| 422 } | |
| 423 | |
| 424 void OpenSSLCertificate::ToDER(Buffer* der_buffer) const { | |
| 425 // In case of failure, make sure to leave the buffer empty. | |
| 426 der_buffer->SetSize(0); | |
| 427 | |
| 428 // Calculates the DER representation of the certificate, from scratch. | |
| 429 BIO* bio = BIO_new(BIO_s_mem()); | |
| 430 if (!bio) { | |
| 431 FATAL() << "unreachable code"; | |
| 432 } | |
| 433 if (!i2d_X509_bio(bio, x509_)) { | |
| 434 BIO_free(bio); | |
| 435 FATAL() << "unreachable code"; | |
| 436 } | |
| 437 char* data; | |
| 438 size_t length = BIO_get_mem_data(bio, &data); | |
| 439 der_buffer->SetData(data, length); | |
| 440 BIO_free(bio); | |
| 441 } | |
| 442 | |
| 443 void OpenSSLCertificate::AddReference() const { | |
| 444 RTC_DCHECK(x509_ != nullptr); | |
| 445 #if defined(OPENSSL_IS_BORINGSSL) | |
| 446 X509_up_ref(x509_); | |
| 447 #else | |
| 448 CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509); | |
| 449 #endif | |
| 450 } | |
| 451 | |
| 452 bool OpenSSLCertificate::operator==(const OpenSSLCertificate& other) const { | |
| 453 return X509_cmp(this->x509_, other.x509_) == 0; | |
| 454 } | |
| 455 | |
| 456 bool OpenSSLCertificate::operator!=(const OpenSSLCertificate& other) const { | |
| 457 return !(*this == other); | |
| 458 } | |
| 459 | |
| 460 // Documented in sslidentity.h. | |
| 461 int64_t OpenSSLCertificate::CertificateExpirationTime() const { | |
| 462 ASN1_TIME* expire_time = X509_get_notAfter(x509_); | |
| 463 bool long_format; | |
| 464 | |
| 465 if (expire_time->type == V_ASN1_UTCTIME) { | |
| 466 long_format = false; | |
| 467 } else if (expire_time->type == V_ASN1_GENERALIZEDTIME) { | |
| 468 long_format = true; | |
| 469 } else { | |
| 470 return -1; | |
| 471 } | |
| 472 | |
| 473 return ASN1TimeToSec(expire_time->data, expire_time->length, long_format); | |
| 474 } | |
| 475 | |
| 476 OpenSSLIdentity::OpenSSLIdentity(OpenSSLKeyPair* key_pair, | |
| 477 OpenSSLCertificate* certificate) | |
| 478 : key_pair_(key_pair), certificate_(certificate) { | |
| 479 RTC_DCHECK(key_pair != nullptr); | |
| 480 RTC_DCHECK(certificate != nullptr); | |
| 481 } | |
| 482 | |
| 483 OpenSSLIdentity::~OpenSSLIdentity() = default; | |
| 484 | |
| 485 OpenSSLIdentity* OpenSSLIdentity::GenerateInternal( | |
| 486 const SSLIdentityParams& params) { | |
| 487 OpenSSLKeyPair* key_pair = OpenSSLKeyPair::Generate(params.key_params); | |
| 488 if (key_pair) { | |
| 489 OpenSSLCertificate* certificate = | |
| 490 OpenSSLCertificate::Generate(key_pair, params); | |
| 491 if (certificate) | |
| 492 return new OpenSSLIdentity(key_pair, certificate); | |
| 493 delete key_pair; | |
| 494 } | |
| 495 LOG(LS_INFO) << "Identity generation failed"; | |
| 496 return nullptr; | |
| 497 } | |
| 498 | |
| 499 OpenSSLIdentity* OpenSSLIdentity::GenerateWithExpiration( | |
| 500 const std::string& common_name, | |
| 501 const KeyParams& key_params, | |
| 502 time_t certificate_lifetime) { | |
| 503 SSLIdentityParams params; | |
| 504 params.key_params = key_params; | |
| 505 params.common_name = common_name; | |
| 506 time_t now = time(nullptr); | |
| 507 params.not_before = now + kCertificateWindowInSeconds; | |
| 508 params.not_after = now + certificate_lifetime; | |
| 509 if (params.not_before > params.not_after) | |
| 510 return nullptr; | |
| 511 return GenerateInternal(params); | |
| 512 } | |
| 513 | |
| 514 OpenSSLIdentity* OpenSSLIdentity::GenerateForTest( | |
| 515 const SSLIdentityParams& params) { | |
| 516 return GenerateInternal(params); | |
| 517 } | |
| 518 | |
| 519 SSLIdentity* OpenSSLIdentity::FromPEMStrings( | |
| 520 const std::string& private_key, | |
| 521 const std::string& certificate) { | |
| 522 std::unique_ptr<OpenSSLCertificate> cert( | |
| 523 OpenSSLCertificate::FromPEMString(certificate)); | |
| 524 if (!cert) { | |
| 525 LOG(LS_ERROR) << "Failed to create OpenSSLCertificate from PEM string."; | |
| 526 return nullptr; | |
| 527 } | |
| 528 | |
| 529 OpenSSLKeyPair* key_pair = | |
| 530 OpenSSLKeyPair::FromPrivateKeyPEMString(private_key); | |
| 531 if (!key_pair) { | |
| 532 LOG(LS_ERROR) << "Failed to create key pair from PEM string."; | |
| 533 return nullptr; | |
| 534 } | |
| 535 | |
| 536 return new OpenSSLIdentity(key_pair, | |
| 537 cert.release()); | |
| 538 } | |
| 539 | |
| 540 const OpenSSLCertificate& OpenSSLIdentity::certificate() const { | |
| 541 return *certificate_; | |
| 542 } | |
| 543 | |
| 544 OpenSSLIdentity* OpenSSLIdentity::GetReference() const { | |
| 545 return new OpenSSLIdentity(key_pair_->GetReference(), | |
| 546 certificate_->GetReference()); | |
| 547 } | |
| 548 | |
| 549 bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) { | |
| 550 // 1 is the documented success return code. | |
| 551 if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 || | |
| 552 SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) { | |
| 553 LogSSLErrors("Configuring key and certificate"); | |
| 554 return false; | |
| 555 } | |
| 556 return true; | |
| 557 } | |
| 558 | |
| 559 std::string OpenSSLIdentity::PrivateKeyToPEMString() const { | |
| 560 return key_pair_->PrivateKeyToPEMString(); | |
| 561 } | |
| 562 | |
| 563 std::string OpenSSLIdentity::PublicKeyToPEMString() const { | |
| 564 return key_pair_->PublicKeyToPEMString(); | |
| 565 } | |
| 566 | |
| 567 bool OpenSSLIdentity::operator==(const OpenSSLIdentity& other) const { | |
| 568 return *this->key_pair_ == *other.key_pair_ && | |
| 569 *this->certificate_ == *other.certificate_; | |
| 570 } | |
| 571 | |
| 572 bool OpenSSLIdentity::operator!=(const OpenSSLIdentity& other) const { | |
| 573 return !(*this == other); | |
| 574 } | |
| 575 | |
| 576 } // namespace rtc | |
| OLD | NEW |