Async 1.8.0
AsyncSslKeypair.h
Go to the documentation of this file.
1
31#ifndef ASYNC_SSL_KEYPAIR_INCLUDED
32#define ASYNC_SSL_KEYPAIR_INCLUDED
33
34
35/****************************************************************************
36 *
37 * System Includes
38 *
39 ****************************************************************************/
40
41#include <stdio.h>
42#include <sys/stat.h>
43#include <openssl/evp.h>
44#include <openssl/rsa.h>
45#include <openssl/bn.h>
46#include <openssl/pem.h>
47
48#include <cassert>
49#include <string>
50
51
52/****************************************************************************
53 *
54 * Project Includes
55 *
56 ****************************************************************************/
57
58
59
60/****************************************************************************
61 *
62 * Local Includes
63 *
64 ****************************************************************************/
65
66
67
68/****************************************************************************
69 *
70 * Forward declarations
71 *
72 ****************************************************************************/
73
74
75
76/****************************************************************************
77 *
78 * Namespace
79 *
80 ****************************************************************************/
81
82namespace Async
83{
84
85
86/****************************************************************************
87 *
88 * Forward declarations of classes inside of the declared namespace
89 *
90 ****************************************************************************/
91
92
93
94/****************************************************************************
95 *
96 * Defines & typedefs
97 *
98 ****************************************************************************/
99
100
101
102/****************************************************************************
103 *
104 * Exported Global Variables
105 *
106 ****************************************************************************/
107
108
109
110/****************************************************************************
111 *
112 * Class definitions
113 *
114 ****************************************************************************/
115
124{
125 public:
129 SslKeypair(void) {}
130
135 explicit SslKeypair(EVP_PKEY* pkey)
136 {
137 m_pkey = pkey;
138 }
139
145 {
146 m_pkey = other.m_pkey;
147 other.m_pkey = nullptr;
148 }
149
155 {
156 EVP_PKEY_up_ref(other.m_pkey);
157 m_pkey = other.m_pkey;
158 }
159
166 {
167 EVP_PKEY_up_ref(other.m_pkey);
168 m_pkey = other.m_pkey;
169 return *this;
170 }
171
176 {
177 EVP_PKEY_free(m_pkey);
178 m_pkey = nullptr;
179 }
180
185 bool isNull(void) const { return (m_pkey == nullptr); }
186
192 bool generate(unsigned int bits)
193 {
194 EVP_PKEY_free(m_pkey);
195#if OPENSSL_VERSION_MAJOR >= 3
196 m_pkey = EVP_RSA_gen(bits);
197 return (m_pkey != nullptr);
198#else
199 m_pkey = EVP_PKEY_new();
200 if (m_pkey == nullptr)
201 {
202 return false;
203 }
204
205 BIGNUM* rsa_f4 = BN_new();
206 if (rsa_f4 == nullptr)
207 {
208 EVP_PKEY_free(m_pkey);
209 m_pkey = nullptr;
210 return false;
211 }
212 BN_set_word(rsa_f4, RSA_F4);
213
214 // FIXME: Accoring to the manual page we need to seed the random number
215 // generator. How?!
216 RSA* rsa = RSA_new();
217 if (rsa == nullptr)
218 {
219 BN_free(rsa_f4);
220 EVP_PKEY_free(m_pkey);
221 m_pkey = nullptr;
222 return false;
223 }
224 int ret = RSA_generate_key_ex(
225 rsa, /* the RSA object to fill in */
226 bits, /* number of bits for the key - 2048 is a sensible value */
227 rsa_f4, /* exponent - RSA_F4 is defined as 0x10001L */
228 NULL /* callback - can be NULL if we aren't displaying progress */
229 );
230 if (ret != 1)
231 {
232 RSA_free(rsa);
233 BN_free(rsa_f4);
234 EVP_PKEY_free(m_pkey);
235 m_pkey = nullptr;
236 return false;
237 }
238 ret = EVP_PKEY_assign_RSA(m_pkey, rsa);
239 if (ret != 1)
240 {
241 RSA_free(rsa);
242 BN_free(rsa_f4);
243 EVP_PKEY_free(m_pkey);
244 m_pkey = nullptr;
245 return false;
246 }
247 BN_free(rsa_f4);
248 return true;
249#endif
250 }
251
263 template <class T>
264 bool newRawPrivateKey(int type, const T& key)
265 {
266 EVP_PKEY_free(m_pkey);
267#if OPENSSL_VERSION_MAJOR >= 3
268 m_pkey = EVP_PKEY_new_raw_private_key(type, nullptr,
269 reinterpret_cast<const unsigned char*>(key.data()), key.size());
270#else
271 m_pkey = EVP_PKEY_new_mac_key(type, nullptr,
272 reinterpret_cast<const unsigned char*>(key.data()), key.size());
273#endif
274 return (m_pkey != nullptr);
275 }
276
281 std::string privateKeyPem(void) const
282 {
283 assert(m_pkey != nullptr);
284 BIO *mem = BIO_new(BIO_s_mem());
285 assert(mem != nullptr);
286 int ret = PEM_write_bio_PrivateKey(
287 mem, /* use the FILE* that was opened */
288 m_pkey, /* EVP_PKEY structure */
289 NULL, /* default cipher for encrypting the key on disk */
290 NULL, /* passphrase required for decrypting the key on disk */
291 0, /* length of the passphrase string */
292 NULL, /* callback for requesting a password */
293 NULL /* data to pass to the callback */
294 );
295 std::string pem;
296 if (ret == 1)
297 {
298 char buf[16384];
299 int len = BIO_read(mem, buf, sizeof(buf));
300 assert(len > 0);
301 pem = std::string(buf, len);
302 }
303 BIO_free(mem);
304 return pem;
305 }
306
312 bool privateKeyFromPem(const std::string& pem)
313 {
314 BIO *mem = BIO_new(BIO_s_mem());
315 BIO_puts(mem, pem.c_str());
316 if (m_pkey != nullptr)
317 {
318 EVP_PKEY_free(m_pkey);
319 }
320 m_pkey = PEM_read_bio_PrivateKey(mem, nullptr, nullptr, nullptr);
321 BIO_free(mem);
322 return (m_pkey != nullptr);
323 }
324
330 bool writePrivateKeyFile(const std::string& filename)
331 {
332 FILE* f = fopen(filename.c_str(), "wb");
333 if (f == nullptr)
334 {
335 return false;
336 }
337 if (fchmod(fileno(f), 0600) != 0)
338 {
339 fclose(f);
340 return false;
341 }
342 int ret = PEM_write_PrivateKey(
343 f, /* use the FILE* that was opened */
344 m_pkey, /* EVP_PKEY structure */
345 NULL, /* default cipher for encrypting the key on disk */
346 NULL, /* passphrase required for decrypting the key on disk */
347 0, /* length of the passphrase string */
348 NULL, /* callback for requesting a password */
349 NULL /* data to pass to the callback */
350 );
351 if (ret != 1)
352 {
353 fclose(f);
354 return false;
355 }
356 if (fclose(f) != 0)
357 {
358 return false;
359 }
360 return true;
361 }
362
368 bool readPrivateKeyFile(const std::string& filename)
369 {
370 FILE* f = fopen(filename.c_str(), "rb");
371 if (f == nullptr)
372 {
373 return false;
374 }
375 EVP_PKEY* pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL);
376 if (pkey == nullptr)
377 {
378 fclose(f);
379 return false;
380 }
381 if (fclose(f) != 0)
382 {
383 return false;
384 }
385 EVP_PKEY_free(m_pkey);
386 m_pkey = pkey;
387 return true;
388 }
389
394 std::string publicKeyPem(void) const
395 {
396 assert(m_pkey != nullptr);
397 BIO *mem = BIO_new(BIO_s_mem());
398 assert(mem != nullptr);
399 int ret = PEM_write_bio_PUBKEY(mem, m_pkey);
400 std::string pem;
401 if (ret == 1)
402 {
403 char buf[16384];
404 int len = BIO_read(mem, buf, sizeof(buf));
405 assert(len > 0);
406 pem = std::string(buf, len);
407 }
408 BIO_free(mem);
409 return pem;
410 }
411
417 bool publicKeyFromPem(const std::string& pem)
418 {
419 if (m_pkey != nullptr)
420 {
421 EVP_PKEY_free(m_pkey);
422 }
423 BIO* mem = BIO_new(BIO_s_mem());
424 assert(mem != nullptr);
425 int rc = BIO_puts(mem, pem.c_str());
426 std::cout << "### rc=" << rc << std::endl;
427 if (rc > 0)
428 {
429 m_pkey = PEM_read_bio_PUBKEY(mem, nullptr, nullptr, nullptr);
430 }
431 BIO_free(mem);
432 return (m_pkey != nullptr);
433 }
434
439 operator EVP_PKEY*(void) { return m_pkey; }
440 operator const EVP_PKEY*(void) const { return m_pkey; }
441
447 bool operator!=(const SslKeypair& other) const
448 {
449#if OPENSSL_VERSION_MAJOR >= 3
450 return (EVP_PKEY_eq(m_pkey, other.m_pkey) != 1);
451#else
452 return (EVP_PKEY_cmp(m_pkey, other.m_pkey) != 1);
453#endif
454 }
455
456 protected:
457
458 private:
459 EVP_PKEY* m_pkey = nullptr;
460
461}; /* class SslKeypair */
462
463
464} /* namespace */
465
466#endif /* ASYNC_SSL_KEYPAIR_INCLUDED */
467
468/*
469 * This file has not been truncated
470 */
A class representing private and public keys.
std::string publicKeyPem(void) const
Get the public key on PEM form.
bool readPrivateKeyFile(const std::string &filename)
Read key data from PEM file.
bool privateKeyFromPem(const std::string &pem)
Create key from the given PEM data.
SslKeypair(SslKeypair &other)
Copy constructor.
SslKeypair & operator=(SslKeypair &other)
Copy assignment operator.
bool writePrivateKeyFile(const std::string &filename)
Write key data to file on PEM format.
bool newRawPrivateKey(int type, const T &key)
Generate a key using the given algorithm and raw key data.
SslKeypair(SslKeypair &&other)
Move constructor.
bool isNull(void) const
Check if the object is empty.
bool publicKeyFromPem(const std::string &pem)
Create public key from PEM string.
std::string privateKeyPem(void) const
Return the private key on PEM form.
~SslKeypair(void)
Destructor.
SslKeypair(EVP_PKEY *pkey)
Constructor.
SslKeypair(void)
Default constructor.
bool operator!=(const SslKeypair &other) const
Check if two keys is not equal to each other.
bool generate(unsigned int bits)
Generate a new RSA keypair.
Namespace for the asynchronous programming classes.