blob: 98f5bd649e7a1bd24e1aeed5b121edf21bb963cd [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/*
Davide Pesavento794f6872017-05-15 23:33:38 -04003 * 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#ifndef NDN_CXX_SECURITY_TRANSFORM_PRIVATE_KEY_HPP
23#define NDN_CXX_SECURITY_TRANSFORM_PRIVATE_KEY_HPP
24
Yingdi Yu202a2e92015-07-12 16:49:25 -070025#include "../../encoding/buffer.hpp"
26
27namespace ndn {
28
29class KeyParams;
30
31namespace security {
32namespace transform {
33
34/**
35 * @brief Abstraction of private key in crypto transformation
36 */
37class PrivateKey : noncopyable
38{
39public:
40 class Error : public std::runtime_error
41 {
42 public:
43 explicit
44 Error(const std::string& what)
45 : std::runtime_error(what)
46 {
47 }
48 };
49
Yingdi Yu202a2e92015-07-12 16:49:25 -070050 /**
51 * @brief Callback for application to handle password input
52 *
Luca Keidel941fd8c2017-07-24 15:21:22 +020053 * The password must be written to @p buf and must not be longer than @p bufSize chars.
54 * It is recommended to ask the user to verify the password if @p shouldConfirm is true,
55 * e.g., by prompting for it twice. The callback must return the number of characters
56 * in the password or 0 if an error occurred.
Yingdi Yu202a2e92015-07-12 16:49:25 -070057 */
58 typedef function<int(char* buf, size_t bufSize, bool shouldConfirm)> PasswordCallback;
59
60public:
61 /**
Davide Pesaventof45fa212017-09-14 17:23:56 -040062 * @brief Create an empty private key instance
Yingdi Yu202a2e92015-07-12 16:49:25 -070063 *
Davide Pesaventof45fa212017-09-14 17:23:56 -040064 * One must call loadXXXX(...) to load a private key.
Yingdi Yu202a2e92015-07-12 16:49:25 -070065 */
66 PrivateKey();
67
68 ~PrivateKey();
69
70 /**
71 * @brief Load the private key in PKCS#1 format from a buffer @p buf
72 */
73 void
74 loadPkcs1(const uint8_t* buf, size_t size);
75
76 /**
77 * @brief Load the private key in PKCS#1 format from a stream @p is
78 */
79 void
80 loadPkcs1(std::istream& is);
81
82 /**
83 * @brief Load the private key in base64-encoded PKCS#1 format from a buffer @p buf
84 */
85 void
86 loadPkcs1Base64(const uint8_t* buf, size_t size);
87
88 /**
89 * @brief Load the private key in base64-encoded PKCS#1 format from a stream @p is
90 */
91 void
92 loadPkcs1Base64(std::istream& is);
93
94 /**
95 * @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 -070096 * @pre strlen(pw) == pwLen
97 */
98 void
99 loadPkcs8(const uint8_t* buf, size_t size, const char* pw, size_t pwLen);
100
101 /**
102 * @brief Load the private key in encrypted PKCS#8 format from a buffer @p buf with
103 * passphrase obtained from @p pwCallback
104 *
105 * The default password callback is provided by OpenSSL
106 */
107 void
108 loadPkcs8(const uint8_t* buf, size_t size, PasswordCallback pwCallback = nullptr);
109
110 /**
111 * @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 -0700112 * @pre strlen(pw) == pwLen
113 */
114 void
115 loadPkcs8(std::istream& is, const char* pw, size_t pwLen);
116
117 /**
118 * @brief Load the private key in encrypted PKCS#8 format from a stream @p is with passphrase
119 * obtained from @p pwCallback
120 *
121 * The default password callback is provided by OpenSSL
122 */
123 void
124 loadPkcs8(std::istream& is, PasswordCallback pwCallback = nullptr);
125
126 /**
127 * @brief Load the private key in base64-encoded encrypted PKCS#8 format from a buffer @p buf
128 * with passphrase @p pw
Yingdi Yu202a2e92015-07-12 16:49:25 -0700129 * @pre strlen(pw) == pwLen
130 */
131 void
132 loadPkcs8Base64(const uint8_t* buf, size_t size, const char* pw, size_t pwLen);
133
134 /**
135 * @brief Load the private key in encrypted PKCS#8 format from a buffer @p buf with
136 * passphrase obtained from @p pwCallback
137 *
138 * The default password callback is provided by OpenSSL
139 */
140 void
141 loadPkcs8Base64(const uint8_t* buf, size_t size, PasswordCallback pwCallback = nullptr);
142
143 /**
144 * @brief Load the private key in base64-encoded encrypted PKCS#8 format from a stream @p is
145 * with passphrase @p pw
Yingdi Yu202a2e92015-07-12 16:49:25 -0700146 * @pre strlen(pw) == pwLen
147 */
148 void
149 loadPkcs8Base64(std::istream& is, const char* pw, size_t pwLen);
150
151 /**
152 * @brief Load the private key in base64-encoded encrypted PKCS#8 format from a stream @p is
153 * with passphrase obtained from @p pwCallback
154 *
155 * The default password callback is provided by OpenSSL
156 */
157 void
158 loadPkcs8Base64(std::istream& is, PasswordCallback pwCallback = nullptr);
159
160 /**
161 * @brief Save the private key in PKCS#1 format into a stream @p os
162 */
163 void
164 savePkcs1(std::ostream& os) const;
165
166 /**
167 * @brief Save the private key in base64-encoded PKCS#1 format into a stream @p os
168 */
169 void
170 savePkcs1Base64(std::ostream& os) const;
171
172 /**
173 * @brief Save the private key in encrypted PKCS#8 format into a stream @p os
174 */
175 void
176 savePkcs8(std::ostream& os, const char* pw, size_t pwLen) const;
177
178 /**
179 * @brief Save the private key in encrypted PKCS#8 format into a stream @p os with passphrase
180 * obtained from @p pwCallback
181 *
182 * The default password callback is provided by OpenSSL
183 */
184 void
185 savePkcs8(std::ostream& os, PasswordCallback pwCallback = nullptr) const;
186
187 /**
188 * @brief Save the private key in base64-encoded encrypted PKCS#8 format into a stream @p os
189 */
190 void
191 savePkcs8Base64(std::ostream& os, const char* pw, size_t pwLen) const;
192
193 /**
194 * @brief Save the private key in base64-encoded encrypted PKCS#8 format into a stream @p os
195 * with passphrase obtained from @p pwCallback
196 *
197 * The default password callback is provided by OpenSSL
198 */
199 void
200 savePkcs8Base64(std::ostream& os, PasswordCallback pwCallback = nullptr) const;
201
202 /**
203 * @return Public key bits in PKCS#8 format
204 */
205 ConstBufferPtr
206 derivePublicKey() const;
207
208 /**
Davide Pesaventof45fa212017-09-14 17:23:56 -0400209 * @return Plain text of @p cipherText decrypted using this private key.
Yingdi Yu202a2e92015-07-12 16:49:25 -0700210 *
211 * Only RSA encryption is supported for now.
212 */
213 ConstBufferPtr
214 decrypt(const uint8_t* cipherText, size_t cipherLen) const;
215
216private:
Davide Pesaventof45fa212017-09-14 17:23:56 -0400217 friend class SignerFilter;
218
Yingdi Yu202a2e92015-07-12 16:49:25 -0700219 /**
Davide Pesaventof45fa212017-09-14 17:23:56 -0400220 * @return A pointer to an OpenSSL EVP_PKEY instance.
Yingdi Yu202a2e92015-07-12 16:49:25 -0700221 *
Davide Pesaventof45fa212017-09-14 17:23:56 -0400222 * The caller needs to explicitly cast the return value to `EVP_PKEY*`.
Yingdi Yu202a2e92015-07-12 16:49:25 -0700223 */
224 void*
225 getEvpPkey() const;
226
227private:
228 ConstBufferPtr
229 toPkcs1() const;
230
231 ConstBufferPtr
232 toPkcs8(const char* pw, size_t pwLen) const;
233
234 ConstBufferPtr
235 toPkcs8(PasswordCallback pwCallback = nullptr) const;
236
237 ConstBufferPtr
238 rsaDecrypt(const uint8_t* cipherText, size_t cipherLen) const;
239
240private:
Davide Pesaventof45fa212017-09-14 17:23:56 -0400241 friend unique_ptr<PrivateKey> generatePrivateKey(const KeyParams&);
242
243 static unique_ptr<PrivateKey>
244 generateRsaKey(uint32_t keySize);
245
246 static unique_ptr<PrivateKey>
247 generateEcKey(uint32_t keySize);
248
249private:
Yingdi Yu202a2e92015-07-12 16:49:25 -0700250 class Impl;
Davide Pesavento794f6872017-05-15 23:33:38 -0400251 const unique_ptr<Impl> m_impl;
Yingdi Yu202a2e92015-07-12 16:49:25 -0700252};
253
254/**
Davide Pesaventof45fa212017-09-14 17:23:56 -0400255 * @brief Generate a private key according to @p keyParams
Yingdi Yu202a2e92015-07-12 16:49:25 -0700256 *
Davide Pesaventof45fa212017-09-14 17:23:56 -0400257 * @note The public key can be derived from the private key.
Yingdi Yu202a2e92015-07-12 16:49:25 -0700258 *
Davide Pesaventof45fa212017-09-14 17:23:56 -0400259 * @throw std::invalid_argument the specified key type is not supported
260 * @throw std::runtime_error key generation fails
Yingdi Yu202a2e92015-07-12 16:49:25 -0700261 */
262unique_ptr<PrivateKey>
263generatePrivateKey(const KeyParams& keyParams);
264
265} // namespace transform
266} // namespace security
267} // namespace ndn
268
269#endif // NDN_CXX_SECURITY_TRANSFORM_PRIVATE_KEY_HPP