| OLD | NEW | 
|    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |    1 // Copyright (c) 2012 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/base/x509_util.h" |    5 #include "net/base/x509_util.h" | 
|    6 #include "net/base/x509_util_nss.h" |    6 #include "net/base/x509_util_nss.h" | 
|    7  |    7  | 
|    8 #include <cert.h> |    8 #include <cert.h> | 
|    9 #include <cryptohi.h> |    9 #include <cryptohi.h> | 
 |   10 #include <nss.h> | 
|   10 #include <pk11pub.h> |   11 #include <pk11pub.h> | 
|   11 #include <prerror.h> |   12 #include <prerror.h> | 
 |   13 #include <secder.h> | 
|   12 #include <secmod.h> |   14 #include <secmod.h> | 
|   13 #include <secport.h> |   15 #include <secport.h> | 
|   14  |   16  | 
|   15 #include "base/debug/leak_annotations.h" |   17 #include "base/debug/leak_annotations.h" | 
|   16 #include "base/logging.h" |   18 #include "base/logging.h" | 
|   17 #include "base/memory/scoped_ptr.h" |   19 #include "base/memory/scoped_ptr.h" | 
|   18 #include "base/memory/singleton.h" |   20 #include "base/memory/singleton.h" | 
 |   21 #include "base/pickle.h" | 
|   19 #include "crypto/ec_private_key.h" |   22 #include "crypto/ec_private_key.h" | 
|   20 #include "crypto/nss_util.h" |   23 #include "crypto/nss_util.h" | 
|   21 #include "crypto/nss_util_internal.h" |   24 #include "crypto/nss_util_internal.h" | 
|   22 #include "crypto/scoped_nss_types.h" |   25 #include "crypto/scoped_nss_types.h" | 
|   23 #include "crypto/third_party/nss/chromium-nss.h" |   26 #include "crypto/third_party/nss/chromium-nss.h" | 
 |   27 #include "net/base/x509_certificate.h" | 
 |   28  | 
 |   29 namespace net { | 
|   24  |   30  | 
|   25 namespace { |   31 namespace { | 
|   26  |   32  | 
|   27 class DomainBoundCertOIDWrapper { |   33 class DomainBoundCertOIDWrapper { | 
|   28  public: |   34  public: | 
|   29   static DomainBoundCertOIDWrapper* GetInstance() { |   35   static DomainBoundCertOIDWrapper* GetInstance() { | 
|   30     // Instantiated as a leaky singleton to allow the singleton to be |   36     // Instantiated as a leaky singleton to allow the singleton to be | 
|   31     // constructed on a worker thead that is not joined when a process |   37     // constructed on a worker thead that is not joined when a process | 
|   32     // shuts down. |   38     // shuts down. | 
|   33     return Singleton<DomainBoundCertOIDWrapper, |   39     return Singleton<DomainBoundCertOIDWrapper, | 
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  241  |  247  | 
|  242   DCHECK(cert->derCert.len); |  248   DCHECK(cert->derCert.len); | 
|  243   // XXX copied from X509Certificate::GetDEREncoded |  249   // XXX copied from X509Certificate::GetDEREncoded | 
|  244   der_cert->clear(); |  250   der_cert->clear(); | 
|  245   der_cert->append(reinterpret_cast<char*>(cert->derCert.data), |  251   der_cert->append(reinterpret_cast<char*>(cert->derCert.data), | 
|  246                    cert->derCert.len); |  252                    cert->derCert.len); | 
|  247   CERT_DestroyCertificate(cert); |  253   CERT_DestroyCertificate(cert); | 
|  248   return true; |  254   return true; | 
|  249 } |  255 } | 
|  250  |  256  | 
 |  257 // Callback for CERT_DecodeCertPackage(), used in | 
 |  258 // CreateOSCertHandlesFromBytes(). | 
 |  259 SECStatus PR_CALLBACK CollectCertsCallback(void* arg, | 
 |  260                                            SECItem** certs, | 
 |  261                                            int num_certs) { | 
 |  262   X509Certificate::OSCertHandles* results = | 
 |  263       reinterpret_cast<X509Certificate::OSCertHandles*>(arg); | 
 |  264  | 
 |  265   for (int i = 0; i < num_certs; ++i) { | 
 |  266     X509Certificate::OSCertHandle handle = | 
 |  267         X509Certificate::CreateOSCertHandleFromBytes( | 
 |  268             reinterpret_cast<char*>(certs[i]->data), certs[i]->len); | 
 |  269     if (handle) | 
 |  270       results->push_back(handle); | 
 |  271   } | 
 |  272  | 
 |  273   return SECSuccess; | 
 |  274 } | 
 |  275  | 
|  251 }  // namespace |  276 }  // namespace | 
|  252  |  277  | 
|  253 namespace net { |  | 
|  254  |  | 
|  255 namespace x509_util { |  278 namespace x509_util { | 
|  256  |  279  | 
|  257 CERTCertificate* CreateSelfSignedCert( |  280 CERTCertificate* CreateSelfSignedCert( | 
|  258     SECKEYPublicKey* public_key, |  281     SECKEYPublicKey* public_key, | 
|  259     SECKEYPrivateKey* private_key, |  282     SECKEYPrivateKey* private_key, | 
|  260     const std::string& subject, |  283     const std::string& subject, | 
|  261     uint32 serial_number, |  284     uint32 serial_number, | 
|  262     base::Time not_valid_before, |  285     base::Time not_valid_before, | 
|  263     base::Time not_valid_after) { |  286     base::Time not_valid_after) { | 
|  264   CERTCertificate* cert = CreateCertificate(public_key, |  287   CERTCertificate* cert = CreateCertificate(public_key, | 
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  300   DCHECK(key); |  323   DCHECK(key); | 
|  301   return CreateDomainBoundCertInternal(key->public_key(), |  324   return CreateDomainBoundCertInternal(key->public_key(), | 
|  302                                        key->key(), |  325                                        key->key(), | 
|  303                                        domain, |  326                                        domain, | 
|  304                                        serial_number, |  327                                        serial_number, | 
|  305                                        not_valid_before, |  328                                        not_valid_before, | 
|  306                                        not_valid_after, |  329                                        not_valid_after, | 
|  307                                        der_cert); |  330                                        der_cert); | 
|  308 } |  331 } | 
|  309  |  332  | 
 |  333 #if defined(USE_NSS) || defined(OS_IOS) | 
 |  334 void ParsePrincipal(CERTName* name, CertPrincipal* principal) { | 
 |  335   typedef char* (*CERTGetNameFunc)(CERTName* name); | 
 |  336  | 
 |  337   // TODO(jcampan): add business_category and serial_number. | 
 |  338   // TODO(wtc): NSS has the CERT_GetOrgName, CERT_GetOrgUnitName, and | 
 |  339   // CERT_GetDomainComponentName functions, but they return only the most | 
 |  340   // general (the first) RDN.  NSS doesn't have a function for the street | 
 |  341   // address. | 
 |  342   static const SECOidTag kOIDs[] = { | 
 |  343     SEC_OID_AVA_STREET_ADDRESS, | 
 |  344     SEC_OID_AVA_ORGANIZATION_NAME, | 
 |  345     SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, | 
 |  346     SEC_OID_AVA_DC }; | 
 |  347  | 
 |  348   std::vector<std::string>* values[] = { | 
 |  349     &principal->street_addresses, | 
 |  350     &principal->organization_names, | 
 |  351     &principal->organization_unit_names, | 
 |  352     &principal->domain_components }; | 
 |  353   DCHECK_EQ(arraysize(kOIDs), arraysize(values)); | 
 |  354  | 
 |  355   CERTRDN** rdns = name->rdns; | 
 |  356   for (size_t rdn = 0; rdns[rdn]; ++rdn) { | 
 |  357     CERTAVA** avas = rdns[rdn]->avas; | 
 |  358     for (size_t pair = 0; avas[pair] != 0; ++pair) { | 
 |  359       SECOidTag tag = CERT_GetAVATag(avas[pair]); | 
 |  360       for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) { | 
 |  361         if (kOIDs[oid] == tag) { | 
 |  362           SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value); | 
 |  363           if (!decode_item) | 
 |  364             break; | 
 |  365           // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote. | 
 |  366           std::string value(reinterpret_cast<char*>(decode_item->data), | 
 |  367                             decode_item->len); | 
 |  368           values[oid]->push_back(value); | 
 |  369           SECITEM_FreeItem(decode_item, PR_TRUE); | 
 |  370           break; | 
 |  371         } | 
 |  372       } | 
 |  373     } | 
 |  374   } | 
 |  375  | 
 |  376   // Get CN, L, S, and C. | 
 |  377   CERTGetNameFunc get_name_funcs[4] = { | 
 |  378     CERT_GetCommonName, CERT_GetLocalityName, | 
 |  379     CERT_GetStateName, CERT_GetCountryName }; | 
 |  380   std::string* single_values[4] = { | 
 |  381     &principal->common_name, &principal->locality_name, | 
 |  382     &principal->state_or_province_name, &principal->country_name }; | 
 |  383   for (size_t i = 0; i < arraysize(get_name_funcs); ++i) { | 
 |  384     char* value = get_name_funcs[i](name); | 
 |  385     if (value) { | 
 |  386       single_values[i]->assign(value); | 
 |  387       PORT_Free(value); | 
 |  388     } | 
 |  389   } | 
 |  390 } | 
 |  391  | 
 |  392 void ParseDate(const SECItem* der_date, base::Time* result) { | 
 |  393   PRTime prtime; | 
 |  394   SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date); | 
 |  395   DCHECK_EQ(SECSuccess, rv); | 
 |  396   *result = crypto::PRTimeToBaseTime(prtime); | 
 |  397 } | 
 |  398  | 
 |  399 std::string ParseSerialNumber(const CERTCertificate* certificate) { | 
 |  400   return std::string(reinterpret_cast<char*>(certificate->serialNumber.data), | 
 |  401                      certificate->serialNumber.len); | 
 |  402 } | 
 |  403  | 
 |  404 void GetSubjectAltName(CERTCertificate* cert_handle, | 
 |  405                        std::vector<std::string>* dns_names, | 
 |  406                        std::vector<std::string>* ip_addrs) { | 
 |  407   if (dns_names) | 
 |  408     dns_names->clear(); | 
 |  409   if (ip_addrs) | 
 |  410     ip_addrs->clear(); | 
 |  411  | 
 |  412   SECItem alt_name; | 
 |  413   SECStatus rv = CERT_FindCertExtension(cert_handle, | 
 |  414                                         SEC_OID_X509_SUBJECT_ALT_NAME, | 
 |  415                                         &alt_name); | 
 |  416   if (rv != SECSuccess) | 
 |  417     return; | 
 |  418  | 
 |  419   PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 
 |  420   DCHECK(arena != NULL); | 
 |  421  | 
 |  422   CERTGeneralName* alt_name_list; | 
 |  423   alt_name_list = CERT_DecodeAltNameExtension(arena, &alt_name); | 
 |  424   SECITEM_FreeItem(&alt_name, PR_FALSE); | 
 |  425  | 
 |  426   CERTGeneralName* name = alt_name_list; | 
 |  427   while (name) { | 
 |  428     // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs | 
 |  429     // respectively, both of which can be byte copied from | 
 |  430     // SECItemType::data into the appropriate output vector. | 
 |  431     if (dns_names && name->type == certDNSName) { | 
 |  432       dns_names->push_back(std::string( | 
 |  433           reinterpret_cast<char*>(name->name.other.data), | 
 |  434           name->name.other.len)); | 
 |  435     } else if (ip_addrs && name->type == certIPAddress) { | 
 |  436       ip_addrs->push_back(std::string( | 
 |  437           reinterpret_cast<char*>(name->name.other.data), | 
 |  438           name->name.other.len)); | 
 |  439     } | 
 |  440     name = CERT_GetNextGeneralName(name); | 
 |  441     if (name == alt_name_list) | 
 |  442       break; | 
 |  443   } | 
 |  444   PORT_FreeArena(arena, PR_FALSE); | 
 |  445 } | 
 |  446  | 
 |  447 X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes( | 
 |  448     const char* data, | 
 |  449     int length, | 
 |  450     X509Certificate::Format format) { | 
 |  451   X509Certificate::OSCertHandles results; | 
 |  452   if (length < 0) | 
 |  453     return results; | 
 |  454  | 
 |  455   crypto::EnsureNSSInit(); | 
 |  456  | 
 |  457   if (!NSS_IsInitialized()) | 
 |  458     return results; | 
 |  459  | 
 |  460   switch (format) { | 
 |  461     case X509Certificate::FORMAT_SINGLE_CERTIFICATE: { | 
 |  462       X509Certificate::OSCertHandle handle = | 
 |  463           X509Certificate::CreateOSCertHandleFromBytes(data, length); | 
 |  464       if (handle) | 
 |  465         results.push_back(handle); | 
 |  466       break; | 
 |  467     } | 
 |  468     case X509Certificate::FORMAT_PKCS7: { | 
 |  469       // Make a copy since CERT_DecodeCertPackage may modify it | 
 |  470       std::vector<char> data_copy(data, data + length); | 
 |  471  | 
 |  472       SECStatus result = CERT_DecodeCertPackage(&data_copy[0], | 
 |  473           length, CollectCertsCallback, &results); | 
 |  474       if (result != SECSuccess) | 
 |  475         results.clear(); | 
 |  476       break; | 
 |  477     } | 
 |  478     default: | 
 |  479       NOTREACHED() << "Certificate format " << format << " unimplemented"; | 
 |  480       break; | 
 |  481   } | 
 |  482  | 
 |  483   return results; | 
 |  484 } | 
 |  485  | 
 |  486 X509Certificate::OSCertHandle ReadOSCertHandleFromPickle( | 
 |  487     PickleIterator* pickle_iter) { | 
 |  488   const char* data; | 
 |  489   int length; | 
 |  490   if (!pickle_iter->ReadData(&data, &length)) | 
 |  491     return NULL; | 
 |  492  | 
 |  493   return X509Certificate::CreateOSCertHandleFromBytes(data, length); | 
 |  494 } | 
 |  495  | 
 |  496 void GetPublicKeyInfo(CERTCertificate* handle, | 
 |  497                       size_t* size_bits, | 
 |  498                       X509Certificate::PublicKeyType* type) { | 
 |  499   // Since we might fail, set the output parameters to default values first. | 
 |  500   *type = X509Certificate::kPublicKeyTypeUnknown; | 
 |  501   *size_bits = 0; | 
 |  502  | 
 |  503   crypto::ScopedSECKEYPublicKey key(CERT_ExtractPublicKey(handle)); | 
 |  504   if (!key.get()) | 
 |  505     return; | 
 |  506  | 
 |  507   *size_bits = SECKEY_PublicKeyStrengthInBits(key.get()); | 
 |  508  | 
 |  509   switch (key->keyType) { | 
 |  510     case rsaKey: | 
 |  511       *type = X509Certificate::kPublicKeyTypeRSA; | 
 |  512       break; | 
 |  513     case dsaKey: | 
 |  514       *type = X509Certificate::kPublicKeyTypeDSA; | 
 |  515       break; | 
 |  516     case dhKey: | 
 |  517       *type = X509Certificate::kPublicKeyTypeDH; | 
 |  518       break; | 
 |  519     case ecKey: | 
 |  520       *type = X509Certificate::kPublicKeyTypeECDSA; | 
 |  521       break; | 
 |  522     default: | 
 |  523       *type = X509Certificate::kPublicKeyTypeUnknown; | 
 |  524       *size_bits = 0; | 
 |  525       break; | 
 |  526   } | 
 |  527 } | 
 |  528 #endif  // defined(USE_NSS) || defined(OS_IOS) | 
 |  529  | 
|  310 } // namespace x509_util |  530 } // namespace x509_util | 
|  311  |  531  | 
|  312 } // namespace net |  532 } // namespace net | 
| OLD | NEW |