Home | History | Annotate | Download | only in test
      1 // Copyright 2014 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/test/cert_test_util.h"
      6 
      7 #include <pk11pub.h>
      8 #include <secmodt.h>
      9 
     10 #include "base/files/file_path.h"
     11 #include "base/files/file_util.h"
     12 #include "base/path_service.h"
     13 #include "crypto/nss_util.h"
     14 #include "crypto/rsa_private_key.h"
     15 #include "net/cert/cert_type.h"
     16 
     17 namespace net {
     18 
     19 scoped_ptr<crypto::RSAPrivateKey> ImportSensitiveKeyFromFile(
     20     const base::FilePath& dir,
     21     const std::string& key_filename,
     22     PK11SlotInfo* slot) {
     23   base::FilePath key_path = dir.AppendASCII(key_filename);
     24   std::string key_pkcs8;
     25   bool success = base::ReadFileToString(key_path, &key_pkcs8);
     26   if (!success) {
     27     LOG(ERROR) << "Failed to read file " << key_path.value();
     28     return scoped_ptr<crypto::RSAPrivateKey>();
     29   }
     30 
     31   const uint8* key_pkcs8_begin =
     32       reinterpret_cast<const uint8*>(key_pkcs8.data());
     33   std::vector<uint8> key_vector(key_pkcs8_begin,
     34                                 key_pkcs8_begin + key_pkcs8.length());
     35 
     36   scoped_ptr<crypto::RSAPrivateKey> private_key(
     37       crypto::RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(slot,
     38                                                                key_vector));
     39   LOG_IF(ERROR, !private_key) << "Could not create key from file "
     40                               << key_path.value();
     41   return private_key.Pass();
     42 }
     43 
     44 bool ImportClientCertToSlot(const scoped_refptr<X509Certificate>& cert,
     45                             PK11SlotInfo* slot) {
     46   std::string nickname = cert->GetDefaultNickname(USER_CERT);
     47   {
     48     crypto::AutoNSSWriteLock lock;
     49     SECStatus rv = PK11_ImportCert(slot,
     50                                    cert->os_cert_handle(),
     51                                    CK_INVALID_HANDLE,
     52                                    nickname.c_str(),
     53                                    PR_FALSE);
     54     if (rv != SECSuccess) {
     55       LOG(ERROR) << "Could not import cert";
     56       return false;
     57     }
     58   }
     59   return true;
     60 }
     61 
     62 scoped_refptr<X509Certificate> ImportClientCertAndKeyFromFile(
     63     const base::FilePath& dir,
     64     const std::string& cert_filename,
     65     const std::string& key_filename,
     66     PK11SlotInfo* slot) {
     67   if (!ImportSensitiveKeyFromFile(dir, key_filename, slot)) {
     68     LOG(ERROR) << "Could not import private key from file " << key_filename;
     69     return NULL;
     70   }
     71 
     72   scoped_refptr<X509Certificate> cert(ImportCertFromFile(dir, cert_filename));
     73 
     74   if (!cert.get()) {
     75     LOG(ERROR) << "Failed to parse cert from file " << cert_filename;
     76     return NULL;
     77   }
     78 
     79   if (!ImportClientCertToSlot(cert, slot))
     80     return NULL;
     81 
     82   // |cert| continues to point to the original X509Certificate before the
     83   // import to |slot|. However this should not make a difference as NSS handles
     84   // state globally.
     85   return cert;
     86 }
     87 
     88 }  // namespace net
     89