OLD | NEW |
---|---|
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 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 | 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/cert_verify_proc_ios.h" | 5 #include "net/cert/cert_verify_proc_ios.h" |
6 | 6 |
7 #include <CommonCrypto/CommonDigest.h> | 7 #include <CommonCrypto/CommonDigest.h> |
8 #include <Security/Security.h> | 8 #include <Security/Security.h> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 continue; | 133 continue; |
134 | 134 |
135 HashValue sha1(HASH_VALUE_SHA1); | 135 HashValue sha1(HASH_VALUE_SHA1); |
136 CC_SHA1(spki_bytes.data(), spki_bytes.size(), sha1.data()); | 136 CC_SHA1(spki_bytes.data(), spki_bytes.size(), sha1.data()); |
137 verify_result->public_key_hashes.push_back(sha1); | 137 verify_result->public_key_hashes.push_back(sha1); |
138 | 138 |
139 HashValue sha256(HASH_VALUE_SHA256); | 139 HashValue sha256(HASH_VALUE_SHA256); |
140 CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.data()); | 140 CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.data()); |
141 verify_result->public_key_hashes.push_back(sha256); | 141 verify_result->public_key_hashes.push_back(sha256); |
142 | 142 |
143 // Ignore the signature algorithm for the trust anchor. | |
144 if (i == count - 1) | |
145 continue; | |
146 | |
143 int sig_alg = OBJ_obj2nid(x509_cert->sig_alg->algorithm); | 147 int sig_alg = OBJ_obj2nid(x509_cert->sig_alg->algorithm); |
144 if (sig_alg == NID_md2WithRSAEncryption) { | 148 if (sig_alg == NID_md2WithRSAEncryption) { |
145 verify_result->has_md2 = true; | 149 verify_result->has_md2 = true; |
146 } else if (sig_alg == NID_md4WithRSAEncryption) { | 150 } else if (sig_alg == NID_md4WithRSAEncryption) { |
147 verify_result->has_md4 = true; | 151 verify_result->has_md4 = true; |
148 } else if (sig_alg == NID_md5WithRSAEncryption || | 152 } else if (sig_alg == NID_md5WithRSAEncryption || |
149 sig_alg == NID_md5WithRSA) { | 153 sig_alg == NID_md5WithRSA) { |
150 verify_result->has_md5 = true; | 154 verify_result->has_md5 = true; |
151 } else if (sig_alg == NID_sha1WithRSAEncryption || | 155 } else if (sig_alg == NID_sha1WithRSAEncryption || |
152 sig_alg == NID_dsaWithSHA || sig_alg == NID_dsaWithSHA1 || | 156 sig_alg == NID_dsaWithSHA || sig_alg == NID_dsaWithSHA1 || |
153 sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA || | 157 sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA || |
154 sig_alg == NID_ecdsa_with_SHA1) { | 158 sig_alg == NID_ecdsa_with_SHA1) { |
155 verify_result->has_sha1 = true; | 159 verify_result->has_sha1 = true; |
156 if (i == 0) | 160 if (i == 0) |
157 verify_result->has_sha1_leaf = true; | 161 verify_result->has_sha1_leaf = true; |
158 } | 162 } |
159 } | 163 } |
160 if (!verified_cert) { | 164 if (!verified_cert) { |
161 NOTREACHED(); | 165 NOTREACHED(); |
162 return; | 166 return; |
163 } | 167 } |
164 | 168 |
165 verify_result->verified_cert = | 169 verify_result->verified_cert = |
166 X509Certificate::CreateFromHandle(verified_cert, verified_chain); | 170 X509Certificate::CreateFromHandle(verified_cert, verified_chain); |
167 } | 171 } |
168 | 172 |
173 // Due to the lack of an iOS API to get the reason for cert verification | |
174 // failures, we instead check the error messages that are attached to the | |
175 // certificate chain to differentiate between various verification failures. | |
Ryan Sleevi
2016/04/08 20:44:21
Let's expand this more:
// The iOS APIs don't exp
svaldez
2016/04/08 20:51:37
Done.
| |
176 CertStatus GetFailureFromTrustProperties(CFArrayRef properties) { | |
177 CertStatus reason = 0; | |
178 | |
179 if (!properties) | |
180 return CERT_STATUS_INVALID; | |
181 | |
182 const CFIndex properties_length = CFArrayGetCount(properties); | |
183 if (properties_length == 0) | |
184 return CERT_STATUS_INVALID; | |
185 | |
186 CFBundleRef bundle = | |
187 CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Security")); | |
188 CFStringRef date_string = | |
189 CFSTR("One or more certificates have expired or are not valid yet."); | |
190 CFStringRef date_error = CFBundleCopyLocalizedString( | |
191 bundle, date_string, date_string, CFSTR("SecCertificate")); | |
Ryan Sleevi
2016/04/08 20:44:21
Can you add a DCHECK that each of the error string
svaldez
2016/04/08 20:51:38
Done.
| |
192 CFStringRef trust_string = CFSTR("Root certificate is not trusted."); | |
193 CFStringRef trust_error = CFBundleCopyLocalizedString( | |
194 bundle, trust_string, trust_string, CFSTR("SecCertificate")); | |
195 CFStringRef weak_string = | |
196 CFSTR("One or more certificates is using a weak key size."); | |
197 CFStringRef weak_error = CFBundleCopyLocalizedString( | |
198 bundle, weak_string, weak_string, CFSTR("SecCertificate")); | |
199 | |
200 for (CFIndex i = 0; i < properties_length; ++i) { | |
201 CFDictionaryRef dict = reinterpret_cast<CFDictionaryRef>( | |
202 const_cast<void*>(CFArrayGetValueAtIndex(properties, i))); | |
203 CFStringRef error = reinterpret_cast<CFStringRef>( | |
204 const_cast<void*>(CFDictionaryGetValue(dict, CFSTR("value")))); | |
205 | |
206 if (CFEqual(error, date_error)) { | |
207 reason |= CERT_STATUS_DATE_INVALID; | |
208 } else if (CFEqual(error, trust_error)) { | |
209 reason |= CERT_STATUS_AUTHORITY_INVALID; | |
210 } else if (CFEqual(error, weak_error)) { | |
211 reason |= CERT_STATUS_WEAK_KEY; | |
212 } else { | |
213 reason |= CERT_STATUS_INVALID; | |
214 } | |
215 } | |
216 | |
217 return reason; | |
218 } | |
219 | |
169 } // namespace | 220 } // namespace |
170 | 221 |
171 CertVerifyProcIOS::CertVerifyProcIOS() {} | 222 CertVerifyProcIOS::CertVerifyProcIOS() {} |
172 | 223 |
173 CertVerifyProcIOS::~CertVerifyProcIOS() {} | 224 CertVerifyProcIOS::~CertVerifyProcIOS() {} |
174 | 225 |
175 bool CertVerifyProcIOS::SupportsAdditionalTrustAnchors() const { | 226 bool CertVerifyProcIOS::SupportsAdditionalTrustAnchors() const { |
176 return false; | 227 return false; |
177 } | 228 } |
178 | 229 |
(...skipping 24 matching lines...) Expand all Loading... | |
203 &final_chain, &trust_result); | 254 &final_chain, &trust_result); |
204 if (status) | 255 if (status) |
205 return NetErrorFromOSStatus(status); | 256 return NetErrorFromOSStatus(status); |
206 | 257 |
207 if (CFArrayGetCount(final_chain) == 0) | 258 if (CFArrayGetCount(final_chain) == 0) |
208 return ERR_FAILED; | 259 return ERR_FAILED; |
209 | 260 |
210 GetCertChainInfo(final_chain, verify_result); | 261 GetCertChainInfo(final_chain, verify_result); |
211 | 262 |
212 // TODO(sleevi): Support CRLSet revocation. | 263 // 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) { | 264 switch (trust_result) { |
216 case kSecTrustResultUnspecified: | 265 case kSecTrustResultUnspecified: |
217 case kSecTrustResultProceed: | 266 case kSecTrustResultProceed: |
218 break; | 267 break; |
219 case kSecTrustResultDeny: | 268 case kSecTrustResultDeny: |
220 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; | 269 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; |
270 break; | |
221 default: | 271 default: |
222 verify_result->cert_status |= CERT_STATUS_INVALID; | 272 CFArrayRef properties = SecTrustCopyProperties(trust_ref); |
273 verify_result->cert_status |= GetFailureFromTrustProperties(properties); | |
223 } | 274 } |
224 | 275 |
225 // Perform hostname verification independent of SecTrustEvaluate. | 276 // Perform hostname verification independent of SecTrustEvaluate. |
226 if (!verify_result->verified_cert->VerifyNameMatch( | 277 if (!verify_result->verified_cert->VerifyNameMatch( |
227 hostname, &verify_result->common_name_fallback_used)) { | 278 hostname, &verify_result->common_name_fallback_used)) { |
228 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | 279 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; |
229 } | 280 } |
230 | 281 |
231 verify_result->is_issued_by_known_root = false; | 282 verify_result->is_issued_by_known_root = false; |
232 | 283 |
233 if (IsCertStatusError(verify_result->cert_status)) | 284 if (IsCertStatusError(verify_result->cert_status)) |
234 return MapCertStatusToNetError(verify_result->cert_status); | 285 return MapCertStatusToNetError(verify_result->cert_status); |
235 | 286 |
236 return OK; | 287 return OK; |
237 } | 288 } |
238 | 289 |
239 } // namespace net | 290 } // namespace net |
OLD | NEW |