1 // Copyright 2013 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/ct_objects_extractor.h" 6 7 #include <string.h> 8 9 #include <openssl/bytestring.h> 10 #include <openssl/obj.h> 11 #include <openssl/x509.h> 12 13 #include "base/logging.h" 14 #include "base/sha1.h" 15 #include "base/strings/string_util.h" 16 #include "crypto/scoped_openssl_types.h" 17 #include "crypto/sha2.h" 18 #include "net/cert/asn1_util.h" 19 #include "net/cert/signed_certificate_timestamp.h" 20 21 namespace net { 22 23 namespace ct { 24 25 namespace { 26 27 typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509; 28 29 void FreeX509_EXTENSIONS(X509_EXTENSIONS* ptr) { 30 sk_X509_EXTENSION_pop_free(ptr, X509_EXTENSION_free); 31 } 32 33 typedef crypto::ScopedOpenSSL<X509_EXTENSIONS, FreeX509_EXTENSIONS>::Type 34 ScopedX509_EXTENSIONS; 35 36 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of 37 // RFC6962. 38 const uint8_t kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79, 39 0x02, 0x04, 0x02}; 40 41 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for 42 // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see 43 // Section 3.3 of RFC6962. 44 const uint8_t kOCSPExtensionOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79, 45 0x02, 0x04, 0x05}; 46 47 bool StringEqualToCBS(const std::string& value1, const CBS* value2) { 48 if (CBS_len(value2) != value1.size()) 49 return false; 50 return memcmp(value1.data(), CBS_data(value2), CBS_len(value2)) == 0; 51 } 52 53 ScopedX509 OSCertHandleToOpenSSL(X509Certificate::OSCertHandle os_handle) { 54 #if defined(USE_OPENSSL_CERTS) 55 return ScopedX509(X509Certificate::DupOSCertHandle(os_handle)); 56 #else 57 std::string der_encoded; 58 if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded)) 59 return ScopedX509(); 60 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data()); 61 return ScopedX509(d2i_X509(NULL, &bytes, der_encoded.size())); 62 #endif 63 } 64 65 // Finds the SignedCertificateTimestampList in an extension with OID |oid| in 66 // |x509_exts|. If found, returns true and sets |*out_sct_list| to the encoded 67 // SCT list. |out_sct_list| may be NULL. 68 bool GetSCTListFromX509_EXTENSIONS(const X509_EXTENSIONS* x509_exts, 69 const uint8_t* oid, 70 size_t oid_len, 71 std::string* out_sct_list) { 72 for (size_t i = 0; i < sk_X509_EXTENSION_num(x509_exts); i++) { 73 X509_EXTENSION* x509_ext = sk_X509_EXTENSION_value(x509_exts, i); 74 if (static_cast<size_t>(x509_ext->object->length) == oid_len && 75 memcmp(x509_ext->object->data, oid, oid_len) == 0) { 76 // The SCT list is an OCTET STRING inside the extension. 77 CBS ext_value, sct_list; 78 CBS_init(&ext_value, x509_ext->value->data, x509_ext->value->length); 79 if (!CBS_get_asn1(&ext_value, &sct_list, CBS_ASN1_OCTETSTRING) || 80 CBS_len(&ext_value) != 0) { 81 return false; 82 } 83 if (out_sct_list) { 84 *out_sct_list = std::string( 85 reinterpret_cast<const char*>(CBS_data(&sct_list)), 86 CBS_len(&sct_list)); 87 } 88 return true; 89 } 90 } 91 return false; 92 } 93 94 // Finds the SingleResponse in |responses| which matches |issuer| and 95 // |cert_serial_number|. On success, returns true and sets 96 // |*out_single_response| to the body of the SingleResponse starting at the 97 // |certStatus| field. 98 bool FindMatchingSingleResponse(CBS* responses, 99 X509Certificate::OSCertHandle issuer, 100 const std::string& cert_serial_number, 101 CBS* out_single_response) { 102 std::string issuer_der; 103 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der)) 104 return false; 105 106 base::StringPiece issuer_spki; 107 if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_spki)) 108 return false; 109 110 // In OCSP, only the key itself is under hash. 111 base::StringPiece issuer_spk; 112 if (!asn1::ExtractSubjectPublicKeyFromSPKI(issuer_spki, &issuer_spk)) 113 return false; 114 115 // ExtractSubjectPublicKey... does not remove the initial octet encoding the 116 // number of unused bits in the ASN.1 BIT STRING so we do it here. For public 117 // keys, the bitstring is in practice always byte-aligned. 118 if (issuer_spk.empty() || issuer_spk[0] != 0) 119 return false; 120 issuer_spk.remove_prefix(1); 121 122 // TODO(ekasper): add SHA-384 to crypto/sha2.h and here if it proves 123 // necessary. 124 // TODO(ekasper): only compute the hashes on demand. 125 std::string issuer_key_sha256_hash = crypto::SHA256HashString(issuer_spk); 126 std::string issuer_key_sha1_hash = base::SHA1HashString( 127 issuer_spk.as_string()); 128 129 while (CBS_len(responses) > 0) { 130 CBS single_response, cert_id; 131 if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE) || 132 !CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) { 133 return false; 134 } 135 136 CBS hash_algorithm, hash, serial_number, issuer_name_hash, issuer_key_hash; 137 if (!CBS_get_asn1(&cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) || 138 !CBS_get_asn1(&hash_algorithm, &hash, CBS_ASN1_OBJECT) || 139 !CBS_get_asn1(&cert_id, &issuer_name_hash, CBS_ASN1_OCTETSTRING) || 140 !CBS_get_asn1(&cert_id, &issuer_key_hash, CBS_ASN1_OCTETSTRING) || 141 !CBS_get_asn1(&cert_id, &serial_number, CBS_ASN1_INTEGER) || 142 CBS_len(&cert_id) != 0) { 143 return false; 144 } 145 146 // Check the serial number matches. 147 if (!StringEqualToCBS(cert_serial_number, &serial_number)) 148 continue; 149 150 // Check if the issuer_key_hash matches. 151 // TODO(ekasper): also use the issuer name hash in matching. 152 switch (OBJ_cbs2nid(&hash)) { 153 case NID_sha1: 154 if (StringEqualToCBS(issuer_key_sha1_hash, &issuer_key_hash)) { 155 *out_single_response = single_response; 156 return true; 157 } 158 break; 159 case NID_sha256: 160 if (StringEqualToCBS(issuer_key_sha256_hash, &issuer_key_hash)) { 161 *out_single_response = single_response; 162 return true; 163 } 164 break; 165 } 166 } 167 168 return false; 169 } 170 171 } // namespace 172 173 bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert, 174 std::string* sct_list) { 175 ScopedX509 x509(OSCertHandleToOpenSSL(cert)); 176 if (!x509) 177 return false; 178 X509_EXTENSIONS* x509_exts = x509->cert_info->extensions; 179 if (!x509_exts) 180 return false; 181 return GetSCTListFromX509_EXTENSIONS( 182 x509->cert_info->extensions, kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), 183 sct_list); 184 } 185 186 bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf, 187 X509Certificate::OSCertHandle issuer, 188 LogEntry* result) { 189 result->Reset(); 190 191 ScopedX509 leaf_x509(OSCertHandleToOpenSSL(leaf)); 192 if (!leaf_x509) 193 return false; 194 195 // XXX(rsleevi): This check may be overkill, since we should be able to 196 // generate precerts for certs without the extension. For now, just a sanity 197 // check to match the reference implementation. 198 if (!leaf_x509->cert_info->extensions || 199 !GetSCTListFromX509_EXTENSIONS(leaf_x509->cert_info->extensions, 200 kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), 201 NULL)) { 202 return false; 203 } 204 205 // The Precertificate log entry is the final certificate's TBSCertificate 206 // without the SCT extension (RFC6962, section 3.2). 207 ScopedX509 leaf_copy(X509_dup(leaf_x509.get())); 208 if (!leaf_copy || !leaf_copy->cert_info->extensions) { 209 NOTREACHED(); 210 return false; 211 } 212 X509_EXTENSIONS* leaf_copy_exts = leaf_copy->cert_info->extensions; 213 for (size_t i = 0; i < sk_X509_EXTENSION_num(leaf_copy_exts); i++) { 214 X509_EXTENSION* ext = sk_X509_EXTENSION_value(leaf_copy_exts, i); 215 if (static_cast<size_t>(ext->object->length) == sizeof(kEmbeddedSCTOid) && 216 memcmp(ext->object->data, 217 kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid)) == 0) { 218 X509_EXTENSION_free(sk_X509_EXTENSION_delete(leaf_copy_exts, i)); 219 X509_CINF_set_modified(leaf_copy->cert_info); 220 break; 221 } 222 } 223 224 std::string to_be_signed; 225 int len = i2d_X509_CINF(leaf_copy->cert_info, NULL); 226 if (len < 0) 227 return false; 228 uint8_t* ptr = reinterpret_cast<uint8_t*>(WriteInto(&to_be_signed, len + 1)); 229 if (i2d_X509_CINF(leaf_copy->cert_info, &ptr) < 0) 230 return false; 231 232 // Extract the issuer's public key. 233 std::string issuer_der; 234 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der)) 235 return ScopedX509(); 236 base::StringPiece issuer_key; 237 if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_key)) 238 return false; 239 240 // Fill in the LogEntry. 241 result->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT; 242 result->tbs_certificate.swap(to_be_signed); 243 crypto::SHA256HashString(issuer_key, 244 result->issuer_key_hash.data, 245 sizeof(result->issuer_key_hash.data)); 246 247 return true; 248 } 249 250 bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) { 251 DCHECK(leaf); 252 253 std::string encoded; 254 if (!X509Certificate::GetDEREncoded(leaf, &encoded)) 255 return false; 256 257 result->Reset(); 258 result->type = ct::LogEntry::LOG_ENTRY_TYPE_X509; 259 result->leaf_certificate.swap(encoded); 260 return true; 261 } 262 263 bool ExtractSCTListFromOCSPResponse(X509Certificate::OSCertHandle issuer, 264 const std::string& cert_serial_number, 265 const std::string& ocsp_response, 266 std::string* sct_list) { 267 // The input is an OCSPResponse. See RFC2560, section 4.2.1. The SCT list is 268 // in the extensions field of the SingleResponse which matches the input 269 // certificate. 270 CBS cbs; 271 CBS_init(&cbs, 272 reinterpret_cast<const uint8_t*>(ocsp_response.data()), 273 ocsp_response.size()); 274 275 // Parse down to the ResponseBytes. The ResponseBytes is optional, but if it's 276 // missing, this can't include an SCT list. 277 CBS sequence, response_status, tagged_response_bytes, response_bytes; 278 CBS response_type, response; 279 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE) || 280 CBS_len(&cbs) != 0 || 281 !CBS_get_asn1(&sequence, &response_status, CBS_ASN1_ENUMERATED) || 282 !CBS_get_asn1(&sequence, &tagged_response_bytes, 283 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || 284 CBS_len(&sequence) != 0 || 285 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, 286 CBS_ASN1_SEQUENCE) || 287 CBS_len(&tagged_response_bytes) != 0 || 288 !CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) || 289 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING) || 290 CBS_len(&response_bytes) != 0) { 291 return false; 292 } 293 294 // The only relevant ResponseType is id-pkix-ocsp-basic. 295 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) 296 return false; 297 298 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest. 299 CBS basic_response, response_data, responses; 300 if (!CBS_get_asn1(&response, &basic_response, CBS_ASN1_SEQUENCE) || 301 CBS_len(&response) != 0 || 302 !CBS_get_asn1(&basic_response, &response_data, CBS_ASN1_SEQUENCE)) { 303 } 304 305 // Skip the optional version. 306 const int kVersionTag = 307 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; 308 if (CBS_len(&response_data) > 0 && 309 CBS_data(&response_data)[0] == kVersionTag && 310 !CBS_get_asn1(&response_data, NULL /* version */, kVersionTag)) { 311 return false; 312 } 313 314 // Extract the list of SingleResponses. 315 if (!CBS_get_any_asn1_element(&response_data, 316 NULL /* responderID */, NULL, NULL) || 317 !CBS_get_any_asn1_element(&response_data, 318 NULL /* producedAt */, NULL, NULL) || 319 !CBS_get_asn1(&response_data, &responses, CBS_ASN1_SEQUENCE)) { 320 return false; 321 } 322 323 CBS single_response; 324 if (!FindMatchingSingleResponse(&responses, issuer, cert_serial_number, 325 &single_response)) { 326 return false; 327 } 328 329 // Skip the certStatus and thisUpdate fields. 330 if (!CBS_get_any_asn1_element(&single_response, 331 NULL /* certStatus */, NULL, NULL) || 332 !CBS_get_any_asn1_element(&single_response, 333 NULL /* thisUpdate */, NULL, NULL)) { 334 return false; 335 } 336 337 const int kNextUpdateTag = 338 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; 339 const int kSingleExtensionsTag = 340 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1; 341 342 // Skip the optional nextUpdate field. 343 if (CBS_len(&single_response) > 0 && 344 CBS_data(&single_response)[0] == kNextUpdateTag && 345 !CBS_get_asn1(&single_response, NULL /* nextUpdate */, kNextUpdateTag)) { 346 return false; 347 } 348 349 CBS extensions; 350 if (!CBS_get_asn1(&single_response, &extensions, kSingleExtensionsTag)) 351 return false; 352 const uint8_t* ptr = CBS_data(&extensions); 353 ScopedX509_EXTENSIONS x509_exts( 354 d2i_X509_EXTENSIONS(NULL, &ptr, CBS_len(&extensions))); 355 if (!x509_exts || ptr != CBS_data(&extensions) + CBS_len(&extensions)) 356 return false; 357 358 return GetSCTListFromX509_EXTENSIONS( 359 x509_exts.get(), kOCSPExtensionOid, sizeof(kOCSPExtensionOid), sct_list); 360 } 361 362 } // namespace ct 363 364 } // namespace net 365