Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: net/cert/cert_verify_proc_ios.cc

Issue 1810153002: Adding iOS OpenSSL Implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixing more nits. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016 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/cert_verify_proc_ios.h"
6
7 #include <CommonCrypto/CommonDigest.h>
8 #include <Security/Security.h>
9
10 #include "base/logging.h"
11 #include "base/mac/scoped_cftyperef.h"
12 #include "crypto/sha2.h"
13 #include "net/base/net_errors.h"
14 #include "net/cert/asn1_util.h"
15 #include "net/cert/cert_verify_result.h"
16 #include "net/cert/test_root_certs.h"
17 #include "net/cert/x509_certificate.h"
18 #include "net/ssl/openssl_ssl_util.h"
19
20 using base::ScopedCFTypeRef;
21
22 namespace net {
23
24 namespace {
25
26 int NetErrorFromOSStatus(OSStatus status) {
27 switch (status) {
28 case noErr:
29 return OK;
30 case errSecNotAvailable:
31 return ERR_NOT_IMPLEMENTED;
32 case errSecAuthFailed:
33 return ERR_ACCESS_DENIED;
34 default:
35 return ERR_FAILED;
36 }
37 }
38
39 // Creates a series of SecPolicyRefs to be added to a SecTrustRef used to
40 // validate a certificate for an SSL server. |hostname| contains the name of
41 // the SSL server that the certificate should be verified against. If
42 // successful, returns noErr, and stores the resultant array of SecPolicyRefs
43 // in |policies|.
44 OSStatus CreateTrustPolicies(ScopedCFTypeRef<CFArrayRef>* policies) {
45 ScopedCFTypeRef<CFMutableArrayRef> local_policies(
46 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
47 if (!local_policies)
48 return errSecAllocate;
49
50 SecPolicyRef ssl_policy = SecPolicyCreateBasicX509();
51 CFArrayAppendValue(local_policies, ssl_policy);
52 CFRelease(ssl_policy);
53 ssl_policy = SecPolicyCreateSSL(true, nullptr);
54 CFArrayAppendValue(local_policies, ssl_policy);
55 CFRelease(ssl_policy);
56
57 policies->reset(local_policies.release());
58 return noErr;
59 }
60
61 // Builds and evaluates a SecTrustRef for the certificate chain contained
62 // in |cert_array|, using the verification policies in |trust_policies|. On
63 // success, returns OK, and updates |trust_ref| and |trust_result|. On failure,
64 // no output parameters are modified.
65 //
66 // Note: An OK return does not mean that |cert_array| is trusted, merely that
67 // verification was performed successfully.
68 int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array,
69 CFArrayRef trust_policies,
70 ScopedCFTypeRef<SecTrustRef>* trust_ref,
71 ScopedCFTypeRef<CFArrayRef>* verified_chain,
72 SecTrustResultType* trust_result) {
73 SecTrustRef tmp_trust = nullptr;
74 OSStatus status =
75 SecTrustCreateWithCertificates(cert_array, trust_policies, &tmp_trust);
76 if (status)
77 return NetErrorFromOSStatus(status);
78 ScopedCFTypeRef<SecTrustRef> scoped_tmp_trust(tmp_trust);
79
80 if (TestRootCerts::HasInstance()) {
81 status = TestRootCerts::GetInstance()->FixupSecTrustRef(tmp_trust);
82 if (status)
83 return NetErrorFromOSStatus(status);
84 }
85
86 SecTrustResultType tmp_trust_result;
87 status = SecTrustEvaluate(tmp_trust, &tmp_trust_result);
88 if (status)
89 return NetErrorFromOSStatus(status);
90
91 ScopedCFTypeRef<CFMutableArrayRef> tmp_verified_chain(
92 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
93 const CFIndex chain_length = SecTrustGetCertificateCount(tmp_trust);
94 for (CFIndex i = 0; i < chain_length; ++i) {
95 SecCertificateRef chain_cert = SecTrustGetCertificateAtIndex(tmp_trust, i);
96 CFArrayAppendValue(tmp_verified_chain, chain_cert);
97 }
98
99 trust_ref->swap(scoped_tmp_trust);
100 *trust_result = tmp_trust_result;
101 verified_chain->reset(tmp_verified_chain.release());
102 return OK;
103 }
104
105 void GetCertChainInfo(CFArrayRef cert_chain, CertVerifyResult* verify_result) {
106 DCHECK_LT(0, CFArrayGetCount(cert_chain));
107
108 verify_result->has_md2 = false;
109 verify_result->has_md4 = false;
110 verify_result->has_md5 = false;
111 verify_result->has_sha1 = false;
112 verify_result->has_sha1_leaf = false;
113
114 SecCertificateRef verified_cert = nullptr;
115 std::vector<SecCertificateRef> verified_chain;
116 for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
117 SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>(
118 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
119 if (i == 0) {
120 verified_cert = chain_cert;
121 } else {
122 verified_chain.push_back(chain_cert);
123 }
124
125 std::string der_bytes;
126 if (!X509Certificate::GetDEREncoded(chain_cert, &der_bytes))
127 return;
128 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_bytes.data());
129 ScopedX509 x509_cert(d2i_X509(NULL, &bytes, der_bytes.size()));
130
131 base::StringPiece spki_bytes;
132 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
133 continue;
134
135 HashValue sha1(HASH_VALUE_SHA1);
136 CC_SHA1(spki_bytes.data(), spki_bytes.size(), sha1.data());
137 verify_result->public_key_hashes.push_back(sha1);
138
139 HashValue sha256(HASH_VALUE_SHA256);
140 CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.data());
141 verify_result->public_key_hashes.push_back(sha256);
142
143 int sig_alg = OBJ_obj2nid(x509_cert->sig_alg->algorithm);
144 if (sig_alg == NID_md2WithRSAEncryption) {
145 verify_result->has_md2 = true;
146 } else if (sig_alg == NID_md4WithRSAEncryption) {
147 verify_result->has_md4 = true;
148 } else if (sig_alg == NID_md5WithRSAEncryption ||
149 sig_alg == NID_md5WithRSA) {
150 verify_result->has_md5 = true;
151 } else if (sig_alg == NID_sha1WithRSAEncryption ||
152 sig_alg == NID_dsaWithSHA || sig_alg == NID_dsaWithSHA1 ||
153 sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA ||
154 sig_alg == NID_ecdsa_with_SHA1) {
155 verify_result->has_sha1 = true;
156 if (i == 0)
157 verify_result->has_sha1_leaf = true;
158 }
159 }
160 if (!verified_cert) {
161 NOTREACHED();
162 return;
163 }
164
165 verify_result->verified_cert =
166 X509Certificate::CreateFromHandle(verified_cert, verified_chain);
167 }
168
169 } // namespace
170
171 CertVerifyProcIOS::CertVerifyProcIOS() {}
172
173 CertVerifyProcIOS::~CertVerifyProcIOS() {}
174
175 bool CertVerifyProcIOS::SupportsAdditionalTrustAnchors() const {
176 return false;
177 }
178
179 bool CertVerifyProcIOS::SupportsOCSPStapling() const {
180 return false;
181 }
182
183 int CertVerifyProcIOS::VerifyInternal(
184 X509Certificate* cert,
185 const std::string& hostname,
186 const std::string& ocsp_response,
187 int flags,
188 CRLSet* crl_set,
189 const CertificateList& additional_trust_anchors,
190 CertVerifyResult* verify_result) {
191 ScopedCFTypeRef<CFArrayRef> trust_policies;
192 OSStatus status = CreateTrustPolicies(&trust_policies);
193 if (status)
194 return NetErrorFromOSStatus(status);
195
196 ScopedCFTypeRef<CFMutableArrayRef> cert_array(
197 cert->CreateOSCertChainForCert());
198 ScopedCFTypeRef<SecTrustRef> trust_ref;
199 SecTrustResultType trust_result = kSecTrustResultDeny;
200 ScopedCFTypeRef<CFArrayRef> final_chain;
201
202 status = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, &trust_ref,
203 &final_chain, &trust_result);
204 if (status)
205 return NetErrorFromOSStatus(status);
206
207 if (CFArrayGetCount(final_chain) == 0)
208 return ERR_FAILED;
209
210 GetCertChainInfo(final_chain, verify_result);
211
212 // TODO(sleevi): Support CRLSet revocation.
213 // TODO(svaldez): Add specific error codes for trust errors resulting from
214 // expired/not-yet-valid certs.
215 switch (trust_result) {
216 case kSecTrustResultUnspecified:
217 case kSecTrustResultProceed:
218 break;
219 case kSecTrustResultDeny:
220 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
221 default:
222 verify_result->cert_status |= CERT_STATUS_INVALID;
223 }
224
225 // Perform hostname verification independent of SecTrustEvaluate.
226 if (!verify_result->verified_cert->VerifyNameMatch(
227 hostname, &verify_result->common_name_fallback_used)) {
228 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
229 }
230
231 verify_result->is_issued_by_known_root = false;
232
233 if (IsCertStatusError(verify_result->cert_status))
234 return MapCertStatusToNetError(verify_result->cert_status);
235
236 return OK;
237 }
238
239 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698