blob: b81cd780b111b39f7c62067b9ef67b01ec1d5dd6 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Contains the implementation of class Pkcs11Init.
#include "cryptohome/pkcs11_init.h"
#include <string.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chaps/isolate.h>
#include <chaps/token_manager_client.h>
#include <chromeos/cryptohome.h>
#include <errno.h>
#include <glib.h>
using base::FilePath;
namespace cryptohome {
// static
const char Pkcs11Init::kDefaultPin[] = "111111";
const char Pkcs11Init::kDefaultSystemLabel[] = "System TPM Token";
const char Pkcs11Init::kDefaultUserLabelPrefix[] = "User TPM Token ";
extern const char* kTpmOwnedFile;
Pkcs11Init::Pkcs11Init() : default_platform_(new Platform),
platform_(default_platform_.get()) {
}
Pkcs11Init::~Pkcs11Init() {
}
void Pkcs11Init::GetTpmTokenInfo(gchar **OUT_label,
gchar **OUT_user_pin) {
*OUT_label = g_strdup(reinterpret_cast<const gchar*>(kDefaultSystemLabel));
*OUT_user_pin = g_strdup(reinterpret_cast<const gchar*>(kDefaultPin));
}
void Pkcs11Init::GetTpmTokenInfoForUser(gchar *username,
gchar **OUT_label,
gchar **OUT_user_pin) {
std::string label = GetTpmTokenLabelForUser(
reinterpret_cast<const char*>(username));
*OUT_label = g_strdup(reinterpret_cast<const gchar*>(label.c_str()));
*OUT_user_pin = g_strdup(reinterpret_cast<const gchar*>(kDefaultPin));
}
std::string Pkcs11Init::GetTpmTokenLabelForUser(const std::string& username) {
// Use a truncated sanitized username in the token label so a label collision
// is extremely unlikely.
return std::string(kDefaultUserLabelPrefix) +
chromeos::cryptohome::home::SanitizeUserName(username).substr(0, 16);
}
bool Pkcs11Init::GetTpmTokenSlotForPath(const base::FilePath& path,
CK_SLOT_ID_PTR slot) {
CK_RV rv;
rv = C_Initialize(NULL);
if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
LOG(WARNING) << __func__ << ": C_Initialize failed.";
return false;
}
CK_ULONG num_slots = 0;
rv = C_GetSlotList(CK_TRUE, NULL, &num_slots);
if (rv != CKR_OK) {
LOG(WARNING) << __func__ << ": C_GetSlotList(NULL) failed.";
return false;
}
scoped_ptr<CK_SLOT_ID[]> slot_list(new CK_SLOT_ID[num_slots]);
rv = C_GetSlotList(CK_TRUE, slot_list.get(), &num_slots);
if (rv != CKR_OK) {
LOG(WARNING) << __func__ << ": C_GetSlotList failed.";
return false;
}
chaps::TokenManagerClient token_manager;
for (CK_ULONG i = 0; i < num_slots; ++i) {
FilePath slot_path;
if (token_manager.GetTokenPath(
chaps::IsolateCredentialManager::GetDefaultIsolateCredential(),
slot_list[i],
&slot_path) && (path == slot_path)) {
*slot = slot_list[i];
return true;
}
}
LOG(WARNING) << __func__ << ": Path not found.";
return false;
}
bool Pkcs11Init::IsUserTokenOK() {
if (!platform_->FileExists(kTpmOwnedFile)) {
LOG(WARNING) << "TPM is not owned, token can not be valid.";
return false;
}
CK_RV rv;
rv = C_Initialize(NULL);
if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
LOG(WARNING) << __func__ << ": C_Initialize failed.";
return false;
}
CK_ULONG num_slots = 0;
rv = C_GetSlotList(CK_TRUE, NULL, &num_slots);
if (rv != CKR_OK) {
LOG(WARNING) << __func__ << ": C_GetSlotList(NULL) failed.";
return false;
}
scoped_ptr<CK_SLOT_ID[]> slot_list(new CK_SLOT_ID[num_slots]);
rv = C_GetSlotList(CK_TRUE, slot_list.get(), &num_slots);
if (rv != CKR_OK) {
LOG(WARNING) << __func__ << ": C_GetSlotList failed.";
return false;
}
// Check if at least one sane user token exists.
for (CK_ULONG i = 0; i < num_slots; ++i) {
if (CheckTokenInSlot(slot_list[i], kDefaultUserLabelPrefix)) {
LOG(INFO) << "User PKCS #11 token looks ok.";
return true;
}
}
LOG(WARNING) << "Cannot find sane user token.";
return false;
}
bool Pkcs11Init::CheckTokenInSlot(CK_SLOT_ID slot_id,
const std::string& expected_label_prefix) {
CK_RV rv;
CK_SESSION_HANDLE session_handle = 0;
CK_SESSION_INFO session_info;
CK_TOKEN_INFO token_info;
rv = C_Initialize(NULL);
if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
LOG(WARNING) << "C_Initialize failed while checking token: "
<< std::hex << rv;
return false;
}
rv = C_OpenSession(slot_id, CKF_RW_SESSION | CKF_SERIAL_SESSION,
NULL, NULL,
&session_handle);
if (rv != CKR_OK) {
LOG(WARNING) << "Could not open session on slot " << slot_id
<< " while checking token." << std::hex << rv;
C_CloseAllSessions(slot_id);
return false;
}
memset(&session_info, 0, sizeof(session_info));
rv = C_GetSessionInfo(session_handle, &session_info);
if (rv != CKR_OK || session_info.slotID != slot_id) {
LOG(WARNING) << "Could not get session info on " << slot_id
<< " while checking token: " << std::hex << rv;
C_CloseAllSessions(slot_id);
return false;
}
rv = C_GetTokenInfo(slot_id, &token_info);
if (rv != CKR_OK || !(token_info.flags & CKF_TOKEN_INITIALIZED)) {
LOG(WARNING) << "Could not get token info on " << slot_id
<< " while checking token: " << std::hex << rv;
C_CloseAllSessions(slot_id);
return false;
}
std::string label(reinterpret_cast<const char*>(token_info.label),
arraysize(token_info.label));
if (!StartsWithASCII(label, expected_label_prefix, true)) {
LOG(WARNING) << "Token Label (" << label << ") does not match expected "
<< "label prefix (" << expected_label_prefix << ")";
return false;
}
C_CloseAllSessions(slot_id);
return true;
}
} // namespace cryptohome