1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/common/net/x509_certificate_model.h" 6 7 #include <openssl/bio.h> 8 #include <openssl/obj_mac.h> 9 #include <openssl/sha.h> 10 #include <openssl/x509v3.h> 11 12 #include "base/logging.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "crypto/openssl_bio_string.h" 15 #include "crypto/openssl_util.h" 16 #include "net/cert/x509_util_openssl.h" 17 18 namespace x509_util = net::x509_util; 19 20 namespace { 21 22 std::string AlternativeWhenEmpty(const std::string& text, 23 const std::string& alternative) { 24 return text.empty() ? alternative : text; 25 } 26 27 std::string GetKeyValuesFromName(X509_NAME* name) { 28 std::string ret; 29 int rdns = X509_NAME_entry_count(name) - 1; 30 for (int i = rdns; i >= 0; --i) { 31 std::string key; 32 std::string value; 33 if (!x509_util::ParsePrincipalKeyAndValueByIndex(name, i, &key, &value)) 34 break; 35 ret += key; 36 ret += " = "; 37 ret += value; 38 ret += '\n'; 39 } 40 return ret; 41 } 42 43 } // namespace 44 45 namespace x509_certificate_model { 46 47 using net::X509Certificate; 48 49 std::string GetCertNameOrNickname(X509Certificate::OSCertHandle cert_handle) { 50 std::string name = 51 ProcessIDN(GetSubjectCommonName(cert_handle, std::string())); 52 if (!name.empty()) 53 return name; 54 55 crypto::ScopedOpenSSL<BIO, BIO_free_all> bio(crypto::BIO_new_string(&name)); 56 if (!bio.get()) 57 return name; 58 X509_NAME_print_ex(bio.get(), 59 X509_get_subject_name(cert_handle), 60 0 /* indent */, 61 XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB); 62 return name; 63 } 64 65 std::string GetTokenName(X509Certificate::OSCertHandle cert_handle) { 66 // TODO(bulach): implement me. 67 return ""; 68 } 69 70 std::string GetVersion(net::X509Certificate::OSCertHandle cert_handle) { 71 unsigned long version = X509_get_version(cert_handle); 72 if (version != ULONG_MAX) 73 return base::UintToString(version + 1); 74 return ""; 75 } 76 77 net::CertType GetType(X509Certificate::OSCertHandle os_cert) { 78 // TODO(bulach): implement me. 79 return net::OTHER_CERT; 80 } 81 82 void GetUsageStrings(X509Certificate::OSCertHandle cert_handle, 83 std::vector<std::string>* usages) { 84 // TODO(bulach): implement me. 85 } 86 87 std::string GetSerialNumberHexified( 88 X509Certificate::OSCertHandle cert_handle, 89 const std::string& alternative_text) { 90 ASN1_INTEGER* num = X509_get_serialNumber(cert_handle); 91 const char kSerialNumberSeparator = ':'; 92 std::string hex_string = ProcessRawBytesWithSeparators( 93 num->data, num->length, kSerialNumberSeparator, kSerialNumberSeparator); 94 return AlternativeWhenEmpty(hex_string, alternative_text); 95 } 96 97 std::string GetIssuerCommonName( 98 X509Certificate::OSCertHandle cert_handle, 99 const std::string& alternative_text) { 100 std::string ret; 101 x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle), 102 NID_commonName, &ret); 103 return AlternativeWhenEmpty(ret, alternative_text); 104 } 105 106 std::string GetIssuerOrgName( 107 X509Certificate::OSCertHandle cert_handle, 108 const std::string& alternative_text) { 109 std::string ret; 110 x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle), 111 NID_organizationName, &ret); 112 return AlternativeWhenEmpty(ret, alternative_text); 113 } 114 115 std::string GetIssuerOrgUnitName( 116 X509Certificate::OSCertHandle cert_handle, 117 const std::string& alternative_text) { 118 std::string ret; 119 x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle), 120 NID_organizationalUnitName, &ret); 121 return AlternativeWhenEmpty(ret, alternative_text); 122 } 123 124 std::string GetSubjectOrgName( 125 X509Certificate::OSCertHandle cert_handle, 126 const std::string& alternative_text) { 127 std::string ret; 128 x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle), 129 NID_organizationName, &ret); 130 return AlternativeWhenEmpty(ret, alternative_text); 131 } 132 133 std::string GetSubjectOrgUnitName( 134 X509Certificate::OSCertHandle cert_handle, 135 const std::string& alternative_text) { 136 std::string ret; 137 x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle), 138 NID_organizationalUnitName, &ret); 139 return AlternativeWhenEmpty(ret, alternative_text); 140 } 141 142 std::string GetSubjectCommonName(X509Certificate::OSCertHandle cert_handle, 143 const std::string& alternative_text) { 144 std::string ret; 145 x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle), 146 NID_commonName, &ret); 147 return AlternativeWhenEmpty(ret, alternative_text); 148 } 149 150 bool GetTimes(X509Certificate::OSCertHandle cert_handle, 151 base::Time* issued, base::Time* expires) { 152 return x509_util::ParseDate(X509_get_notBefore(cert_handle), issued) && 153 x509_util::ParseDate(X509_get_notAfter(cert_handle), expires); 154 } 155 156 std::string GetTitle(net::X509Certificate::OSCertHandle cert_handle) { 157 // TODO(mattm): merge GetTitle and GetCertNameOrNickname? 158 // Is there any reason GetCertNameOrNickname calls ProcessIDN and this 159 // doesn't? 160 std::string title = 161 GetSubjectCommonName(cert_handle, std::string()); 162 if (!title.empty()) 163 return title; 164 165 crypto::ScopedOpenSSL<BIO, BIO_free_all> bio(crypto::BIO_new_string(&title)); 166 if (!bio.get()) 167 return title; 168 X509_NAME_print_ex(bio.get(), 169 X509_get_subject_name(cert_handle), 170 0 /* indent */, 171 XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB); 172 return title; 173 } 174 175 std::string GetIssuerName(net::X509Certificate::OSCertHandle cert_handle) { 176 return GetKeyValuesFromName(X509_get_issuer_name(cert_handle)); 177 } 178 179 std::string GetSubjectName(net::X509Certificate::OSCertHandle cert_handle) { 180 return GetKeyValuesFromName(X509_get_subject_name(cert_handle)); 181 } 182 183 void GetExtensions( 184 const std::string& critical_label, 185 const std::string& non_critical_label, 186 net::X509Certificate::OSCertHandle cert_handle, 187 Extensions* extensions) { 188 // TODO(bulach): implement me. 189 } 190 191 std::string HashCertSHA256(net::X509Certificate::OSCertHandle cert_handle) { 192 unsigned char sha256_data[SHA256_DIGEST_LENGTH] = {0}; 193 unsigned int sha256_size = sizeof(sha256_data); 194 int ret = X509_digest(cert_handle, EVP_sha256(), sha256_data, &sha256_size); 195 DCHECK(ret); 196 DCHECK_EQ(sha256_size, sizeof(sha256_data)); 197 return ProcessRawBytes(sha256_data, sha256_size); 198 } 199 200 std::string HashCertSHA1(net::X509Certificate::OSCertHandle cert_handle) { 201 unsigned char sha1_data[SHA_DIGEST_LENGTH] = {0}; 202 unsigned int sha1_size = sizeof(sha1_data); 203 int ret = X509_digest(cert_handle, EVP_sha1(), sha1_data, &sha1_size); 204 DCHECK(ret); 205 DCHECK_EQ(sha1_size, sizeof(sha1_data)); 206 return ProcessRawBytes(sha1_data, sha1_size); 207 } 208 209 void GetCertChainFromCert(net::X509Certificate::OSCertHandle cert_handle, 210 net::X509Certificate::OSCertHandles* cert_handles) { 211 // TODO(bulach): how to get the chain out of a certificate? 212 cert_handles->push_back(net::X509Certificate::DupOSCertHandle(cert_handle)); 213 } 214 215 void DestroyCertChain(net::X509Certificate::OSCertHandles* cert_handles) { 216 for (net::X509Certificate::OSCertHandles::iterator i = cert_handles->begin(); 217 i != cert_handles->end(); ++i) 218 X509_free(*i); 219 cert_handles->clear(); 220 } 221 222 std::string GetDerString(net::X509Certificate::OSCertHandle cert_handle) { 223 // TODO(bulach): implement me. 224 return ""; 225 } 226 227 std::string GetCMSString(const net::X509Certificate::OSCertHandles& cert_chain, 228 size_t start, size_t end) { 229 // TODO(bulach): implement me. 230 return ""; 231 } 232 233 std::string ProcessSecAlgorithmSignature( 234 net::X509Certificate::OSCertHandle cert_handle) { 235 // TODO(bulach): implement me. 236 return ""; 237 } 238 239 std::string ProcessSecAlgorithmSubjectPublicKey( 240 net::X509Certificate::OSCertHandle cert_handle) { 241 // TODO(bulach): implement me. 242 return ""; 243 } 244 245 std::string ProcessSecAlgorithmSignatureWrap( 246 net::X509Certificate::OSCertHandle cert_handle) { 247 // TODO(bulach): implement me. 248 return ""; 249 } 250 251 std::string ProcessSubjectPublicKeyInfo( 252 net::X509Certificate::OSCertHandle cert_handle) { 253 // TODO(bulach): implement me. 254 return ""; 255 } 256 257 std::string ProcessRawBitsSignatureWrap( 258 net::X509Certificate::OSCertHandle cert_handle) { 259 // TODO(bulach): implement me. 260 return ""; 261 } 262 263 } // namespace x509_certificate_model 264