16a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek/* 26a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek * Copyright 2012 The WebRTC Project Authors. All rights reserved. 36a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek * 46a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek * Use of this source code is governed by a BSD-style license 56a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek * that can be found in the LICENSE file in the root of the source 66a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek * tree. An additional intellectual property rights grant can be found 76a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek * in the file PATENTS. All contributing project authors may 86a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek * be found in the AUTHORS file in the root of the source tree. 96a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek */ 106a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 116a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include <algorithm> 126a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include <string> 136a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include <vector> 146a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 15339b9c27759d7b6a53e2370f83f66e78b3254595Ted Kremenek#if HAVE_CONFIG_H 166a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include "config.h" 176a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#endif // HAVE_CONFIG_H 18867924dbeca06870573fd58d620032da6994b223Chris Lattner 193245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner#if HAVE_NSS_SSL_H 206a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 2157df3b950061c73d13d3116f747e79d7955a216aChris Lattner#include "webrtc/base/nssidentity.h" 22339b9c27759d7b6a53e2370f83f66e78b3254595Ted Kremenek 236a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include "cert.h" 24a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek#include "cryptohi.h" 256a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include "keyhi.h" 266a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek#include "nss.h" 279402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner#include "pk11pub.h" 285ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner#include "sechash.h" 295ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner 305ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner#include "webrtc/base/logging.h" 315ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner#include "webrtc/base/helpers.h" 325ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner#include "webrtc/base/nssstreamadapter.h" 335ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner#include "webrtc/base/safe_conversions.h" 345ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner 35f7cf85b330bedd2877e1371fb0a83e99751ae162Chris Lattnernamespace rtc { 36f7cf85b330bedd2877e1371fb0a83e99751ae162Chris Lattner 37a11d61793341fea195c29a0dab3fbd74f2b39a8cChris Lattner// Certificate validity lifetime in seconds. 38a11d61793341fea195c29a0dab3fbd74f2b39a8cChris Lattnerstatic const int CERTIFICATE_LIFETIME = 60*60*24*30; // 30 days, arbitrarily 395ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner// Certificate validity window in seconds. 4052c29081281955d3db9e11d10573b2d38f709099Chris Lattner// This is to compensate for slightly incorrect system clocks. 4152c29081281955d3db9e11d10573b2d38f709099Chris Lattnerstatic const int CERTIFICATE_WINDOW = -60*60*24; 425ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner 435ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris LattnerNSSKeyPair::~NSSKeyPair() { 442c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner if (privkey_) 455ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner SECKEY_DestroyPrivateKey(privkey_); 462b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner if (pubkey_) 472b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner SECKEY_DestroyPublicKey(pubkey_); 485ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner} 495ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner 505ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris LattnerNSSKeyPair *NSSKeyPair::Generate() { 515ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner SECKEYPrivateKey *privkey = NULL; 525ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner SECKEYPublicKey *pubkey = NULL; 535ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner PK11RSAGenParams rsaparams; 545ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner rsaparams.keySizeInBits = 1024; 559402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner rsaparams.pe = 0x010001; // 65537 -- a common RSA public exponent. 56d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar 57d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar privkey = PK11_GenerateKeyPair(NSSContext::GetSlot(), 585ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner CKM_RSA_PKCS_KEY_PAIR_GEN, 599402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner &rsaparams, &pubkey, PR_FALSE /*permanent*/, 609402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner PR_FALSE /*sensitive*/, NULL); 619402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner if (!privkey) { 629402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner LOG(LS_ERROR) << "Couldn't generate key pair"; 639402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner return NULL; 649402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner } 659402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner 669402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner return new NSSKeyPair(privkey, pubkey); 679402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner} 689402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner 699402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner// Just make a copy. 709402b57a0dca4058fe56d7fd84e97fc496421125Chris LattnerNSSKeyPair *NSSKeyPair::GetReference() { 71d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar SECKEYPrivateKey *privkey = SECKEY_CopyPrivateKey(privkey_); 729402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner if (!privkey) 739402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner return NULL; 749402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner 759402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner SECKEYPublicKey *pubkey = SECKEY_CopyPublicKey(pubkey_); 769402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner if (!pubkey) { 779402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner SECKEY_DestroyPrivateKey(privkey); 789402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner return NULL; 799402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner } 809402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner 819402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner return new NSSKeyPair(privkey, pubkey); 829402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner} 839402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner 849402b57a0dca4058fe56d7fd84e97fc496421125Chris LattnerNSSCertificate::NSSCertificate(CERTCertificate* cert) 859402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner : certificate_(CERT_DupCertificate(cert)) { 869402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner ASSERT(certificate_ != NULL); 879402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner} 889402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner 899402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattnerstatic void DeleteCert(SSLCertificate* cert) { 90d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar delete cert; 919402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner} 929402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner 939402b57a0dca4058fe56d7fd84e97fc496421125Chris LattnerNSSCertificate::NSSCertificate(CERTCertList* cert_list) { 949402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner // Copy the first cert into certificate_. 959402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 969402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner certificate_ = CERT_DupCertificate(node->cert); 979402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner 989402b57a0dca4058fe56d7fd84e97fc496421125Chris Lattner // Put any remaining certificates into the chain. 995ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner node = CERT_LIST_NEXT(node); 1005ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner std::vector<SSLCertificate*> certs; 1012b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { 102fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek certs.push_back(new NSSCertificate(node->cert)); 1036a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek } 1042b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner 1056a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek if (!certs.empty()) 1066a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek chain_.reset(new SSLCertChain(certs)); 1076a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek 1086a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek // The SSLCertChain constructor copies its input, so now we have to delete 1096a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek // the originals. 1102b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner std::for_each(certs.begin(), certs.end(), DeleteCert); 1115c176f7a9ba9f7084b903393845be24f85e091daChris Lattner} 1125c176f7a9ba9f7084b903393845be24f85e091daChris Lattner 1136a34083e9f74a45e2f79c9fab66f177809a5db66Ted KremenekNSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain) 1146a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek : certificate_(CERT_DupCertificate(cert)) { 1155c176f7a9ba9f7084b903393845be24f85e091daChris Lattner ASSERT(certificate_ != NULL); 1165c176f7a9ba9f7084b903393845be24f85e091daChris Lattner if (chain) 1175c176f7a9ba9f7084b903393845be24f85e091daChris Lattner chain_.reset(chain->Copy()); 1185c176f7a9ba9f7084b903393845be24f85e091daChris Lattner} 1195c176f7a9ba9f7084b903393845be24f85e091daChris Lattner 120735271479ac57c27f744806859efd5b001dea248Chris Lattner 121735271479ac57c27f744806859efd5b001dea248Chris LattnerNSSCertificate *NSSCertificate::FromPEMString(const std::string &pem_string) { 122735271479ac57c27f744806859efd5b001dea248Chris Lattner std::string der; 123d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) 1245c176f7a9ba9f7084b903393845be24f85e091daChris Lattner return NULL; 125735271479ac57c27f744806859efd5b001dea248Chris Lattner 126f3d8d19caf6f1a21785eee8d62c45ef5a0a0e72eChris Lattner SECItem der_cert; 127d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>( 128f3d8d19caf6f1a21785eee8d62c45ef5a0a0e72eChris Lattner der.data())); 129f3d8d19caf6f1a21785eee8d62c45ef5a0a0e72eChris Lattner der_cert.len = checked_cast<unsigned int>(der.size()); 130f3d8d19caf6f1a21785eee8d62c45ef5a0a0e72eChris Lattner CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 1315c176f7a9ba9f7084b903393845be24f85e091daChris Lattner &der_cert, NULL, PR_FALSE, PR_TRUE); 132735271479ac57c27f744806859efd5b001dea248Chris Lattner 13349cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek if (!cert) 1345c176f7a9ba9f7084b903393845be24f85e091daChris Lattner return NULL; 135735271479ac57c27f744806859efd5b001dea248Chris Lattner 136d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar NSSCertificate* ret = new NSSCertificate(cert); 137d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar CERT_DestroyCertificate(cert); 138d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar return ret; 139735271479ac57c27f744806859efd5b001dea248Chris Lattner} 140d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar 1415c176f7a9ba9f7084b903393845be24f85e091daChris LattnerNSSCertificate *NSSCertificate::GetReference() const { 142735271479ac57c27f744806859efd5b001dea248Chris Lattner return new NSSCertificate(certificate_, chain_.get()); 1435c176f7a9ba9f7084b903393845be24f85e091daChris Lattner} 144735271479ac57c27f744806859efd5b001dea248Chris Lattner 145d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbarstd::string NSSCertificate::ToPEMString() const { 1465c176f7a9ba9f7084b903393845be24f85e091daChris Lattner return SSLIdentity::DerToPem(kPemTypeCertificate, 147735271479ac57c27f744806859efd5b001dea248Chris Lattner certificate_->derCert.data, 148735271479ac57c27f744806859efd5b001dea248Chris Lattner certificate_->derCert.len); 149735271479ac57c27f744806859efd5b001dea248Chris Lattner} 150d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar 1515c176f7a9ba9f7084b903393845be24f85e091daChris Lattnervoid NSSCertificate::ToDER(Buffer* der_buffer) const { 152735271479ac57c27f744806859efd5b001dea248Chris Lattner der_buffer->SetData(certificate_->derCert.data, certificate_->derCert.len); 153735271479ac57c27f744806859efd5b001dea248Chris Lattner} 154735271479ac57c27f744806859efd5b001dea248Chris Lattner 155d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbarstatic bool Certifies(CERTCertificate* parent, CERTCertificate* child) { 1565c176f7a9ba9f7084b903393845be24f85e091daChris Lattner // TODO(bemasc): Identify stricter validation checks to use here. In the 157735271479ac57c27f744806859efd5b001dea248Chris Lattner // context of some future identity standard, it might make sense to check 1586a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek // the certificates' roles, expiration dates, self-signatures (if 1596a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek // self-signed), certificate transparency logging, or many other attributes. 1606a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek // NOTE: Future changes to this validation may reject some previously allowed 1616a34083e9f74a45e2f79c9fab66f177809a5db66Ted Kremenek // certificate chains. Users should be advised not to deploy chained 162fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek // certificates except in controlled environments until the validity 163fa5be3617294f0e3c341f0ecb6b2076478b1b5acTed Kremenek // requirements are finalized. 164053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 165053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek // Check that the parent's name is the same as the child's claimed issuer. 166a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek SECComparison name_status = 167a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek CERT_CompareName(&child->issuer, &parent->subject); 168053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek if (name_status != SECEqual) 169053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek return false; 170053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 171053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek // Extract the parent's public key, or fail if the key could not be read 172053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek // (e.g. certificate is corrupted). 1738570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner SECKEYPublicKey* parent_key = CERT_ExtractPublicKey(parent); 1748570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner if (!parent_key) 1758570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner return false; 1768570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner 1778570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner // Check that the parent's privkey was actually used to generate the child's 1788570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner // signature. 1798570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner SECStatus verified = CERT_VerifySignedDataWithPublicKey( 1808570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner &child->signatureWrap, parent_key, NULL); 181c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu SECKEY_DestroyPublicKey(parent_key); 182c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu return verified == SECSuccess; 183c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu} 184c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu 185c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xubool NSSCertificate::IsValidChain(const CERTCertList* cert_list) { 186c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu CERTCertListNode* child = CERT_LIST_HEAD(cert_list); 187c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu for (CERTCertListNode* parent = CERT_LIST_NEXT(child); 188c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu !CERT_LIST_END(parent, cert_list); 189c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu child = parent, parent = CERT_LIST_NEXT(parent)) { 190c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu if (!Certifies(parent->cert, child->cert)) 191c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu return false; 1928570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner } 193c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu return true; 1948570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner} 195c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu 196c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xubool NSSCertificate::GetDigestLength(const std::string& algorithm, 197c01b46e2f115bed83f2f6f4a55809bf4003ee015Zhongxing Xu size_t* length) { 198053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek const SECHashObject *ho; 199053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 200053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek if (!GetDigestObject(algorithm, &ho)) 201053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek return false; 202053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek 203053ef593fa9d2b890645a914eee203231fb34458Ted Kremenek *length = ho->length; 2048570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner 2058570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner return true; 2067e37c818f9f77608c602ffb32c1135e3cd0132a8Daniel Dunbar} 2077e37c818f9f77608c602ffb32c1135e3cd0132a8Daniel Dunbar 2087e37c818f9f77608c602ffb32c1135e3cd0132a8Daniel Dunbarbool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const { 2097e37c818f9f77608c602ffb32c1135e3cd0132a8Daniel Dunbar // The function sec_DecodeSigAlg in NSS provides this mapping functionality. 2107e37c818f9f77608c602ffb32c1135e3cd0132a8Daniel Dunbar // Unfortunately it is private, so the functionality must be duplicated here. 2117e37c818f9f77608c602ffb32c1135e3cd0132a8Daniel Dunbar // See https://bugzilla.mozilla.org/show_bug.cgi?id=925165 . 21257df3b950061c73d13d3116f747e79d7955a216aChris Lattner SECOidTag sig_alg = SECOID_GetAlgorithmTag(&certificate_->signature); 21349cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek switch (sig_alg) { 2147e37c818f9f77608c602ffb32c1135e3cd0132a8Daniel Dunbar case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: 215d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar *algorithm = DIGEST_MD5; 21657df3b950061c73d13d3116f747e79d7955a216aChris Lattner break; 217d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: 218d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: 21949cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE: 220b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: 221b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: 2222b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: 223b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_MISSI_DSS: 2242b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner case SEC_OID_MISSI_KEA_DSS: 225b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_MISSI_KEA_DSS_OLD: 226b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_MISSI_DSS_OLD: 227b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek *algorithm = DIGEST_SHA_1; 2282b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner break; 229b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: 230b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION: 231b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST: 232b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek *algorithm = DIGEST_SHA_224; 233b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek break; 234b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: 235b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: 236b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST: 237b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek *algorithm = DIGEST_SHA_256; 238b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek break; 239b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: 240b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: 241b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek *algorithm = DIGEST_SHA_384; 242b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek break; 243b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: 244b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: 245b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek *algorithm = DIGEST_SHA_512; 24649cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek break; 24749cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek default: 24849cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek // Unknown algorithm. There are several unhandled options that are less 24949cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek // common and more complex. 25049cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek algorithm->clear(); 25149cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek return false; 252b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek } 253b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek return true; 25449cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek} 25549cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenek 25649cd6354d5373245dd2e69ca7b7113e6a795d36eTed Kremenekbool NSSCertificate::ComputeDigest(const std::string& algorithm, 257b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek unsigned char* digest, 2588570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner size_t size, 259d6c1360c2bf234c73572a865f119d0518aca8154Ted Kremenek size_t* length) const { 260d6c1360c2bf234c73572a865f119d0518aca8154Ted Kremenek const SECHashObject *ho; 2618570f0b0fde7ca812f8d37f52305f3df4dd2ce01Chris Lattner 262d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar if (!GetDigestObject(algorithm, &ho)) 263d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar return false; 264b485cd1e0a5a1e942d0e682b9b1c4bc9df111528Ted Kremenek 265ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek if (size < ho->length) // Sanity check for fit 2662b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner return false; 267f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek 268ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek SECStatus rv = HASH_HashBuf(ho->type, digest, 2692b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner certificate_->derCert.data, 270ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek certificate_->derCert.len); 271ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek if (rv != SECSuccess) 272ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek return false; 2732b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner 2742b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner *length = ho->length; 275ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek 276a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek return true; 277a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek} 278f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek 279f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenekbool NSSCertificate::GetChain(SSLCertChain** chain) const { 280f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek if (!chain_) 281f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek return false; 282f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek 283f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek *chain = chain_->Copy(); 284f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek return true; 28570bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek} 28670bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek 2874b0f81323b518429203051bbcd4864bbf4b000a9Ted Kremenekbool NSSCertificate::Equals(const NSSCertificate *tocompare) const { 288f5016260522e449e9bacdb0e5a87ad3932d9fbd4Ted Kremenek if (!certificate_->derCert.len) 28970bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek return false; 29070bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek if (!tocompare->certificate_->derCert.len) 291f5016260522e449e9bacdb0e5a87ad3932d9fbd4Ted Kremenek return false; 292f5016260522e449e9bacdb0e5a87ad3932d9fbd4Ted Kremenek 293cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek if (certificate_->derCert.len != tocompare->certificate_->derCert.len) 294f5016260522e449e9bacdb0e5a87ad3932d9fbd4Ted Kremenek return false; 2956f46be279f4bc8fc24611f060258bcfbe1c175c4Chris Lattner 29607339a63b46e38c954fcccbef721c609d0c2040eTed Kremenek return memcmp(certificate_->derCert.data, 29707339a63b46e38c954fcccbef721c609d0c2040eTed Kremenek tocompare->certificate_->derCert.data, 298dc5be47542e6d4a28d20abf9c0f0a0edd72939b6Chris Lattner certificate_->derCert.len) == 0; 2996f46be279f4bc8fc24611f060258bcfbe1c175c4Chris Lattner} 3008aa06aca8b2d3771a5405d789b2e704149045dd4Chris Lattner 301f5016260522e449e9bacdb0e5a87ad3932d9fbd4Ted Kremenek 3026f46be279f4bc8fc24611f060258bcfbe1c175c4Chris Lattnerbool NSSCertificate::GetDigestObject(const std::string &algorithm, 3036f46be279f4bc8fc24611f060258bcfbe1c175c4Chris Lattner const SECHashObject **hop) { 30470bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek const SECHashObject *ho; 3052223622d113d7cba04c2dfdbe032e2ba6ba10bc4Ted Kremenek HASH_HashType hash_type; 30670bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek 30770bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek if (algorithm == DIGEST_SHA_1) { 30870bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek hash_type = HASH_AlgSHA1; 30970bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek // HASH_AlgSHA224 is not supported in the chromium linux build system. 31070bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek#if 0 3112223622d113d7cba04c2dfdbe032e2ba6ba10bc4Ted Kremenek } else if (algorithm == DIGEST_SHA_224) { 31270bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek hash_type = HASH_AlgSHA224; 3133c59823096fe28a69a81f899c7f9f0e6eb8071a0Ted Kremenek#endif 31470bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek } else if (algorithm == DIGEST_SHA_256) { 3152f10398814e8d58cce029a7e73af21bb274dcd42Ted Kremenek hash_type = HASH_AlgSHA256; 31680bae763da8bf3f3c73379a1e5d10f5bce266bcaTed Kremenek } else if (algorithm == DIGEST_SHA_384) { 31780bae763da8bf3f3c73379a1e5d10f5bce266bcaTed Kremenek hash_type = HASH_AlgSHA384; 3182f10398814e8d58cce029a7e73af21bb274dcd42Ted Kremenek } else if (algorithm == DIGEST_SHA_512) { 31980bae763da8bf3f3c73379a1e5d10f5bce266bcaTed Kremenek hash_type = HASH_AlgSHA512; 32070bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek } else { 32170bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek return false; 3223c59823096fe28a69a81f899c7f9f0e6eb8071a0Ted Kremenek } 3233c59823096fe28a69a81f899c7f9f0e6eb8071a0Ted Kremenek 32400f01e440573b2bdf6549991e0ca48cc6747e3a2Ted Kremenek ho = HASH_GetHashObject(hash_type); 32500f01e440573b2bdf6549991e0ca48cc6747e3a2Ted Kremenek 32600f01e440573b2bdf6549991e0ca48cc6747e3a2Ted Kremenek ASSERT(ho->length >= 20); // Can't happen 3274b2d3f7bcc4df31157df443af1b80bcaa9b58bbaDouglas Gregor *hop = ho; 3284b2d3f7bcc4df31157df443af1b80bcaa9b58bbaDouglas Gregor 3294b2d3f7bcc4df31157df443af1b80bcaa9b58bbaDouglas Gregor return true; 3304b0f81323b518429203051bbcd4864bbf4b000a9Ted Kremenek} 3314b0f81323b518429203051bbcd4864bbf4b000a9Ted Kremenek 3324b0f81323b518429203051bbcd4864bbf4b000a9Ted Kremenek 3334b0f81323b518429203051bbcd4864bbf4b000a9Ted KremenekNSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params) { 3344b0f81323b518429203051bbcd4864bbf4b000a9Ted Kremenek std::string subject_name_string = "CN=" + params.common_name; 3354b0f81323b518429203051bbcd4864bbf4b000a9Ted Kremenek CERTName *subject_name = CERT_AsciiToName( 3364b0f81323b518429203051bbcd4864bbf4b000a9Ted Kremenek const_cast<char *>(subject_name_string.c_str())); 3374b0f81323b518429203051bbcd4864bbf4b000a9Ted Kremenek NSSIdentity *identity = NULL; 3384b0f81323b518429203051bbcd4864bbf4b000a9Ted Kremenek CERTSubjectPublicKeyInfo *spki = NULL; 339f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek CERTCertificateRequest *certreq = NULL; 34070bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek CERTValidity *validity = NULL; 341f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek CERTCertificate *certificate = NULL; 342f6f593fae2f0531b4bc06891941f7fbba5217618Ted Kremenek NSSKeyPair *keypair = NSSKeyPair::Generate(); 343ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek SECItem inner_der; 344ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek SECStatus rv; 34570bcba6030a76edf46c4f941ad9a5297a1f98c47Ted Kremenek PLArenaPool* arena; 346ad0a203130dc5d1fb7231b88767174511424fa98Ted Kremenek SECItem signed_cert; 3473245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner PRTime now = PR_Now(); 3483245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner PRTime not_before = 3493245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner now + static_cast<PRTime>(params.not_before) * PR_USEC_PER_SEC; 3503245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner PRTime not_after = 3513245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner now + static_cast<PRTime>(params.not_after) * PR_USEC_PER_SEC; 3522b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner 3532b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner inner_der.len = 0; 3543245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner inner_der.data = NULL; 35505db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 35605db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner if (!keypair) { 357025c3a66402fb713c2d9bf5dc174ff264765379aChris Lattner LOG(LS_ERROR) << "Couldn't generate key pair"; 358a745e8c52839d9c8dd0fd8d5276b4eab182ec7f2Chris Lattner goto fail; 3593245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner } 3603245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner 361678c6358c8d4e368c78629099142397c63c1ee35Chris Lattner if (!subject_name) { 3623245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner LOG(LS_ERROR) << "Couldn't convert subject name " << subject_name; 363c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner goto fail; 364c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner } 3653245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner 366590f0cc643274267d4d41125b62557e1d87886c3Chris Lattner spki = SECKEY_CreateSubjectPublicKeyInfo(keypair->pubkey()); 36774ea3e5c57c087c046223096a97ea4e365f85eb6Chris Lattner if (!spki) { 36874ea3e5c57c087c046223096a97ea4e365f85eb6Chris Lattner LOG(LS_ERROR) << "Couldn't create SPKI"; 36974ea3e5c57c087c046223096a97ea4e365f85eb6Chris Lattner goto fail; 37074ea3e5c57c087c046223096a97ea4e365f85eb6Chris Lattner } 37105db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 3723245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner certreq = CERT_CreateCertificateRequest(subject_name, spki, NULL); 3733245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner if (!certreq) { 374a745e8c52839d9c8dd0fd8d5276b4eab182ec7f2Chris Lattner LOG(LS_ERROR) << "Couldn't create certificate signing request"; 375a745e8c52839d9c8dd0fd8d5276b4eab182ec7f2Chris Lattner goto fail; 376a745e8c52839d9c8dd0fd8d5276b4eab182ec7f2Chris Lattner } 377a745e8c52839d9c8dd0fd8d5276b4eab182ec7f2Chris Lattner 378a745e8c52839d9c8dd0fd8d5276b4eab182ec7f2Chris Lattner validity = CERT_CreateValidity(not_before, not_after); 379a745e8c52839d9c8dd0fd8d5276b4eab182ec7f2Chris Lattner if (!validity) { 380a745e8c52839d9c8dd0fd8d5276b4eab182ec7f2Chris Lattner LOG(LS_ERROR) << "Couldn't create validity"; 3815ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner goto fail; 3825ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner } 3835ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner 384c4586c234edd8df0477a895aebcbc3eb220aed6bChris Lattner unsigned long serial; 385a745e8c52839d9c8dd0fd8d5276b4eab182ec7f2Chris Lattner // Note: This serial in principle could collide, but it's unlikely 3863245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner rv = PK11_GenerateRandom(reinterpret_cast<unsigned char *>(&serial), 3875ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner sizeof(serial)); 3885ef3e2c45f13fccdb0d7bbcf24c1beee8eee6f64Chris Lattner if (rv != SECSuccess) { 3893245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner LOG(LS_ERROR) << "Couldn't generate random serial"; 390cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek goto fail; 391cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek } 392cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek 393cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek certificate = CERT_CreateCertificate(serial, subject_name, validity, certreq); 394cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek if (!certificate) { 395cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek LOG(LS_ERROR) << "Couldn't create certificate"; 396cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek goto fail; 397cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek } 398cc1b8532a113fa3216096757b3b4e203867bd5e0Ted Kremenek 3995deb96d06583abb751463427457d46041af262d0Chris Lattner arena = certificate->arena; 40074ea3e5c57c087c046223096a97ea4e365f85eb6Chris Lattner 4015deb96d06583abb751463427457d46041af262d0Chris Lattner rv = SECOID_SetAlgorithmID(arena, &certificate->signature, 4025deb96d06583abb751463427457d46041af262d0Chris Lattner SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, NULL); 4035deb96d06583abb751463427457d46041af262d0Chris Lattner if (rv != SECSuccess) 4045deb96d06583abb751463427457d46041af262d0Chris Lattner goto fail; 4055deb96d06583abb751463427457d46041af262d0Chris Lattner 4065deb96d06583abb751463427457d46041af262d0Chris Lattner // Set version to X509v3. 407590f0cc643274267d4d41125b62557e1d87886c3Chris Lattner *(certificate->version.data) = 2; 4085deb96d06583abb751463427457d46041af262d0Chris Lattner certificate->version.len = 1; 40905db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 410590f0cc643274267d4d41125b62557e1d87886c3Chris Lattner if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate, 41174ea3e5c57c087c046223096a97ea4e365f85eb6Chris Lattner SEC_ASN1_GET(CERT_CertificateTemplate))) 4125deb96d06583abb751463427457d46041af262d0Chris Lattner goto fail; 4135deb96d06583abb751463427457d46041af262d0Chris Lattner 4145deb96d06583abb751463427457d46041af262d0Chris Lattner rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, 4155deb96d06583abb751463427457d46041af262d0Chris Lattner keypair->privkey(), 4165deb96d06583abb751463427457d46041af262d0Chris Lattner SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION); 4175deb96d06583abb751463427457d46041af262d0Chris Lattner if (rv != SECSuccess) { 4185deb96d06583abb751463427457d46041af262d0Chris Lattner LOG(LS_ERROR) << "Couldn't sign certificate"; 4195deb96d06583abb751463427457d46041af262d0Chris Lattner goto fail; 4203245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner } 4213245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner certificate->derCert = signed_cert; 422590f0cc643274267d4d41125b62557e1d87886c3Chris Lattner 42374ea3e5c57c087c046223096a97ea4e365f85eb6Chris Lattner identity = new NSSIdentity(keypair, new NSSCertificate(certificate)); 4243245a0a1c7a4fd74fca845b2edba275bb126d773Chris Lattner 425c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner goto done; 4267c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner 4277c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner fail: 4287c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner delete keypair; 4297c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner 4307c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner done: 4317c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner if (certificate) CERT_DestroyCertificate(certificate); 4327c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner if (subject_name) CERT_DestroyName(subject_name); 4337c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki); 4347c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner if (certreq) CERT_DestroyCertificateRequest(certreq); 4357c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner if (validity) CERT_DestroyValidity(validity); 4367c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner return identity; 437c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner} 43805db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 439c54d50a4180520370c12dd7d06d035263d357d56Chris LattnerNSSIdentity* NSSIdentity::Generate(const std::string &common_name) { 440c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner SSLIdentityParams params; 4412b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner params.common_name = common_name; 44205db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner params.not_before = CERTIFICATE_WINDOW; 44305db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner params.not_after = CERTIFICATE_LIFETIME; 44405db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner return GenerateInternal(params); 44505db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner} 44605db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 44705db4278ecd193edcff63fb8c54818226fceaad2Chris LattnerNSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params) { 44805db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner return GenerateInternal(params); 44905db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner} 45005db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 45105db4278ecd193edcff63fb8c54818226fceaad2Chris LattnerSSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, 45205db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner const std::string& certificate) { 45305db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner std::string private_key_der; 45405db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner if (!SSLIdentity::PemToDer( 45505db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner kPemTypeRsaPrivateKey, private_key, &private_key_der)) 45605db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner return NULL; 45705db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 45805db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner SECItem private_key_item; 459f0b26b1d9dee57c84e55f05200802658a7312683Chris Lattner private_key_item.data = reinterpret_cast<unsigned char *>( 460f0b26b1d9dee57c84e55f05200802658a7312683Chris Lattner const_cast<char *>(private_key_der.c_str())); 461f0b26b1d9dee57c84e55f05200802658a7312683Chris Lattner private_key_item.len = checked_cast<unsigned int>(private_key_der.size()); 462f0b26b1d9dee57c84e55f05200802658a7312683Chris Lattner 463f0b26b1d9dee57c84e55f05200802658a7312683Chris Lattner const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | 46405db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner KU_DIGITAL_SIGNATURE; 46505db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 46605db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner SECKEYPrivateKey* privkey = NULL; 46705db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner SECStatus rv = 46805db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner PK11_ImportDERPrivateKeyInfoAndReturnKey(NSSContext::GetSlot(), 46905db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner &private_key_item, 47005db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner NULL, NULL, PR_FALSE, PR_FALSE, 47105db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner key_usage, &privkey, NULL); 47205db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner if (rv != SECSuccess) { 47305db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner LOG(LS_ERROR) << "Couldn't import private key"; 47405db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner return NULL; 47505db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner } 47605db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 47705db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(privkey); 47805db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner if (rv != SECSuccess) { 4797c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner SECKEY_DestroyPrivateKey(privkey); 4807c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner LOG(LS_ERROR) << "Couldn't convert private key to public key"; 4817c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner return NULL; 4827c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner } 4837c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner 4847c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner // Assign to a scoped_ptr so we don't leak on error. 4857c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey)); 4867c175fb196a2bc3dbc86ea3865c713e1875f3f6dChris Lattner 487c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate)); 488fb58609c5b3f0d665ea58e37ef39eb7ea74758a4Ted Kremenek if (!cert) { 48905db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner LOG(LS_ERROR) << "Couldn't parse certificate"; 49005db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner return NULL; 49105db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner } 49205db4278ecd193edcff63fb8c54818226fceaad2Chris Lattner 493c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner // TODO(ekr@rtfm.com): Check the public key against the certificate. 494867924dbeca06870573fd58d620032da6994b223Chris Lattner 495867924dbeca06870573fd58d620032da6994b223Chris Lattner return new NSSIdentity(keypair.release(), cert.release()); 496c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner} 497c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner 498fb58609c5b3f0d665ea58e37ef39eb7ea74758a4Ted KremenekNSSIdentity *NSSIdentity::GetReference() const { 499c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner NSSKeyPair *keypair = keypair_->GetReference(); 500c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner if (!keypair) 501c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner return NULL; 502fb58609c5b3f0d665ea58e37ef39eb7ea74758a4Ted Kremenek 503c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner NSSCertificate *certificate = certificate_->GetReference(); 504c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner if (!certificate) { 505c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner delete keypair; 506b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris Lattner return NULL; 507b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris Lattner } 508b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris Lattner 509b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris Lattner return new NSSIdentity(keypair, certificate); 510b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris Lattner} 511c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner 512b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris Lattner 513b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris LattnerNSSCertificate &NSSIdentity::certificate() const { 514fb58609c5b3f0d665ea58e37ef39eb7ea74758a4Ted Kremenek return *certificate_; 515c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner} 516c54d50a4180520370c12dd7d06d035263d357d56Chris Lattner 517b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris Lattner 518b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris Lattner} // rtc namespace 519b7949a9a91ad8e49124cd6a82ff98972d7efaadcChris Lattner 520e9e6cb93afa51eee1f83abc7e2cb7d8a0453d810Chris Lattner#endif // HAVE_NSS_SSL_H 521b83ded0db9824b3b0417bf46540ed34d48776673Ted Kremenek 5226f46be279f4bc8fc24611f060258bcfbe1c175c4Chris Lattner