28 #include "../detail/openssl-helper.hpp" 29 #include "../key-params.hpp" 30 #include "../../encoding/buffer-stream.hpp" 32 #include <boost/lexical_cast.hpp> 35 #define ENSURE_PRIVATE_KEY_LOADED(key) \ 37 if ((key) == nullptr) \ 38 BOOST_THROW_EXCEPTION(Error("Private key has not been loaded yet")); \ 41 #define ENSURE_PRIVATE_KEY_NOT_LOADED(key) \ 43 if ((key) != nullptr) \ 44 BOOST_THROW_EXCEPTION(Error("Private key has already been loaded")); \ 54 #if OPENSSL_VERSION_NUMBER < 0x1010000fL 55 static bool isInitialized =
false;
57 OpenSSL_add_all_algorithms();
60 #endif // OPENSSL_VERSION_NUMBER < 0x1010000fL 109 if (d2i_AutoPrivateKey(&m_impl->key, &buf, static_cast<long>(size)) ==
nullptr)
110 BOOST_THROW_EXCEPTION(
Error(
"Failed to load private key"));
140 BOOST_ASSERT(std::strlen(pw) == pwLen);
145 if (!membio.
write(buf, size))
146 BOOST_THROW_EXCEPTION(
Error(
"Failed to copy buffer"));
148 if (d2i_PKCS8PrivateKey_bio(membio, &m_impl->key,
nullptr, const_cast<char*>(pw)) ==
nullptr)
149 BOOST_THROW_EXCEPTION(
Error(
"Failed to load private key"));
155 BOOST_ASSERT(size >= 0);
157 return (*cb)(buf,
static_cast<size_t>(size), rwflag);
167 if (!membio.
write(buf, size))
168 BOOST_THROW_EXCEPTION(
Error(
"Failed to copy buffer"));
173 m_impl->key = d2i_PKCS8PrivateKey_bio(membio,
nullptr,
nullptr,
nullptr);
175 if (m_impl->key ==
nullptr)
176 BOOST_THROW_EXCEPTION(
Error(
"Failed to load private key"));
268 uint8_t* pkcs8 =
nullptr;
269 int len = i2d_PUBKEY(m_impl->key, &pkcs8);
271 BOOST_THROW_EXCEPTION(
Error(
"Failed to derive public key"));
273 auto result = make_shared<Buffer>(pkcs8, len);
287 BOOST_THROW_EXCEPTION(
Error(
"Failed to determine key type"));
289 return rsaDecrypt(cipherText, cipherLen);
291 BOOST_THROW_EXCEPTION(
Error(
"Decryption is not supported for key type " +
to_string(keyType)));
296 PrivateKey::getEvpPkey()
const 302 PrivateKey::toPkcs1()
const 308 if (!i2d_PrivateKey_bio(membio, m_impl->key))
309 BOOST_THROW_EXCEPTION(
Error(
"Cannot convert key to PKCS #1 format"));
311 auto buffer = make_shared<Buffer>(BIO_pending(membio));
312 membio.
read(buffer->data(), buffer->size());
318 PrivateKey::toPkcs8(
const char* pw,
size_t pwLen)
const 320 BOOST_ASSERT(std::strlen(pw) == pwLen);
325 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_des_ede3_cbc(),
nullptr, 0,
326 nullptr, const_cast<char*>(pw)))
327 BOOST_THROW_EXCEPTION(
Error(
"Cannot convert key to PKCS #8 format"));
329 auto buffer = make_shared<Buffer>(BIO_pending(membio));
330 membio.
read(buffer->data(), buffer->size());
342 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_des_ede3_cbc(),
nullptr, 0,
344 BOOST_THROW_EXCEPTION(
Error(
"Cannot convert key to PKCS #8 format"));
346 auto buffer = make_shared<Buffer>(BIO_pending(membio));
347 membio.
read(buffer->data(), buffer->size());
353 PrivateKey::rsaDecrypt(
const uint8_t* cipherText,
size_t cipherLen)
const 357 if (EVP_PKEY_decrypt_init(ctx) <= 0)
358 BOOST_THROW_EXCEPTION(
Error(
"Failed to initialize decryption context"));
360 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
361 BOOST_THROW_EXCEPTION(
Error(
"Failed to set padding"));
365 if (EVP_PKEY_decrypt(ctx,
nullptr, &outlen, cipherText, cipherLen) <= 0)
366 BOOST_THROW_EXCEPTION(
Error(
"Failed to estimate output length"));
368 auto out = make_shared<Buffer>(outlen);
369 if (EVP_PKEY_decrypt(ctx, out->data(), &outlen, cipherText, cipherLen) <= 0)
370 BOOST_THROW_EXCEPTION(
Error(
"Failed to decrypt ciphertext"));
376 unique_ptr<PrivateKey>
377 PrivateKey::generateRsaKey(uint32_t keySize)
381 if (EVP_PKEY_keygen_init(kctx) <= 0)
382 BOOST_THROW_EXCEPTION(
PrivateKey::Error(
"Failed to initialize RSA keygen context"));
384 if (EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, static_cast<int>(keySize)) <= 0)
387 auto privateKey = make_unique<PrivateKey>();
388 if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
394 unique_ptr<PrivateKey>
395 PrivateKey::generateEcKey(uint32_t keySize)
399 if (EVP_PKEY_paramgen_init(pctx) <= 0)
400 BOOST_THROW_EXCEPTION(
PrivateKey::Error(
"Failed to initialize EC paramgen context"));
405 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1);
408 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_secp384r1);
417 if (EVP_PKEY_paramgen(pctx, ¶ms.key) <= 0)
421 if (EVP_PKEY_keygen_init(kctx) <= 0)
422 BOOST_THROW_EXCEPTION(
PrivateKey::Error(
"Failed to initialize EC keygen context"));
424 auto privateKey = make_unique<PrivateKey>();
425 if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
431 unique_ptr<PrivateKey>
437 return PrivateKey::generateRsaKey(rsaParams.
getKeySize());
441 return PrivateKey::generateEcKey(ecParams.
getKeySize());
444 BOOST_THROW_EXCEPTION(std::invalid_argument(
"Unsupported asymmetric key type " +
445 boost::lexical_cast<std::string>(keyParams.
getKeyType())));
Copyright (c) 2011-2015 Regents of the University of California.
int getEvpPkeyType(EVP_PKEY *key)
#define ENSURE_PRIVATE_KEY_NOT_LOADED(key)
KeyType getKeyType() const
uint32_t getKeySize() const
RSA key, supports sign/verify and encrypt/decrypt operations.
unique_ptr< T > make_unique(Args &&...args)
#define ENSURE_PRIVATE_KEY_LOADED(key)
Catch-all error for security policy errors that don't fit in other categories.
KeyType
The type of a cryptographic key.
bool read(uint8_t *buf, size_t buflen) const noexcept
Elliptic Curve key (e.g. for ECDSA), supports sign/verify operations.
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
Base class of key parameters.
implements an output stream that constructs ndn::Buffer
std::string to_string(const V &v)
SimplePublicKeyParams is a template for public keys with only one parameter: size.
shared_ptr< const Buffer > ConstBufferPtr
bool write(const uint8_t *buf, size_t buflen) noexcept