OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 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_util_ios.h" | 5 #include "net/cert/x509_util_ios.h" |
6 | 6 |
7 #include "net/cert/x509_certificate.h" | 7 #include "net/cert/x509_certificate.h" |
| 8 #include "third_party/boringssl/src/include/openssl/pool.h" |
8 | 9 |
9 namespace net { | 10 namespace net { |
10 | 11 |
11 namespace x509_util { | 12 namespace x509_util { |
12 | 13 |
| 14 namespace { |
| 15 |
| 16 // Returns true if a given |cert_handle| is actually a valid X.509 certificate |
| 17 // handle. |
| 18 // |
| 19 // SecCertificateCreateFromData() does not always force the immediate parsing of |
| 20 // the certificate, and as such, may return a SecCertificateRef for an |
| 21 // invalid/unparsable certificate. Force parsing to occur to ensure that the |
| 22 // SecCertificateRef is correct. On later versions where |
| 23 // SecCertificateCreateFromData() immediately parses, rather than lazily, this |
| 24 // call is cheap, as the subject is cached. |
| 25 bool IsValidSecCertificate(SecCertificateRef cert_handle) { |
| 26 base::ScopedCFTypeRef<CFStringRef> sanity_check( |
| 27 SecCertificateCopySubjectSummary(cert_handle)); |
| 28 return sanity_check != nullptr; |
| 29 } |
| 30 |
| 31 } // namespace |
| 32 |
| 33 base::ScopedCFTypeRef<SecCertificateRef> CreateSecCertificateFromBytes( |
| 34 const uint8_t* data, |
| 35 size_t length) { |
| 36 base::ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy( |
| 37 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), |
| 38 base::checked_cast<CFIndex>(length), kCFAllocatorNull)); |
| 39 if (!cert_data) |
| 40 return base::ScopedCFTypeRef<SecCertificateRef>(); |
| 41 |
| 42 base::ScopedCFTypeRef<SecCertificateRef> cert_handle( |
| 43 SecCertificateCreateWithData(nullptr, cert_data)); |
| 44 if (!cert_handle) |
| 45 return base::ScopedCFTypeRef<SecCertificateRef>(); |
| 46 |
| 47 if (!IsValidSecCertificate(cert_handle.get())) |
| 48 return base::ScopedCFTypeRef<SecCertificateRef>(); |
| 49 return cert_handle; |
| 50 } |
| 51 |
13 base::ScopedCFTypeRef<SecCertificateRef> | 52 base::ScopedCFTypeRef<SecCertificateRef> |
14 CreateSecCertificateFromX509Certificate(const X509Certificate* cert) { | 53 CreateSecCertificateFromX509Certificate(const X509Certificate* cert) { |
| 54 #if BUILDFLAG(USE_BYTE_CERTS) |
| 55 return CreateSecCertificateFromBytes( |
| 56 CRYPTO_BUFFER_data(cert->os_cert_handle()), |
| 57 CRYPTO_BUFFER_len(cert->os_cert_handle())); |
| 58 #else |
15 return base::ScopedCFTypeRef<SecCertificateRef>( | 59 return base::ScopedCFTypeRef<SecCertificateRef>( |
16 reinterpret_cast<SecCertificateRef>( | 60 reinterpret_cast<SecCertificateRef>( |
17 const_cast<void*>(CFRetain(cert->os_cert_handle())))); | 61 const_cast<void*>(CFRetain(cert->os_cert_handle())))); |
| 62 #endif |
| 63 } |
| 64 |
| 65 scoped_refptr<X509Certificate> CreateX509CertificateFromSecCertificate( |
| 66 SecCertificateRef sec_cert, |
| 67 const std::vector<SecCertificateRef>& sec_chain) { |
| 68 #if BUILDFLAG(USE_BYTE_CERTS) |
| 69 if (!sec_cert) |
| 70 return nullptr; |
| 71 base::ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(sec_cert)); |
| 72 if (!der_data) |
| 73 return nullptr; |
| 74 bssl::UniquePtr<CRYPTO_BUFFER> cert_handle( |
| 75 X509Certificate::CreateOSCertHandleFromBytes( |
| 76 reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)), |
| 77 CFDataGetLength(der_data))); |
| 78 if (!cert_handle) |
| 79 return nullptr; |
| 80 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates; |
| 81 X509Certificate::OSCertHandles intermediates_raw; |
| 82 for (const SecCertificateRef& sec_intermediate : sec_chain) { |
| 83 if (!sec_intermediate) |
| 84 return nullptr; |
| 85 der_data.reset(SecCertificateCopyData(sec_intermediate)); |
| 86 if (!der_data) |
| 87 return nullptr; |
| 88 bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle( |
| 89 X509Certificate::CreateOSCertHandleFromBytes( |
| 90 reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)), |
| 91 CFDataGetLength(der_data))); |
| 92 if (!intermediate_cert_handle) |
| 93 return nullptr; |
| 94 intermediates_raw.push_back(intermediate_cert_handle.get()); |
| 95 intermediates.push_back(std::move(intermediate_cert_handle)); |
| 96 } |
| 97 scoped_refptr<X509Certificate> result( |
| 98 X509Certificate::CreateFromHandle(cert_handle.get(), intermediates_raw)); |
| 99 return result; |
| 100 #else |
| 101 return X509Certificate::CreateFromHandle(sec_cert, sec_chain); |
| 102 #endif |
18 } | 103 } |
19 | 104 |
20 } // namespace x509_util | 105 } // namespace x509_util |
21 | 106 |
22 } // namespace net | 107 } // namespace net |
OLD | NEW |