29 #include "ndn-cxx/security/impl/openssl-helper.hpp" 34 #include <boost/lexical_cast.hpp> 37 #define ENSURE_PRIVATE_KEY_LOADED(key) \ 39 if ((key) == nullptr) \ 40 NDN_THROW(Error("Private key has not been loaded yet")); \ 43 #define ENSURE_PRIVATE_KEY_NOT_LOADED(key) \ 45 if ((key) != nullptr) \ 46 NDN_THROW(Error("Private key has already been loaded")); \ 56 #if OPENSSL_VERSION_NUMBER < 0x1010000fL 57 static bool isInitialized =
false;
59 OpenSSL_add_all_algorithms();
62 #endif // OPENSSL_VERSION_NUMBER < 0x1010000fL 65 class PrivateKey::Impl : noncopyable
74 EVP_PKEY* key =
nullptr;
76 #if OPENSSL_VERSION_NUMBER < 0x1010100fL 82 : m_impl(make_unique<Impl>())
94 switch (detail::getEvpPkeyType(m_impl->key)) {
112 return static_cast<size_t>(EVP_PKEY_bits(m_impl->key));
114 #if OPENSSL_VERSION_NUMBER >= 0x1010100fL 116 EVP_PKEY_get_raw_private_key(m_impl->key,
nullptr, &nBytes);
119 return m_impl->keySize;
132 boost::lexical_cast<std::string>(
getKeyType())));
134 const uint8_t*
buf =
nullptr;
136 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL 137 buf = EVP_PKEY_get0_hmac(m_impl->key, &len);
139 const auto* octstr =
reinterpret_cast<ASN1_OCTET_STRING*
>(EVP_PKEY_get0(m_impl->key));
141 len = octstr->length;
161 pkeyType = EVP_PKEY_HMAC;
164 NDN_THROW(std::invalid_argument(
"Unsupported key type " + boost::lexical_cast<std::string>(type)));
168 #if OPENSSL_VERSION_NUMBER >= 0x1010100fL 169 EVP_PKEY_new_raw_private_key(pkeyType,
nullptr, buf, size);
171 EVP_PKEY_new_mac_key(pkeyType,
nullptr, buf, static_cast<int>(size));
173 if (m_impl->key ==
nullptr)
176 #if OPENSSL_VERSION_NUMBER < 0x1010100fL 177 m_impl->keySize = size * 8;
187 if (d2i_AutoPrivateKey(&m_impl->key, &buf, static_cast<long>(size)) ==
nullptr)
218 BOOST_ASSERT(std::strlen(pw) == pwLen);
222 detail::Bio membio(BIO_s_mem());
223 if (!membio.write(buf, size))
226 if (d2i_PKCS8PrivateKey_bio(membio, &m_impl->key,
nullptr, const_cast<char*>(pw)) ==
nullptr)
233 BOOST_ASSERT(size >= 0);
235 return (*cb)(
buf,
static_cast<size_t>(size), rwflag);
244 detail::Bio membio(BIO_s_mem());
245 if (!membio.write(buf, size))
251 m_impl->key = d2i_PKCS8PrivateKey_bio(membio,
nullptr,
nullptr,
nullptr);
253 if (m_impl->key ==
nullptr)
346 uint8_t* pkcs8 =
nullptr;
347 int len = i2d_PUBKEY(m_impl->key, &pkcs8);
351 auto result = make_shared<Buffer>(pkcs8, len);
362 int keyType = detail::getEvpPkeyType(m_impl->key);
367 return rsaDecrypt(cipherText, cipherLen);
374 PrivateKey::getEvpPkey()
const 380 PrivateKey::toPkcs1()
const 385 detail::Bio membio(BIO_s_mem());
386 if (!i2d_PrivateKey_bio(membio, m_impl->key))
389 auto buffer = make_shared<Buffer>(BIO_pending(membio));
390 if (!membio.read(buffer->data(), buffer->size()))
397 PrivateKey::toPkcs8(
const char* pw,
size_t pwLen)
const 399 BOOST_ASSERT(std::strlen(pw) == pwLen);
403 detail::Bio membio(BIO_s_mem());
404 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_aes_256_cbc(),
nullptr, 0,
405 nullptr, const_cast<char*>(pw)))
408 auto buffer = make_shared<Buffer>(BIO_pending(membio));
409 if (!membio.read(buffer->data(), buffer->size()))
421 detail::Bio membio(BIO_s_mem());
422 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_aes_256_cbc(),
nullptr, 0,
426 auto buffer = make_shared<Buffer>(BIO_pending(membio));
427 if (!membio.read(buffer->data(), buffer->size()))
434 PrivateKey::rsaDecrypt(
const uint8_t* cipherText,
size_t cipherLen)
const 436 detail::EvpPkeyCtx ctx(m_impl->key);
438 if (EVP_PKEY_decrypt_init(ctx) <= 0)
441 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
446 if (EVP_PKEY_decrypt(ctx,
nullptr, &outlen, cipherText, cipherLen) <= 0)
449 auto out = make_shared<Buffer>(outlen);
450 if (EVP_PKEY_decrypt(ctx, out->data(), &outlen, cipherText, cipherLen) <= 0)
457 unique_ptr<PrivateKey>
458 PrivateKey::generateRsaKey(uint32_t keySize)
460 detail::EvpPkeyCtx kctx(EVP_PKEY_RSA);
462 if (EVP_PKEY_keygen_init(kctx) <= 0)
465 if (EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, static_cast<int>(keySize)) <= 0)
468 auto privateKey = make_unique<PrivateKey>();
469 if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
475 unique_ptr<PrivateKey>
476 PrivateKey::generateEcKey(uint32_t keySize)
478 detail::EvpPkeyCtx pctx(EVP_PKEY_EC);
480 if (EVP_PKEY_paramgen_init(pctx) <= 0)
486 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_secp224r1);
489 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1);
492 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_secp384r1);
495 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_secp521r1);
504 if (EVP_PKEY_paramgen(pctx, ¶ms.key) <= 0)
507 detail::EvpPkeyCtx kctx(params.key);
508 if (EVP_PKEY_keygen_init(kctx) <= 0)
511 auto privateKey = make_unique<PrivateKey>();
512 if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
518 unique_ptr<PrivateKey>
519 PrivateKey::generateHmacKey(uint32_t keySize)
521 std::vector<uint8_t> rawKey(keySize / 8);
524 auto privateKey = make_unique<PrivateKey>();
526 privateKey->loadRaw(
KeyType::HMAC, rawKey.data(), rawKey.size());
535 unique_ptr<PrivateKey>
541 return PrivateKey::generateRsaKey(rsaParams.
getKeySize());
545 return PrivateKey::generateEcKey(ecParams.
getKeySize());
549 return PrivateKey::generateHmacKey(hmacParams.
getKeySize());
552 NDN_THROW(std::invalid_argument(
"Unsupported key type " +
553 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