x509_certificate_model_nss.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/net/x509_certificate_model.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cert.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cms.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <hasht.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <keyhi.h>  // SECKEY_DestroyPrivateKey
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <keythi.h>  // SECKEYPrivateKey
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pk11pub.h>  // PK11_FindKeyByAnyCert
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <seccomon.h>  // SECItem
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sechash.h>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_number_conversions.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/scoped_nss_types.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/x509_certificate.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/third_party/mozilla_security_manager/nsNSSCertificate.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/third_party/mozilla_security_manager/nsUsageArrayHelper.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace psm = mozilla_security_manager;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert a char* return value from NSS into a std::string and free the NSS
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory.  If the arg is NULL, an empty string will be returned instead.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Stringize(char* nss_text, const std::string& alternative_text) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nss_text)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return alternative_text;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string s = nss_text;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PORT_Free(nss_text);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return s;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Hash a certificate using the given algorithm, return the result as a
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// colon-seperated hex string.  The len specified is the number of bytes
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// required for storing the raw fingerprint.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (It's a bit redundant that the caller needs to specify len in addition to the
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// algorithm, but given the limited uses, not worth fixing.)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string HashCert(CERTCertificate* cert, HASH_HashType algorithm, int len) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char fingerprint[HASH_LENGTH_MAX];
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(NULL != cert->derCert.data);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(0U, cert->derCert.len);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(len, HASH_LENGTH_MAX);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(fingerprint, 0, len);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = HASH_HashBuf(algorithm, fingerprint, cert->derCert.data,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              cert->derCert.len);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(rv, SECSuccess);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return x509_certificate_model::ProcessRawBytes(fingerprint, len);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProcessSecAlgorithmInternal(SECAlgorithmID* algorithm_id) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return psm::GetOIDText(&algorithm_id->algorithm);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProcessExtension(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& critical_label,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& non_critical_label,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERTCertExtension* extension) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string criticality =
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension->critical.data && extension->critical.data[0] ?
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          critical_label : non_critical_label;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return criticality + "\n" +
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      psm::ProcessExtensionData(SECOID_FindOIDTag(&extension->id),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                &extension->value);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NSS certificate export functions.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FreeNSSCMSMessage {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void operator()(NSSCMSMessage* x) const {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSS_CMSMessage_Destroy(x);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef scoped_ptr_malloc<NSSCMSMessage, FreeNSSCMSMessage>
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedNSSCMSMessage;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FreeNSSCMSSignedData {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void operator()(NSSCMSSignedData* x) const {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSS_CMSSignedData_Destroy(x);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef scoped_ptr_malloc<NSSCMSSignedData, FreeNSSCMSSignedData>
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedNSSCMSSignedData;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace x509_certificate_model {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::X509Certificate;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetCertNameOrNickname(X509Certificate::OSCertHandle cert_handle) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string name = ProcessIDN(Stringize(CERT_GetCommonName(&cert_handle->subject),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     ""));
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!name.empty())
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return name;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetNickname(cert_handle);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetNickname(X509Certificate::OSCertHandle cert_handle) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string name;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert_handle->nickname) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = cert_handle->nickname;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hack copied from mozilla: Cut off text before first :, which seems to
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // just be the token name.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t colon_pos = name.find(':');
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (colon_pos != string::npos)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = name.substr(colon_pos + 1);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return name;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetTokenName(X509Certificate::OSCertHandle cert_handle) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return psm::GetCertTokenName(cert_handle);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetVersion(X509Certificate::OSCertHandle cert_handle) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the version field is omitted from the certificate, the default
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value is v1(0).
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long version = 0;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert_handle->version.len == 0 ||
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SEC_ASN1DecodeInteger(&cert_handle->version, &version) == SECSuccess) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::UintToString(version + 1);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "";
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::CertType GetType(X509Certificate::OSCertHandle cert_handle) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return psm::GetCertType(cert_handle);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetEmailAddress(X509Certificate::OSCertHandle cert_handle) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert_handle->emailAddr)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cert_handle->emailAddr;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "";
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetUsageStrings(X509Certificate::OSCertHandle cert_handle,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     std::vector<string>* usages) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  psm::GetCertUsageStrings(cert_handle, usages);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetKeyUsageString(X509Certificate::OSCertHandle cert_handle) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem key_usage;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_usage.data = NULL;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string key_usage_str;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CERT_FindKeyUsageExtension(cert_handle, &key_usage) == SECSuccess) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key_usage_str = psm::ProcessKeyUsageBitString(&key_usage, ',');
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Free(key_usage.data);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return key_usage_str;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSerialNumberHexified(X509Certificate::OSCertHandle cert_handle,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const string& alternative_text) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Stringize(CERT_Hexify(&cert_handle->serialNumber, true),
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   alternative_text);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetIssuerCommonName(X509Certificate::OSCertHandle cert_handle,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const string& alternative_text) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Stringize(CERT_GetCommonName(&cert_handle->issuer), alternative_text);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetIssuerOrgName(X509Certificate::OSCertHandle cert_handle,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const string& alternative_text) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Stringize(CERT_GetOrgName(&cert_handle->issuer), alternative_text);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetIssuerOrgUnitName(X509Certificate::OSCertHandle cert_handle,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const string& alternative_text) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Stringize(CERT_GetOrgUnitName(&cert_handle->issuer), alternative_text);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSubjectOrgName(X509Certificate::OSCertHandle cert_handle,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const string& alternative_text) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Stringize(CERT_GetOrgName(&cert_handle->subject), alternative_text);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSubjectOrgUnitName(X509Certificate::OSCertHandle cert_handle,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const string& alternative_text) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Stringize(CERT_GetOrgUnitName(&cert_handle->subject),
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   alternative_text);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSubjectCommonName(X509Certificate::OSCertHandle cert_handle,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const string& alternative_text) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Stringize(CERT_GetCommonName(&cert_handle->subject), alternative_text);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetTimes(X509Certificate::OSCertHandle cert_handle,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              base::Time* issued, base::Time* expires) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRTime pr_issued, pr_expires;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CERT_GetCertTimes(cert_handle, &pr_issued, &pr_expires) == SECSuccess) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *issued = crypto::PRTimeToBaseTime(pr_issued);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *expires = crypto::PRTimeToBaseTime(pr_expires);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetTitle(X509Certificate::OSCertHandle cert_handle) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return psm::GetCertTitle(cert_handle);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetIssuerName(X509Certificate::OSCertHandle cert_handle) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return psm::ProcessName(&cert_handle->issuer);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSubjectName(X509Certificate::OSCertHandle cert_handle) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return psm::ProcessName(&cert_handle->subject);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetEmailAddresses(X509Certificate::OSCertHandle cert_handle,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       std::vector<string>* email_addresses) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (const char* addr = CERT_GetFirstEmailAddress(cert_handle);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       addr; addr = CERT_GetNextEmailAddress(cert_handle, addr)) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The first email addr (from Subject) may be duplicated in Subject
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Alternative Name, so check subsequent addresses are not equal to the
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // first one before adding to the list.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!email_addresses->size() || (*email_addresses)[0] != addr)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      email_addresses->push_back(addr);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetNicknameStringsFromCertList(
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<scoped_refptr<X509Certificate> >& certs,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& cert_expired,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& cert_not_yet_valid,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<string>* nick_names) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERTCertList* cert_list = CERT_NewCertList();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < certs.size(); ++i) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERT_AddCertToListTail(
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_list,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CERT_DupCertificate(certs[i]->os_cert_handle()));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Would like to use CERT_GetCertNicknameWithValidity on each cert
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // individually instead of having to build a CERTCertList for this, but that
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // function is not exported.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERTCertNicknames* cert_nicknames = CERT_NicknameStringsFromCertList(
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_list,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const_cast<char*>(cert_expired.c_str()),
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const_cast<char*>(cert_not_yet_valid.c_str()));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(cert_nicknames->numnicknames,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<int>(certs.size()));
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < cert_nicknames->numnicknames; ++i)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nick_names->push_back(cert_nicknames->nicknames[i]);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERT_FreeNicknames(cert_nicknames);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERT_DestroyCertList(cert_list);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For background see this discussion on dev-tech-crypto.lists.mozilla.org:
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://web.archiveorange.com/archive/v/6JJW7E40sypfZGtbkzxX
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: This function relies on the convention that the same PKCS#11 ID
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is shared between a certificate and its associated private and public
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// keys.  I tried to implement this with PK11_GetLowLevelKeyIDForCert(),
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but that always returns NULL on Chrome OS for me.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetPkcs11Id(net::X509Certificate::OSCertHandle cert_handle) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string pkcs11_id;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEYPrivateKey *priv_key = PK11_FindKeyByAnyCert(cert_handle,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     NULL /* wincx */);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (priv_key) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Get the CKA_ID attribute for a key.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem* sec_item = PK11_GetLowLevelKeyIDForPrivateKey(priv_key);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sec_item) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pkcs11_id = base::HexEncode(sec_item->data, sec_item->len);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SECITEM_FreeItem(sec_item, PR_TRUE);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEY_DestroyPrivateKey(priv_key);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pkcs11_id;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetExtensions(
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& critical_label,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& non_critical_label,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    X509Certificate::OSCertHandle cert_handle,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Extensions* extensions) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert_handle->extensions) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; cert_handle->extensions[i] != NULL; ++i) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Extension extension;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension.name = psm::GetOIDText(&cert_handle->extensions[i]->id);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension.value = ProcessExtension(
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          critical_label, non_critical_label, cert_handle->extensions[i]);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions->push_back(extension);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string HashCertSHA256(X509Certificate::OSCertHandle cert_handle) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HashCert(cert_handle, HASH_AlgSHA256, SHA256_LENGTH);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string HashCertSHA1(X509Certificate::OSCertHandle cert_handle) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HashCert(cert_handle, HASH_AlgSHA1, SHA1_LENGTH);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCertChainFromCert(X509Certificate::OSCertHandle cert_handle,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          X509Certificate::OSCertHandles* cert_handles) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERTCertList* cert_list =
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_GetCertChainFromCert(cert_handle, PR_Now(), certUsageSSLServer);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERTCertListNode* node;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (node = CERT_LIST_HEAD(cert_list);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !CERT_LIST_END(node, cert_list);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       node = CERT_LIST_NEXT(node)) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cert_handles->push_back(CERT_DupCertificate(node->cert));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERT_DestroyCertList(cert_list);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DestroyCertChain(X509Certificate::OSCertHandles* cert_handles) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (X509Certificate::OSCertHandles::iterator i(cert_handles->begin());
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != cert_handles->end(); ++i)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERT_DestroyCertificate(*i);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_handles->clear();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetDerString(X509Certificate::OSCertHandle cert_handle) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return string(reinterpret_cast<const char*>(cert_handle->derCert.data),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                cert_handle->derCert.len);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetCMSString(const X509Certificate::OSCertHandles& cert_chain,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    size_t start, size_t end) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::ScopedPLArenaPool arena(PORT_NewArena(1024));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(arena.get());
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedNSSCMSMessage message(NSS_CMSMessage_Create(arena.get()));
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message.get());
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First, create SignedData with the certificate only (no chain).
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedNSSCMSSignedData signed_data(NSS_CMSSignedData_CreateCertsOnly(
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message.get(), cert_chain[start], PR_FALSE));
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!signed_data.get()) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "NSS_CMSSignedData_Create failed";
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "";
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the rest of the chain (if any).
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = start + 1; i < end; ++i) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NSS_CMSSignedData_AddCertificate(signed_data.get(), cert_chain[i]) !=
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SECSuccess) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(ERROR) << "NSS_CMSSignedData_AddCertificate failed on " << i;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "";
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSSCMSContentInfo *cinfo = NSS_CMSMessage_GetContentInfo(message.get());
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NSS_CMSContentInfo_SetContent_SignedData(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message.get(), cinfo, signed_data.get()) == SECSuccess) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ignore_result(signed_data.release());
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "NSS_CMSMessage_GetContentInfo failed";
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "";
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem cert_p7 = { siBuffer, NULL, 0 };
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSSCMSEncoderContext *ecx = NSS_CMSEncoder_Start(message.get(), NULL, NULL,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &cert_p7, arena.get(), NULL,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   NULL, NULL, NULL, NULL,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   NULL);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ecx) {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "NSS_CMSEncoder_Start failed";
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "";
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "NSS_CMSEncoder_Finish failed";
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "";
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return string(reinterpret_cast<const char*>(cert_p7.data), cert_p7.len);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessSecAlgorithmSignature(X509Certificate::OSCertHandle cert_handle) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProcessSecAlgorithmInternal(&cert_handle->signature);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessSecAlgorithmSubjectPublicKey(
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    X509Certificate::OSCertHandle cert_handle) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProcessSecAlgorithmInternal(
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &cert_handle->subjectPublicKeyInfo.algorithm);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessSecAlgorithmSignatureWrap(
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    X509Certificate::OSCertHandle cert_handle) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProcessSecAlgorithmInternal(
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &cert_handle->signatureWrap.signatureAlgorithm);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessSubjectPublicKeyInfo(X509Certificate::OSCertHandle cert_handle) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return psm::ProcessSubjectPublicKeyInfo(&cert_handle->subjectPublicKeyInfo);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessRawBitsSignatureWrap(X509Certificate::OSCertHandle cert_handle) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProcessRawBits(cert_handle->signatureWrap.signature.data,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        cert_handle->signatureWrap.signature.len);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RegisterDynamicOids() {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  psm::RegisterDynamicOids();
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace x509_certificate_model
417