OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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 "net/cert/x509_util_win.h" |
| 6 |
| 7 #include "crypto/scoped_capi_types.h" |
| 8 #include "crypto/sha2.h" |
| 9 #include "net/cert/x509_certificate.h" |
| 10 #include "net/net_features.h" |
| 11 #include "third_party/boringssl/src/include/openssl/pool.h" |
| 12 |
| 13 namespace net { |
| 14 |
| 15 namespace x509_util { |
| 16 |
| 17 namespace { |
| 18 |
| 19 using ScopedHCERTSTORE = crypto::ScopedCAPIHandle< |
| 20 HCERTSTORE, |
| 21 crypto::CAPIDestroyerWithFlags<HCERTSTORE, CertCloseStore, 0>>; |
| 22 |
| 23 } // namespace |
| 24 |
| 25 scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts( |
| 26 PCCERT_CONTEXT os_cert, |
| 27 const std::vector<PCCERT_CONTEXT>& os_chain) { |
| 28 #if BUILDFLAG(USE_BYTE_CERTS) |
| 29 if (!os_cert || !os_cert->pbCertEncoded || !os_cert->cbCertEncoded) |
| 30 return nullptr; |
| 31 bssl::UniquePtr<CRYPTO_BUFFER> cert_handle( |
| 32 X509Certificate::CreateOSCertHandleFromBytes( |
| 33 reinterpret_cast<const char*>(os_cert->pbCertEncoded), |
| 34 os_cert->cbCertEncoded)); |
| 35 if (!cert_handle) |
| 36 return nullptr; |
| 37 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates; |
| 38 X509Certificate::OSCertHandles intermediates_raw; |
| 39 for (PCCERT_CONTEXT os_intermediate : os_chain) { |
| 40 if (!os_intermediate || !os_intermediate->pbCertEncoded || |
| 41 !os_intermediate->cbCertEncoded) |
| 42 return nullptr; |
| 43 bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle( |
| 44 X509Certificate::CreateOSCertHandleFromBytes( |
| 45 reinterpret_cast<const char*>(os_intermediate->pbCertEncoded), |
| 46 os_intermediate->cbCertEncoded)); |
| 47 if (!intermediate_cert_handle) |
| 48 return nullptr; |
| 49 intermediates_raw.push_back(intermediate_cert_handle.get()); |
| 50 intermediates.push_back(std::move(intermediate_cert_handle)); |
| 51 } |
| 52 scoped_refptr<X509Certificate> result( |
| 53 X509Certificate::CreateFromHandle(cert_handle.get(), intermediates_raw)); |
| 54 return result; |
| 55 #else |
| 56 return X509Certificate::CreateFromHandle(os_cert, os_chain); |
| 57 #endif |
| 58 } |
| 59 |
| 60 ScopedPCCERT_CONTEXT CreateCertContextWithChain(const X509Certificate* cert) { |
| 61 // Create an in-memory certificate store to hold the certificate and its |
| 62 // intermediate certificates. The store will be referenced in the returned |
| 63 // PCCERT_CONTEXT, and will not be freed until the PCCERT_CONTEXT is freed. |
| 64 ScopedHCERTSTORE store( |
| 65 CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, |
| 66 CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL)); |
| 67 if (!store.get()) |
| 68 return nullptr; |
| 69 |
| 70 PCCERT_CONTEXT primary_cert = nullptr; |
| 71 |
| 72 #if BUILDFLAG(USE_BYTE_CERTS) |
| 73 BOOL ok = CertAddEncodedCertificateToStore( |
| 74 store.get(), X509_ASN_ENCODING, |
| 75 CRYPTO_BUFFER_data(cert->os_cert_handle()), |
| 76 base::checked_cast<DWORD>(CRYPTO_BUFFER_len(cert->os_cert_handle())), |
| 77 CERT_STORE_ADD_ALWAYS, &primary_cert); |
| 78 if (!ok || !primary_cert) |
| 79 return nullptr; |
| 80 ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert); |
| 81 |
| 82 for (X509Certificate::OSCertHandle intermediate : |
| 83 cert->GetIntermediateCertificates()) { |
| 84 ok = CertAddEncodedCertificateToStore( |
| 85 store.get(), X509_ASN_ENCODING, CRYPTO_BUFFER_data(intermediate), |
| 86 base::checked_cast<DWORD>(CRYPTO_BUFFER_len(intermediate)), |
| 87 CERT_STORE_ADD_ALWAYS, NULL); |
| 88 if (!ok) |
| 89 return nullptr; |
| 90 } |
| 91 #else |
| 92 PCCERT_CONTEXT os_cert_handle = cert->os_cert_handle(); |
| 93 const std::vector<PCCERT_CONTEXT>& intermediate_ca_certs = |
| 94 cert->GetIntermediateCertificates(); |
| 95 |
| 96 // NOTE: This preserves all of the properties of |os_cert_handle| except |
| 97 // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two |
| 98 // properties that hold access to already-opened private keys. If a handle |
| 99 // has already been unlocked (eg: PIN prompt), then the first time that the |
| 100 // identity is used for client auth, it may prompt the user again. |
| 101 BOOL ok = CertAddCertificateContextToStore( |
| 102 store.get(), os_cert_handle, CERT_STORE_ADD_ALWAYS, &primary_cert); |
| 103 if (!ok || !primary_cert) |
| 104 return nullptr; |
| 105 ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert); |
| 106 |
| 107 for (PCCERT_CONTEXT intermediate : intermediate_ca_certs) { |
| 108 CertAddCertificateContextToStore(store.get(), intermediate, |
| 109 CERT_STORE_ADD_ALWAYS, NULL); |
| 110 } |
| 111 #endif |
| 112 |
| 113 // Note: |primary_cert| retains a reference to |store|, so the store will |
| 114 // actually be freed when |primary_cert| is freed. |
| 115 return scoped_primary_cert; |
| 116 } |
| 117 |
| 118 SHA256HashValue CalculateFingerprint256(PCCERT_CONTEXT cert) { |
| 119 DCHECK(NULL != cert->pbCertEncoded); |
| 120 DCHECK_NE(0u, cert->cbCertEncoded); |
| 121 |
| 122 SHA256HashValue sha256; |
| 123 |
| 124 // Use crypto::SHA256HashString for two reasons: |
| 125 // * < Windows Vista does not have universal SHA-256 support. |
| 126 // * More efficient on Windows > Vista (less overhead since non-default CSP |
| 127 // is not needed). |
| 128 base::StringPiece der_cert(reinterpret_cast<const char*>(cert->pbCertEncoded), |
| 129 cert->cbCertEncoded); |
| 130 crypto::SHA256HashString(der_cert, sha256.data, sizeof(sha256.data)); |
| 131 return sha256; |
| 132 } |
| 133 |
| 134 bool IsSelfSigned(PCCERT_CONTEXT cert_handle) { |
| 135 bool valid_signature = !!CryptVerifyCertificateSignatureEx( |
| 136 NULL, X509_ASN_ENCODING, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, |
| 137 reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)), |
| 138 CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, |
| 139 reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)), 0, NULL); |
| 140 if (!valid_signature) |
| 141 return false; |
| 142 return !!CertCompareCertificateName(X509_ASN_ENCODING, |
| 143 &cert_handle->pCertInfo->Subject, |
| 144 &cert_handle->pCertInfo->Issuer); |
| 145 } |
| 146 |
| 147 } // namespace x509_util |
| 148 |
| 149 } // namespace net |
OLD | NEW |