| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/common/net/x509_certificate_model.h" |
| |
| #include <openssl/bio.h> |
| #include <openssl/obj_mac.h> |
| #include <openssl/sha.h> |
| #include <openssl/x509v3.h> |
| |
| #include "base/logging.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "crypto/openssl_bio_string.h" |
| #include "crypto/openssl_util.h" |
| #include "net/cert/x509_util_openssl.h" |
| |
| namespace x509_util = net::x509_util; |
| |
| namespace { |
| |
| std::string AlternativeWhenEmpty(const std::string& text, |
| const std::string& alternative) { |
| return text.empty() ? alternative : text; |
| } |
| |
| std::string GetKeyValuesFromName(X509_NAME* name) { |
| std::string ret; |
| int rdns = X509_NAME_entry_count(name) - 1; |
| for (int i = rdns; i >= 0; --i) { |
| std::string key; |
| std::string value; |
| if (!x509_util::ParsePrincipalKeyAndValueByIndex(name, i, &key, &value)) |
| break; |
| ret += key; |
| ret += " = "; |
| ret += value; |
| ret += '\n'; |
| } |
| return ret; |
| } |
| |
| } // namespace |
| |
| namespace x509_certificate_model { |
| |
| using net::X509Certificate; |
| |
| std::string GetCertNameOrNickname(X509Certificate::OSCertHandle cert_handle) { |
| std::string name = |
| ProcessIDN(GetSubjectCommonName(cert_handle, std::string())); |
| if (!name.empty()) |
| return name; |
| |
| crypto::ScopedOpenSSL<BIO, BIO_free_all> bio(crypto::BIO_new_string(&name)); |
| if (!bio.get()) |
| return name; |
| X509_NAME_print_ex(bio.get(), |
| X509_get_subject_name(cert_handle), |
| 0 /* indent */, |
| XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB); |
| return name; |
| } |
| |
| std::string GetTokenName(X509Certificate::OSCertHandle cert_handle) { |
| // TODO(bulach): implement me. |
| return ""; |
| } |
| |
| std::string GetVersion(net::X509Certificate::OSCertHandle cert_handle) { |
| unsigned long version = X509_get_version(cert_handle); |
| if (version != ULONG_MAX) |
| return base::UintToString(version + 1); |
| return ""; |
| } |
| |
| net::CertType GetType(X509Certificate::OSCertHandle os_cert) { |
| // TODO(bulach): implement me. |
| return net::OTHER_CERT; |
| } |
| |
| void GetUsageStrings(X509Certificate::OSCertHandle cert_handle, |
| std::vector<std::string>* usages) { |
| // TODO(bulach): implement me. |
| } |
| |
| std::string GetSerialNumberHexified( |
| X509Certificate::OSCertHandle cert_handle, |
| const std::string& alternative_text) { |
| ASN1_INTEGER* num = X509_get_serialNumber(cert_handle); |
| const char kSerialNumberSeparator = ':'; |
| std::string hex_string = ProcessRawBytesWithSeparators( |
| num->data, num->length, kSerialNumberSeparator, kSerialNumberSeparator); |
| return AlternativeWhenEmpty(hex_string, alternative_text); |
| } |
| |
| std::string GetIssuerCommonName( |
| X509Certificate::OSCertHandle cert_handle, |
| const std::string& alternative_text) { |
| std::string ret; |
| x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle), |
| NID_commonName, &ret); |
| return AlternativeWhenEmpty(ret, alternative_text); |
| } |
| |
| std::string GetIssuerOrgName( |
| X509Certificate::OSCertHandle cert_handle, |
| const std::string& alternative_text) { |
| std::string ret; |
| x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle), |
| NID_organizationName, &ret); |
| return AlternativeWhenEmpty(ret, alternative_text); |
| } |
| |
| std::string GetIssuerOrgUnitName( |
| X509Certificate::OSCertHandle cert_handle, |
| const std::string& alternative_text) { |
| std::string ret; |
| x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle), |
| NID_organizationalUnitName, &ret); |
| return AlternativeWhenEmpty(ret, alternative_text); |
| } |
| |
| std::string GetSubjectOrgName( |
| X509Certificate::OSCertHandle cert_handle, |
| const std::string& alternative_text) { |
| std::string ret; |
| x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle), |
| NID_organizationName, &ret); |
| return AlternativeWhenEmpty(ret, alternative_text); |
| } |
| |
| std::string GetSubjectOrgUnitName( |
| X509Certificate::OSCertHandle cert_handle, |
| const std::string& alternative_text) { |
| std::string ret; |
| x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle), |
| NID_organizationalUnitName, &ret); |
| return AlternativeWhenEmpty(ret, alternative_text); |
| } |
| |
| std::string GetSubjectCommonName(X509Certificate::OSCertHandle cert_handle, |
| const std::string& alternative_text) { |
| std::string ret; |
| x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle), |
| NID_commonName, &ret); |
| return AlternativeWhenEmpty(ret, alternative_text); |
| } |
| |
| bool GetTimes(X509Certificate::OSCertHandle cert_handle, |
| base::Time* issued, base::Time* expires) { |
| return x509_util::ParseDate(X509_get_notBefore(cert_handle), issued) && |
| x509_util::ParseDate(X509_get_notAfter(cert_handle), expires); |
| } |
| |
| std::string GetTitle(net::X509Certificate::OSCertHandle cert_handle) { |
| // TODO(mattm): merge GetTitle and GetCertNameOrNickname? |
| // Is there any reason GetCertNameOrNickname calls ProcessIDN and this |
| // doesn't? |
| std::string title = |
| GetSubjectCommonName(cert_handle, std::string()); |
| if (!title.empty()) |
| return title; |
| |
| crypto::ScopedOpenSSL<BIO, BIO_free_all> bio(crypto::BIO_new_string(&title)); |
| if (!bio.get()) |
| return title; |
| X509_NAME_print_ex(bio.get(), |
| X509_get_subject_name(cert_handle), |
| 0 /* indent */, |
| XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB); |
| return title; |
| } |
| |
| std::string GetIssuerName(net::X509Certificate::OSCertHandle cert_handle) { |
| return GetKeyValuesFromName(X509_get_issuer_name(cert_handle)); |
| } |
| |
| std::string GetSubjectName(net::X509Certificate::OSCertHandle cert_handle) { |
| return GetKeyValuesFromName(X509_get_subject_name(cert_handle)); |
| } |
| |
| void GetExtensions( |
| const std::string& critical_label, |
| const std::string& non_critical_label, |
| net::X509Certificate::OSCertHandle cert_handle, |
| Extensions* extensions) { |
| // TODO(bulach): implement me. |
| } |
| |
| std::string HashCertSHA256(net::X509Certificate::OSCertHandle cert_handle) { |
| unsigned char sha256_data[SHA256_DIGEST_LENGTH] = {0}; |
| unsigned int sha256_size = sizeof(sha256_data); |
| int ret = X509_digest(cert_handle, EVP_sha256(), sha256_data, &sha256_size); |
| DCHECK(ret); |
| DCHECK_EQ(sha256_size, sizeof(sha256_data)); |
| return ProcessRawBytes(sha256_data, sha256_size); |
| } |
| |
| std::string HashCertSHA1(net::X509Certificate::OSCertHandle cert_handle) { |
| unsigned char sha1_data[SHA_DIGEST_LENGTH] = {0}; |
| unsigned int sha1_size = sizeof(sha1_data); |
| int ret = X509_digest(cert_handle, EVP_sha1(), sha1_data, &sha1_size); |
| DCHECK(ret); |
| DCHECK_EQ(sha1_size, sizeof(sha1_data)); |
| return ProcessRawBytes(sha1_data, sha1_size); |
| } |
| |
| void GetCertChainFromCert(net::X509Certificate::OSCertHandle cert_handle, |
| net::X509Certificate::OSCertHandles* cert_handles) { |
| // TODO(bulach): how to get the chain out of a certificate? |
| cert_handles->push_back(net::X509Certificate::DupOSCertHandle(cert_handle)); |
| } |
| |
| void DestroyCertChain(net::X509Certificate::OSCertHandles* cert_handles) { |
| for (net::X509Certificate::OSCertHandles::iterator i = cert_handles->begin(); |
| i != cert_handles->end(); ++i) |
| X509_free(*i); |
| cert_handles->clear(); |
| } |
| |
| std::string GetDerString(net::X509Certificate::OSCertHandle cert_handle) { |
| // TODO(bulach): implement me. |
| return ""; |
| } |
| |
| std::string GetCMSString(const net::X509Certificate::OSCertHandles& cert_chain, |
| size_t start, size_t end) { |
| // TODO(bulach): implement me. |
| return ""; |
| } |
| |
| std::string ProcessSecAlgorithmSignature( |
| net::X509Certificate::OSCertHandle cert_handle) { |
| // TODO(bulach): implement me. |
| return ""; |
| } |
| |
| std::string ProcessSecAlgorithmSubjectPublicKey( |
| net::X509Certificate::OSCertHandle cert_handle) { |
| // TODO(bulach): implement me. |
| return ""; |
| } |
| |
| std::string ProcessSecAlgorithmSignatureWrap( |
| net::X509Certificate::OSCertHandle cert_handle) { |
| // TODO(bulach): implement me. |
| return ""; |
| } |
| |
| std::string ProcessSubjectPublicKeyInfo( |
| net::X509Certificate::OSCertHandle cert_handle) { |
| // TODO(bulach): implement me. |
| return ""; |
| } |
| |
| std::string ProcessRawBitsSignatureWrap( |
| net::X509Certificate::OSCertHandle cert_handle) { |
| // TODO(bulach): implement me. |
| return ""; |
| } |
| |
| } // namespace x509_certificate_model |