1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file.
4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/test/cert_test_util.h"
6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <pk11pub.h>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <secmodt.h>
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/files/file_path.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/path_service.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "crypto/nss_util.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crypto/rsa_private_key.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/cert/cert_type.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace net {
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdochscoped_ptr<crypto::RSAPrivateKey> ImportSensitiveKeyFromFile(
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& dir,
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& key_filename,
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    PK11SlotInfo* slot) {
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::FilePath key_path = dir.AppendASCII(key_filename);
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string key_pkcs8;
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool success = base::ReadFileToString(key_path, &key_pkcs8);
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!success) {
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG(ERROR) << "Failed to read file " << key_path.value();
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return scoped_ptr<crypto::RSAPrivateKey>();
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const uint8* key_pkcs8_begin =
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      reinterpret_cast<const uint8*>(key_pkcs8.data());
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::vector<uint8> key_vector(key_pkcs8_begin,
34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                key_pkcs8_begin + key_pkcs8.length());
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<crypto::RSAPrivateKey> private_key(
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crypto::RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(slot,
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                               key_vector));
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LOG_IF(ERROR, !private_key) << "Could not create key from file "
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                              << key_path.value();
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return private_key.Pass();
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ImportClientCertToSlot(const scoped_refptr<X509Certificate>& cert,
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            PK11SlotInfo* slot) {
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string nickname = cert->GetDefaultNickname(USER_CERT);
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  {
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    crypto::AutoNSSWriteLock lock;
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SECStatus rv = PK11_ImportCert(slot,
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   cert->os_cert_handle(),
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   CK_INVALID_HANDLE,
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   nickname.c_str(),
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   PR_FALSE);
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (rv != SECSuccess) {
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LOG(ERROR) << "Could not import cert";
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return false;
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_refptr<X509Certificate> ImportClientCertAndKeyFromFile(
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::FilePath& dir,
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& cert_filename,
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& key_filename,
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PK11SlotInfo* slot) {
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ImportSensitiveKeyFromFile(dir, key_filename, slot)) {
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Could not import private key from file " << key_filename;
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return NULL;
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<X509Certificate> cert(ImportCertFromFile(dir, cert_filename));
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!cert.get()) {
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Failed to parse cert from file " << cert_filename;
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return NULL;
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ImportClientCertToSlot(cert, slot))
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return NULL;
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |cert| continues to point to the original X509Certificate before the
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // import to |slot|. However this should not make a difference as NSS handles
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // state globally.
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return cert;
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace net
89