13daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
23daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// Copyright (C) 2015 The Android Open Source Project
33daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
43daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// Licensed under the Apache License, Version 2.0 (the "License");
53daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// you may not use this file except in compliance with the License.
63daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// You may obtain a copy of the License at
73daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
83daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//      http://www.apache.org/licenses/LICENSE-2.0
93daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
103daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// Unless required by applicable law or agreed to in writing, software
113daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// distributed under the License is distributed on an "AS IS" BASIS,
123daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// See the License for the specific language governing permissions and
143daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// limitations under the License.
153daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
16d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
17d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include "attestation/server/pkcs11_key_store.h"
18d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
19d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <memory>
20d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <string>
21d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
22d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <base/bind.h>
23d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <base/callback.h>
24d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <base/files/file_path.h>
25d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <base/logging.h>
26d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <base/stl_util.h>
27d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <base/strings/string_util.h>
28d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <chaps/isolate.h>
29d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <chaps/pkcs11/cryptoki.h>
30d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <chaps/token_manager_client.h>
31e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko#include <brillo/cryptohome.h>
32d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <crypto/scoped_openssl_types.h>
33d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <openssl/rsa.h>
34d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <openssl/sha.h>
35d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn#include <openssl/x509.h>
36d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
37d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnnamespace {
38d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
39d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnstd::string Sha1(const std::string& input) {
40d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  unsigned char output[SHA_DIGEST_LENGTH];
41d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  SHA1(reinterpret_cast<const unsigned char*>(input.data()), input.size(),
42d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn       output);
43d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return std::string(reinterpret_cast<char*>(output), SHA_DIGEST_LENGTH);
44d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
45d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
46d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}  // namespace
47d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
48d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnnamespace attestation {
49d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
50d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahntypedef crypto::ScopedOpenSSL<X509, X509_free> ScopedX509;
51d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
52d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn// An arbitrary application ID to identify PKCS #11 objects.
53d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnconst char kApplicationID[] = "CrOS_d5bbc079d2497110feadfc97c40d718ae46f4658";
54d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
55d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn// A helper class to scope a PKCS #11 session.
56d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnclass ScopedSession {
57d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn public:
58d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  explicit ScopedSession(CK_SLOT_ID slot) : handle_(CK_INVALID_HANDLE) {
59d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    CK_RV rv = C_Initialize(nullptr);
60d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
61d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      // This may be normal in a test environment.
62d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      LOG(INFO) << "PKCS #11 is not available.";
63d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      return;
64d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
65d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    CK_FLAGS flags = CKF_RW_SESSION | CKF_SERIAL_SESSION;
66d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    if (C_OpenSession(slot, flags, nullptr, nullptr, &handle_) != CKR_OK) {
67d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      LOG(ERROR) << "Failed to open PKCS #11 session.";
68d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      return;
69d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
70d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
71d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
72d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  ~ScopedSession() {
73d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    if (IsValid() && (C_CloseSession(handle_) != CKR_OK)) {
74d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      LOG(WARNING) << "Failed to close PKCS #11 session.";
75d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      handle_ = CK_INVALID_HANDLE;
76d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
77d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
78d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
79d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_SESSION_HANDLE handle() const {
80d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return handle_;
81d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
82d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
83d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  bool IsValid() const {
84d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return (handle_ != CK_INVALID_HANDLE);
85d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
86d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
87d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn private:
88d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_SESSION_HANDLE handle_;
89d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
90d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  DISALLOW_COPY_AND_ASSIGN(ScopedSession);
91d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn};
92d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
93d7ae21ca48a717fec15836b62701da26d9ec519dDarren KrahnPkcs11KeyStore::Pkcs11KeyStore(chaps::TokenManagerClient* token_manager)
94d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    : token_manager_(token_manager) {}
95d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
96d7ae21ca48a717fec15836b62701da26d9ec519dDarren KrahnPkcs11KeyStore::~Pkcs11KeyStore() {}
97d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
98d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::Read(const std::string& username,
99d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                          const std::string& key_name,
100d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                          std::string* key_data) {
101d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_SLOT_ID slot;
102d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!GetUserSlot(username, &slot)) {
103594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(ERROR) << "Pkcs11KeyStore: No token for user.";
104d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
105d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
106d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  ScopedSession session(slot);
107d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!session.IsValid()) {
108d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to open token session.";
109d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
110d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
111d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_HANDLE key_handle = FindObject(session.handle(), key_name);
112d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (key_handle == CK_INVALID_HANDLE) {
113d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(WARNING) << "Pkcs11KeyStore: Key does not exist: " << key_name;
114d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
115d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
116d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // First get the attribute with a NULL buffer which will give us the length.
117d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ATTRIBUTE attribute = {CKA_VALUE, nullptr, 0};
118d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (C_GetAttributeValue(session.handle(),
119d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                          key_handle,
120d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                          &attribute, 1) != CKR_OK) {
121d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to read key data: " << key_name;
122d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
123d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
124d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  key_data->resize(attribute.ulValueLen);
125d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  attribute.pValue = string_as_array(key_data);
126d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (C_GetAttributeValue(session.handle(),
127d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                          key_handle,
128d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                          &attribute, 1) != CKR_OK) {
129d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to read key data: " << key_name;
130d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
131d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
132d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  key_data->resize(attribute.ulValueLen);
133d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
134d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
135d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
136d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::Write(const std::string& username,
137d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                           const std::string& key_name,
138d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                           const std::string& key_data) {
139d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Delete any existing key with the same name.
140d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!Delete(username, key_name)) {
141d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
142d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
143d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_SLOT_ID slot;
144d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!GetUserSlot(username, &slot)) {
145594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(ERROR) << "Pkcs11KeyStore: No token for user.";
146d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
147d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
148d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  ScopedSession session(slot);
149d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!session.IsValid()) {
150d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to open token session.";
151d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
152d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
153d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_key_name(key_name);
154d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_key_data(key_data);
155d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_application_id(kApplicationID);
156d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Create a new data object for the key.
157d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_CLASS object_class = CKO_DATA;
158d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL true_value = CK_TRUE;
159d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL false_value = CK_FALSE;
160d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ATTRIBUTE attributes[] = {
161d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_CLASS, &object_class, sizeof(object_class)},
162d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {
163d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKA_LABEL,
164d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&mutable_key_name),
165d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      mutable_key_name.size()
166d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    },
167d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {
168d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKA_VALUE,
169d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&mutable_key_data),
170d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      mutable_key_data.size()
171d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    },
172d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {
173d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKA_APPLICATION,
174d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&mutable_application_id),
175d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      mutable_application_id.size()
176d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    },
177d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_TOKEN, &true_value, sizeof(true_value)},
178d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_PRIVATE, &true_value, sizeof(true_value)},
179d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_MODIFIABLE, &false_value, sizeof(false_value)}
180d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  };
181d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE;
182d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (C_CreateObject(session.handle(),
183d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     attributes,
184d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     arraysize(attributes),
185d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     &key_handle) != CKR_OK) {
186d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to write key data: " << key_name;
187d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
188d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
189d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
190d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
191d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
192d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::Delete(const std::string& username,
193d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                            const std::string& key_name) {
194d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_SLOT_ID slot;
195d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!GetUserSlot(username, &slot)) {
196594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(ERROR) << "Pkcs11KeyStore: No token for user.";
197d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
198d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
199d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  ScopedSession session(slot);
200d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!session.IsValid()) {
201d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to open token session.";
202d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
203d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
204d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_HANDLE key_handle = FindObject(session.handle(), key_name);
205d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (key_handle != CK_INVALID_HANDLE) {
206d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    if (C_DestroyObject(session.handle(), key_handle) != CKR_OK) {
207d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      LOG(ERROR) << "Pkcs11KeyStore: Failed to delete key data.";
208d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      return false;
209d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
210d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
211d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
212d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
213d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
214d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::DeleteByPrefix(const std::string& username,
215d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                    const std::string& key_prefix) {
216d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_SLOT_ID slot;
217d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!GetUserSlot(username, &slot)) {
218594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(ERROR) << "Pkcs11KeyStore: No token for user.";
219d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
220d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
221d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  ScopedSession session(slot);
222d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!session.IsValid()) {
223d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to open token session.";
224d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
225d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
226d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  EnumObjectsCallback callback = base::Bind(
227d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      &Pkcs11KeyStore::DeleteIfMatchesPrefix,
228d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      base::Unretained(this),
229d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      session.handle(),
230d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      key_prefix);
231d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!EnumObjects(session.handle(), callback)) {
232d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to delete key data.";
233d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
234d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
235d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
236d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
237d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
238d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::Register(const std::string& username,
239d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                              const std::string& label,
240594849c7cf872d055575277b930f4f596bef1988Darren Krahn                              KeyType key_type,
241594849c7cf872d055575277b930f4f596bef1988Darren Krahn                              KeyUsage key_usage,
242d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                              const std::string& private_key_blob,
243d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                              const std::string& public_key_der,
244d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                              const std::string& certificate) {
245d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  const CK_ATTRIBUTE_TYPE kKeyBlobAttribute = CKA_VENDOR_DEFINED + 1;
246d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
247594849c7cf872d055575277b930f4f596bef1988Darren Krahn  if (key_type != KEY_TYPE_RSA) {
248594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Only RSA supported.";
249594849c7cf872d055575277b930f4f596bef1988Darren Krahn    return false;
250594849c7cf872d055575277b930f4f596bef1988Darren Krahn  }
251d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_SLOT_ID slot;
252d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!GetUserSlot(username, &slot)) {
253594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(ERROR) << "Pkcs11KeyStore: No token for user.";
254d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
255d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
256d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  ScopedSession session(slot);
257d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!session.IsValid()) {
258d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to open token session.";
259d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
260d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
261d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
262d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Extract the modulus from the public key.
263d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  const unsigned char* asn1_ptr = reinterpret_cast<const unsigned char*>(
264d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      public_key_der.data());
265d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  crypto::ScopedRSA public_key(d2i_RSAPublicKey(nullptr,
266d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                                &asn1_ptr,
267d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                                public_key_der.size()));
268d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!public_key.get()) {
269d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to decode public key.";
270d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
271d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
272d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string modulus(BN_num_bytes(public_key.get()->n), 0);
273d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  int length = BN_bn2bin(public_key.get()->n, reinterpret_cast<unsigned char*>(
274d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&modulus)));
275d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (length <= 0) {
276d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to extract public key modulus.";
277d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
278d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
279d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  modulus.resize(length);
280d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
281d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Construct a PKCS #11 template for the public key object.
282d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL true_value = CK_TRUE;
283d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL false_value = CK_FALSE;
284594849c7cf872d055575277b930f4f596bef1988Darren Krahn  CK_KEY_TYPE p11_key_type = CKK_RSA;
285d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_CLASS public_key_class = CKO_PUBLIC_KEY;
286d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string id = Sha1(modulus);
287d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_label(label);
288d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ULONG modulus_bits = modulus.size() * 8;
289594849c7cf872d055575277b930f4f596bef1988Darren Krahn  CK_BBOOL sign_usage = (key_usage == KEY_USAGE_SIGN);
290594849c7cf872d055575277b930f4f596bef1988Darren Krahn  CK_BBOOL decrypt_usage = (key_usage == KEY_USAGE_DECRYPT);
291d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  unsigned char public_exponent[] = {1, 0, 1};
292d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ATTRIBUTE public_key_attributes[] = {
293d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_CLASS, &public_key_class, sizeof(public_key_class)},
294d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_TOKEN, &true_value, sizeof(true_value)},
295d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_DERIVE, &false_value, sizeof(false_value)},
296d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_WRAP, &false_value, sizeof(false_value)},
297594849c7cf872d055575277b930f4f596bef1988Darren Krahn    {CKA_VERIFY, &sign_usage, sizeof(sign_usage)},
298d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_VERIFY_RECOVER, &false_value, sizeof(false_value)},
299594849c7cf872d055575277b930f4f596bef1988Darren Krahn    {CKA_ENCRYPT, &decrypt_usage, sizeof(decrypt_usage)},
300594849c7cf872d055575277b930f4f596bef1988Darren Krahn    {CKA_KEY_TYPE, &p11_key_type, sizeof(p11_key_type)},
301d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_ID, string_as_array(&id), id.size()},
302d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_LABEL, string_as_array(&mutable_label), mutable_label.size()},
303d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_MODULUS_BITS, &modulus_bits, sizeof(modulus_bits)},
304d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_PUBLIC_EXPONENT, public_exponent, arraysize(public_exponent)},
305d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_MODULUS, string_as_array(&modulus), modulus.size()}
306d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  };
307d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
308d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_HANDLE object_handle = CK_INVALID_HANDLE;
309d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (C_CreateObject(session.handle(),
310d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     public_key_attributes,
311d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     arraysize(public_key_attributes),
312d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     &object_handle) != CKR_OK) {
313d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to create public key object.";
314d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
315d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
316d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
317d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Construct a PKCS #11 template for the private key object.
318d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_private_key_blob(private_key_blob);
319d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
320d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ATTRIBUTE private_key_attributes[] = {
321d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_CLASS, &private_key_class, sizeof(private_key_class)},
322d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_TOKEN, &true_value, sizeof(true_value)},
323d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_PRIVATE, &true_value, sizeof(true_value)},
324d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_SENSITIVE, &true_value, sizeof(true_value)},
325d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_EXTRACTABLE, &false_value, sizeof(false_value)},
326d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_DERIVE, &false_value, sizeof(false_value)},
327d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_UNWRAP, &false_value, sizeof(false_value)},
328594849c7cf872d055575277b930f4f596bef1988Darren Krahn    {CKA_SIGN, &sign_usage, sizeof(sign_usage)},
329d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_SIGN_RECOVER, &false_value, sizeof(false_value)},
330594849c7cf872d055575277b930f4f596bef1988Darren Krahn    {CKA_DECRYPT, &decrypt_usage, sizeof(decrypt_usage)},
331594849c7cf872d055575277b930f4f596bef1988Darren Krahn    {CKA_KEY_TYPE, &p11_key_type, sizeof(p11_key_type)},
332d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_ID, string_as_array(&id), id.size()},
333d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_LABEL, string_as_array(&mutable_label), mutable_label.size()},
334d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_PUBLIC_EXPONENT, public_exponent, arraysize(public_exponent)},
335d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_MODULUS, string_as_array(&modulus), modulus.size()},
336d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {
337d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      kKeyBlobAttribute,
338d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&mutable_private_key_blob),
339d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      mutable_private_key_blob.size()
340d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
341d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  };
342d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
343d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (C_CreateObject(session.handle(),
344d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     private_key_attributes,
345d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     arraysize(private_key_attributes),
346d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     &object_handle) != CKR_OK) {
347d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to create private key object.";
348d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
349d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
350d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
351d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!certificate.empty()) {
352d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    std::string subject;
353594849c7cf872d055575277b930f4f596bef1988Darren Krahn    std::string issuer;
354594849c7cf872d055575277b930f4f596bef1988Darren Krahn    std::string serial_number;
355594849c7cf872d055575277b930f4f596bef1988Darren Krahn    if (!GetCertificateFields(certificate, &subject, &issuer, &serial_number)) {
356594849c7cf872d055575277b930f4f596bef1988Darren Krahn      LOG(WARNING) << "Pkcs11KeyStore: Failed to find certificate fields.";
357d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
358d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    // Construct a PKCS #11 template for a certificate object.
359d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    std::string mutable_certificate = certificate;
360d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    CK_OBJECT_CLASS certificate_class = CKO_CERTIFICATE;
361d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    CK_CERTIFICATE_TYPE certificate_type = CKC_X_509;
362d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    CK_ATTRIBUTE certificate_attributes[] = {
363d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      {CKA_CLASS, &certificate_class, sizeof(certificate_class)},
364d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      {CKA_TOKEN, &true_value, sizeof(true_value)},
365d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      {CKA_PRIVATE, &false_value, sizeof(false_value)},
366d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      {CKA_ID, string_as_array(&id), id.size()},
367d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      {CKA_LABEL, string_as_array(&mutable_label), mutable_label.size()},
368d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      {CKA_CERTIFICATE_TYPE, &certificate_type, sizeof(certificate_type)},
369d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      {CKA_SUBJECT, string_as_array(&subject), subject.size()},
370594849c7cf872d055575277b930f4f596bef1988Darren Krahn      {CKA_ISSUER, string_as_array(&issuer), issuer.size()},
371594849c7cf872d055575277b930f4f596bef1988Darren Krahn      {
372594849c7cf872d055575277b930f4f596bef1988Darren Krahn        CKA_SERIAL_NUMBER,
373594849c7cf872d055575277b930f4f596bef1988Darren Krahn        string_as_array(&serial_number),
374594849c7cf872d055575277b930f4f596bef1988Darren Krahn        serial_number.size()
375594849c7cf872d055575277b930f4f596bef1988Darren Krahn      },
376d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      {
377d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn        CKA_VALUE,
378d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn        string_as_array(&mutable_certificate),
379d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn        mutable_certificate.size()
380d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      }
381d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    };
382d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
383d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    if (C_CreateObject(session.handle(),
384d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                       certificate_attributes,
385d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                       arraysize(certificate_attributes),
386d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                       &object_handle) != CKR_OK) {
387d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      LOG(ERROR) << "Pkcs11KeyStore: Failed to create certificate object.";
388d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      return false;
389d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
390d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
391d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
392d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Close all sessions in an attempt to trigger other modules to find the new
393d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // objects.
394d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  C_CloseAllSessions(slot);
395d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
396d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
397d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
398d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
399d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::RegisterCertificate(const std::string& username,
400d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                         const std::string& certificate) {
401d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_SLOT_ID slot;
402d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!GetUserSlot(username, &slot)) {
403594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(ERROR) << "Pkcs11KeyStore: No token for user.";
404d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
405d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
406d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  ScopedSession session(slot);
407d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!session.IsValid()) {
408d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to open token session.";
409d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
410d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
411d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
412d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (DoesCertificateExist(session.handle(), certificate)) {
413d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(INFO) << "Pkcs11KeyStore: Certificate already exists.";
414d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return true;
415d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
416d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string subject;
417594849c7cf872d055575277b930f4f596bef1988Darren Krahn  std::string issuer;
418594849c7cf872d055575277b930f4f596bef1988Darren Krahn  std::string serial_number;
419594849c7cf872d055575277b930f4f596bef1988Darren Krahn  if (!GetCertificateFields(certificate, &subject, &issuer, &serial_number)) {
420594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(WARNING) << "Pkcs11KeyStore: Failed to find certificate fields.";
421d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
422d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Construct a PKCS #11 template for a certificate object.
423d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_certificate = certificate;
424d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_CLASS certificate_class = CKO_CERTIFICATE;
425d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_CERTIFICATE_TYPE certificate_type = CKC_X_509;
426d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL true_value = CK_TRUE;
427d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL false_value = CK_FALSE;
428d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ATTRIBUTE certificate_attributes[] = {
429d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_CLASS, &certificate_class, sizeof(certificate_class)},
430d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_TOKEN, &true_value, sizeof(true_value)},
431d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_PRIVATE, &false_value, sizeof(false_value)},
432d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_CERTIFICATE_TYPE, &certificate_type, sizeof(certificate_type)},
433d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_SUBJECT, string_as_array(&subject), subject.size()},
434594849c7cf872d055575277b930f4f596bef1988Darren Krahn    {CKA_ISSUER, string_as_array(&issuer), issuer.size()},
435594849c7cf872d055575277b930f4f596bef1988Darren Krahn    {CKA_SERIAL_NUMBER, string_as_array(&serial_number), serial_number.size()},
436d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {
437d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKA_VALUE,
438d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&mutable_certificate),
439d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      mutable_certificate.size()
440d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
441d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  };
442d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_HANDLE object_handle = CK_INVALID_HANDLE;
443d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (C_CreateObject(session.handle(),
444d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     certificate_attributes,
445d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     arraysize(certificate_attributes),
446d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                     &object_handle) != CKR_OK) {
447d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Pkcs11KeyStore: Failed to create certificate object.";
448d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
449d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
450d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
451d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
452d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
453d7ae21ca48a717fec15836b62701da26d9ec519dDarren KrahnCK_OBJECT_HANDLE Pkcs11KeyStore::FindObject(CK_SESSION_HANDLE session_handle,
454d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                            const std::string& key_name) {
455d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Assemble a search template.
456d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_key_name(key_name);
457d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_application_id(kApplicationID);
458d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_CLASS object_class = CKO_DATA;
459d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL true_value = CK_TRUE;
460d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL false_value = CK_FALSE;
461d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ATTRIBUTE attributes[] = {
462d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_CLASS, &object_class, sizeof(object_class)},
463d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {
464d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKA_LABEL,
465d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&mutable_key_name),
466d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      mutable_key_name.size()
467d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    },
468d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {
469d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKA_APPLICATION,
470d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&mutable_application_id),
471d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      mutable_application_id.size()
472d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    },
473d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_TOKEN, &true_value, sizeof(true_value)},
474d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_PRIVATE, &true_value, sizeof(true_value)},
475d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_MODIFIABLE, &false_value, sizeof(false_value)}
476d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  };
477d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE;
478d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ULONG count = 0;
479d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if ((C_FindObjectsInit(session_handle,
480d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                         attributes,
481d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                         arraysize(attributes)) != CKR_OK) ||
482d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      (C_FindObjects(session_handle, &key_handle, 1, &count) != CKR_OK) ||
483d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      (C_FindObjectsFinal(session_handle) != CKR_OK)) {
484d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Key search failed: " << key_name;
485d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return CK_INVALID_HANDLE;
486d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
487d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (count == 1)
488d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return key_handle;
489d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return CK_INVALID_HANDLE;
490d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
491d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
492d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::GetUserSlot(const std::string& username,
493d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                 CK_SLOT_ID_PTR slot) {
494d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  const char kChapsDaemonName[] = "chaps";
495d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  const char kChapsSystemToken[] = "/var/lib/chaps";
496d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  base::FilePath token_path = username.empty() ?
497d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      base::FilePath(kChapsSystemToken) :
498e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko      brillo::cryptohome::home::GetDaemonPath(username, kChapsDaemonName);
499d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_RV rv;
500d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  rv = C_Initialize(nullptr);
501d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
502d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(WARNING) << __func__ << ": C_Initialize failed.";
503d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
504d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
505d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ULONG num_slots = 0;
506d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  rv = C_GetSlotList(CK_TRUE, nullptr, &num_slots);
507d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (rv != CKR_OK) {
508d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(WARNING) << __func__ << ": C_GetSlotList(nullptr) failed.";
509d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
510d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
511d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::unique_ptr<CK_SLOT_ID[]> slot_list(new CK_SLOT_ID[num_slots]);
512d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  rv = C_GetSlotList(CK_TRUE, slot_list.get(), &num_slots);
513d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (rv != CKR_OK) {
514d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(WARNING) << __func__ << ": C_GetSlotList failed.";
515d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
516d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
517d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Look through all slots for |token_path|.
518d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  for (CK_ULONG i = 0; i < num_slots; ++i) {
519d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    base::FilePath slot_path;
520d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    if (token_manager_->GetTokenPath(
521d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn        chaps::IsolateCredentialManager::GetDefaultIsolateCredential(),
522d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn        slot_list[i],
523d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn        &slot_path) && (token_path == slot_path)) {
524d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      *slot = slot_list[i];
525d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      return true;
526d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
527d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
528d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  LOG(WARNING) << __func__ << ": Path not found.";
529d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return false;
530d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
531d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
532d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::EnumObjects(
533d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    CK_SESSION_HANDLE session_handle,
534d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    const Pkcs11KeyStore::EnumObjectsCallback& callback) {
535d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_application_id(kApplicationID);
536d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  // Assemble a search template.
537d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_CLASS object_class = CKO_DATA;
538d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL true_value = CK_TRUE;
539d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL false_value = CK_FALSE;
540d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ATTRIBUTE attributes[] = {
541d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_CLASS, &object_class, sizeof(object_class)},
542d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {
543d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKA_APPLICATION,
544d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&mutable_application_id),
545d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      mutable_application_id.size()
546d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    },
547d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_TOKEN, &true_value, sizeof(true_value)},
548d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_PRIVATE, &true_value, sizeof(true_value)},
549d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_MODIFIABLE, &false_value, sizeof(false_value)}
550d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  };
551d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  const CK_ULONG kMaxHandles = 100;  // Arbitrary.
552d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_HANDLE handles[kMaxHandles];
553d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ULONG count = 0;
554d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if ((C_FindObjectsInit(session_handle,
555d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                         attributes,
556d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                         arraysize(attributes)) != CKR_OK) ||
557d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      (C_FindObjects(session_handle, handles, kMaxHandles, &count) != CKR_OK)) {
558d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "Key search failed.";
559d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
560d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
561d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  while (count > 0) {
562d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    for (CK_ULONG i = 0; i < count; ++i) {
563d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      std::string key_name;
564d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      if (!GetKeyName(session_handle, handles[i], &key_name)) {
565d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn        LOG(WARNING) << "Found key object but failed to get name.";
566d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn        continue;
567d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      }
568d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      if (!callback.Run(key_name, handles[i]))
569d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn        return false;
570d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
571d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    if (C_FindObjects(session_handle, handles, kMaxHandles, &count) != CKR_OK) {
572d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      LOG(ERROR) << "Key search continuation failed.";
573d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      return false;
574d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
575d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
576d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (C_FindObjectsFinal(session_handle) != CKR_OK) {
577d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(WARNING) << "Failed to finalize key search.";
578d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
579d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
580d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
581d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
582d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::GetKeyName(CK_SESSION_HANDLE session_handle,
583d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                CK_OBJECT_HANDLE object_handle,
584d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                std::string* key_name) {
585d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ATTRIBUTE attribute = {CKA_LABEL, nullptr, 0};
586d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (C_GetAttributeValue(session_handle, object_handle, &attribute, 1) !=
587d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKR_OK) {
588d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "C_GetAttributeValue(CKA_LABEL) [length] failed.";
589d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
590d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
591d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  key_name->resize(attribute.ulValueLen);
592d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  attribute.pValue = string_as_array(key_name);
593d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (C_GetAttributeValue(session_handle, object_handle, &attribute, 1) !=
594d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKR_OK) {
595d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(ERROR) << "C_GetAttributeValue(CKA_LABEL) failed.";
596d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
597d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
598d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
599d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
600d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
601d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::DeleteIfMatchesPrefix(CK_SESSION_HANDLE session_handle,
602d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                           const std::string& key_prefix,
603d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                           const std::string& key_name,
604d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                                           CK_OBJECT_HANDLE object_handle) {
6057e763a9434e12c7980529980de5f8eced22b310aAlex Vakulenko  if (base::StartsWith(key_name, key_prefix, base::CompareCase::SENSITIVE)) {
606d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    if (C_DestroyObject(session_handle, object_handle) != CKR_OK) {
607d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      LOG(ERROR) << "C_DestroyObject failed.";
608d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      return false;
609d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
610d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
611d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
612d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
613d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
614594849c7cf872d055575277b930f4f596bef1988Darren Krahnbool Pkcs11KeyStore::GetCertificateFields(const std::string& certificate,
615594849c7cf872d055575277b930f4f596bef1988Darren Krahn                                          std::string* subject,
616594849c7cf872d055575277b930f4f596bef1988Darren Krahn                                          std::string* issuer,
617594849c7cf872d055575277b930f4f596bef1988Darren Krahn                                          std::string* serial_number) {
618d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  const unsigned char* asn1_ptr = reinterpret_cast<const unsigned char*>(
619d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      certificate.data());
620d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  ScopedX509 x509(d2i_X509(nullptr, &asn1_ptr, certificate.size()));
621d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (!x509.get() || !x509->cert_info || !x509->cert_info->subject) {
622d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(WARNING) << "Pkcs11KeyStore: Failed to decode certificate.";
623d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
624d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
625594849c7cf872d055575277b930f4f596bef1988Darren Krahn  unsigned char* subject_buffer = nullptr;
626594849c7cf872d055575277b930f4f596bef1988Darren Krahn  int length = i2d_X509_NAME(x509->cert_info->subject, &subject_buffer);
627594849c7cf872d055575277b930f4f596bef1988Darren Krahn  crypto::ScopedOpenSSLBytes scoped_subject_buffer(subject_buffer);
628d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if (length <= 0) {
629d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    LOG(WARNING) << "Pkcs11KeyStore: Failed to encode certificate subject.";
630d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
631d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
632594849c7cf872d055575277b930f4f596bef1988Darren Krahn  subject->assign(reinterpret_cast<char*>(subject_buffer), length);
633594849c7cf872d055575277b930f4f596bef1988Darren Krahn
634594849c7cf872d055575277b930f4f596bef1988Darren Krahn  unsigned char* issuer_buffer = nullptr;
635594849c7cf872d055575277b930f4f596bef1988Darren Krahn  length = i2d_X509_NAME(x509->cert_info->issuer, &issuer_buffer);
636594849c7cf872d055575277b930f4f596bef1988Darren Krahn  crypto::ScopedOpenSSLBytes scoped_issuer_buffer(issuer_buffer);
637594849c7cf872d055575277b930f4f596bef1988Darren Krahn  if (length <= 0) {
638594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(WARNING) << "Pkcs11KeyStore: Failed to encode certificate issuer.";
639594849c7cf872d055575277b930f4f596bef1988Darren Krahn    return false;
640594849c7cf872d055575277b930f4f596bef1988Darren Krahn  }
641594849c7cf872d055575277b930f4f596bef1988Darren Krahn  issuer->assign(reinterpret_cast<char*>(issuer_buffer), length);
642594849c7cf872d055575277b930f4f596bef1988Darren Krahn
643594849c7cf872d055575277b930f4f596bef1988Darren Krahn  unsigned char* serial_number_buffer = nullptr;
644594849c7cf872d055575277b930f4f596bef1988Darren Krahn  length = i2d_ASN1_INTEGER(x509->cert_info->serialNumber,
645594849c7cf872d055575277b930f4f596bef1988Darren Krahn                            &serial_number_buffer);
646594849c7cf872d055575277b930f4f596bef1988Darren Krahn  crypto::ScopedOpenSSLBytes scoped_serial_number_buffer(serial_number_buffer);
647594849c7cf872d055575277b930f4f596bef1988Darren Krahn  if (length <= 0) {
648594849c7cf872d055575277b930f4f596bef1988Darren Krahn    LOG(WARNING) << "Pkcs11KeyStore: Failed to encode certificate serial "
649594849c7cf872d055575277b930f4f596bef1988Darren Krahn                    "number.";
650594849c7cf872d055575277b930f4f596bef1988Darren Krahn    return false;
651594849c7cf872d055575277b930f4f596bef1988Darren Krahn  }
652594849c7cf872d055575277b930f4f596bef1988Darren Krahn  serial_number->assign(reinterpret_cast<char*>(serial_number_buffer), length);
653d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return true;
654d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
655d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
656d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahnbool Pkcs11KeyStore::DoesCertificateExist(
657d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    CK_SESSION_HANDLE session_handle,
658d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    const std::string& certificate) {
659d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_CLASS object_class = CKO_CERTIFICATE;
660d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL true_value = CK_TRUE;
661d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_BBOOL false_value = CK_FALSE;
662d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  std::string mutable_certificate = certificate;
663d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ATTRIBUTE attributes[] = {
664d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_CLASS, &object_class, sizeof(object_class)},
665d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_TOKEN, &true_value, sizeof(true_value)},
666d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {CKA_PRIVATE, &false_value, sizeof(false_value)},
667d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    {
668d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      CKA_VALUE,
669d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      string_as_array(&mutable_certificate),
670d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      mutable_certificate.size()
671d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    }
672d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  };
673d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_OBJECT_HANDLE object_handle = CK_INVALID_HANDLE;
674d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  CK_ULONG count = 0;
675d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  if ((C_FindObjectsInit(session_handle,
676d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                         attributes,
677d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn                         arraysize(attributes)) != CKR_OK) ||
678d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      (C_FindObjects(session_handle, &object_handle, 1, &count) != CKR_OK) ||
679d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn      (C_FindObjectsFinal(session_handle) != CKR_OK)) {
680d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn    return false;
681d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  }
682d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn  return (count > 0);
683d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}
684d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn
685d7ae21ca48a717fec15836b62701da26d9ec519dDarren Krahn}  // namespace attestation
686