This source file includes following definitions.
- Stringize
- HashCert
- ProcessSecAlgorithmInternal
- ProcessExtension
- GetCertNameOrNickname
- GetNickname
- GetTokenName
- GetVersion
- GetType
- GetEmailAddress
- GetUsageStrings
- GetKeyUsageString
- GetSerialNumberHexified
- GetIssuerCommonName
- GetIssuerOrgName
- GetIssuerOrgUnitName
- GetSubjectOrgName
- GetSubjectOrgUnitName
- GetSubjectCommonName
- GetTimes
- GetTitle
- GetIssuerName
- GetSubjectName
- GetEmailAddresses
- GetNicknameStringsFromCertList
- GetPkcs11Id
- GetExtensions
- HashCertSHA256
- HashCertSHA1
- GetCertChainFromCert
- DestroyCertChain
- GetDerString
- GetCMSString
- ProcessSecAlgorithmSignature
- ProcessSecAlgorithmSubjectPublicKey
- ProcessSecAlgorithmSignatureWrap
- ProcessSubjectPublicKeyInfo
- ProcessRawBitsSignatureWrap
- RegisterDynamicOids
#include "chrome/common/net/x509_certificate_model.h"
#include <cert.h>
#include <cms.h>
#include <hasht.h>
#include <keyhi.h>
#include <keythi.h>
#include <pk11pub.h>
#include <seccomon.h>
#include <sechash.h>
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h"
#include "chrome/third_party/mozilla_security_manager/nsNSSCertificate.h"
#include "chrome/third_party/mozilla_security_manager/nsUsageArrayHelper.h"
#include "crypto/nss_util.h"
#include "crypto/scoped_nss_types.h"
#include "net/cert/x509_certificate.h"
namespace psm = mozilla_security_manager;
namespace {
std::string Stringize(char* nss_text, const std::string& alternative_text) {
if (!nss_text)
return alternative_text;
std::string s = nss_text;
PORT_Free(nss_text);
return s;
}
std::string HashCert(CERTCertificate* cert, HASH_HashType algorithm, int len) {
unsigned char fingerprint[HASH_LENGTH_MAX];
DCHECK(NULL != cert->derCert.data);
DCHECK_NE(0U, cert->derCert.len);
DCHECK_LE(len, HASH_LENGTH_MAX);
memset(fingerprint, 0, len);
SECStatus rv = HASH_HashBuf(algorithm, fingerprint, cert->derCert.data,
cert->derCert.len);
DCHECK_EQ(rv, SECSuccess);
return x509_certificate_model::ProcessRawBytes(fingerprint, len);
}
std::string ProcessSecAlgorithmInternal(SECAlgorithmID* algorithm_id) {
return psm::GetOIDText(&algorithm_id->algorithm);
}
std::string ProcessExtension(
const std::string& critical_label,
const std::string& non_critical_label,
CERTCertExtension* extension) {
std::string criticality =
extension->critical.data && extension->critical.data[0] ?
critical_label : non_critical_label;
return criticality + "\n" +
psm::ProcessExtensionData(SECOID_FindOIDTag(&extension->id),
&extension->value);
}
struct NSSCMSMessageDeleter {
inline void operator()(NSSCMSMessage* x) const {
NSS_CMSMessage_Destroy(x);
}
};
typedef scoped_ptr<NSSCMSMessage, NSSCMSMessageDeleter> ScopedNSSCMSMessage;
struct FreeNSSCMSSignedData {
inline void operator()(NSSCMSSignedData* x) const {
NSS_CMSSignedData_Destroy(x);
}
};
typedef scoped_ptr<NSSCMSSignedData, FreeNSSCMSSignedData>
ScopedNSSCMSSignedData;
}
namespace x509_certificate_model {
using net::X509Certificate;
using std::string;
string GetCertNameOrNickname(X509Certificate::OSCertHandle cert_handle) {
string name = ProcessIDN(
Stringize(CERT_GetCommonName(&cert_handle->subject), std::string()));
if (!name.empty())
return name;
return GetNickname(cert_handle);
}
string GetNickname(X509Certificate::OSCertHandle cert_handle) {
string name;
if (cert_handle->nickname) {
name = cert_handle->nickname;
size_t colon_pos = name.find(':');
if (colon_pos != string::npos)
name = name.substr(colon_pos + 1);
}
return name;
}
string GetTokenName(X509Certificate::OSCertHandle cert_handle) {
return psm::GetCertTokenName(cert_handle);
}
string GetVersion(X509Certificate::OSCertHandle cert_handle) {
unsigned long version = 0;
if (cert_handle->version.len == 0 ||
SEC_ASN1DecodeInteger(&cert_handle->version, &version) == SECSuccess) {
return base::UintToString(version + 1);
}
return std::string();
}
net::CertType GetType(X509Certificate::OSCertHandle cert_handle) {
return psm::GetCertType(cert_handle);
}
string GetEmailAddress(X509Certificate::OSCertHandle cert_handle) {
if (cert_handle->emailAddr)
return cert_handle->emailAddr;
return std::string();
}
void GetUsageStrings(X509Certificate::OSCertHandle cert_handle,
std::vector<string>* usages) {
psm::GetCertUsageStrings(cert_handle, usages);
}
string GetKeyUsageString(X509Certificate::OSCertHandle cert_handle) {
SECItem key_usage;
key_usage.data = NULL;
string key_usage_str;
if (CERT_FindKeyUsageExtension(cert_handle, &key_usage) == SECSuccess) {
key_usage_str = psm::ProcessKeyUsageBitString(&key_usage, ',');
PORT_Free(key_usage.data);
}
return key_usage_str;
}
string GetSerialNumberHexified(X509Certificate::OSCertHandle cert_handle,
const string& alternative_text) {
return Stringize(CERT_Hexify(&cert_handle->serialNumber, true),
alternative_text);
}
string GetIssuerCommonName(X509Certificate::OSCertHandle cert_handle,
const string& alternative_text) {
return Stringize(CERT_GetCommonName(&cert_handle->issuer), alternative_text);
}
string GetIssuerOrgName(X509Certificate::OSCertHandle cert_handle,
const string& alternative_text) {
return Stringize(CERT_GetOrgName(&cert_handle->issuer), alternative_text);
}
string GetIssuerOrgUnitName(X509Certificate::OSCertHandle cert_handle,
const string& alternative_text) {
return Stringize(CERT_GetOrgUnitName(&cert_handle->issuer), alternative_text);
}
string GetSubjectOrgName(X509Certificate::OSCertHandle cert_handle,
const string& alternative_text) {
return Stringize(CERT_GetOrgName(&cert_handle->subject), alternative_text);
}
string GetSubjectOrgUnitName(X509Certificate::OSCertHandle cert_handle,
const string& alternative_text) {
return Stringize(CERT_GetOrgUnitName(&cert_handle->subject),
alternative_text);
}
string GetSubjectCommonName(X509Certificate::OSCertHandle cert_handle,
const string& alternative_text) {
return Stringize(CERT_GetCommonName(&cert_handle->subject), alternative_text);
}
bool GetTimes(X509Certificate::OSCertHandle cert_handle,
base::Time* issued, base::Time* expires) {
PRTime pr_issued, pr_expires;
if (CERT_GetCertTimes(cert_handle, &pr_issued, &pr_expires) == SECSuccess) {
*issued = crypto::PRTimeToBaseTime(pr_issued);
*expires = crypto::PRTimeToBaseTime(pr_expires);
return true;
}
return false;
}
string GetTitle(X509Certificate::OSCertHandle cert_handle) {
return psm::GetCertTitle(cert_handle);
}
string GetIssuerName(X509Certificate::OSCertHandle cert_handle) {
return psm::ProcessName(&cert_handle->issuer);
}
string GetSubjectName(X509Certificate::OSCertHandle cert_handle) {
return psm::ProcessName(&cert_handle->subject);
}
void GetEmailAddresses(X509Certificate::OSCertHandle cert_handle,
std::vector<string>* email_addresses) {
for (const char* addr = CERT_GetFirstEmailAddress(cert_handle);
addr; addr = CERT_GetNextEmailAddress(cert_handle, addr)) {
if (!email_addresses->size() || (*email_addresses)[0] != addr)
email_addresses->push_back(addr);
}
}
void GetNicknameStringsFromCertList(
const std::vector<scoped_refptr<X509Certificate> >& certs,
const string& cert_expired,
const string& cert_not_yet_valid,
std::vector<string>* nick_names) {
CERTCertList* cert_list = CERT_NewCertList();
for (size_t i = 0; i < certs.size(); ++i) {
CERT_AddCertToListTail(
cert_list,
CERT_DupCertificate(certs[i]->os_cert_handle()));
}
CERTCertNicknames* cert_nicknames = CERT_NicknameStringsFromCertList(
cert_list,
const_cast<char*>(cert_expired.c_str()),
const_cast<char*>(cert_not_yet_valid.c_str()));
DCHECK_EQ(cert_nicknames->numnicknames,
static_cast<int>(certs.size()));
for (int i = 0; i < cert_nicknames->numnicknames; ++i)
nick_names->push_back(cert_nicknames->nicknames[i]);
CERT_FreeNicknames(cert_nicknames);
CERT_DestroyCertList(cert_list);
}
std::string GetPkcs11Id(net::X509Certificate::OSCertHandle cert_handle) {
std::string pkcs11_id;
SECKEYPrivateKey *priv_key = PK11_FindKeyByAnyCert(cert_handle,
NULL );
if (priv_key) {
SECItem* sec_item = PK11_GetLowLevelKeyIDForPrivateKey(priv_key);
if (sec_item) {
pkcs11_id = base::HexEncode(sec_item->data, sec_item->len);
SECITEM_FreeItem(sec_item, PR_TRUE);
}
SECKEY_DestroyPrivateKey(priv_key);
}
return pkcs11_id;
}
void GetExtensions(
const string& critical_label,
const string& non_critical_label,
X509Certificate::OSCertHandle cert_handle,
Extensions* extensions) {
if (cert_handle->extensions) {
for (size_t i = 0; cert_handle->extensions[i] != NULL; ++i) {
Extension extension;
extension.name = psm::GetOIDText(&cert_handle->extensions[i]->id);
extension.value = ProcessExtension(
critical_label, non_critical_label, cert_handle->extensions[i]);
extensions->push_back(extension);
}
}
}
string HashCertSHA256(X509Certificate::OSCertHandle cert_handle) {
return HashCert(cert_handle, HASH_AlgSHA256, SHA256_LENGTH);
}
string HashCertSHA1(X509Certificate::OSCertHandle cert_handle) {
return HashCert(cert_handle, HASH_AlgSHA1, SHA1_LENGTH);
}
void GetCertChainFromCert(X509Certificate::OSCertHandle cert_handle,
X509Certificate::OSCertHandles* cert_handles) {
CERTCertList* cert_list =
CERT_GetCertChainFromCert(cert_handle, PR_Now(), certUsageSSLServer);
CERTCertListNode* node;
for (node = CERT_LIST_HEAD(cert_list);
!CERT_LIST_END(node, cert_list);
node = CERT_LIST_NEXT(node)) {
cert_handles->push_back(CERT_DupCertificate(node->cert));
}
CERT_DestroyCertList(cert_list);
}
void DestroyCertChain(X509Certificate::OSCertHandles* cert_handles) {
for (X509Certificate::OSCertHandles::iterator i(cert_handles->begin());
i != cert_handles->end(); ++i)
CERT_DestroyCertificate(*i);
cert_handles->clear();
}
string GetDerString(X509Certificate::OSCertHandle cert_handle) {
return string(reinterpret_cast<const char*>(cert_handle->derCert.data),
cert_handle->derCert.len);
}
string GetCMSString(const X509Certificate::OSCertHandles& cert_chain,
size_t start, size_t end) {
crypto::ScopedPLArenaPool arena(PORT_NewArena(1024));
DCHECK(arena.get());
ScopedNSSCMSMessage message(NSS_CMSMessage_Create(arena.get()));
DCHECK(message.get());
ScopedNSSCMSSignedData signed_data(NSS_CMSSignedData_CreateCertsOnly(
message.get(), cert_chain[start], PR_FALSE));
if (!signed_data.get()) {
DLOG(ERROR) << "NSS_CMSSignedData_Create failed";
return std::string();
}
for (size_t i = start + 1; i < end; ++i) {
if (NSS_CMSSignedData_AddCertificate(signed_data.get(), cert_chain[i]) !=
SECSuccess) {
DLOG(ERROR) << "NSS_CMSSignedData_AddCertificate failed on " << i;
return std::string();
}
}
NSSCMSContentInfo *cinfo = NSS_CMSMessage_GetContentInfo(message.get());
if (NSS_CMSContentInfo_SetContent_SignedData(
message.get(), cinfo, signed_data.get()) == SECSuccess) {
ignore_result(signed_data.release());
} else {
DLOG(ERROR) << "NSS_CMSMessage_GetContentInfo failed";
return std::string();
}
SECItem cert_p7 = { siBuffer, NULL, 0 };
NSSCMSEncoderContext *ecx = NSS_CMSEncoder_Start(message.get(), NULL, NULL,
&cert_p7, arena.get(), NULL,
NULL, NULL, NULL, NULL,
NULL);
if (!ecx) {
DLOG(ERROR) << "NSS_CMSEncoder_Start failed";
return std::string();
}
if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) {
DLOG(ERROR) << "NSS_CMSEncoder_Finish failed";
return std::string();
}
return string(reinterpret_cast<const char*>(cert_p7.data), cert_p7.len);
}
string ProcessSecAlgorithmSignature(X509Certificate::OSCertHandle cert_handle) {
return ProcessSecAlgorithmInternal(&cert_handle->signature);
}
string ProcessSecAlgorithmSubjectPublicKey(
X509Certificate::OSCertHandle cert_handle) {
return ProcessSecAlgorithmInternal(
&cert_handle->subjectPublicKeyInfo.algorithm);
}
string ProcessSecAlgorithmSignatureWrap(
X509Certificate::OSCertHandle cert_handle) {
return ProcessSecAlgorithmInternal(
&cert_handle->signatureWrap.signatureAlgorithm);
}
string ProcessSubjectPublicKeyInfo(X509Certificate::OSCertHandle cert_handle) {
return psm::ProcessSubjectPublicKeyInfo(&cert_handle->subjectPublicKeyInfo);
}
string ProcessRawBitsSignatureWrap(X509Certificate::OSCertHandle cert_handle) {
return ProcessRawBits(cert_handle->signatureWrap.signature.data,
cert_handle->signatureWrap.signature.len);
}
void RegisterDynamicOids() {
psm::RegisterDynamicOids();
}
}