29 #include "ndn-cxx/security/impl/openssl-helper.hpp" 35 #include <boost/lexical_cast.hpp> 38 #define ENSURE_PRIVATE_KEY_LOADED(key) \ 40 if ((key) == nullptr) \ 41 NDN_THROW(Error("Private key has not been loaded yet")); \ 44 #define ENSURE_PRIVATE_KEY_NOT_LOADED(key) \ 46 if ((key) != nullptr) \ 47 NDN_THROW(Error("Private key has already been loaded")); \ 57 #if OPENSSL_VERSION_NUMBER < 0x1010000fL 58 static bool isInitialized =
false;
60 OpenSSL_add_all_algorithms();
63 #endif // OPENSSL_VERSION_NUMBER < 0x1010000fL 66 class PrivateKey::Impl : noncopyable
75 EVP_PKEY* key =
nullptr;
77 #if OPENSSL_VERSION_NUMBER < 0x1010100fL 83 : m_impl(make_unique<Impl>())
95 switch (detail::getEvpPkeyType(m_impl->key)) {
113 return static_cast<size_t>(EVP_PKEY_bits(m_impl->key));
115 #if OPENSSL_VERSION_NUMBER >= 0x1010100fL 117 EVP_PKEY_get_raw_private_key(m_impl->key,
nullptr, &nBytes);
120 return m_impl->keySize;
133 boost::lexical_cast<std::string>(
getKeyType())));
135 const uint8_t* buf =
nullptr;
137 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL 138 buf = EVP_PKEY_get0_hmac(m_impl->key, &len);
140 const auto* octstr =
reinterpret_cast<ASN1_OCTET_STRING*
>(EVP_PKEY_get0(m_impl->key));
142 len = octstr->length;
162 pkeyType = EVP_PKEY_HMAC;
165 NDN_THROW(std::invalid_argument(
"Unsupported key type " + boost::lexical_cast<std::string>(type)));
169 #if OPENSSL_VERSION_NUMBER >= 0x1010100fL 170 EVP_PKEY_new_raw_private_key(pkeyType,
nullptr, buf, size);
172 EVP_PKEY_new_mac_key(pkeyType,
nullptr, buf, static_cast<int>(size));
174 if (m_impl->key ==
nullptr)
177 #if OPENSSL_VERSION_NUMBER < 0x1010100fL 178 m_impl->keySize = size * 8;
188 if (d2i_AutoPrivateKey(&m_impl->key, &buf, static_cast<long>(size)) ==
nullptr)
219 BOOST_ASSERT(std::strlen(pw) == pwLen);
223 detail::Bio membio(BIO_s_mem());
224 if (!membio.write(buf, size))
227 if (d2i_PKCS8PrivateKey_bio(membio, &m_impl->key,
nullptr, const_cast<char*>(pw)) ==
nullptr)
234 BOOST_ASSERT(size >= 0);
236 return (*cb)(buf,
static_cast<size_t>(size), rwflag);
245 detail::Bio membio(BIO_s_mem());
246 if (!membio.write(buf, size))
252 m_impl->key = d2i_PKCS8PrivateKey_bio(membio,
nullptr,
nullptr,
nullptr);
254 if (m_impl->key ==
nullptr)
347 uint8_t* pkcs8 =
nullptr;
348 int len = i2d_PUBKEY(m_impl->key, &pkcs8);
352 auto result = make_shared<Buffer>(pkcs8, len);
363 int keyType = detail::getEvpPkeyType(m_impl->key);
368 return rsaDecrypt(cipherText, cipherLen);
375 PrivateKey::getEvpPkey()
const 381 PrivateKey::toPkcs1()
const 386 detail::Bio membio(BIO_s_mem());
387 if (!i2d_PrivateKey_bio(membio, m_impl->key))
390 auto buffer = make_shared<Buffer>(BIO_pending(membio));
391 if (!membio.read(buffer->data(), buffer->size()))
398 PrivateKey::toPkcs8(
const char* pw,
size_t pwLen)
const 400 BOOST_ASSERT(std::strlen(pw) == pwLen);
404 detail::Bio membio(BIO_s_mem());
405 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_aes_256_cbc(),
nullptr, 0,
406 nullptr, const_cast<char*>(pw)))
409 auto buffer = make_shared<Buffer>(BIO_pending(membio));
410 if (!membio.read(buffer->data(), buffer->size()))
422 detail::Bio membio(BIO_s_mem());
423 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_aes_256_cbc(),
nullptr, 0,
427 auto buffer = make_shared<Buffer>(BIO_pending(membio));
428 if (!membio.read(buffer->data(), buffer->size()))
435 PrivateKey::rsaDecrypt(
const uint8_t* cipherText,
size_t cipherLen)
const 437 detail::EvpPkeyCtx ctx(m_impl->key);
439 if (EVP_PKEY_decrypt_init(ctx) <= 0)
442 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
447 if (EVP_PKEY_decrypt(ctx,
nullptr, &outlen, cipherText, cipherLen) <= 0)
450 auto out = make_shared<Buffer>(outlen);
451 if (EVP_PKEY_decrypt(ctx, out->data(), &outlen, cipherText, cipherLen) <= 0)
458 unique_ptr<PrivateKey>
459 PrivateKey::generateRsaKey(uint32_t keySize)
461 detail::EvpPkeyCtx kctx(EVP_PKEY_RSA);
463 if (EVP_PKEY_keygen_init(kctx) <= 0)
466 if (EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, static_cast<int>(keySize)) <= 0)
469 auto privateKey = make_unique<PrivateKey>();
470 if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
476 unique_ptr<PrivateKey>
477 PrivateKey::generateEcKey(uint32_t keySize)
479 EC_KEY* eckey =
nullptr;
482 eckey = EC_KEY_new_by_curve_name(NID_secp224r1);
485 eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
488 eckey = EC_KEY_new_by_curve_name(NID_secp384r1);
491 eckey = EC_KEY_new_by_curve_name(NID_secp521r1);
496 if (eckey ==
nullptr) {
500 auto guard = make_scope_exit([eckey] { EC_KEY_free(eckey); });
502 #if OPENSSL_VERSION_NUMBER < 0x1010000fL 503 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
504 #endif // OPENSSL_VERSION_NUMBER < 0x1010000fL 506 if (EC_KEY_generate_key(eckey) != 1) {
510 auto privateKey = make_unique<PrivateKey>();
511 privateKey->m_impl->key = EVP_PKEY_new();
512 if (privateKey->m_impl->key ==
nullptr)
514 if (EVP_PKEY_set1_EC_KEY(privateKey->m_impl->key, eckey) != 1)
520 unique_ptr<PrivateKey>
521 PrivateKey::generateHmacKey(uint32_t keySize)
523 std::vector<uint8_t> rawKey(keySize / 8);
526 auto privateKey = make_unique<PrivateKey>();
528 privateKey->loadRaw(
KeyType::HMAC, rawKey.data(), rawKey.size());
537 unique_ptr<PrivateKey>
543 return PrivateKey::generateRsaKey(rsaParams.
getKeySize());
547 return PrivateKey::generateEcKey(ecParams.
getKeySize());
551 return PrivateKey::generateHmacKey(hmacParams.
getKeySize());
554 NDN_THROW(std::invalid_argument(
"Unsupported key type " +
555 boost::lexical_cast<std::string>(keyParams.
getKeyType())));
Unknown or unsupported key type.
SimpleSymmetricKeyParams is a template for symmetric keys with only one parameter: size...
#define ENSURE_PRIVATE_KEY_NOT_LOADED(key)
std::string to_string(const T &val)
RSA key, supports sign/verify and encrypt/decrypt operations.
#define ENSURE_PRIVATE_KEY_LOADED(key)
HMAC key, supports sign/verify operations.
KeyType
The type of a cryptographic key.
Elliptic Curve key (e.g. for ECDSA), supports sign/verify operations.
uint32_t getKeySize() const
KeyType getKeyType() const
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
void generateSecureBytes(uint8_t *bytes, size_t size)
Fill bytes of size with cryptographically secure random bytes.
Base class for key parameters.
uint32_t getKeySize() const
implements an output stream that constructs ndn::Buffer
SimplePublicKeyParams is a template for public keys with only one parameter: size.
shared_ptr< const Buffer > ConstBufferPtr