| OLD | NEW |
| (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/x509_certificate.h" | |
| 6 | |
| 7 #include <CommonCrypto/CommonDigest.h> | |
| 8 #include <Security/Security.h> | |
| 9 | |
| 10 #include <openssl/x509.h> | |
| 11 #include <openssl/x509v3.h> | |
| 12 | |
| 13 #include "base/mac/scoped_cftyperef.h" | |
| 14 #include "base/pickle.h" | |
| 15 #include "base/strings/string_piece.h" | |
| 16 #include "base/strings/string_util.h" | |
| 17 #include "crypto/openssl_util.h" | |
| 18 #include "crypto/scoped_openssl_types.h" | |
| 19 #include "net/base/ip_address_number.h" | |
| 20 #include "net/cert/x509_util_openssl.h" | |
| 21 #include "net/ssl/openssl_ssl_util.h" | |
| 22 | |
| 23 using base::ScopedCFTypeRef; | |
| 24 | |
| 25 namespace net { | |
| 26 | |
| 27 namespace { | |
| 28 | |
| 29 using ScopedGENERAL_NAMES = | |
| 30 crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>; | |
| 31 | |
| 32 // Returns true if a given |cert_handle| is actually a valid X.509 certificate | |
| 33 // handle. | |
| 34 // | |
| 35 // SecCertificateCreateFromData() does not always force the immediate parsing of | |
| 36 // the certificate, and as such, may return a SecCertificateRef for an | |
| 37 // invalid/unparsable certificate. Force parsing to occur to ensure that the | |
| 38 // SecCertificateRef is correct. On later versions where | |
| 39 // SecCertificateCreateFromData() immediately parses, rather than lazily, this | |
| 40 // call is cheap, as the subject is cached. | |
| 41 bool IsValidOSCertHandle(SecCertificateRef cert_handle) { | |
| 42 ScopedCFTypeRef<CFStringRef> sanity_check( | |
| 43 SecCertificateCopySubjectSummary(cert_handle)); | |
| 44 return sanity_check != nullptr; | |
| 45 } | |
| 46 | |
| 47 void CreateOSCertHandlesFromPKCS7Bytes( | |
| 48 const char* data, | |
| 49 size_t length, | |
| 50 X509Certificate::OSCertHandles* handles) { | |
| 51 crypto::EnsureOpenSSLInit(); | |
| 52 crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE); | |
| 53 | |
| 54 CBS der_data; | |
| 55 CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length); | |
| 56 STACK_OF(X509)* certs = sk_X509_new_null(); | |
| 57 | |
| 58 if (PKCS7_get_certificates(certs, &der_data)) { | |
| 59 for (size_t i = 0; i < sk_X509_num(certs); ++i) { | |
| 60 X509* x509_cert = sk_X509_value(certs, i); | |
| 61 base::StringPiece der; | |
| 62 if (!x509_util::GetDER(x509_cert, &der)) | |
| 63 return; | |
| 64 handles->push_back(X509Certificate::CreateOSCertHandleFromBytes( | |
| 65 der.data(), der.length())); | |
| 66 } | |
| 67 } | |
| 68 sk_X509_pop_free(certs, X509_free); | |
| 69 } | |
| 70 | |
| 71 void ParsePrincipalValues(X509_NAME* name, | |
| 72 int nid, | |
| 73 std::vector<std::string>* fields) { | |
| 74 for (int index = -1; | |
| 75 (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) { | |
| 76 std::string field; | |
| 77 if (!x509_util::ParsePrincipalValueByIndex(name, index, &field)) | |
| 78 break; | |
| 79 fields->push_back(field); | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 void ParsePrincipal(X509Certificate::OSCertHandle os_cert, | |
| 84 X509_NAME* x509_name, | |
| 85 CertPrincipal* principal) { | |
| 86 if (!x509_name) | |
| 87 return; | |
| 88 | |
| 89 ParsePrincipalValues(x509_name, NID_streetAddress, | |
| 90 &principal->street_addresses); | |
| 91 ParsePrincipalValues(x509_name, NID_organizationName, | |
| 92 &principal->organization_names); | |
| 93 ParsePrincipalValues(x509_name, NID_organizationalUnitName, | |
| 94 &principal->organization_unit_names); | |
| 95 ParsePrincipalValues(x509_name, NID_domainComponent, | |
| 96 &principal->domain_components); | |
| 97 | |
| 98 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, | |
| 99 &principal->common_name); | |
| 100 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, | |
| 101 &principal->locality_name); | |
| 102 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, | |
| 103 &principal->state_or_province_name); | |
| 104 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, | |
| 105 &principal->country_name); | |
| 106 } | |
| 107 | |
| 108 void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, | |
| 109 std::vector<std::string>* dns_names, | |
| 110 std::vector<std::string>* ip_addresses) { | |
| 111 DCHECK(dns_names || ip_addresses); | |
| 112 ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); | |
| 113 if (!cert.get()) | |
| 114 return; | |
| 115 int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); | |
| 116 X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index); | |
| 117 if (!alt_name_ext) | |
| 118 return; | |
| 119 | |
| 120 ScopedGENERAL_NAMES alt_names( | |
| 121 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); | |
| 122 if (!alt_names.get()) | |
| 123 return; | |
| 124 | |
| 125 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { | |
| 126 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); | |
| 127 if (name->type == GEN_DNS && dns_names) { | |
| 128 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); | |
| 129 if (!dns_name) | |
| 130 continue; | |
| 131 int dns_name_len = ASN1_STRING_length(name->d.dNSName); | |
| 132 dns_names->push_back( | |
| 133 std::string(reinterpret_cast<const char*>(dns_name), dns_name_len)); | |
| 134 } else if (name->type == GEN_IPADD && ip_addresses) { | |
| 135 const unsigned char* ip_addr = name->d.iPAddress->data; | |
| 136 if (!ip_addr) | |
| 137 continue; | |
| 138 int ip_addr_len = name->d.iPAddress->length; | |
| 139 if (ip_addr_len != static_cast<int>(kIPv4AddressSize) && | |
| 140 ip_addr_len != static_cast<int>(kIPv6AddressSize)) { | |
| 141 // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress | |
| 142 // to have 4 or 16 bytes, whereas in a name constraint it includes a | |
| 143 // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup. | |
| 144 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; | |
| 145 continue; | |
| 146 } | |
| 147 ip_addresses->push_back( | |
| 148 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); | |
| 149 } | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 // Used to free a list of X509_NAMEs and the objects it points to. | |
| 154 void sk_X509_NAME_free_all(STACK_OF(X509_NAME) * sk) { | |
| 155 sk_X509_NAME_pop_free(sk, X509_NAME_free); | |
| 156 } | |
| 157 | |
| 158 } // namespace | |
| 159 | |
| 160 // static | |
| 161 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | |
| 162 OSCertHandle handle) { | |
| 163 if (!handle) | |
| 164 return nullptr; | |
| 165 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); | |
| 166 } | |
| 167 | |
| 168 // static | |
| 169 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | |
| 170 if (cert_handle) | |
| 171 CFRelease(cert_handle); | |
| 172 } | |
| 173 | |
| 174 void X509Certificate::Initialize() { | |
| 175 crypto::EnsureOpenSSLInit(); | |
| 176 fingerprint_ = CalculateFingerprint(cert_handle_); | |
| 177 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); | |
| 178 ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); | |
| 179 if (!x509_cert) | |
| 180 return; | |
| 181 ASN1_INTEGER* serial_num = X509_get_serialNumber(x509_cert.get()); | |
| 182 if (serial_num) { | |
| 183 // ASN1_INTEGERS represent the decoded number, in a format internal to | |
| 184 // OpenSSL. Most notably, this may have leading zeroes stripped off for | |
| 185 // numbers whose first byte is >= 0x80. Thus, it is necessary to | |
| 186 // re-encoded the integer back into DER, which is what the interface | |
| 187 // of X509Certificate exposes, to ensure callers get the proper (DER) | |
| 188 // value. | |
| 189 int bytes_required = i2c_ASN1_INTEGER(serial_num, nullptr); | |
| 190 unsigned char* buffer = reinterpret_cast<unsigned char*>( | |
| 191 base::WriteInto(&serial_number_, bytes_required + 1)); | |
| 192 int bytes_written = i2c_ASN1_INTEGER(serial_num, &buffer); | |
| 193 DCHECK_EQ(static_cast<size_t>(bytes_written), serial_number_.size()); | |
| 194 } | |
| 195 | |
| 196 ParsePrincipal(cert_handle_, X509_get_subject_name(x509_cert.get()), | |
| 197 &subject_); | |
| 198 ParsePrincipal(cert_handle_, X509_get_issuer_name(x509_cert.get()), &issuer_); | |
| 199 x509_util::ParseDate(X509_get_notBefore(x509_cert.get()), &valid_start_); | |
| 200 x509_util::ParseDate(X509_get_notAfter(x509_cert.get()), &valid_expiry_); | |
| 201 } | |
| 202 | |
| 203 // static | |
| 204 SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) { | |
| 205 SHA1HashValue sha1; | |
| 206 memset(sha1.data, 0, sizeof(sha1.data)); | |
| 207 | |
| 208 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert)); | |
| 209 if (!cert_data) | |
| 210 return sha1; | |
| 211 DCHECK(CFDataGetBytePtr(cert_data)); | |
| 212 DCHECK_NE(0, CFDataGetLength(cert_data)); | |
| 213 CC_SHA1(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), sha1.data); | |
| 214 | |
| 215 return sha1; | |
| 216 } | |
| 217 | |
| 218 // static | |
| 219 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) { | |
| 220 SHA256HashValue sha256; | |
| 221 memset(sha256.data, 0, sizeof(sha256.data)); | |
| 222 | |
| 223 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert)); | |
| 224 if (!cert_data) | |
| 225 return sha256; | |
| 226 DCHECK(CFDataGetBytePtr(cert_data)); | |
| 227 DCHECK_NE(0, CFDataGetLength(cert_data)); | |
| 228 CC_SHA256(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), | |
| 229 sha256.data); | |
| 230 | |
| 231 return sha256; | |
| 232 } | |
| 233 | |
| 234 // static | |
| 235 SHA1HashValue X509Certificate::CalculateCAFingerprint( | |
| 236 const OSCertHandles& intermediates) { | |
| 237 SHA1HashValue sha1; | |
| 238 memset(sha1.data, 0, sizeof(sha1.data)); | |
| 239 | |
| 240 CC_SHA1_CTX sha1_ctx; | |
| 241 CC_SHA1_Init(&sha1_ctx); | |
| 242 for (size_t i = 0; i < intermediates.size(); ++i) { | |
| 243 ScopedCFTypeRef<CFDataRef> cert_data( | |
| 244 SecCertificateCopyData(intermediates[i])); | |
| 245 if (!cert_data) | |
| 246 return sha1; | |
| 247 CC_SHA1_Update(&sha1_ctx, CFDataGetBytePtr(cert_data), | |
| 248 CFDataGetLength(cert_data)); | |
| 249 } | |
| 250 CC_SHA1_Final(sha1.data, &sha1_ctx); | |
| 251 return sha1; | |
| 252 } | |
| 253 | |
| 254 // static | |
| 255 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | |
| 256 const char* data, | |
| 257 size_t length) { | |
| 258 ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy( | |
| 259 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), | |
| 260 base::checked_cast<CFIndex>(length), kCFAllocatorNull)); | |
| 261 if (!cert_data) | |
| 262 return nullptr; | |
| 263 OSCertHandle cert_handle = SecCertificateCreateWithData(nullptr, cert_data); | |
| 264 if (!cert_handle) | |
| 265 return nullptr; | |
| 266 if (!IsValidOSCertHandle(cert_handle)) { | |
| 267 CFRelease(cert_handle); | |
| 268 return nullptr; | |
| 269 } | |
| 270 return cert_handle; | |
| 271 } | |
| 272 | |
| 273 // static | |
| 274 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | |
| 275 const char* data, | |
| 276 size_t length, | |
| 277 Format format) { | |
| 278 OSCertHandles results; | |
| 279 | |
| 280 switch (format) { | |
| 281 case FORMAT_SINGLE_CERTIFICATE: { | |
| 282 OSCertHandle handle = | |
| 283 X509Certificate::CreateOSCertHandleFromBytes(data, length); | |
| 284 if (handle) | |
| 285 results.push_back(handle); | |
| 286 break; | |
| 287 } | |
| 288 case FORMAT_PKCS7: { | |
| 289 CreateOSCertHandlesFromPKCS7Bytes(data, length, &results); | |
| 290 break; | |
| 291 } | |
| 292 default: { | |
| 293 NOTREACHED() << "Certificate format " << format << " unimplemented"; | |
| 294 break; | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 return results; | |
| 299 } | |
| 300 | |
| 301 void X509Certificate::GetSubjectAltName( | |
| 302 std::vector<std::string>* dns_names, | |
| 303 std::vector<std::string>* ip_addrs) const { | |
| 304 if (dns_names) | |
| 305 dns_names->clear(); | |
| 306 if (ip_addrs) | |
| 307 ip_addrs->clear(); | |
| 308 | |
| 309 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); | |
| 310 } | |
| 311 | |
| 312 // static | |
| 313 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | |
| 314 std::string* encoded) { | |
| 315 base::StringPiece der; | |
| 316 if (!cert_handle) | |
| 317 return false; | |
| 318 ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle)); | |
| 319 if (!der_data) | |
| 320 return false; | |
| 321 encoded->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)), | |
| 322 CFDataGetLength(der_data)); | |
| 323 return true; | |
| 324 } | |
| 325 | |
| 326 // static | |
| 327 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | |
| 328 X509Certificate::OSCertHandle b) { | |
| 329 DCHECK(a && b); | |
| 330 return CFEqual(a, b); | |
| 331 } | |
| 332 | |
| 333 // static | |
| 334 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( | |
| 335 base::PickleIterator* pickle_iter) { | |
| 336 const char* data; | |
| 337 int length; | |
| 338 if (!pickle_iter->ReadData(&data, &length)) | |
| 339 return nullptr; | |
| 340 | |
| 341 return X509Certificate::CreateOSCertHandleFromBytes(data, length); | |
| 342 } | |
| 343 | |
| 344 // static | |
| 345 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, | |
| 346 base::Pickle* pickle) { | |
| 347 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle)); | |
| 348 if (!cert_data) | |
| 349 return false; | |
| 350 | |
| 351 return pickle->WriteData( | |
| 352 reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)), | |
| 353 CFDataGetLength(cert_data)); | |
| 354 } | |
| 355 | |
| 356 // static | |
| 357 void X509Certificate::GetPublicKeyInfo(OSCertHandle os_cert, | |
| 358 size_t* size_bits, | |
| 359 PublicKeyType* type) { | |
| 360 *type = kPublicKeyTypeUnknown; | |
| 361 *size_bits = 0; | |
| 362 ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); | |
| 363 if (!cert) | |
| 364 return; | |
| 365 crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); | |
| 366 if (!scoped_key) | |
| 367 return; | |
| 368 | |
| 369 EVP_PKEY* key = scoped_key.get(); | |
| 370 | |
| 371 switch (key->type) { | |
| 372 case EVP_PKEY_RSA: | |
| 373 *type = kPublicKeyTypeRSA; | |
| 374 break; | |
| 375 case EVP_PKEY_DSA: | |
| 376 *type = kPublicKeyTypeDSA; | |
| 377 break; | |
| 378 case EVP_PKEY_EC: | |
| 379 *type = kPublicKeyTypeECDSA; | |
| 380 break; | |
| 381 case EVP_PKEY_DH: | |
| 382 *type = kPublicKeyTypeDH; | |
| 383 break; | |
| 384 } | |
| 385 *size_bits = EVP_PKEY_bits(key); | |
| 386 } | |
| 387 | |
| 388 bool X509Certificate::SupportsSSLClientAuth() const { | |
| 389 return false; | |
| 390 } | |
| 391 | |
| 392 CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const { | |
| 393 CFMutableArrayRef cert_list = | |
| 394 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
| 395 if (!cert_list) | |
| 396 return nullptr; | |
| 397 | |
| 398 CFArrayAppendValue(cert_list, os_cert_handle()); | |
| 399 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) | |
| 400 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); | |
| 401 | |
| 402 return cert_list; | |
| 403 } | |
| 404 | |
| 405 bool X509Certificate::IsIssuedByEncoded( | |
| 406 const std::vector<std::string>& valid_issuers) { | |
| 407 if (valid_issuers.empty()) | |
| 408 return false; | |
| 409 | |
| 410 // Convert to a temporary list of X509_NAME objects. | |
| 411 // It will own the objects it points to. | |
| 412 crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all> | |
| 413 issuer_names(sk_X509_NAME_new_null()); | |
| 414 if (!issuer_names) | |
| 415 return false; | |
| 416 | |
| 417 for (std::vector<std::string>::const_iterator it = valid_issuers.begin(); | |
| 418 it != valid_issuers.end(); ++it) { | |
| 419 const unsigned char* p = reinterpret_cast<const unsigned char*>(it->data()); | |
| 420 long len = static_cast<long>(it->length()); | |
| 421 X509_NAME* ca_name = d2i_X509_NAME(nullptr, &p, len); | |
| 422 if (ca_name == nullptr) | |
| 423 return false; | |
| 424 sk_X509_NAME_push(issuer_names.get(), ca_name); | |
| 425 } | |
| 426 | |
| 427 // Create a temporary list of X509_NAME objects corresponding | |
| 428 // to the certificate chain. It doesn't own the object it points to. | |
| 429 std::vector<X509_NAME*> cert_names; | |
| 430 ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); | |
| 431 if (!x509_cert) | |
| 432 return false; | |
| 433 X509_NAME* issuer = X509_get_issuer_name(x509_cert.get()); | |
| 434 if (issuer == nullptr) | |
| 435 return false; | |
| 436 | |
| 437 cert_names.push_back(issuer); | |
| 438 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); | |
| 439 it != intermediate_ca_certs_.end(); ++it) { | |
| 440 ScopedX509 intermediate_cert = OSCertHandleToOpenSSL(*it); | |
| 441 if (!intermediate_cert) | |
| 442 return false; | |
| 443 issuer = X509_get_issuer_name(intermediate_cert.get()); | |
| 444 if (issuer == nullptr) | |
| 445 return false; | |
| 446 cert_names.push_back(issuer); | |
| 447 } | |
| 448 | |
| 449 // and 'cert_names'. | |
| 450 for (size_t n = 0; n < cert_names.size(); ++n) { | |
| 451 for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) { | |
| 452 X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m); | |
| 453 if (X509_NAME_cmp(issuer, cert_names[n]) == 0) { | |
| 454 return true; | |
| 455 } | |
| 456 } | |
| 457 } | |
| 458 | |
| 459 return false; | |
| 460 } | |
| 461 | |
| 462 // static | |
| 463 bool X509Certificate::IsSelfSigned(OSCertHandle os_cert) { | |
| 464 ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); | |
| 465 if (!cert) | |
| 466 return false; | |
| 467 crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); | |
| 468 if (!scoped_key) | |
| 469 return false; | |
| 470 | |
| 471 // NOTE: X509_verify() returns 1 in case of success, 0 or -1 on error. | |
| 472 return X509_verify(cert.get(), scoped_key.get()) == 1; | |
| 473 } | |
| 474 | |
| 475 } // namespace net | |
| OLD | NEW |