• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "rtc_base/openssl_identity.h"
12 
13 #include <memory>
14 #include <utility>
15 #include <vector>
16 
17 #if defined(WEBRTC_WIN)
18 // Must be included first before openssl headers.
19 #include "rtc_base/win32.h"  // NOLINT
20 #endif                       // WEBRTC_WIN
21 
22 #include <openssl/bio.h>
23 #include <openssl/bn.h>
24 #include <openssl/err.h>
25 #include <openssl/pem.h>
26 #include <openssl/rsa.h>
27 #include <stdint.h>
28 
29 #include "absl/memory/memory.h"
30 #include "rtc_base/checks.h"
31 #include "rtc_base/logging.h"
32 #include "rtc_base/numerics/safe_conversions.h"
33 #include "rtc_base/openssl.h"
34 #include "rtc_base/openssl_utility.h"
35 
36 namespace rtc {
37 
38 // We could have exposed a myriad of parameters for the crypto stuff,
39 // but keeping it simple seems best.
40 
41 // Generate a key pair. Caller is responsible for freeing the returned object.
MakeKey(const KeyParams & key_params)42 static EVP_PKEY* MakeKey(const KeyParams& key_params) {
43   RTC_LOG(LS_INFO) << "Making key pair";
44   EVP_PKEY* pkey = EVP_PKEY_new();
45   if (key_params.type() == KT_RSA) {
46     int key_length = key_params.rsa_params().mod_size;
47     BIGNUM* exponent = BN_new();
48     RSA* rsa = RSA_new();
49     if (!pkey || !exponent || !rsa ||
50         !BN_set_word(exponent, key_params.rsa_params().pub_exp) ||
51         !RSA_generate_key_ex(rsa, key_length, exponent, nullptr) ||
52         !EVP_PKEY_assign_RSA(pkey, rsa)) {
53       EVP_PKEY_free(pkey);
54       BN_free(exponent);
55       RSA_free(rsa);
56       RTC_LOG(LS_ERROR) << "Failed to make RSA key pair";
57       return nullptr;
58     }
59     // ownership of rsa struct was assigned, don't free it.
60     BN_free(exponent);
61   } else if (key_params.type() == KT_ECDSA) {
62     if (key_params.ec_curve() == EC_NIST_P256) {
63       EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
64 
65       // Ensure curve name is included when EC key is serialized.
66       // Without this call, OpenSSL versions before 1.1.0 will create
67       // certificates that don't work for TLS.
68       // This is a no-op for BoringSSL and OpenSSL 1.1.0+
69       EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE);
70 
71       if (!pkey || !ec_key || !EC_KEY_generate_key(ec_key) ||
72           !EVP_PKEY_assign_EC_KEY(pkey, ec_key)) {
73         EVP_PKEY_free(pkey);
74         EC_KEY_free(ec_key);
75         RTC_LOG(LS_ERROR) << "Failed to make EC key pair";
76         return nullptr;
77       }
78       // ownership of ec_key struct was assigned, don't free it.
79     } else {
80       // Add generation of any other curves here.
81       EVP_PKEY_free(pkey);
82       RTC_LOG(LS_ERROR) << "ECDSA key requested for unknown curve";
83       return nullptr;
84     }
85   } else {
86     EVP_PKEY_free(pkey);
87     RTC_LOG(LS_ERROR) << "Key type requested not understood";
88     return nullptr;
89   }
90 
91   RTC_LOG(LS_INFO) << "Returning key pair";
92   return pkey;
93 }
94 
Generate(const KeyParams & key_params)95 OpenSSLKeyPair* OpenSSLKeyPair::Generate(const KeyParams& key_params) {
96   EVP_PKEY* pkey = MakeKey(key_params);
97   if (!pkey) {
98     openssl::LogSSLErrors("Generating key pair");
99     return nullptr;
100   }
101   return new OpenSSLKeyPair(pkey);
102 }
103 
FromPrivateKeyPEMString(const std::string & pem_string)104 OpenSSLKeyPair* OpenSSLKeyPair::FromPrivateKeyPEMString(
105     const std::string& pem_string) {
106   BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1);
107   if (!bio) {
108     RTC_LOG(LS_ERROR) << "Failed to create a new BIO buffer.";
109     return nullptr;
110   }
111   BIO_set_mem_eof_return(bio, 0);
112   EVP_PKEY* pkey =
113       PEM_read_bio_PrivateKey(bio, nullptr, nullptr, const_cast<char*>("\0"));
114   BIO_free(bio);  // Frees the BIO, but not the pointed-to string.
115   if (!pkey) {
116     RTC_LOG(LS_ERROR) << "Failed to create the private key from PEM string.";
117     return nullptr;
118   }
119   if (EVP_PKEY_missing_parameters(pkey) != 0) {
120     RTC_LOG(LS_ERROR)
121         << "The resulting key pair is missing public key parameters.";
122     EVP_PKEY_free(pkey);
123     return nullptr;
124   }
125   return new OpenSSLKeyPair(pkey);
126 }
127 
~OpenSSLKeyPair()128 OpenSSLKeyPair::~OpenSSLKeyPair() {
129   EVP_PKEY_free(pkey_);
130 }
131 
GetReference()132 OpenSSLKeyPair* OpenSSLKeyPair::GetReference() {
133   AddReference();
134   return new OpenSSLKeyPair(pkey_);
135 }
136 
AddReference()137 void OpenSSLKeyPair::AddReference() {
138   EVP_PKEY_up_ref(pkey_);
139 }
140 
PrivateKeyToPEMString() const141 std::string OpenSSLKeyPair::PrivateKeyToPEMString() const {
142   BIO* temp_memory_bio = BIO_new(BIO_s_mem());
143   if (!temp_memory_bio) {
144     RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
145     RTC_NOTREACHED();
146     return "";
147   }
148   if (!PEM_write_bio_PrivateKey(temp_memory_bio, pkey_, nullptr, nullptr, 0,
149                                 nullptr, nullptr)) {
150     RTC_LOG_F(LS_ERROR) << "Failed to write private key";
151     BIO_free(temp_memory_bio);
152     RTC_NOTREACHED();
153     return "";
154   }
155   BIO_write(temp_memory_bio, "\0", 1);
156   char* buffer;
157   BIO_get_mem_data(temp_memory_bio, &buffer);
158   std::string priv_key_str = buffer;
159   BIO_free(temp_memory_bio);
160   return priv_key_str;
161 }
162 
PublicKeyToPEMString() const163 std::string OpenSSLKeyPair::PublicKeyToPEMString() const {
164   BIO* temp_memory_bio = BIO_new(BIO_s_mem());
165   if (!temp_memory_bio) {
166     RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
167     RTC_NOTREACHED();
168     return "";
169   }
170   if (!PEM_write_bio_PUBKEY(temp_memory_bio, pkey_)) {
171     RTC_LOG_F(LS_ERROR) << "Failed to write public key";
172     BIO_free(temp_memory_bio);
173     RTC_NOTREACHED();
174     return "";
175   }
176   BIO_write(temp_memory_bio, "\0", 1);
177   char* buffer;
178   BIO_get_mem_data(temp_memory_bio, &buffer);
179   std::string pub_key_str = buffer;
180   BIO_free(temp_memory_bio);
181   return pub_key_str;
182 }
183 
operator ==(const OpenSSLKeyPair & other) const184 bool OpenSSLKeyPair::operator==(const OpenSSLKeyPair& other) const {
185   return EVP_PKEY_cmp(this->pkey_, other.pkey_) == 1;
186 }
187 
operator !=(const OpenSSLKeyPair & other) const188 bool OpenSSLKeyPair::operator!=(const OpenSSLKeyPair& other) const {
189   return !(*this == other);
190 }
191 
OpenSSLIdentity(std::unique_ptr<OpenSSLKeyPair> key_pair,std::unique_ptr<OpenSSLCertificate> certificate)192 OpenSSLIdentity::OpenSSLIdentity(
193     std::unique_ptr<OpenSSLKeyPair> key_pair,
194     std::unique_ptr<OpenSSLCertificate> certificate)
195     : key_pair_(std::move(key_pair)) {
196   RTC_DCHECK(key_pair_ != nullptr);
197   RTC_DCHECK(certificate != nullptr);
198   std::vector<std::unique_ptr<SSLCertificate>> certs;
199   certs.push_back(std::move(certificate));
200   cert_chain_.reset(new SSLCertChain(std::move(certs)));
201 }
202 
OpenSSLIdentity(std::unique_ptr<OpenSSLKeyPair> key_pair,std::unique_ptr<SSLCertChain> cert_chain)203 OpenSSLIdentity::OpenSSLIdentity(std::unique_ptr<OpenSSLKeyPair> key_pair,
204                                  std::unique_ptr<SSLCertChain> cert_chain)
205     : key_pair_(std::move(key_pair)), cert_chain_(std::move(cert_chain)) {
206   RTC_DCHECK(key_pair_ != nullptr);
207   RTC_DCHECK(cert_chain_ != nullptr);
208 }
209 
210 OpenSSLIdentity::~OpenSSLIdentity() = default;
211 
CreateInternal(const SSLIdentityParams & params)212 std::unique_ptr<OpenSSLIdentity> OpenSSLIdentity::CreateInternal(
213     const SSLIdentityParams& params) {
214   std::unique_ptr<OpenSSLKeyPair> key_pair(
215       OpenSSLKeyPair::Generate(params.key_params));
216   if (key_pair) {
217     std::unique_ptr<OpenSSLCertificate> certificate(
218         OpenSSLCertificate::Generate(key_pair.get(), params));
219     if (certificate != nullptr) {
220       return absl::WrapUnique(
221           new OpenSSLIdentity(std::move(key_pair), std::move(certificate)));
222     }
223   }
224   RTC_LOG(LS_INFO) << "Identity generation failed";
225   return nullptr;
226 }
227 
228 // static
CreateWithExpiration(const std::string & common_name,const KeyParams & key_params,time_t certificate_lifetime)229 std::unique_ptr<OpenSSLIdentity> OpenSSLIdentity::CreateWithExpiration(
230     const std::string& common_name,
231     const KeyParams& key_params,
232     time_t certificate_lifetime) {
233   SSLIdentityParams params;
234   params.key_params = key_params;
235   params.common_name = common_name;
236   time_t now = time(nullptr);
237   params.not_before = now + kCertificateWindowInSeconds;
238   params.not_after = now + certificate_lifetime;
239   if (params.not_before > params.not_after)
240     return nullptr;
241   return CreateInternal(params);
242 }
243 
CreateForTest(const SSLIdentityParams & params)244 std::unique_ptr<OpenSSLIdentity> OpenSSLIdentity::CreateForTest(
245     const SSLIdentityParams& params) {
246   return CreateInternal(params);
247 }
248 
CreateFromPEMStrings(const std::string & private_key,const std::string & certificate)249 std::unique_ptr<SSLIdentity> OpenSSLIdentity::CreateFromPEMStrings(
250     const std::string& private_key,
251     const std::string& certificate) {
252   std::unique_ptr<OpenSSLCertificate> cert(
253       OpenSSLCertificate::FromPEMString(certificate));
254   if (!cert) {
255     RTC_LOG(LS_ERROR) << "Failed to create OpenSSLCertificate from PEM string.";
256     return nullptr;
257   }
258 
259   std::unique_ptr<OpenSSLKeyPair> key_pair(
260       OpenSSLKeyPair::FromPrivateKeyPEMString(private_key));
261   if (!key_pair) {
262     RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string.";
263     return nullptr;
264   }
265 
266   return absl::WrapUnique(
267       new OpenSSLIdentity(std::move(key_pair), std::move(cert)));
268 }
269 
CreateFromPEMChainStrings(const std::string & private_key,const std::string & certificate_chain)270 std::unique_ptr<SSLIdentity> OpenSSLIdentity::CreateFromPEMChainStrings(
271     const std::string& private_key,
272     const std::string& certificate_chain) {
273   BIO* bio = BIO_new_mem_buf(certificate_chain.data(),
274                              rtc::dchecked_cast<int>(certificate_chain.size()));
275   if (!bio)
276     return nullptr;
277   BIO_set_mem_eof_return(bio, 0);
278   std::vector<std::unique_ptr<SSLCertificate>> certs;
279   while (true) {
280     X509* x509 =
281         PEM_read_bio_X509(bio, nullptr, nullptr, const_cast<char*>("\0"));
282     if (x509 == nullptr) {
283       uint32_t err = ERR_peek_error();
284       if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
285           ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
286         break;
287       }
288       RTC_LOG(LS_ERROR) << "Failed to parse certificate from PEM string.";
289       BIO_free(bio);
290       return nullptr;
291     }
292     certs.emplace_back(new OpenSSLCertificate(x509));
293     X509_free(x509);
294   }
295   BIO_free(bio);
296   if (certs.empty()) {
297     RTC_LOG(LS_ERROR) << "Found no certificates in PEM string.";
298     return nullptr;
299   }
300 
301   std::unique_ptr<OpenSSLKeyPair> key_pair(
302       OpenSSLKeyPair::FromPrivateKeyPEMString(private_key));
303   if (!key_pair) {
304     RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string.";
305     return nullptr;
306   }
307 
308   return absl::WrapUnique(new OpenSSLIdentity(
309       std::move(key_pair), std::make_unique<SSLCertChain>(std::move(certs))));
310 }
311 
certificate() const312 const OpenSSLCertificate& OpenSSLIdentity::certificate() const {
313   return *static_cast<const OpenSSLCertificate*>(&cert_chain_->Get(0));
314 }
315 
cert_chain() const316 const SSLCertChain& OpenSSLIdentity::cert_chain() const {
317   return *cert_chain_.get();
318 }
319 
CloneInternal() const320 std::unique_ptr<SSLIdentity> OpenSSLIdentity::CloneInternal() const {
321   // We cannot use std::make_unique here because the referenced OpenSSLIdentity
322   // constructor is private.
323   return absl::WrapUnique(new OpenSSLIdentity(
324       absl::WrapUnique(key_pair_->GetReference()), cert_chain_->Clone()));
325 }
326 
ConfigureIdentity(SSL_CTX * ctx)327 bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
328   // 1 is the documented success return code.
329   const OpenSSLCertificate* cert = &certificate();
330   if (SSL_CTX_use_certificate(ctx, cert->x509()) != 1 ||
331       SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) {
332     openssl::LogSSLErrors("Configuring key and certificate");
333     return false;
334   }
335   // If a chain is available, use it.
336   for (size_t i = 1; i < cert_chain_->GetSize(); ++i) {
337     cert = static_cast<const OpenSSLCertificate*>(&cert_chain_->Get(i));
338     if (SSL_CTX_add1_chain_cert(ctx, cert->x509()) != 1) {
339       openssl::LogSSLErrors("Configuring intermediate certificate");
340       return false;
341     }
342   }
343 
344   return true;
345 }
346 
PrivateKeyToPEMString() const347 std::string OpenSSLIdentity::PrivateKeyToPEMString() const {
348   return key_pair_->PrivateKeyToPEMString();
349 }
350 
PublicKeyToPEMString() const351 std::string OpenSSLIdentity::PublicKeyToPEMString() const {
352   return key_pair_->PublicKeyToPEMString();
353 }
354 
operator ==(const OpenSSLIdentity & other) const355 bool OpenSSLIdentity::operator==(const OpenSSLIdentity& other) const {
356   return *this->key_pair_ == *other.key_pair_ &&
357          this->certificate() == other.certificate();
358 }
359 
operator !=(const OpenSSLIdentity & other) const360 bool OpenSSLIdentity::operator!=(const OpenSSLIdentity& other) const {
361   return !(*this == other);
362 }
363 
364 }  // namespace rtc
365