blob: d1da79b3ad2ca88081af0da0eab8b3ba08aef86a [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2013-2021 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#ifndef NDN_CXX_SECURITY_TPM_TPM_HPP
#define NDN_CXX_SECURITY_TPM_TPM_HPP
#include "ndn-cxx/name.hpp"
#include "ndn-cxx/security/key-params.hpp"
#include "ndn-cxx/security/tpm/key-handle.hpp"
#include <unordered_map>
#include <boost/logic/tribool.hpp>
namespace ndn {
namespace security {
namespace transform {
class PrivateKey;
} // namespace transform
inline namespace v2 {
class KeyChain;
} // inline namespace v2
namespace tpm {
class BackEnd;
/**
* @brief TPM front-end class.
*
* The TPM (Trusted Platform Module) stores the private portion of a user's cryptography keys.
* The format and location of stored information is indicated by the TpmLocator.
* The TPM is designed to work with a PIB (Public Information Base) which stores public keys and
* related information such as certificate.
*
* The TPM also provides functionalities of crypto transformation, such as signing and decryption.
*
* A TPM consists of a unified front-end interface and a back-end implementation. The front-end
* cache the handles of private keys which is provided by the back-end implementation.
*
* @note Tpm instance is created and managed only by KeyChain. KeyChain::getTpm() returns
* a const reference to the managed Tpm instance, through which it is possible to
* check the existence of private keys, get the public key corresponding to a private
* key, sign, and decrypt the supplied buffers using managed private keys.
*/
class Tpm : noncopyable
{
public:
class Error : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
~Tpm();
std::string
getTpmLocator() const;
/**
* @brief Check if a private key exists.
*
* @param keyName The key name
* @return true if the key exists
*/
bool
hasKey(const Name& keyName) const;
/**
* @return The public portion of an asymmetric key with name @p keyName,
* or nullptr if the key does not exist,
*
* The public key is in PKCS#8 format.
*/
ConstBufferPtr
getPublicKey(const Name& keyName) const;
/**
* @brief Sign discontiguous ranges using the key with name @p keyName and using the digest
* @p digestAlgorithm.
*
* @return The signature, or nullptr if the key does not exist.
*/
ConstBufferPtr
sign(const InputBuffers& bufs, const Name& keyName, DigestAlgorithm digestAlgorithm) const;
/**
* @brief Sign blob using the key with name @p keyName and using the digest @p digestAlgorithm.
*
* @return The signature, or nullptr if the key does not exist.
*/
ConstBufferPtr
sign(const uint8_t* buf, size_t size, const Name& keyName, DigestAlgorithm digestAlgorithm) const
{
return sign({{buf, size}}, keyName, digestAlgorithm);
}
/**
* @brief Verify discontiguous ranges using the key with name @p keyName and using the digest
* @p digestAlgorithm.
*
* @retval true the signature is valid
* @retval false the signature is not valid
* @retval indeterminate the key does not exist
*/
boost::logic::tribool
verify(const InputBuffers& bufs, const uint8_t* sig, size_t sigLen, const Name& keyName,
DigestAlgorithm digestAlgorithm) const;
/**
* @brief Verify blob using the key with name @p keyName and using the digest @p digestAlgorithm.
*
* @retval true the signature is valid
* @retval false the signature is not valid
* @retval indeterminate the key does not exist
*/
boost::logic::tribool
verify(const uint8_t* buf, size_t bufLen, const uint8_t* sig, size_t sigLen,
const Name& keyName, DigestAlgorithm digestAlgorithm) const
{
return verify({{buf, bufLen}}, sig, sigLen, keyName, digestAlgorithm);
}
/**
* @brief Decrypt blob using the key with name @p keyName.
*
* @return The decrypted data, or nullptr if the key does not exist.
*/
ConstBufferPtr
decrypt(const uint8_t* buf, size_t size, const Name& keyName) const;
public: // Management
/**
* @brief Check if the TPM is in terminal mode.
*/
bool
isTerminalMode() const;
/**
* @brief Set the terminal mode of the TPM.
*
* When in terminal mode, the TPM will not ask user permission from GUI.
*/
void
setTerminalMode(bool isTerminal) const;
/**
* @return true if the TPM is locked, otherwise false.
*/
bool
isTpmLocked() const;
/**
* @brief Unlock the TPM.
*
* @param password The password to unlock the TPM.
* @param passwordLength The password size.
*/
NDN_CXX_NODISCARD bool
unlockTpm(const char* password, size_t passwordLength) const;
NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/**
* @brief Create a new TPM instance with the specified @p location.
*
* @param scheme The scheme for the TPM
* @param location The location for the TPM
* @param impl The back-end implementation
*/
Tpm(const std::string& scheme, const std::string& location, unique_ptr<BackEnd> impl);
/**
* @brief Create key for @p identityName according to @p params.
*
* The created key is named as follows:
* - RSA and EC keys: `/<identityName>/KEY/<keyId>`
* - HMAC keys: `/<identityName>/<keyDigest>`
*
* @return The key name.
* @throw Error The key already exists or @p params is invalid.
*/
Name
createKey(const Name& identityName, const KeyParams& params);
/**
* @brief Delete a key pair with name @p keyName.
*/
void
deleteKey(const Name& keyName);
/**
* @brief Export a private key.
*
* Export a private key in encrypted PKCS #8 format.
*
* @param keyName The private key name
* @param pw The password to encrypt the private key
* @param pwLen The length of the password
* @return The encoded private key wrapper.
* @throw Error The key does not exist or it could not be exported.
*/
ConstBufferPtr
exportPrivateKey(const Name& keyName, const char* pw, size_t pwLen) const;
/**
* @brief Import a private key.
*
* @param keyName The private key name
* @param pkcs8 The private key wrapper
* @param pkcs8Len The length of the private key wrapper
* @param pw The password to encrypt the private key
* @param pwLen The length of the password
* @throw Error The key could not be imported.
*/
void
importPrivateKey(const Name& keyName, const uint8_t* pkcs8, size_t pkcs8Len,
const char* pw, size_t pwLen);
/**
* @brief Import a private key.
*/
void
importPrivateKey(const Name& keyName, shared_ptr<transform::PrivateKey> key);
/**
* @brief Clear the key cache.
*
* An empty cache can force Tpm to do key lookup in the back-end.
*/
void
clearKeyCache()
{
m_keys.clear();
}
private:
/**
* @brief Internal KeyHandle lookup.
*
* @return A pointer to the handle of key @p keyName if it exists, otherwise nullptr.
*/
const KeyHandle*
findKey(const Name& keyName) const;
private:
std::string m_scheme;
std::string m_location;
mutable std::unordered_map<Name, unique_ptr<KeyHandle>> m_keys;
const unique_ptr<BackEnd> m_backEnd;
friend KeyChain;
};
} // namespace tpm
using tpm::Tpm;
} // namespace security
} // namespace ndn
#endif // NDN_CXX_SECURITY_TPM_TPM_HPP