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