blob: 69eae13dbb5871ad0fc46e3a5b2549a0827d576d [file] [log] [blame]
Ed Tanous0fdddb12017-02-28 11:06:34 -08001#pragma once
2
3#include <openssl/bio.h>
4#include <openssl/dh.h>
5#include <openssl/dsa.h>
6#include <openssl/dsa.h>
7#include <openssl/err.h>
8#include <openssl/evp.h>
9#include <openssl/pem.h>
10#include <openssl/rand.h>
11#include <openssl/rsa.h>
12#include <openssl/ssl.h>
13
Ed Tanous99923322017-03-03 14:21:24 -080014namespace ensuressl {
Ed Tanous0fdddb12017-02-28 11:06:34 -080015static void init_openssl(void);
16static void cleanup_openssl(void);
17static EVP_PKEY *create_rsa_key(void);
18static void handle_openssl_error(void);
19
Ed Tanous99923322017-03-03 14:21:24 -080020inline bool verify_openssl_key_cert(const std::string &filepath) {
21 bool private_key_valid = false;
22 bool cert_valid = false;
23 FILE *file = fopen(filepath.c_str(), "r");
24 if (file != NULL) {
25 EVP_PKEY *pkey = PEM_read_PrivateKey(file, NULL, NULL, NULL);
26 int rc;
27 if (pkey) {
28 int type = EVP_PKEY_type(pkey->type);
29 switch (type) {
30 case EVP_PKEY_RSA:
31 case EVP_PKEY_RSA2: {
32 RSA *rsa = EVP_PKEY_get1_RSA(pkey);
33 rc = RSA_check_key(rsa);
34 if (rc == 1) {
35 private_key_valid = true;
36 }
Ed Tanous0fdddb12017-02-28 11:06:34 -080037
Ed Tanous99923322017-03-03 14:21:24 -080038 // RSA_free(rsa);
Ed Tanous0fdddb12017-02-28 11:06:34 -080039
Ed Tanous99923322017-03-03 14:21:24 -080040 break;
Ed Tanous0fdddb12017-02-28 11:06:34 -080041 }
Ed Tanous99923322017-03-03 14:21:24 -080042 default:
43 break;
44 }
45
46 if (private_key_valid) {
47 X509 *x509 = PEM_read_X509(file, NULL, NULL, NULL);
48 unsigned long err = ERR_get_error();
49
50 rc = X509_verify(x509, pkey);
51 err = ERR_get_error();
52 if (err == 0 && rc == 1) {
53 cert_valid = true;
54 }
55 }
56
57 EVP_PKEY_free(pkey);
Ed Tanous0fdddb12017-02-28 11:06:34 -080058 }
Ed Tanous99923322017-03-03 14:21:24 -080059 fclose(file);
60 }
61 return cert_valid;
Ed Tanous0fdddb12017-02-28 11:06:34 -080062}
63
Ed Tanous99923322017-03-03 14:21:24 -080064inline void generate_ssl_certificate(const std::string &filepath) {
65 EVP_PKEY *pPrivKey = NULL;
66 FILE *pFile = NULL;
67 init_openssl();
Ed Tanous0fdddb12017-02-28 11:06:34 -080068
Ed Tanous99923322017-03-03 14:21:24 -080069 pPrivKey = create_rsa_key();
Ed Tanous0fdddb12017-02-28 11:06:34 -080070
Ed Tanous99923322017-03-03 14:21:24 -080071 // Use this code to directly generate a certificate
72 X509 *x509;
73 x509 = X509_new();
74 if (x509) {
75 // TODO get actually random int
76 ASN1_INTEGER_set(X509_get_serialNumber(x509), 1584);
Ed Tanous0fdddb12017-02-28 11:06:34 -080077
Ed Tanous99923322017-03-03 14:21:24 -080078 // not before this moment
79 X509_gmtime_adj(X509_get_notBefore(x509), 0);
80 // Cert is valid for 10 years
81 X509_gmtime_adj(X509_get_notAfter(x509), 60L * 60L * 24L * 365L * 10L);
Ed Tanous0fdddb12017-02-28 11:06:34 -080082
Ed Tanous99923322017-03-03 14:21:24 -080083 // set the public key to the key we just generated
84 X509_set_pubkey(x509, pPrivKey);
Ed Tanous0fdddb12017-02-28 11:06:34 -080085
Ed Tanous99923322017-03-03 14:21:24 -080086 // Get the subject name
87 X509_NAME *name;
88 name = X509_get_subject_name(x509);
Ed Tanous0fdddb12017-02-28 11:06:34 -080089
Ed Tanous99923322017-03-03 14:21:24 -080090 X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0);
91 X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"Intel BMC", -1, -1, 0);
92 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"testhost", -1, -1, 0);
93 // set the CSR options
94 X509_set_issuer_name(x509, name);
Ed Tanous0fdddb12017-02-28 11:06:34 -080095
Ed Tanous99923322017-03-03 14:21:24 -080096 // Sign the certificate with our private key
97 X509_sign(x509, pPrivKey, EVP_sha256());
Ed Tanous0fdddb12017-02-28 11:06:34 -080098
Ed Tanous99923322017-03-03 14:21:24 -080099 pFile = fopen(filepath.c_str(), "wt");
Ed Tanous0fdddb12017-02-28 11:06:34 -0800100
Ed Tanous99923322017-03-03 14:21:24 -0800101 if (pFile) {
102 PEM_write_PrivateKey(pFile, pPrivKey, NULL, NULL, 0, 0, NULL);
103 PEM_write_X509(pFile, x509);
104 fclose(pFile);
105 pFile = NULL;
Ed Tanous0fdddb12017-02-28 11:06:34 -0800106 }
107
Ed Tanous99923322017-03-03 14:21:24 -0800108 X509_free(x509);
109 }
110
111 if (pPrivKey) {
112 EVP_PKEY_free(pPrivKey);
113 pPrivKey = NULL;
114 }
115
116 // cleanup_openssl();
117}
118
119EVP_PKEY *create_rsa_key(void) {
120 RSA *pRSA = NULL;
121 EVP_PKEY *pKey = NULL;
122 pRSA = RSA_generate_key(2048, RSA_3, NULL, NULL);
123 pKey = EVP_PKEY_new();
124 if (pRSA && pKey && EVP_PKEY_assign_RSA(pKey, pRSA)) {
125 /* pKey owns pRSA from now */
126 if (RSA_check_key(pRSA) <= 0) {
127 fprintf(stderr, "RSA_check_key failed.\n");
128 handle_openssl_error();
129 EVP_PKEY_free(pKey);
130 pKey = NULL;
Ed Tanous0fdddb12017-02-28 11:06:34 -0800131 }
Ed Tanous99923322017-03-03 14:21:24 -0800132 } else {
133 handle_openssl_error();
134 if (pRSA) {
135 RSA_free(pRSA);
136 pRSA = NULL;
Ed Tanous0fdddb12017-02-28 11:06:34 -0800137 }
Ed Tanous99923322017-03-03 14:21:24 -0800138 if (pKey) {
139 EVP_PKEY_free(pKey);
140 pKey = NULL;
141 }
142 }
143 return pKey;
Ed Tanous0fdddb12017-02-28 11:06:34 -0800144}
145
Ed Tanous99923322017-03-03 14:21:24 -0800146void init_openssl(void) {
147 if (SSL_library_init()) {
148 SSL_load_error_strings();
149 OpenSSL_add_all_algorithms();
150 RAND_load_file("/dev/urandom", 1024);
151 } else
152 exit(EXIT_FAILURE);
Ed Tanous0fdddb12017-02-28 11:06:34 -0800153}
154
Ed Tanous99923322017-03-03 14:21:24 -0800155void cleanup_openssl(void) {
156 CRYPTO_cleanup_all_ex_data();
157 ERR_free_strings();
158 ERR_remove_thread_state(0);
159 EVP_cleanup();
Ed Tanous0fdddb12017-02-28 11:06:34 -0800160}
161
162void handle_openssl_error(void) { ERR_print_errors_fp(stderr); }
Ed Tanous99923322017-03-03 14:21:24 -0800163inline void ensure_openssl_key_present_and_valid(const std::string &filepath) {
164 bool pem_file_valid = false;
Ed Tanous0fdddb12017-02-28 11:06:34 -0800165
Ed Tanous99923322017-03-03 14:21:24 -0800166 pem_file_valid = verify_openssl_key_cert(filepath);
Ed Tanous0fdddb12017-02-28 11:06:34 -0800167
Ed Tanous99923322017-03-03 14:21:24 -0800168 if (!pem_file_valid) {
169 generate_ssl_certificate(filepath);
170 }
Ed Tanous0fdddb12017-02-28 11:06:34 -0800171}
172}