| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/cert/x509_certificate.h" | 5 #include "net/cert/x509_certificate.h" |
| 6 | 6 |
| 7 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS. | 7 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS. |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/pickle.h" | 11 #include "base/pickle.h" |
| 12 #include "base/sha1.h" | 12 #include "base/sha1.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "crypto/capi_util.h" | 15 #include "crypto/capi_util.h" |
| 16 #include "crypto/scoped_capi_types.h" | 16 #include "crypto/scoped_capi_types.h" |
| 17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 18 | 18 |
| 19 #pragma comment(lib, "crypt32.lib") | 19 #pragma comment(lib, "crypt32.lib") |
| 20 | 20 |
| 21 using base::Time; | 21 using base::Time; |
| 22 | 22 |
| 23 namespace net { | 23 namespace net { |
| 24 | 24 |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 typedef crypto::ScopedCAPIHandle< | 27 typedef crypto::ScopedCAPIHandle< |
| 28 HCERTSTORE, | 28 HCERTSTORE, |
| 29 crypto::CAPIDestroyerWithFlags<HCERTSTORE, | 29 crypto::CAPIDestroyerWithFlags<HCERTSTORE, CertCloseStore, 0> > |
| 30 CertCloseStore, 0> > ScopedHCERTSTORE; | 30 ScopedHCERTSTORE; |
| 31 | 31 |
| 32 void ExplodedTimeToSystemTime(const base::Time::Exploded& exploded, | 32 void ExplodedTimeToSystemTime(const base::Time::Exploded& exploded, |
| 33 SYSTEMTIME* system_time) { | 33 SYSTEMTIME* system_time) { |
| 34 system_time->wYear = exploded.year; | 34 system_time->wYear = exploded.year; |
| 35 system_time->wMonth = exploded.month; | 35 system_time->wMonth = exploded.month; |
| 36 system_time->wDayOfWeek = exploded.day_of_week; | 36 system_time->wDayOfWeek = exploded.day_of_week; |
| 37 system_time->wDay = exploded.day_of_month; | 37 system_time->wDay = exploded.day_of_month; |
| 38 system_time->wHour = exploded.hour; | 38 system_time->wHour = exploded.hour; |
| 39 system_time->wMinute = exploded.minute; | 39 system_time->wMinute = exploded.minute; |
| 40 system_time->wSecond = exploded.second; | 40 system_time->wSecond = exploded.second; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 output->reset(alt_name_info); | 73 output->reset(alt_name_info); |
| 74 } | 74 } |
| 75 | 75 |
| 76 void AddCertsFromStore(HCERTSTORE store, | 76 void AddCertsFromStore(HCERTSTORE store, |
| 77 X509Certificate::OSCertHandles* results) { | 77 X509Certificate::OSCertHandles* results) { |
| 78 PCCERT_CONTEXT cert = NULL; | 78 PCCERT_CONTEXT cert = NULL; |
| 79 | 79 |
| 80 while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) { | 80 while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) { |
| 81 PCCERT_CONTEXT to_add = NULL; | 81 PCCERT_CONTEXT to_add = NULL; |
| 82 if (CertAddCertificateContextToStore( | 82 if (CertAddCertificateContextToStore( |
| 83 NULL, // The cert won't be persisted in any cert store. This breaks | 83 NULL, // The cert won't be persisted in any cert store. This breaks |
| 84 // any association the context currently has to |store|, which | 84 // any association the context currently has to |store|, which |
| 85 // allows us, the caller, to safely close |store| without | 85 // allows us, the caller, to safely close |store| without |
| 86 // releasing the cert handles. | 86 // releasing the cert handles. |
| 87 cert, | 87 cert, |
| 88 CERT_STORE_ADD_USE_EXISTING, | 88 CERT_STORE_ADD_USE_EXISTING, |
| 89 &to_add) && to_add != NULL) { | 89 &to_add) && |
| 90 to_add != NULL) { |
| 90 // When processing stores generated from PKCS#7/PKCS#12 files, it | 91 // When processing stores generated from PKCS#7/PKCS#12 files, it |
| 91 // appears that the order returned is the inverse of the order that it | 92 // appears that the order returned is the inverse of the order that it |
| 92 // appeared in the file. | 93 // appeared in the file. |
| 93 // TODO(rsleevi): Ensure this order is consistent across all Win | 94 // TODO(rsleevi): Ensure this order is consistent across all Win |
| 94 // versions | 95 // versions |
| 95 results->insert(results->begin(), to_add); | 96 results->insert(results->begin(), to_add); |
| 96 } | 97 } |
| 97 } | 98 } |
| 98 } | 99 } |
| 99 | 100 |
| 100 X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) { | 101 X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) { |
| 101 X509Certificate::OSCertHandles results; | 102 X509Certificate::OSCertHandles results; |
| 102 CERT_BLOB data_blob; | 103 CERT_BLOB data_blob; |
| 103 data_blob.cbData = length; | 104 data_blob.cbData = length; |
| 104 data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data)); | 105 data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data)); |
| 105 | 106 |
| 106 HCERTSTORE out_store = NULL; | 107 HCERTSTORE out_store = NULL; |
| 107 | 108 |
| 108 DWORD expected_types = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | | 109 DWORD expected_types = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | |
| 109 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | | 110 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | |
| 110 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED; | 111 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED; |
| 111 | 112 |
| 112 if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &data_blob, expected_types, | 113 if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, |
| 113 CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, | 114 &data_blob, |
| 114 &out_store, NULL, NULL) || out_store == NULL) { | 115 expected_types, |
| 116 CERT_QUERY_FORMAT_FLAG_BINARY, |
| 117 0, |
| 118 NULL, |
| 119 NULL, |
| 120 NULL, |
| 121 &out_store, |
| 122 NULL, |
| 123 NULL) || |
| 124 out_store == NULL) { |
| 115 return results; | 125 return results; |
| 116 } | 126 } |
| 117 | 127 |
| 118 AddCertsFromStore(out_store, &results); | 128 AddCertsFromStore(out_store, &results); |
| 119 CertCloseStore(out_store, CERT_CLOSE_STORE_CHECK_FLAG); | 129 CertCloseStore(out_store, CERT_CLOSE_STORE_CHECK_FLAG); |
| 120 | 130 |
| 121 return results; | 131 return results; |
| 122 } | 132 } |
| 123 | 133 |
| 124 // Given a CERT_NAME_BLOB, returns true if it appears in a given list, | 134 // Given a CERT_NAME_BLOB, returns true if it appears in a given list, |
| 125 // formatted as a vector of strings holding DER-encoded X.509 | 135 // formatted as a vector of strings holding DER-encoded X.509 |
| 126 // DistinguishedName entries. | 136 // DistinguishedName entries. |
| 127 bool IsCertNameBlobInIssuerList( | 137 bool IsCertNameBlobInIssuerList(CERT_NAME_BLOB* name_blob, |
| 128 CERT_NAME_BLOB* name_blob, | 138 const std::vector<std::string>& issuer_names) { |
| 129 const std::vector<std::string>& issuer_names) { | |
| 130 for (std::vector<std::string>::const_iterator it = issuer_names.begin(); | 139 for (std::vector<std::string>::const_iterator it = issuer_names.begin(); |
| 131 it != issuer_names.end(); ++it) { | 140 it != issuer_names.end(); |
| 141 ++it) { |
| 132 CERT_NAME_BLOB issuer_blob; | 142 CERT_NAME_BLOB issuer_blob; |
| 133 issuer_blob.pbData = | 143 issuer_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(it->data())); |
| 134 reinterpret_cast<BYTE*>(const_cast<char*>(it->data())); | |
| 135 issuer_blob.cbData = static_cast<DWORD>(it->length()); | 144 issuer_blob.cbData = static_cast<DWORD>(it->length()); |
| 136 | 145 |
| 137 BOOL rb = CertCompareCertificateName( | 146 BOOL rb = CertCompareCertificateName( |
| 138 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &issuer_blob, name_blob); | 147 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &issuer_blob, name_blob); |
| 139 if (rb) | 148 if (rb) |
| 140 return true; | 149 return true; |
| 141 } | 150 } |
| 142 return false; | 151 return false; |
| 143 } | 152 } |
| 144 | 153 |
| 145 } // namespace | 154 } // namespace |
| 146 | 155 |
| 147 void X509Certificate::Initialize() { | 156 void X509Certificate::Initialize() { |
| 148 DCHECK(cert_handle_); | 157 DCHECK(cert_handle_); |
| 149 subject_.ParseDistinguishedName(cert_handle_->pCertInfo->Subject.pbData, | 158 subject_.ParseDistinguishedName(cert_handle_->pCertInfo->Subject.pbData, |
| 150 cert_handle_->pCertInfo->Subject.cbData); | 159 cert_handle_->pCertInfo->Subject.cbData); |
| 151 issuer_.ParseDistinguishedName(cert_handle_->pCertInfo->Issuer.pbData, | 160 issuer_.ParseDistinguishedName(cert_handle_->pCertInfo->Issuer.pbData, |
| 152 cert_handle_->pCertInfo->Issuer.cbData); | 161 cert_handle_->pCertInfo->Issuer.cbData); |
| 153 | 162 |
| 154 valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore); | 163 valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore); |
| 155 valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); | 164 valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); |
| 156 | 165 |
| 157 fingerprint_ = CalculateFingerprint(cert_handle_); | 166 fingerprint_ = CalculateFingerprint(cert_handle_); |
| 158 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); | 167 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); |
| 159 | 168 |
| 160 const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber; | 169 const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber; |
| 161 scoped_ptr<uint8[]> serial_bytes(new uint8[serial->cbData]); | 170 scoped_ptr<uint8[]> serial_bytes(new uint8[serial->cbData]); |
| 162 for (unsigned i = 0; i < serial->cbData; i++) | 171 for (unsigned i = 0; i < serial->cbData; i++) |
| 163 serial_bytes[i] = serial->pbData[serial->cbData - i - 1]; | 172 serial_bytes[i] = serial->pbData[serial->cbData - i - 1]; |
| 164 serial_number_ = std::string( | 173 serial_number_ = |
| 165 reinterpret_cast<char*>(serial_bytes.get()), serial->cbData); | 174 std::string(reinterpret_cast<char*>(serial_bytes.get()), serial->cbData); |
| 166 } | 175 } |
| 167 | 176 |
| 168 void X509Certificate::GetSubjectAltName( | 177 void X509Certificate::GetSubjectAltName( |
| 169 std::vector<std::string>* dns_names, | 178 std::vector<std::string>* dns_names, |
| 170 std::vector<std::string>* ip_addrs) const { | 179 std::vector<std::string>* ip_addrs) const { |
| 171 if (dns_names) | 180 if (dns_names) |
| 172 dns_names->clear(); | 181 dns_names->clear(); |
| 173 if (ip_addrs) | 182 if (ip_addrs) |
| 174 ip_addrs->clear(); | 183 ip_addrs->clear(); |
| 175 | 184 |
| 176 if (!cert_handle_) | 185 if (!cert_handle_) |
| 177 return; | 186 return; |
| 178 | 187 |
| 179 scoped_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter> alt_name_info; | 188 scoped_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter> alt_name_info; |
| 180 GetCertSubjectAltName(cert_handle_, &alt_name_info); | 189 GetCertSubjectAltName(cert_handle_, &alt_name_info); |
| 181 CERT_ALT_NAME_INFO* alt_name = alt_name_info.get(); | 190 CERT_ALT_NAME_INFO* alt_name = alt_name_info.get(); |
| 182 if (alt_name) { | 191 if (alt_name) { |
| 183 int num_entries = alt_name->cAltEntry; | 192 int num_entries = alt_name->cAltEntry; |
| 184 for (int i = 0; i < num_entries; i++) { | 193 for (int i = 0; i < num_entries; i++) { |
| 185 // dNSName is an ASN.1 IA5String representing a string of ASCII | 194 // dNSName is an ASN.1 IA5String representing a string of ASCII |
| 186 // characters, so we can use UTF16ToASCII here. | 195 // characters, so we can use UTF16ToASCII here. |
| 187 const CERT_ALT_NAME_ENTRY& entry = alt_name->rgAltEntry[i]; | 196 const CERT_ALT_NAME_ENTRY& entry = alt_name->rgAltEntry[i]; |
| 188 | 197 |
| 189 if (dns_names && entry.dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) { | 198 if (dns_names && entry.dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) { |
| 190 dns_names->push_back(base::UTF16ToASCII(entry.pwszDNSName)); | 199 dns_names->push_back(base::UTF16ToASCII(entry.pwszDNSName)); |
| 191 } else if (ip_addrs && | 200 } else if (ip_addrs && |
| 192 entry.dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS) { | 201 entry.dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS) { |
| 193 ip_addrs->push_back(std::string( | 202 ip_addrs->push_back( |
| 194 reinterpret_cast<const char*>(entry.IPAddress.pbData), | 203 std::string(reinterpret_cast<const char*>(entry.IPAddress.pbData), |
| 195 entry.IPAddress.cbData)); | 204 entry.IPAddress.cbData)); |
| 196 } | 205 } |
| 197 } | 206 } |
| 198 } | 207 } |
| 199 } | 208 } |
| 200 | 209 |
| 201 PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const { | 210 PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const { |
| 202 // Create an in-memory certificate store to hold this certificate and | 211 // Create an in-memory certificate store to hold this certificate and |
| 203 // any intermediate certificates in |intermediate_ca_certs_|. The store | 212 // any intermediate certificates in |intermediate_ca_certs_|. The store |
| 204 // will be referenced in the returned PCCERT_CONTEXT, and will not be freed | 213 // will be referenced in the returned PCCERT_CONTEXT, and will not be freed |
| 205 // until the PCCERT_CONTEXT is freed. | 214 // until the PCCERT_CONTEXT is freed. |
| 206 ScopedHCERTSTORE store(CertOpenStore( | 215 ScopedHCERTSTORE store( |
| 207 CERT_STORE_PROV_MEMORY, 0, NULL, | 216 CertOpenStore(CERT_STORE_PROV_MEMORY, |
| 208 CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL)); | 217 0, |
| 218 NULL, |
| 219 CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, |
| 220 NULL)); |
| 209 if (!store.get()) | 221 if (!store.get()) |
| 210 return NULL; | 222 return NULL; |
| 211 | 223 |
| 212 // NOTE: This preserves all of the properties of |os_cert_handle()| except | 224 // NOTE: This preserves all of the properties of |os_cert_handle()| except |
| 213 // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two | 225 // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two |
| 214 // properties that hold access to already-opened private keys. If a handle | 226 // properties that hold access to already-opened private keys. If a handle |
| 215 // has already been unlocked (eg: PIN prompt), then the first time that the | 227 // has already been unlocked (eg: PIN prompt), then the first time that the |
| 216 // identity is used for client auth, it may prompt the user again. | 228 // identity is used for client auth, it may prompt the user again. |
| 217 PCCERT_CONTEXT primary_cert; | 229 PCCERT_CONTEXT primary_cert; |
| 218 BOOL ok = CertAddCertificateContextToStore(store.get(), os_cert_handle(), | 230 BOOL ok = CertAddCertificateContextToStore( |
| 219 CERT_STORE_ADD_ALWAYS, | 231 store.get(), os_cert_handle(), CERT_STORE_ADD_ALWAYS, &primary_cert); |
| 220 &primary_cert); | |
| 221 if (!ok || !primary_cert) | 232 if (!ok || !primary_cert) |
| 222 return NULL; | 233 return NULL; |
| 223 | 234 |
| 224 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { | 235 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { |
| 225 CertAddCertificateContextToStore(store.get(), intermediate_ca_certs_[i], | 236 CertAddCertificateContextToStore( |
| 226 CERT_STORE_ADD_ALWAYS, NULL); | 237 store.get(), intermediate_ca_certs_[i], CERT_STORE_ADD_ALWAYS, NULL); |
| 227 } | 238 } |
| 228 | 239 |
| 229 // Note: |store| is explicitly not released, as the call to CertCloseStore() | 240 // Note: |store| is explicitly not released, as the call to CertCloseStore() |
| 230 // when |store| goes out of scope will not actually free the store. Instead, | 241 // when |store| goes out of scope will not actually free the store. Instead, |
| 231 // the store will be freed when |primary_cert| is freed. | 242 // the store will be freed when |primary_cert| is freed. |
| 232 return primary_cert; | 243 return primary_cert; |
| 233 } | 244 } |
| 234 | 245 |
| 235 // static | 246 // static |
| 236 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 247 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, |
| 237 std::string* encoded) { | 248 std::string* encoded) { |
| 238 if (!cert_handle->pbCertEncoded || !cert_handle->cbCertEncoded) | 249 if (!cert_handle->pbCertEncoded || !cert_handle->cbCertEncoded) |
| 239 return false; | 250 return false; |
| 240 encoded->assign(reinterpret_cast<char*>(cert_handle->pbCertEncoded), | 251 encoded->assign(reinterpret_cast<char*>(cert_handle->pbCertEncoded), |
| 241 cert_handle->cbCertEncoded); | 252 cert_handle->cbCertEncoded); |
| 242 return true; | 253 return true; |
| 243 } | 254 } |
| 244 | 255 |
| 245 // static | 256 // static |
| 246 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | 257 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, |
| 247 X509Certificate::OSCertHandle b) { | 258 X509Certificate::OSCertHandle b) { |
| 248 DCHECK(a && b); | 259 DCHECK(a && b); |
| 249 if (a == b) | 260 if (a == b) |
| 250 return true; | 261 return true; |
| 251 return a->cbCertEncoded == b->cbCertEncoded && | 262 return a->cbCertEncoded == b->cbCertEncoded && |
| 252 memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0; | 263 memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0; |
| 253 } | 264 } |
| 254 | 265 |
| 255 // static | 266 // static |
| 256 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 267 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
| 257 const char* data, int length) { | 268 const char* data, |
| 269 int length) { |
| 258 OSCertHandle cert_handle = NULL; | 270 OSCertHandle cert_handle = NULL; |
| 259 if (!CertAddEncodedCertificateToStore( | 271 if (!CertAddEncodedCertificateToStore(NULL, |
| 260 NULL, X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(data), | 272 X509_ASN_ENCODING, |
| 261 length, CERT_STORE_ADD_USE_EXISTING, &cert_handle)) | 273 reinterpret_cast<const BYTE*>(data), |
| 274 length, |
| 275 CERT_STORE_ADD_USE_EXISTING, |
| 276 &cert_handle)) |
| 262 return NULL; | 277 return NULL; |
| 263 | 278 |
| 264 return cert_handle; | 279 return cert_handle; |
| 265 } | 280 } |
| 266 | 281 |
| 267 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | 282 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( |
| 268 const char* data, int length, Format format) { | 283 const char* data, |
| 284 int length, |
| 285 Format format) { |
| 269 OSCertHandles results; | 286 OSCertHandles results; |
| 270 switch (format) { | 287 switch (format) { |
| 271 case FORMAT_SINGLE_CERTIFICATE: { | 288 case FORMAT_SINGLE_CERTIFICATE: { |
| 272 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); | 289 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); |
| 273 if (handle != NULL) | 290 if (handle != NULL) |
| 274 results.push_back(handle); | 291 results.push_back(handle); |
| 275 break; | 292 break; |
| 276 } | 293 } |
| 277 case FORMAT_PKCS7: | 294 case FORMAT_PKCS7: |
| 278 results = ParsePKCS7(data, length); | 295 results = ParsePKCS7(data, length); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 290 OSCertHandle cert_handle) { | 307 OSCertHandle cert_handle) { |
| 291 return CertDuplicateCertificateContext(cert_handle); | 308 return CertDuplicateCertificateContext(cert_handle); |
| 292 } | 309 } |
| 293 | 310 |
| 294 // static | 311 // static |
| 295 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 312 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
| 296 CertFreeCertificateContext(cert_handle); | 313 CertFreeCertificateContext(cert_handle); |
| 297 } | 314 } |
| 298 | 315 |
| 299 // static | 316 // static |
| 300 SHA1HashValue X509Certificate::CalculateFingerprint( | 317 SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) { |
| 301 OSCertHandle cert) { | |
| 302 DCHECK(NULL != cert->pbCertEncoded); | 318 DCHECK(NULL != cert->pbCertEncoded); |
| 303 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); | 319 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); |
| 304 | 320 |
| 305 BOOL rv; | 321 BOOL rv; |
| 306 SHA1HashValue sha1; | 322 SHA1HashValue sha1; |
| 307 DWORD sha1_size = sizeof(sha1.data); | 323 DWORD sha1_size = sizeof(sha1.data); |
| 308 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, | 324 rv = CryptHashCertificate(NULL, |
| 309 cert->cbCertEncoded, sha1.data, &sha1_size); | 325 CALG_SHA1, |
| 326 0, |
| 327 cert->pbCertEncoded, |
| 328 cert->cbCertEncoded, |
| 329 sha1.data, |
| 330 &sha1_size); |
| 310 DCHECK(rv && sha1_size == sizeof(sha1.data)); | 331 DCHECK(rv && sha1_size == sizeof(sha1.data)); |
| 311 if (!rv) | 332 if (!rv) |
| 312 memset(sha1.data, 0, sizeof(sha1.data)); | 333 memset(sha1.data, 0, sizeof(sha1.data)); |
| 313 return sha1; | 334 return sha1; |
| 314 } | 335 } |
| 315 | 336 |
| 316 // TODO(wtc): This function is implemented with NSS low-level hash | 337 // TODO(wtc): This function is implemented with NSS low-level hash |
| 317 // functions to ensure it is fast. Reimplement this function with | 338 // functions to ensure it is fast. Reimplement this function with |
| 318 // CryptoAPI. May need to cache the HCRYPTPROV to reduce the overhead. | 339 // CryptoAPI. May need to cache the HCRYPTPROV to reduce the overhead. |
| 319 // static | 340 // static |
| (...skipping 11 matching lines...) Expand all Loading... |
| 331 SHA1_Update(sha1_ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded); | 352 SHA1_Update(sha1_ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded); |
| 332 } | 353 } |
| 333 unsigned int result_len; | 354 unsigned int result_len; |
| 334 SHA1_End(sha1_ctx, sha1.data, &result_len, SHA1_LENGTH); | 355 SHA1_End(sha1_ctx, sha1.data, &result_len, SHA1_LENGTH); |
| 335 SHA1_DestroyContext(sha1_ctx, PR_TRUE); | 356 SHA1_DestroyContext(sha1_ctx, PR_TRUE); |
| 336 | 357 |
| 337 return sha1; | 358 return sha1; |
| 338 } | 359 } |
| 339 | 360 |
| 340 // static | 361 // static |
| 341 X509Certificate::OSCertHandle | 362 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( |
| 342 X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) { | 363 PickleIterator* pickle_iter) { |
| 343 const char* data; | 364 const char* data; |
| 344 int length; | 365 int length; |
| 345 if (!pickle_iter->ReadData(&data, &length)) | 366 if (!pickle_iter->ReadData(&data, &length)) |
| 346 return NULL; | 367 return NULL; |
| 347 | 368 |
| 348 // Legacy serialized certificates were serialized with extended attributes, | 369 // Legacy serialized certificates were serialized with extended attributes, |
| 349 // rather than as DER only. As a result, these serialized certificates are | 370 // rather than as DER only. As a result, these serialized certificates are |
| 350 // not portable across platforms and may have side-effects on Windows due | 371 // not portable across platforms and may have side-effects on Windows due |
| 351 // to extended attributes being serialized/deserialized - | 372 // to extended attributes being serialized/deserialized - |
| 352 // http://crbug.com/118706. To avoid deserializing these attributes, write | 373 // http://crbug.com/118706. To avoid deserializing these attributes, write |
| 353 // the deserialized cert into a temporary cert store and then create a new | 374 // the deserialized cert into a temporary cert store and then create a new |
| 354 // cert from the DER - that is, without attributes. | 375 // cert from the DER - that is, without attributes. |
| 355 ScopedHCERTSTORE store( | 376 ScopedHCERTSTORE store( |
| 356 CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)); | 377 CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)); |
| 357 if (!store.get()) | 378 if (!store.get()) |
| 358 return NULL; | 379 return NULL; |
| 359 | 380 |
| 360 OSCertHandle cert_handle = NULL; | 381 OSCertHandle cert_handle = NULL; |
| 361 if (!CertAddSerializedElementToStore( | 382 if (!CertAddSerializedElementToStore( |
| 362 store.get(), reinterpret_cast<const BYTE*>(data), length, | 383 store.get(), |
| 363 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, | 384 reinterpret_cast<const BYTE*>(data), |
| 364 NULL, reinterpret_cast<const void **>(&cert_handle))) { | 385 length, |
| 386 CERT_STORE_ADD_NEW, |
| 387 0, |
| 388 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, |
| 389 NULL, |
| 390 reinterpret_cast<const void**>(&cert_handle))) { |
| 365 return NULL; | 391 return NULL; |
| 366 } | 392 } |
| 367 | 393 |
| 368 std::string encoded; | 394 std::string encoded; |
| 369 bool ok = GetDEREncoded(cert_handle, &encoded); | 395 bool ok = GetDEREncoded(cert_handle, &encoded); |
| 370 FreeOSCertHandle(cert_handle); | 396 FreeOSCertHandle(cert_handle); |
| 371 cert_handle = NULL; | 397 cert_handle = NULL; |
| 372 | 398 |
| 373 if (ok) | 399 if (ok) |
| 374 cert_handle = CreateOSCertHandleFromBytes(encoded.data(), encoded.size()); | 400 cert_handle = CreateOSCertHandleFromBytes(encoded.data(), encoded.size()); |
| 375 return cert_handle; | 401 return cert_handle; |
| 376 } | 402 } |
| 377 | 403 |
| 378 // static | 404 // static |
| 379 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, | 405 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, |
| 380 Pickle* pickle) { | 406 Pickle* pickle) { |
| 381 return pickle->WriteData( | 407 return pickle->WriteData(reinterpret_cast<char*>(cert_handle->pbCertEncoded), |
| 382 reinterpret_cast<char*>(cert_handle->pbCertEncoded), | 408 cert_handle->cbCertEncoded); |
| 383 cert_handle->cbCertEncoded); | |
| 384 } | 409 } |
| 385 | 410 |
| 386 // static | 411 // static |
| 387 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, | 412 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, |
| 388 size_t* size_bits, | 413 size_t* size_bits, |
| 389 PublicKeyType* type) { | 414 PublicKeyType* type) { |
| 390 *type = kPublicKeyTypeUnknown; | 415 *type = kPublicKeyTypeUnknown; |
| 391 *size_bits = 0; | 416 *size_bits = 0; |
| 392 | 417 |
| 393 PCCRYPT_OID_INFO oid_info = CryptFindOIDInfo( | 418 PCCRYPT_OID_INFO oid_info = CryptFindOIDInfo( |
| 394 CRYPT_OID_INFO_OID_KEY, | 419 CRYPT_OID_INFO_OID_KEY, |
| 395 cert_handle->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, | 420 cert_handle->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, |
| 396 CRYPT_PUBKEY_ALG_OID_GROUP_ID); | 421 CRYPT_PUBKEY_ALG_OID_GROUP_ID); |
| 397 if (!oid_info) | 422 if (!oid_info) |
| 398 return; | 423 return; |
| 399 | 424 |
| 400 CHECK_EQ(oid_info->dwGroupId, | 425 CHECK_EQ(oid_info->dwGroupId, |
| 401 static_cast<DWORD>(CRYPT_PUBKEY_ALG_OID_GROUP_ID)); | 426 static_cast<DWORD>(CRYPT_PUBKEY_ALG_OID_GROUP_ID)); |
| 402 | 427 |
| 403 *size_bits = CertGetPublicKeyLength( | 428 *size_bits = |
| 404 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | 429 CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, |
| 405 &cert_handle->pCertInfo->SubjectPublicKeyInfo); | 430 &cert_handle->pCertInfo->SubjectPublicKeyInfo); |
| 406 | 431 |
| 407 if (IS_SPECIAL_OID_INFO_ALGID(oid_info->Algid)) { | 432 if (IS_SPECIAL_OID_INFO_ALGID(oid_info->Algid)) { |
| 408 // For an EC public key, oid_info->Algid is CALG_OID_INFO_PARAMETERS | 433 // For an EC public key, oid_info->Algid is CALG_OID_INFO_PARAMETERS |
| 409 // (0xFFFFFFFE). Need to handle it as a special case. | 434 // (0xFFFFFFFE). Need to handle it as a special case. |
| 410 if (strcmp(oid_info->pszOID, szOID_ECC_PUBLIC_KEY) == 0) { | 435 if (strcmp(oid_info->pszOID, szOID_ECC_PUBLIC_KEY) == 0) { |
| 411 *type = kPublicKeyTypeECDSA; | 436 *type = kPublicKeyTypeECDSA; |
| 412 } else { | 437 } else { |
| 413 NOTREACHED(); | 438 NOTREACHED(); |
| 414 } | 439 } |
| 415 return; | 440 return; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 426 *type = kPublicKeyTypeECDSA; | 451 *type = kPublicKeyTypeECDSA; |
| 427 break; | 452 break; |
| 428 case CALG_ECDH: | 453 case CALG_ECDH: |
| 429 *type = kPublicKeyTypeECDH; | 454 *type = kPublicKeyTypeECDH; |
| 430 break; | 455 break; |
| 431 } | 456 } |
| 432 } | 457 } |
| 433 | 458 |
| 434 bool X509Certificate::IsIssuedByEncoded( | 459 bool X509Certificate::IsIssuedByEncoded( |
| 435 const std::vector<std::string>& valid_issuers) { | 460 const std::vector<std::string>& valid_issuers) { |
| 436 | |
| 437 // If the certificate's issuer in the list? | 461 // If the certificate's issuer in the list? |
| 438 if (IsCertNameBlobInIssuerList(&cert_handle_->pCertInfo->Issuer, | 462 if (IsCertNameBlobInIssuerList(&cert_handle_->pCertInfo->Issuer, |
| 439 valid_issuers)) { | 463 valid_issuers)) { |
| 440 return true; | 464 return true; |
| 441 } | 465 } |
| 442 // Otherwise, is any of the intermediate CA subjects in the list? | 466 // Otherwise, is any of the intermediate CA subjects in the list? |
| 443 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); | 467 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); |
| 444 it != intermediate_ca_certs_.end(); ++it) { | 468 it != intermediate_ca_certs_.end(); |
| 445 if (IsCertNameBlobInIssuerList(&(*it)->pCertInfo->Issuer, | 469 ++it) { |
| 446 valid_issuers)) { | 470 if (IsCertNameBlobInIssuerList(&(*it)->pCertInfo->Issuer, valid_issuers)) { |
| 447 return true; | 471 return true; |
| 448 } | 472 } |
| 449 } | 473 } |
| 450 | 474 |
| 451 return false; | 475 return false; |
| 452 } | 476 } |
| 453 | 477 |
| 454 } // namespace net | 478 } // namespace net |
| OLD | NEW |