1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2008, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/opensslidentity.h" 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/ssl.h> 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/bio.h> 32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/err.h> 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/pem.h> 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/bn.h> 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/rsa.h> 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/crypto.h> 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h" 39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/helpers.h" 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base { 42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// We could have exposed a myriad of parameters for the crypto stuff, 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// but keeping it simple seems best. 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Strength of generated keys. Those are RSA. 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const int KEY_LENGTH = 1024; 48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Random bits for certificate serial number 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const int SERIAL_RAND_BITS = 64; 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Certificate validity lifetime 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const int CERTIFICATE_LIFETIME = 60*60*24*365; // one year, arbitrarily 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Generate a key pair. Caller is responsible for freeing the returned object. 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic EVP_PKEY* MakeKey() { 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Making key pair"; 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch EVP_PKEY* pkey = EVP_PKEY_new(); 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if OPENSSL_VERSION_NUMBER < 0x00908000l 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Only RSA_generate_key is available. Use that. 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RSA* rsa = RSA_generate_key(KEY_LENGTH, 0x10001, NULL, NULL); 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!EVP_PKEY_assign_RSA(pkey, rsa)) { 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch EVP_PKEY_free(pkey); 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RSA_free(rsa); 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // RSA_generate_key is deprecated. Use _ex version. 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIGNUM* exponent = BN_new(); 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RSA* rsa = RSA_new(); 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!pkey || !exponent || !rsa || 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !BN_set_word(exponent, 0x10001) || // 65537 RSA exponent 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !RSA_generate_key_ex(rsa, KEY_LENGTH, exponent, NULL) || 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !EVP_PKEY_assign_RSA(pkey, rsa)) { 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch EVP_PKEY_free(pkey); 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BN_free(exponent); 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RSA_free(rsa); 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // ownership of rsa struct was assigned, don't free it. 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BN_free(exponent); 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Returning key pair"; 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return pkey; 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Generate a self-signed certificate, with the public key from the 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// given key pair. Caller is responsible for freeing the returned object. 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic X509* MakeCertificate(EVP_PKEY* pkey, const char* common_name) { 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Making certificate for " << common_name; 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch X509* x509 = NULL; 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIGNUM* serial_number = NULL; 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch X509_NAME* name = NULL; 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((x509=X509_new()) == NULL) 96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch goto error; 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!X509_set_pubkey(x509, pkey)) 99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch goto error; 100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // serial number 102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // temporary reference to serial number inside x509 struct 103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASN1_INTEGER* asn1_serial_number; 104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!(serial_number = BN_new()) || 105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !BN_pseudo_rand(serial_number, SERIAL_RAND_BITS, 0, 0) || 106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !(asn1_serial_number = X509_get_serialNumber(x509)) || 107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)) 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch goto error; 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!X509_set_version(x509, 0L)) // version 1 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch goto error; 112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // There are a lot of possible components for the name entries. In 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // our P2P SSL mode however, the certificates are pre-exchanged 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // (through the secure XMPP channel), and so the certificate 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // identification is arbitrary. It can't be empty, so we set some 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // arbitrary common_name. Note that this certificate goes out in 118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // clear during SSL negotiation, so there may be a privacy issue in 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // putting anything recognizable here. 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!(name = X509_NAME_new()) || 121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8, 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (unsigned char*)common_name, -1, -1, 0) || 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !X509_set_subject_name(x509, name) || 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !X509_set_issuer_name(x509, name)) 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch goto error; 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!X509_gmtime_adj(X509_get_notBefore(x509), 0) || 128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !X509_gmtime_adj(X509_get_notAfter(x509), CERTIFICATE_LIFETIME)) 129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch goto error; 130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!X509_sign(x509, pkey, EVP_sha1())) 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch goto error; 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BN_free(serial_number); 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch X509_NAME_free(name); 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Returning certificate"; 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return x509; 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error: 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BN_free(serial_number); 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch X509_NAME_free(name); 142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch X509_free(x509); 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// This dumps the SSL error stack to the log. 147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic void LogSSLErrors(const std::string& prefix) { 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char error_buf[200]; 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch unsigned long err; 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while ((err = ERR_get_error())) { 151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ERR_error_string_n(err, error_buf, sizeof(error_buf)); 152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_ERROR) << prefix << ": " << error_buf << "\n"; 153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLKeyPair* OpenSSLKeyPair::Generate() { 157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch EVP_PKEY* pkey = MakeKey(); 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!pkey) { 159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LogSSLErrors("Generating key pair"); 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return new OpenSSLKeyPair(pkey); 163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLKeyPair::~OpenSSLKeyPair() { 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch EVP_PKEY_free(pkey_); 167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid OpenSSLKeyPair::AddReference() { 170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CRYPTO_add(&pkey_->references, 1, CRYPTO_LOCK_EVP_PKEY); 171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Print a certificate to the log, for debugging. 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic void PrintCert(X509* x509) { 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO* temp_memory_bio = BIO_new(BIO_s_mem()); 177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!temp_memory_bio) { 178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; 179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0); 182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO_write(temp_memory_bio, "\0", 1); 183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char* buffer; 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO_get_mem_data(temp_memory_bio, &buffer); 185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_VERBOSE) << buffer; 186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO_free(temp_memory_bio); 187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLCertificate* OpenSSLCertificate::Generate( 191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch OpenSSLKeyPair* key_pair, const std::string& common_name) { 192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string actual_common_name = common_name; 193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (actual_common_name.empty()) 194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Use a random string, arbitrarily 8chars long. 195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch actual_common_name = CreateRandomString(8); 196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch X509* x509 = MakeCertificate(key_pair->pkey(), actual_common_name.c_str()); 197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!x509) { 198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LogSSLErrors("Generating certificate"); 199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PrintCert(x509); 203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return new OpenSSLCertificate(x509); 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLCertificate* OpenSSLCertificate::FromPEMString( 208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const std::string& pem_string, int* pem_length) { 209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1); 210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!bio) 211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (void)BIO_set_close(bio, BIO_NOCLOSE); 213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO_set_mem_eof_return(bio, 0); 214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL, 215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const_cast<char*>("\0")); 216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char *ptr; 217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int remaining_length = BIO_get_mem_data(bio, &ptr); 218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO_free(bio); 219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (pem_length) 220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *pem_length = pem_string.length() - remaining_length; 221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (x509) 222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return new OpenSSLCertificate(x509); 223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch else 224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLCertificate::~OpenSSLCertificate() { 228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch X509_free(x509_); 229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string OpenSSLCertificate::ToPEMString() const { 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO* bio = BIO_new(BIO_s_mem()); 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!bio) 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!PEM_write_bio_X509(bio, x509_)) { 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO_free(bio); 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO_write(bio, "\0", 1); 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char* buffer; 241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO_get_mem_data(bio, &buffer); 242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string ret(buffer); 243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BIO_free(bio); 244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ret; 245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid OpenSSLCertificate::AddReference() { 248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509); 249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name) { 252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch OpenSSLKeyPair *key_pair = OpenSSLKeyPair::Generate(); 253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (key_pair) { 254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch OpenSSLCertificate *certificate = 255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch OpenSSLCertificate::Generate(key_pair, common_name); 256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (certificate) 257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return new OpenSSLIdentity(key_pair, certificate); 258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete key_pair; 259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Identity generation failed"; 261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) { 265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // 1 is the documented success return code. 266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 || 267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) { 268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LogSSLErrors("Configuring key and certificate"); 269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // talk_base namespace 275