147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if HAVE_OPENSSL_SSL_H 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/opensslidentity.h" 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Must be included first before openssl headers. 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32.h" // NOLINT 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/bio.h> 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/err.h> 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/pem.h> 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/bn.h> 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/rsa.h> 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/crypto.h> 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/checks.h" 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/helpers.h" 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h" 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/openssl.h" 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/openssldigest.h" 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// We could have exposed a myriad of parameters for the crypto stuff, 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// but keeping it simple seems best. 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Strength of generated keys. Those are RSA. 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int KEY_LENGTH = 1024; 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Random bits for certificate serial number 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int SERIAL_RAND_BITS = 64; 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Certificate validity lifetime 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int CERTIFICATE_LIFETIME = 60*60*24*30; // 30 days, arbitrarily 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Certificate validity window. 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// This is to compensate for slightly incorrect system clocks. 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int CERTIFICATE_WINDOW = -60*60*24; 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Generate a key pair. Caller is responsible for freeing the returned object. 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic EVP_PKEY* MakeKey() { 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Making key pair"; 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org EVP_PKEY* pkey = EVP_PKEY_new(); 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // RSA_generate_key is deprecated. Use _ex version. 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIGNUM* exponent = BN_new(); 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org RSA* rsa = RSA_new(); 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!pkey || !exponent || !rsa || 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !BN_set_word(exponent, 0x10001) || // 65537 RSA exponent 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !RSA_generate_key_ex(rsa, KEY_LENGTH, exponent, NULL) || 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !EVP_PKEY_assign_RSA(pkey, rsa)) { 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org EVP_PKEY_free(pkey); 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BN_free(exponent); 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org RSA_free(rsa); 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // ownership of rsa struct was assigned, don't free it. 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BN_free(exponent); 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Returning key pair"; 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return pkey; 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Generate a self-signed certificate, with the public key from the 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// given key pair. Caller is responsible for freeing the returned object. 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) { 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Making certificate for " << params.common_name; 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509* x509 = NULL; 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIGNUM* serial_number = NULL; 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509_NAME* name = NULL; 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((x509=X509_new()) == NULL) 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org goto error; 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!X509_set_pubkey(x509, pkey)) 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org goto error; 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // serial number 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // temporary reference to serial number inside x509 struct 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASN1_INTEGER* asn1_serial_number; 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((serial_number = BN_new()) == NULL || 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !BN_pseudo_rand(serial_number, SERIAL_RAND_BITS, 0, 0) || 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org (asn1_serial_number = X509_get_serialNumber(x509)) == NULL || 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)) 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org goto error; 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!X509_set_version(x509, 0L)) // version 1 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org goto error; 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // There are a lot of possible components for the name entries. In 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // our P2P SSL mode however, the certificates are pre-exchanged 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // (through the secure XMPP channel), and so the certificate 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // identification is arbitrary. It can't be empty, so we set some 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // arbitrary common_name. Note that this certificate goes out in 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // clear during SSL negotiation, so there may be a privacy issue in 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // putting anything recognizable here. 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((name = X509_NAME_new()) == NULL || 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !X509_NAME_add_entry_by_NID( 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org name, NID_commonName, MBSTRING_UTF8, 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org (unsigned char*)params.common_name.c_str(), -1, -1, 0) || 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !X509_set_subject_name(x509, name) || 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !X509_set_issuer_name(x509, name)) 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org goto error; 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!X509_gmtime_adj(X509_get_notBefore(x509), params.not_before) || 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !X509_gmtime_adj(X509_get_notAfter(x509), params.not_after)) 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org goto error; 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!X509_sign(x509, pkey, EVP_sha1())) 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org goto error; 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BN_free(serial_number); 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509_NAME_free(name); 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Returning certificate"; 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return x509; 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error: 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BN_free(serial_number); 12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509_NAME_free(name); 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509_free(x509); 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// This dumps the SSL error stack to the log. 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void LogSSLErrors(const std::string& prefix) { 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org char error_buf[200]; 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org unsigned long err; 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org while ((err = ERR_get_error()) != 0) { 13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ERR_error_string_n(err, error_buf, sizeof(error_buf)); 13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << prefix << ": " << error_buf << "\n"; 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLKeyPair* OpenSSLKeyPair::Generate() { 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org EVP_PKEY* pkey = MakeKey(); 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!pkey) { 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LogSSLErrors("Generating key pair"); 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return new OpenSSLKeyPair(pkey); 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLKeyPair::~OpenSSLKeyPair() { 15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org EVP_PKEY_free(pkey_); 15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid OpenSSLKeyPair::AddReference() { 15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CRYPTO_add(&pkey_->references, 1, CRYPTO_LOCK_EVP_PKEY); 15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG 15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Print a certificate to the log, for debugging. 16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void PrintCert(X509* x509) { 16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO* temp_memory_bio = BIO_new(BIO_s_mem()); 16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!temp_memory_bio) { 16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; 16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0); 16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_write(temp_memory_bio, "\0", 1); 16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org char* buffer; 16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_get_mem_data(temp_memory_bio, &buffer); 17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_VERBOSE) << buffer; 17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_free(temp_memory_bio); 17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLCertificate* OpenSSLCertificate::Generate( 17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) { 17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SSLIdentityParams actual_params(params); 17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (actual_params.common_name.empty()) { 17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Use a random string, arbitrarily 8chars long. 18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org actual_params.common_name = CreateRandomString(8); 18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509* x509 = MakeCertificate(key_pair->pkey(), actual_params); 18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!x509) { 18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LogSSLErrors("Generating certificate"); 18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG 18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PrintCert(x509); 18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org OpenSSLCertificate* ret = new OpenSSLCertificate(x509); 19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509_free(x509); 19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ret; 19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLCertificate* OpenSSLCertificate::FromPEMString( 19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const std::string& pem_string) { 19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1); 19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!bio) 19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_set_mem_eof_return(bio, 0); 20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL, 20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const_cast<char*>("\0")); 20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_free(bio); // Frees the BIO, but not the pointed-to string. 20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!x509) 20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org OpenSSLCertificate* ret = new OpenSSLCertificate(x509); 20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509_free(x509); 21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ret; 21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// NOTE: This implementation only functions correctly after InitializeSSL 21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// and before CleanupSSL. 21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLCertificate::GetSignatureDigestAlgorithm( 21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org std::string* algorithm) const { 21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return OpenSSLDigest::GetDigestName( 21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org EVP_get_digestbyobj(x509_->sig_alg->algorithm), algorithm); 21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLCertificate::ComputeDigest(const std::string& algorithm, 22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org unsigned char* digest, 22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t size, 22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t* length) const { 22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ComputeDigest(x509_, algorithm, digest, size, length); 22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLCertificate::ComputeDigest(const X509* x509, 22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const std::string& algorithm, 23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org unsigned char* digest, 23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t size, 23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t* length) { 23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const EVP_MD *md; 23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org unsigned int n; 23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!OpenSSLDigest::GetDigestEVP(algorithm, &md)) 23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (size < static_cast<size_t>(EVP_MD_size(md))) 24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509_digest(x509, md, digest, &n); 24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *length = n; 24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLCertificate::~OpenSSLCertificate() { 25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org X509_free(x509_); 25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string OpenSSLCertificate::ToPEMString() const { 25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO* bio = BIO_new(BIO_s_mem()); 25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!bio) { 25654ade8bbee7cea004418c02de3658ffc870fc968andrew@webrtc.org FATAL() << "unreachable code"; 25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!PEM_write_bio_X509(bio, x509_)) { 25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_free(bio); 26054ade8bbee7cea004418c02de3658ffc870fc968andrew@webrtc.org FATAL() << "unreachable code"; 26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_write(bio, "\0", 1); 26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org char* buffer; 26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_get_mem_data(bio, &buffer); 26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org std::string ret(buffer); 26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_free(bio); 26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ret; 26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid OpenSSLCertificate::ToDER(Buffer* der_buffer) const { 27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // In case of failure, make sure to leave the buffer empty. 27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org der_buffer->SetData(NULL, 0); 27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Calculates the DER representation of the certificate, from scratch. 27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO* bio = BIO_new(BIO_s_mem()); 27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!bio) { 27754ade8bbee7cea004418c02de3658ffc870fc968andrew@webrtc.org FATAL() << "unreachable code"; 27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!i2d_X509_bio(bio, x509_)) { 28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_free(bio); 28154ade8bbee7cea004418c02de3658ffc870fc968andrew@webrtc.org FATAL() << "unreachable code"; 28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org char* data; 28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t length = BIO_get_mem_data(bio, &data); 28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org der_buffer->SetData(data, length); 28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_free(bio); 28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid OpenSSLCertificate::AddReference() const { 29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(x509_ != NULL); 29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509); 29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLIdentity* OpenSSLIdentity::GenerateInternal( 29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const SSLIdentityParams& params) { 29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org OpenSSLKeyPair *key_pair = OpenSSLKeyPair::Generate(); 29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (key_pair) { 29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org OpenSSLCertificate *certificate = OpenSSLCertificate::Generate( 29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org key_pair, params); 30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (certificate) 30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return new OpenSSLIdentity(key_pair, certificate); 30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete key_pair; 30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Identity generation failed"; 30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name) { 30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SSLIdentityParams params; 31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org params.common_name = common_name; 31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org params.not_before = CERTIFICATE_WINDOW; 31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org params.not_after = CERTIFICATE_LIFETIME; 31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return GenerateInternal(params); 31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLIdentity* OpenSSLIdentity::GenerateForTest( 31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const SSLIdentityParams& params) { 31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return GenerateInternal(params); 31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSSLIdentity* OpenSSLIdentity::FromPEMStrings( 32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const std::string& private_key, 32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const std::string& certificate) { 32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org scoped_ptr<OpenSSLCertificate> cert( 32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org OpenSSLCertificate::FromPEMString(certificate)); 32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!cert) { 32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Failed to create OpenSSLCertificate from PEM string."; 32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO* bio = BIO_new_mem_buf(const_cast<char*>(private_key.c_str()), -1); 33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!bio) { 33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Failed to create a new BIO buffer."; 33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_set_mem_eof_return(bio, 0); 33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, 33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const_cast<char*>("\0")); 33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BIO_free(bio); // Frees the BIO, but not the pointed-to string. 34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!pkey) { 34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Failed to create the private key from PEM string."; 34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return new OpenSSLIdentity(new OpenSSLKeyPair(pkey), 34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org cert.release()); 34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) { 35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 1 is the documented success return code. 35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 || 35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) { 35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LogSSLErrors("Configuring key and certificate"); 35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif // HAVE_OPENSSL_SSL_H 363