blob: b7820c37ec85af3ac055be932c612913a3a1c4ac [file] [log] [blame]
Yingdi Yu202a2e92015-07-12 16:49:25 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Luca Keidel941fd8c2017-07-24 15:21:22 +02002/*
Spyridon Mastorakis1ece2e32015-08-27 18:52:21 -07003 * Copyright (c) 2013-2017 Regents of the University of California.
Yingdi Yu202a2e92015-07-12 16:49:25 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "private-key.hpp"
Yingdi Yu202a2e92015-07-12 16:49:25 -070023#include "base64-decode.hpp"
Davide Pesaventoe1789892017-02-26 15:50:52 -050024#include "base64-encode.hpp"
25#include "buffer-source.hpp"
Yingdi Yu202a2e92015-07-12 16:49:25 -070026#include "stream-sink.hpp"
Davide Pesaventoe1789892017-02-26 15:50:52 -050027#include "stream-source.hpp"
Yingdi Yu202a2e92015-07-12 16:49:25 -070028#include "../detail/openssl-helper.hpp"
29#include "../key-params.hpp"
Davide Pesaventoe1789892017-02-26 15:50:52 -050030#include "../../encoding/buffer-stream.hpp"
Yingdi Yu202a2e92015-07-12 16:49:25 -070031
Davide Pesaventof45fa212017-09-14 17:23:56 -040032#include <boost/lexical_cast.hpp>
Davide Pesaventoe1789892017-02-26 15:50:52 -050033#include <cstring>
Yingdi Yu202a2e92015-07-12 16:49:25 -070034
35#define ENSURE_PRIVATE_KEY_LOADED(key) \
36 do { \
Davide Pesaventof45fa212017-09-14 17:23:56 -040037 if ((key) == nullptr) \
Yingdi Yu202a2e92015-07-12 16:49:25 -070038 BOOST_THROW_EXCEPTION(Error("Private key has not been loaded yet")); \
39 } while (false)
40
Davide Pesaventof45fa212017-09-14 17:23:56 -040041#define ENSURE_PRIVATE_KEY_NOT_LOADED(key) \
42 do { \
43 if ((key) != nullptr) \
44 BOOST_THROW_EXCEPTION(Error("Private key has already been loaded")); \
45 } while (false)
46
Yingdi Yu202a2e92015-07-12 16:49:25 -070047namespace ndn {
48namespace security {
49namespace transform {
50
Luca Keidel941fd8c2017-07-24 15:21:22 +020051static void
52opensslInitAlgorithms()
53{
54#if OPENSSL_VERSION_NUMBER < 0x1010000fL
55 static bool isInitialized = false;
56 if (!isInitialized) {
57 OpenSSL_add_all_algorithms();
58 isInitialized = true;
59 }
60#endif // OPENSSL_VERSION_NUMBER < 0x1010000fL
61}
62
Yingdi Yu202a2e92015-07-12 16:49:25 -070063class PrivateKey::Impl
64{
65public:
Davide Pesaventof45fa212017-09-14 17:23:56 -040066 Impl() noexcept
Yingdi Yu202a2e92015-07-12 16:49:25 -070067 : key(nullptr)
68 {
69 }
70
71 ~Impl()
72 {
73 EVP_PKEY_free(key);
74 }
75
76public:
77 EVP_PKEY* key;
78};
79
80PrivateKey::PrivateKey()
Davide Pesaventof45fa212017-09-14 17:23:56 -040081 : m_impl(make_unique<Impl>())
Yingdi Yu202a2e92015-07-12 16:49:25 -070082{
83}
84
85PrivateKey::~PrivateKey() = default;
86
87void
88PrivateKey::loadPkcs1(const uint8_t* buf, size_t size)
89{
Davide Pesaventof45fa212017-09-14 17:23:56 -040090 ENSURE_PRIVATE_KEY_NOT_LOADED(m_impl->key);
91 opensslInitAlgorithms();
Yingdi Yu202a2e92015-07-12 16:49:25 -070092
Davide Pesaventof45fa212017-09-14 17:23:56 -040093 if (d2i_AutoPrivateKey(&m_impl->key, &buf, static_cast<long>(size)) == nullptr)
94 BOOST_THROW_EXCEPTION(Error("Failed to load private key"));
Yingdi Yu202a2e92015-07-12 16:49:25 -070095}
96
97void
98PrivateKey::loadPkcs1(std::istream& is)
99{
100 OBufferStream os;
101 streamSource(is) >> streamSink(os);
102 this->loadPkcs1(os.buf()->buf(), os.buf()->size());
103}
104
105void
106PrivateKey::loadPkcs1Base64(const uint8_t* buf, size_t size)
107{
108 OBufferStream os;
109 bufferSource(buf, size) >> base64Decode() >> streamSink(os);
110 this->loadPkcs1(os.buf()->buf(), os.buf()->size());
111}
112
113void
114PrivateKey::loadPkcs1Base64(std::istream& is)
115{
116 OBufferStream os;
117 streamSource(is) >> base64Decode() >> streamSink(os);
118 this->loadPkcs1(os.buf()->buf(), os.buf()->size());
119}
120
121void
122PrivateKey::loadPkcs8(const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
123{
124 BOOST_ASSERT(std::strlen(pw) == pwLen);
Davide Pesaventof45fa212017-09-14 17:23:56 -0400125 ENSURE_PRIVATE_KEY_NOT_LOADED(m_impl->key);
Luca Keidel941fd8c2017-07-24 15:21:22 +0200126 opensslInitAlgorithms();
Yingdi Yu202a2e92015-07-12 16:49:25 -0700127
Davide Pesaventof45fa212017-09-14 17:23:56 -0400128 detail::Bio membio(BIO_s_mem());
129 if (!membio.write(buf, size))
130 BOOST_THROW_EXCEPTION(Error("Failed to copy buffer"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700131
Davide Pesaventof45fa212017-09-14 17:23:56 -0400132 if (d2i_PKCS8PrivateKey_bio(membio, &m_impl->key, nullptr, const_cast<char*>(pw)) == nullptr)
133 BOOST_THROW_EXCEPTION(Error("Failed to load private key"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700134}
135
136static inline int
Davide Pesaventof45fa212017-09-14 17:23:56 -0400137passwordCallbackWrapper(char* buf, int size, int rwflag, void* u)
Yingdi Yu202a2e92015-07-12 16:49:25 -0700138{
Luca Keidel941fd8c2017-07-24 15:21:22 +0200139 BOOST_ASSERT(size >= 0);
Yingdi Yu202a2e92015-07-12 16:49:25 -0700140 auto cb = reinterpret_cast<PrivateKey::PasswordCallback*>(u);
Luca Keidel941fd8c2017-07-24 15:21:22 +0200141 return (*cb)(buf, static_cast<size_t>(size), rwflag);
Yingdi Yu202a2e92015-07-12 16:49:25 -0700142}
143
144void
145PrivateKey::loadPkcs8(const uint8_t* buf, size_t size, PasswordCallback pwCallback)
146{
Davide Pesaventof45fa212017-09-14 17:23:56 -0400147 ENSURE_PRIVATE_KEY_NOT_LOADED(m_impl->key);
Luca Keidel941fd8c2017-07-24 15:21:22 +0200148 opensslInitAlgorithms();
149
Davide Pesaventof45fa212017-09-14 17:23:56 -0400150 detail::Bio membio(BIO_s_mem());
151 if (!membio.write(buf, size))
152 BOOST_THROW_EXCEPTION(Error("Failed to copy buffer"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700153
154 if (pwCallback)
Davide Pesaventof45fa212017-09-14 17:23:56 -0400155 m_impl->key = d2i_PKCS8PrivateKey_bio(membio, nullptr, &passwordCallbackWrapper, &pwCallback);
Yingdi Yu202a2e92015-07-12 16:49:25 -0700156 else
Davide Pesaventof45fa212017-09-14 17:23:56 -0400157 m_impl->key = d2i_PKCS8PrivateKey_bio(membio, nullptr, nullptr, nullptr);
Yingdi Yu202a2e92015-07-12 16:49:25 -0700158
Davide Pesaventof45fa212017-09-14 17:23:56 -0400159 if (m_impl->key == nullptr)
160 BOOST_THROW_EXCEPTION(Error("Failed to load private key"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700161}
162
163void
164PrivateKey::loadPkcs8(std::istream& is, const char* pw, size_t pwLen)
165{
166 OBufferStream os;
167 streamSource(is) >> streamSink(os);
168 this->loadPkcs8(os.buf()->buf(), os.buf()->size(), pw, pwLen);
169}
170
171void
172PrivateKey::loadPkcs8(std::istream& is, PasswordCallback pwCallback)
173{
174 OBufferStream os;
175 streamSource(is) >> streamSink(os);
176 this->loadPkcs8(os.buf()->buf(), os.buf()->size(), pwCallback);
177}
178
179void
180PrivateKey::loadPkcs8Base64(const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
181{
182 OBufferStream os;
183 bufferSource(buf, size) >> base64Decode() >> streamSink(os);
184 this->loadPkcs8(os.buf()->buf(), os.buf()->size(), pw, pwLen);
185}
186
187void
188PrivateKey::loadPkcs8Base64(const uint8_t* buf, size_t size, PasswordCallback pwCallback)
189{
190 OBufferStream os;
191 bufferSource(buf, size) >> base64Decode() >> streamSink(os);
192 this->loadPkcs8(os.buf()->buf(), os.buf()->size(), pwCallback);
193}
194
195void
196PrivateKey::loadPkcs8Base64(std::istream& is, const char* pw, size_t pwLen)
197{
198 OBufferStream os;
199 streamSource(is) >> base64Decode() >> streamSink(os);
200 this->loadPkcs8(os.buf()->buf(), os.buf()->size(), pw, pwLen);
201}
202
203void
204PrivateKey::loadPkcs8Base64(std::istream& is, PasswordCallback pwCallback)
205{
206 OBufferStream os;
207 streamSource(is) >> base64Decode() >> streamSink(os);
208 this->loadPkcs8(os.buf()->buf(), os.buf()->size(), pwCallback);
209}
210
211void
212PrivateKey::savePkcs1(std::ostream& os) const
213{
214 bufferSource(*this->toPkcs1()) >> streamSink(os);
215}
216
217void
218PrivateKey::savePkcs1Base64(std::ostream& os) const
219{
220 bufferSource(*this->toPkcs1()) >> base64Encode() >> streamSink(os);
221}
222
223void
224PrivateKey::savePkcs8(std::ostream& os, const char* pw, size_t pwLen) const
225{
226 bufferSource(*this->toPkcs8(pw, pwLen)) >> streamSink(os);
227}
228
229void
230PrivateKey::savePkcs8(std::ostream& os, PasswordCallback pwCallback) const
231{
232 bufferSource(*this->toPkcs8(pwCallback)) >> streamSink(os);
233}
234
235void
236PrivateKey::savePkcs8Base64(std::ostream& os, const char* pw, size_t pwLen) const
237{
238 bufferSource(*this->toPkcs8(pw, pwLen)) >> base64Encode() >> streamSink(os);
239}
240
241void
242PrivateKey::savePkcs8Base64(std::ostream& os, PasswordCallback pwCallback) const
243{
244 bufferSource(*this->toPkcs8(pwCallback)) >> base64Encode() >> streamSink(os);
245}
246
247ConstBufferPtr
248PrivateKey::derivePublicKey() const
249{
250 ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
251
252 uint8_t* pkcs8 = nullptr;
253 int len = i2d_PUBKEY(m_impl->key, &pkcs8);
Davide Pesaventof45fa212017-09-14 17:23:56 -0400254 if (len < 0)
Yingdi Yu202a2e92015-07-12 16:49:25 -0700255 BOOST_THROW_EXCEPTION(Error("Failed to derive public key"));
256
257 auto result = make_shared<Buffer>(pkcs8, len);
258 OPENSSL_free(pkcs8);
259
260 return result;
261}
262
263ConstBufferPtr
264PrivateKey::decrypt(const uint8_t* cipherText, size_t cipherLen) const
265{
266 ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
267
Davide Pesaventof45fa212017-09-14 17:23:56 -0400268 int keyType =
Alexander Afanasyev02948ec2016-09-12 18:04:50 -0700269#if OPENSSL_VERSION_NUMBER < 0x1010000fL
Davide Pesaventof45fa212017-09-14 17:23:56 -0400270 EVP_PKEY_type(m_impl->key->type);
Alexander Afanasyev02948ec2016-09-12 18:04:50 -0700271#else
Davide Pesaventof45fa212017-09-14 17:23:56 -0400272 EVP_PKEY_base_id(m_impl->key);
Alexander Afanasyev02948ec2016-09-12 18:04:50 -0700273#endif // OPENSSL_VERSION_NUMBER < 0x1010000fL
Davide Pesaventof45fa212017-09-14 17:23:56 -0400274
275 switch (keyType) {
276 case EVP_PKEY_NONE:
277 BOOST_THROW_EXCEPTION(Error("Failed to determine key type"));
Luca Keidel941fd8c2017-07-24 15:21:22 +0200278 case EVP_PKEY_RSA:
279 return rsaDecrypt(cipherText, cipherLen);
280 default:
Davide Pesaventof45fa212017-09-14 17:23:56 -0400281 BOOST_THROW_EXCEPTION(Error("Decryption is not supported for key type " + to_string(keyType)));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700282 }
283}
284
285void*
286PrivateKey::getEvpPkey() const
287{
288 return m_impl->key;
289}
290
291ConstBufferPtr
292PrivateKey::toPkcs1() const
293{
294 ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
Luca Keidel941fd8c2017-07-24 15:21:22 +0200295 opensslInitAlgorithms();
Yingdi Yu202a2e92015-07-12 16:49:25 -0700296
Davide Pesaventof45fa212017-09-14 17:23:56 -0400297 detail::Bio membio(BIO_s_mem());
298 if (!i2d_PrivateKey_bio(membio, m_impl->key))
299 BOOST_THROW_EXCEPTION(Error("Cannot convert key to PKCS #1 format"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700300
Davide Pesaventof45fa212017-09-14 17:23:56 -0400301 auto buffer = make_shared<Buffer>(BIO_pending(membio));
302 membio.read(buffer->buf(), buffer->size());
Yingdi Yu202a2e92015-07-12 16:49:25 -0700303
304 return buffer;
305}
306
307ConstBufferPtr
308PrivateKey::toPkcs8(const char* pw, size_t pwLen) const
309{
Yingdi Yu202a2e92015-07-12 16:49:25 -0700310 BOOST_ASSERT(std::strlen(pw) == pwLen);
Luca Keidel941fd8c2017-07-24 15:21:22 +0200311 ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
312 opensslInitAlgorithms();
Yingdi Yu202a2e92015-07-12 16:49:25 -0700313
Davide Pesaventof45fa212017-09-14 17:23:56 -0400314 detail::Bio membio(BIO_s_mem());
Davide Pesaventocafa4022017-09-15 23:20:20 -0400315 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_des_ede3_cbc(), nullptr, 0,
Davide Pesaventof45fa212017-09-14 17:23:56 -0400316 nullptr, const_cast<char*>(pw)))
317 BOOST_THROW_EXCEPTION(Error("Cannot convert key to PKCS #8 format"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700318
Davide Pesaventof45fa212017-09-14 17:23:56 -0400319 auto buffer = make_shared<Buffer>(BIO_pending(membio));
320 membio.read(buffer->buf(), buffer->size());
Yingdi Yu202a2e92015-07-12 16:49:25 -0700321
322 return buffer;
323}
324
325ConstBufferPtr
326PrivateKey::toPkcs8(PasswordCallback pwCallback) const
327{
328 ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
Luca Keidel941fd8c2017-07-24 15:21:22 +0200329 opensslInitAlgorithms();
Yingdi Yu202a2e92015-07-12 16:49:25 -0700330
Davide Pesaventof45fa212017-09-14 17:23:56 -0400331 detail::Bio membio(BIO_s_mem());
Davide Pesaventocafa4022017-09-15 23:20:20 -0400332 if (!i2d_PKCS8PrivateKey_bio(membio, m_impl->key, EVP_des_ede3_cbc(), nullptr, 0,
Davide Pesaventof45fa212017-09-14 17:23:56 -0400333 &passwordCallbackWrapper, &pwCallback))
334 BOOST_THROW_EXCEPTION(Error("Cannot convert key to PKCS #8 format"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700335
Davide Pesaventof45fa212017-09-14 17:23:56 -0400336 auto buffer = make_shared<Buffer>(BIO_pending(membio));
337 membio.read(buffer->buf(), buffer->size());
Yingdi Yu202a2e92015-07-12 16:49:25 -0700338
339 return buffer;
340}
341
342ConstBufferPtr
343PrivateKey::rsaDecrypt(const uint8_t* cipherText, size_t cipherLen) const
344{
345 detail::EvpPkeyCtx ctx(m_impl->key);
346
Davide Pesaventof45fa212017-09-14 17:23:56 -0400347 if (EVP_PKEY_decrypt_init(ctx) <= 0)
Yingdi Yu202a2e92015-07-12 16:49:25 -0700348 BOOST_THROW_EXCEPTION(Error("Failed to initialize decryption context"));
349
Davide Pesaventof45fa212017-09-14 17:23:56 -0400350 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
Yingdi Yu202a2e92015-07-12 16:49:25 -0700351 BOOST_THROW_EXCEPTION(Error("Failed to set padding"));
352
353 size_t outlen = 0;
354 // Determine buffer length
Davide Pesaventof45fa212017-09-14 17:23:56 -0400355 if (EVP_PKEY_decrypt(ctx, nullptr, &outlen, cipherText, cipherLen) <= 0)
Yingdi Yu202a2e92015-07-12 16:49:25 -0700356 BOOST_THROW_EXCEPTION(Error("Failed to estimate output length"));
357
358 auto out = make_shared<Buffer>(outlen);
Davide Pesaventof45fa212017-09-14 17:23:56 -0400359 if (EVP_PKEY_decrypt(ctx, out->buf(), &outlen, cipherText, cipherLen) <= 0)
360 BOOST_THROW_EXCEPTION(Error("Failed to decrypt ciphertext"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700361
362 out->resize(outlen);
363 return out;
364}
365
Davide Pesaventof45fa212017-09-14 17:23:56 -0400366unique_ptr<PrivateKey>
367PrivateKey::generateRsaKey(uint32_t keySize)
Yingdi Yu202a2e92015-07-12 16:49:25 -0700368{
369 detail::EvpPkeyCtx kctx(EVP_PKEY_RSA);
370
Davide Pesaventof45fa212017-09-14 17:23:56 -0400371 if (EVP_PKEY_keygen_init(kctx) <= 0)
372 BOOST_THROW_EXCEPTION(PrivateKey::Error("Failed to initialize RSA keygen context"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700373
Davide Pesaventof45fa212017-09-14 17:23:56 -0400374 if (EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, static_cast<int>(keySize)) <= 0)
375 BOOST_THROW_EXCEPTION(PrivateKey::Error("Failed to set RSA key length"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700376
377 auto privateKey = make_unique<PrivateKey>();
Davide Pesaventof45fa212017-09-14 17:23:56 -0400378 if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
379 BOOST_THROW_EXCEPTION(PrivateKey::Error("Failed to generate RSA key"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700380
381 return privateKey;
382}
383
Davide Pesaventof45fa212017-09-14 17:23:56 -0400384unique_ptr<PrivateKey>
385PrivateKey::generateEcKey(uint32_t keySize)
Yingdi Yu202a2e92015-07-12 16:49:25 -0700386{
Davide Pesaventof45fa212017-09-14 17:23:56 -0400387 detail::EvpPkeyCtx pctx(EVP_PKEY_EC);
Yingdi Yu202a2e92015-07-12 16:49:25 -0700388
Davide Pesaventof45fa212017-09-14 17:23:56 -0400389 if (EVP_PKEY_paramgen_init(pctx) <= 0)
390 BOOST_THROW_EXCEPTION(PrivateKey::Error("Failed to initialize EC paramgen context"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700391
Davide Pesaventof45fa212017-09-14 17:23:56 -0400392 int ret;
Yingdi Yu202a2e92015-07-12 16:49:25 -0700393 switch (keySize) {
394 case 256:
Davide Pesaventof45fa212017-09-14 17:23:56 -0400395 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1); // same as secp256r1
Yingdi Yu202a2e92015-07-12 16:49:25 -0700396 break;
397 case 384:
Davide Pesaventof45fa212017-09-14 17:23:56 -0400398 ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_secp384r1);
Yingdi Yu202a2e92015-07-12 16:49:25 -0700399 break;
400 default:
Davide Pesaventof45fa212017-09-14 17:23:56 -0400401 BOOST_THROW_EXCEPTION(PrivateKey::Error("Unsupported EC key length"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700402 }
Davide Pesaventof45fa212017-09-14 17:23:56 -0400403 if (ret <= 0)
404 BOOST_THROW_EXCEPTION(PrivateKey::Error("Failed to set EC curve"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700405
Davide Pesaventof45fa212017-09-14 17:23:56 -0400406 Impl params;
407 if (EVP_PKEY_paramgen(pctx, &params.key) <= 0)
408 BOOST_THROW_EXCEPTION(PrivateKey::Error("Failed to generate EC parameters"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700409
Davide Pesaventof45fa212017-09-14 17:23:56 -0400410 detail::EvpPkeyCtx kctx(params.key);
411 if (EVP_PKEY_keygen_init(kctx) <= 0)
412 BOOST_THROW_EXCEPTION(PrivateKey::Error("Failed to initialize EC keygen context"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700413
414 auto privateKey = make_unique<PrivateKey>();
Davide Pesaventof45fa212017-09-14 17:23:56 -0400415 if (EVP_PKEY_keygen(kctx, &privateKey->m_impl->key) <= 0)
416 BOOST_THROW_EXCEPTION(PrivateKey::Error("Failed to generate EC key"));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700417
418 return privateKey;
419}
420
421unique_ptr<PrivateKey>
422generatePrivateKey(const KeyParams& keyParams)
423{
424 switch (keyParams.getKeyType()) {
425 case KeyType::RSA: {
426 const RsaKeyParams& rsaParams = static_cast<const RsaKeyParams&>(keyParams);
Davide Pesaventof45fa212017-09-14 17:23:56 -0400427 return PrivateKey::generateRsaKey(rsaParams.getKeySize());
Yingdi Yu202a2e92015-07-12 16:49:25 -0700428 }
429 case KeyType::EC: {
Spyridon Mastorakis1ece2e32015-08-27 18:52:21 -0700430 const EcKeyParams& ecParams = static_cast<const EcKeyParams&>(keyParams);
Davide Pesaventof45fa212017-09-14 17:23:56 -0400431 return PrivateKey::generateEcKey(ecParams.getKeySize());
Yingdi Yu202a2e92015-07-12 16:49:25 -0700432 }
433 default:
Davide Pesaventof45fa212017-09-14 17:23:56 -0400434 BOOST_THROW_EXCEPTION(std::invalid_argument("Unsupported asymmetric key type " +
435 boost::lexical_cast<std::string>(keyParams.getKeyType())));
Yingdi Yu202a2e92015-07-12 16:49:25 -0700436 }
437}
438
439} // namespace transform
440} // namespace security
441} // namespace ndn