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" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/third_party/mozilla_security_manager/nsNSSCertificate.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/third_party/mozilla_security_manager/nsUsageArrayHelper.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "crypto/nss_util.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "crypto/scoped_nss_types.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.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; 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return criticality + "\n" + psm::ProcessExtensionData(extension); 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::string GetNickname(net::X509Certificate::OSCertHandle cert_handle) { 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string name; 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (cert_handle->nickname) { 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) name = cert_handle->nickname; 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Hack copied from mozilla: Cut off text before first :, which seems to 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // just be the token name. 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t colon_pos = name.find(':'); 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (colon_pos != std::string::npos) 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) name = name.substr(colon_pos + 1); 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return name; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NSS certificate export functions. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct NSSCMSMessageDeleter { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline void operator()(NSSCMSMessage* x) const { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSS_CMSMessage_Destroy(x); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef scoped_ptr<NSSCMSMessage, NSSCMSMessageDeleter> ScopedNSSCMSMessage; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct FreeNSSCMSSignedData { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline void operator()(NSSCMSSignedData* x) const { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSS_CMSSignedData_Destroy(x); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)typedef scoped_ptr<NSSCMSSignedData, FreeNSSCMSSignedData> 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedNSSCMSSignedData; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace x509_certificate_model { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::X509Certificate; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetCertNameOrNickname(X509Certificate::OSCertHandle cert_handle) { 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) string name = ProcessIDN( 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Stringize(CERT_GetCommonName(&cert_handle->subject), std::string())); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!name.empty()) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return name; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetNickname(cert_handle); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetTokenName(X509Certificate::OSCertHandle cert_handle) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return psm::GetCertTokenName(cert_handle); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetVersion(X509Certificate::OSCertHandle cert_handle) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the version field is omitted from the certificate, the default 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // value is v1(0). 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long version = 0; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cert_handle->version.len == 0 || 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SEC_ASN1DecodeInteger(&cert_handle->version, &version) == SECSuccess) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::UintToString(version + 1); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::CertType GetType(X509Certificate::OSCertHandle cert_handle) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return psm::GetCertType(cert_handle); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetUsageStrings(X509Certificate::OSCertHandle cert_handle, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<string>* usages) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) psm::GetCertUsageStrings(cert_handle, usages); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSerialNumberHexified(X509Certificate::OSCertHandle cert_handle, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& alternative_text) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Stringize(CERT_Hexify(&cert_handle->serialNumber, true), 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alternative_text); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetIssuerCommonName(X509Certificate::OSCertHandle cert_handle, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& alternative_text) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Stringize(CERT_GetCommonName(&cert_handle->issuer), alternative_text); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetIssuerOrgName(X509Certificate::OSCertHandle cert_handle, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& alternative_text) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Stringize(CERT_GetOrgName(&cert_handle->issuer), alternative_text); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetIssuerOrgUnitName(X509Certificate::OSCertHandle cert_handle, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& alternative_text) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Stringize(CERT_GetOrgUnitName(&cert_handle->issuer), alternative_text); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSubjectOrgName(X509Certificate::OSCertHandle cert_handle, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& alternative_text) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Stringize(CERT_GetOrgName(&cert_handle->subject), alternative_text); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSubjectOrgUnitName(X509Certificate::OSCertHandle cert_handle, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& alternative_text) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Stringize(CERT_GetOrgUnitName(&cert_handle->subject), 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alternative_text); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSubjectCommonName(X509Certificate::OSCertHandle cert_handle, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& alternative_text) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Stringize(CERT_GetCommonName(&cert_handle->subject), alternative_text); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetTimes(X509Certificate::OSCertHandle cert_handle, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time* issued, base::Time* expires) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRTime pr_issued, pr_expires; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CERT_GetCertTimes(cert_handle, &pr_issued, &pr_expires) == SECSuccess) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *issued = crypto::PRTimeToBaseTime(pr_issued); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *expires = crypto::PRTimeToBaseTime(pr_expires); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetTitle(X509Certificate::OSCertHandle cert_handle) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return psm::GetCertTitle(cert_handle); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetIssuerName(X509Certificate::OSCertHandle cert_handle) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return psm::ProcessName(&cert_handle->issuer); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetSubjectName(X509Certificate::OSCertHandle cert_handle) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return psm::ProcessName(&cert_handle->subject); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetExtensions( 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& critical_label, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& non_critical_label, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::OSCertHandle cert_handle, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Extensions* extensions) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cert_handle->extensions) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; cert_handle->extensions[i] != NULL; ++i) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Extension extension; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension.name = psm::GetOIDText(&cert_handle->extensions[i]->id); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension.value = ProcessExtension( 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) critical_label, non_critical_label, cert_handle->extensions[i]); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions->push_back(extension); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string HashCertSHA256(X509Certificate::OSCertHandle cert_handle) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HashCert(cert_handle, HASH_AlgSHA256, SHA256_LENGTH); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string HashCertSHA1(X509Certificate::OSCertHandle cert_handle) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HashCert(cert_handle, HASH_AlgSHA1, SHA1_LENGTH); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string GetCMSString(const X509Certificate::OSCertHandles& cert_chain, 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t start, size_t end) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::ScopedPLArenaPool arena(PORT_NewArena(1024)); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(arena.get()); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedNSSCMSMessage message(NSS_CMSMessage_Create(arena.get())); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(message.get()); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, create SignedData with the certificate only (no chain). 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedNSSCMSSignedData signed_data(NSS_CMSSignedData_CreateCertsOnly( 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message.get(), cert_chain[start], PR_FALSE)); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!signed_data.get()) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "NSS_CMSSignedData_Create failed"; 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the rest of the chain (if any). 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = start + 1; i < end; ++i) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NSS_CMSSignedData_AddCertificate(signed_data.get(), cert_chain[i]) != 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECSuccess) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "NSS_CMSSignedData_AddCertificate failed on " << i; 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSSCMSContentInfo *cinfo = NSS_CMSMessage_GetContentInfo(message.get()); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NSS_CMSContentInfo_SetContent_SignedData( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message.get(), cinfo, signed_data.get()) == SECSuccess) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_result(signed_data.release()); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "NSS_CMSMessage_GetContentInfo failed"; 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem cert_p7 = { siBuffer, NULL, 0 }; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSSCMSEncoderContext *ecx = NSS_CMSEncoder_Start(message.get(), NULL, NULL, 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cert_p7, arena.get(), NULL, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, NULL, NULL, NULL, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ecx) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "NSS_CMSEncoder_Start failed"; 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "NSS_CMSEncoder_Finish failed"; 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return string(reinterpret_cast<const char*>(cert_p7.data), cert_p7.len); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessSecAlgorithmSignature(X509Certificate::OSCertHandle cert_handle) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProcessSecAlgorithmInternal(&cert_handle->signature); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessSecAlgorithmSubjectPublicKey( 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::OSCertHandle cert_handle) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProcessSecAlgorithmInternal( 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cert_handle->subjectPublicKeyInfo.algorithm); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessSecAlgorithmSignatureWrap( 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::OSCertHandle cert_handle) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProcessSecAlgorithmInternal( 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cert_handle->signatureWrap.signatureAlgorithm); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessSubjectPublicKeyInfo(X509Certificate::OSCertHandle cert_handle) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return psm::ProcessSubjectPublicKeyInfo(&cert_handle->subjectPublicKeyInfo); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProcessRawBitsSignatureWrap(X509Certificate::OSCertHandle cert_handle) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProcessRawBits(cert_handle->signatureWrap.signature.data, 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle->signatureWrap.signature.len); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace x509_certificate_model 303