blob: e1af107530054a3a06c25d57121c7e7bf9fce6e1 [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/*
Junxiao Shi68b53852018-07-25 13:56:38 -06003 * Copyright (c) 2013-2018 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#ifndef NDN_CXX_SECURITY_TRANSFORM_PRIVATE_KEY_HPP
23#define NDN_CXX_SECURITY_TRANSFORM_PRIVATE_KEY_HPP
24
Davide Pesavento06f1bdf2017-09-16 18:59:15 -040025#include "../security-common.hpp"
Yingdi Yu202a2e92015-07-12 16:49:25 -070026#include "../../encoding/buffer.hpp"
27
28namespace ndn {
29
30class KeyParams;
31
32namespace security {
33namespace transform {
34
35/**
36 * @brief Abstraction of private key in crypto transformation
37 */
38class PrivateKey : noncopyable
39{
40public:
41 class Error : public std::runtime_error
42 {
43 public:
Junxiao Shi68b53852018-07-25 13:56:38 -060044 using std::runtime_error::runtime_error;
Yingdi Yu202a2e92015-07-12 16:49:25 -070045 };
46
Yingdi Yu202a2e92015-07-12 16:49:25 -070047 /**
48 * @brief Callback for application to handle password input
49 *
Luca Keidel941fd8c2017-07-24 15:21:22 +020050 * The password must be written to @p buf and must not be longer than @p bufSize chars.
51 * It is recommended to ask the user to verify the password if @p shouldConfirm is true,
52 * e.g., by prompting for it twice. The callback must return the number of characters
53 * in the password or 0 if an error occurred.
Yingdi Yu202a2e92015-07-12 16:49:25 -070054 */
55 typedef function<int(char* buf, size_t bufSize, bool shouldConfirm)> PasswordCallback;
56
57public:
58 /**
Davide Pesaventof45fa212017-09-14 17:23:56 -040059 * @brief Create an empty private key instance
Yingdi Yu202a2e92015-07-12 16:49:25 -070060 *
Davide Pesaventof45fa212017-09-14 17:23:56 -040061 * One must call loadXXXX(...) to load a private key.
Yingdi Yu202a2e92015-07-12 16:49:25 -070062 */
63 PrivateKey();
64
65 ~PrivateKey();
66
67 /**
Davide Pesavento06f1bdf2017-09-16 18:59:15 -040068 * @brief Get the type of the private key
69 */
70 KeyType
71 getKeyType() const;
72
73 /**
Yingdi Yu202a2e92015-07-12 16:49:25 -070074 * @brief Load the private key in PKCS#1 format from a buffer @p buf
75 */
76 void
77 loadPkcs1(const uint8_t* buf, size_t size);
78
79 /**
80 * @brief Load the private key in PKCS#1 format from a stream @p is
81 */
82 void
83 loadPkcs1(std::istream& is);
84
85 /**
86 * @brief Load the private key in base64-encoded PKCS#1 format from a buffer @p buf
87 */
88 void
89 loadPkcs1Base64(const uint8_t* buf, size_t size);
90
91 /**
92 * @brief Load the private key in base64-encoded PKCS#1 format from a stream @p is
93 */
94 void
95 loadPkcs1Base64(std::istream& is);
96
97 /**
98 * @brief Load the private key in encrypted PKCS#8 format from a buffer @p buf with passphrase @p pw
Yingdi Yu202a2e92015-07-12 16:49:25 -070099 * @pre strlen(pw) == pwLen
100 */
101 void
102 loadPkcs8(const uint8_t* buf, size_t size, const char* pw, size_t pwLen);
103
104 /**
105 * @brief Load the private key in encrypted PKCS#8 format from a buffer @p buf with
106 * passphrase obtained from @p pwCallback
107 *
108 * The default password callback is provided by OpenSSL
109 */
110 void
111 loadPkcs8(const uint8_t* buf, size_t size, PasswordCallback pwCallback = nullptr);
112
113 /**
114 * @brief Load the private key in encrypted PKCS#8 format from a stream @p is with passphrase @p pw
Yingdi Yu202a2e92015-07-12 16:49:25 -0700115 * @pre strlen(pw) == pwLen
116 */
117 void
118 loadPkcs8(std::istream& is, const char* pw, size_t pwLen);
119
120 /**
121 * @brief Load the private key in encrypted PKCS#8 format from a stream @p is with passphrase
122 * obtained from @p pwCallback
123 *
124 * The default password callback is provided by OpenSSL
125 */
126 void
127 loadPkcs8(std::istream& is, PasswordCallback pwCallback = nullptr);
128
129 /**
130 * @brief Load the private key in base64-encoded encrypted PKCS#8 format from a buffer @p buf
131 * with passphrase @p pw
Yingdi Yu202a2e92015-07-12 16:49:25 -0700132 * @pre strlen(pw) == pwLen
133 */
134 void
135 loadPkcs8Base64(const uint8_t* buf, size_t size, const char* pw, size_t pwLen);
136
137 /**
138 * @brief Load the private key in encrypted PKCS#8 format from a buffer @p buf with
139 * passphrase obtained from @p pwCallback
140 *
141 * The default password callback is provided by OpenSSL
142 */
143 void
144 loadPkcs8Base64(const uint8_t* buf, size_t size, PasswordCallback pwCallback = nullptr);
145
146 /**
147 * @brief Load the private key in base64-encoded encrypted PKCS#8 format from a stream @p is
148 * with passphrase @p pw
Yingdi Yu202a2e92015-07-12 16:49:25 -0700149 * @pre strlen(pw) == pwLen
150 */
151 void
152 loadPkcs8Base64(std::istream& is, const char* pw, size_t pwLen);
153
154 /**
155 * @brief Load the private key in base64-encoded encrypted PKCS#8 format from a stream @p is
156 * with passphrase obtained from @p pwCallback
157 *
158 * The default password callback is provided by OpenSSL
159 */
160 void
161 loadPkcs8Base64(std::istream& is, PasswordCallback pwCallback = nullptr);
162
163 /**
164 * @brief Save the private key in PKCS#1 format into a stream @p os
165 */
166 void
167 savePkcs1(std::ostream& os) const;
168
169 /**
170 * @brief Save the private key in base64-encoded PKCS#1 format into a stream @p os
171 */
172 void
173 savePkcs1Base64(std::ostream& os) const;
174
175 /**
176 * @brief Save the private key in encrypted PKCS#8 format into a stream @p os
177 */
178 void
179 savePkcs8(std::ostream& os, const char* pw, size_t pwLen) const;
180
181 /**
182 * @brief Save the private key in encrypted PKCS#8 format into a stream @p os with passphrase
183 * obtained from @p pwCallback
184 *
185 * The default password callback is provided by OpenSSL
186 */
187 void
188 savePkcs8(std::ostream& os, PasswordCallback pwCallback = nullptr) const;
189
190 /**
191 * @brief Save the private key in base64-encoded encrypted PKCS#8 format into a stream @p os
192 */
193 void
194 savePkcs8Base64(std::ostream& os, const char* pw, size_t pwLen) const;
195
196 /**
197 * @brief Save the private key in base64-encoded encrypted PKCS#8 format into a stream @p os
198 * with passphrase obtained from @p pwCallback
199 *
200 * The default password callback is provided by OpenSSL
201 */
202 void
203 savePkcs8Base64(std::ostream& os, PasswordCallback pwCallback = nullptr) const;
204
205 /**
206 * @return Public key bits in PKCS#8 format
207 */
208 ConstBufferPtr
209 derivePublicKey() const;
210
211 /**
Davide Pesaventof45fa212017-09-14 17:23:56 -0400212 * @return Plain text of @p cipherText decrypted using this private key.
Yingdi Yu202a2e92015-07-12 16:49:25 -0700213 *
214 * Only RSA encryption is supported for now.
215 */
216 ConstBufferPtr
217 decrypt(const uint8_t* cipherText, size_t cipherLen) const;
218
219private:
Davide Pesaventof45fa212017-09-14 17:23:56 -0400220 friend class SignerFilter;
221
Yingdi Yu202a2e92015-07-12 16:49:25 -0700222 /**
Davide Pesaventof45fa212017-09-14 17:23:56 -0400223 * @return A pointer to an OpenSSL EVP_PKEY instance.
Yingdi Yu202a2e92015-07-12 16:49:25 -0700224 *
Davide Pesaventof45fa212017-09-14 17:23:56 -0400225 * The caller needs to explicitly cast the return value to `EVP_PKEY*`.
Yingdi Yu202a2e92015-07-12 16:49:25 -0700226 */
227 void*
228 getEvpPkey() const;
229
230private:
231 ConstBufferPtr
232 toPkcs1() const;
233
234 ConstBufferPtr
235 toPkcs8(const char* pw, size_t pwLen) const;
236
237 ConstBufferPtr
238 toPkcs8(PasswordCallback pwCallback = nullptr) const;
239
240 ConstBufferPtr
241 rsaDecrypt(const uint8_t* cipherText, size_t cipherLen) const;
242
243private:
Davide Pesaventof45fa212017-09-14 17:23:56 -0400244 friend unique_ptr<PrivateKey> generatePrivateKey(const KeyParams&);
245
246 static unique_ptr<PrivateKey>
247 generateRsaKey(uint32_t keySize);
248
249 static unique_ptr<PrivateKey>
250 generateEcKey(uint32_t keySize);
251
252private:
Yingdi Yu202a2e92015-07-12 16:49:25 -0700253 class Impl;
Davide Pesavento794f6872017-05-15 23:33:38 -0400254 const unique_ptr<Impl> m_impl;
Yingdi Yu202a2e92015-07-12 16:49:25 -0700255};
256
257/**
Davide Pesaventof45fa212017-09-14 17:23:56 -0400258 * @brief Generate a private key according to @p keyParams
Yingdi Yu202a2e92015-07-12 16:49:25 -0700259 *
Davide Pesavento3c7969f2018-09-08 15:31:35 -0400260 * @note The corresponding public key can be derived from the private key.
Yingdi Yu202a2e92015-07-12 16:49:25 -0700261 *
Davide Pesaventof45fa212017-09-14 17:23:56 -0400262 * @throw std::invalid_argument the specified key type is not supported
Davide Pesavento3c7969f2018-09-08 15:31:35 -0400263 * @throw PrivateKey::Error key generation failed
Yingdi Yu202a2e92015-07-12 16:49:25 -0700264 */
265unique_ptr<PrivateKey>
266generatePrivateKey(const KeyParams& keyParams);
267
268} // namespace transform
269} // namespace security
270} // namespace ndn
271
272#endif // NDN_CXX_SECURITY_TRANSFORM_PRIVATE_KEY_HPP