34#include <openssl/pem.h>
35#include <openssl/x509.h>
36#include <openssl/x509v3.h>
39#include "openssl/applink.c"
43EVP_PKEY *generate_key() {
45 EVP_PKEY *pkey = EVP_PKEY_new();
47 std::cerr <<
"Unable to create EVP_PKEY structure." << std::endl;
52 RSA *rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL);
53 if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
54 std::cerr <<
"Unable to generate 2048-bit RSA key." << std::endl;
63int cs_cert_set_subject_alt_name(X509 *x509_cert, std::string name) {
64 const char *subject_alt_name = name.c_str();
65 X509_EXTENSION *extension_san = NULL;
66 ASN1_OCTET_STRING *subject_alt_name_ASN1 = NULL;
69 subject_alt_name_ASN1 = ASN1_OCTET_STRING_new();
70 if (!subject_alt_name_ASN1) {
73 ASN1_OCTET_STRING_set(subject_alt_name_ASN1,
74 (
unsigned char *)subject_alt_name,
75 strlen(subject_alt_name));
76 if (!X509_EXTENSION_create_by_NID(&extension_san, NID_subject_alt_name, 0,
77 subject_alt_name_ASN1)) {
80 ASN1_OCTET_STRING_free(subject_alt_name_ASN1);
81 ret = X509_add_ext(x509_cert, extension_san, -1);
85 X509_EXTENSION_free(extension_san);
89 if (subject_alt_name_ASN1) ASN1_OCTET_STRING_free(subject_alt_name_ASN1);
90 if (extension_san) X509_EXTENSION_free(extension_san);
95X509 *generate_x509(EVP_PKEY *pkey, std::string ip_v4) {
97 X509 *x509 = X509_new();
99 std::cerr <<
"Unable to create X509 structure." << std::endl;
104 ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
108 X509_gmtime_adj(X509_get_notBefore(x509), 0);
109 X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);
112 X509_set_pubkey(x509, pkey);
115 X509_NAME *name = X509_get_subject_name(x509);
118 X509_NAME_add_entry_by_txt(name,
"C", MBSTRING_ASC, (
unsigned char *)
"CA", -1,
120 X509_NAME_add_entry_by_txt(name,
"O", MBSTRING_ASC,
121 (
unsigned char *)
"MyCompany", -1, -1, 0);
122 X509_NAME_add_entry_by_txt(name,
"CN", MBSTRING_ASC,
123 (
unsigned char *)
"localhost", -1, -1, 0);
131 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
132 std::string dns_name =
"www.example.com";
133 GENERAL_NAME *gen_dns = GENERAL_NAME_new();
134 ASN1_IA5STRING *ia5 = ASN1_IA5STRING_new();
135 ASN1_STRING_set(ia5, dns_name.data(), dns_name.length());
136 GENERAL_NAME_set0_value(gen_dns, GEN_DNS, ia5);
137 sk_GENERAL_NAME_push(gens, gen_dns);
139 in_addr_t ipv4 = inet_addr(ip_v4.c_str());
140 GENERAL_NAME *gen_ip = GENERAL_NAME_new();
141 ASN1_OCTET_STRING *octet = ASN1_OCTET_STRING_new();
142 ASN1_STRING_set(octet, &ipv4,
sizeof(ipv4));
143 GENERAL_NAME_set0_value(gen_ip, GEN_IPADD, octet);
144 sk_GENERAL_NAME_push(gens, gen_ip);
146 X509_add1_ext_i2d(x509, NID_subject_alt_name, gens, 0, X509V3_ADD_DEFAULT);
148 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
151 std::string ext_name(
"IP: ");
153 cs_cert_set_subject_alt_name(x509, ext_name);
156 X509_set_issuer_name(x509, name);
159 if (!X509_sign(x509, pkey, EVP_sha1())) {
160 std::cerr <<
"Error signing certificate." << std::endl;
168bool write_to_disk(EVP_PKEY *pkey, X509 *x509, std::string cert_directory) {
170 std::string key_file = cert_directory;
171 key_file +=
"key.pem";
172 FILE *pkey_file = fopen(key_file.c_str(),
"wb");
174 std::cerr <<
"Unable to open \"key.pem\" for writing." << std::endl;
179 bool ret = PEM_write_PrivateKey(pkey_file, pkey, NULL, NULL, 0, NULL, NULL);
183 std::cerr <<
"Unable to write private key to disk." << std::endl;
188 std::string cert_file = cert_directory;
189 cert_file +=
"cert.pem";
191 FILE *x509_file = fopen(cert_file.c_str(),
"wb");
193 std::cerr <<
"Unable to open \"cert.pem\" for writing." << std::endl;
198 ret = PEM_write_X509(x509_file, x509);
202 std::cerr <<
"Unable to write certificate to disk." << std::endl;
209int make_certificate(std::string ipv4, std::string destination_dir) {
211 if (getenv(
"OCPN_DEBUG_CERT"))
212 std::cout <<
"Generating RSA key..." << std::endl;
214 EVP_PKEY *pkey = generate_key();
218 if (getenv(
"OCPN_DEBUG_CERT"))
219 std::cout <<
"Generating x509 certificate..." << std::endl;
221 X509 *x509 = generate_x509(pkey, ipv4);
228 if (getenv(
"OCPN_DEBUG_CERT"))
229 std::cout <<
"Writing key and certificate to disk..." << std::endl;
231 bool ret = write_to_disk(pkey, x509, destination_dir);
236 if (getenv(
"OCPN_DEBUG_CERT")) std::cout <<
"Success!" << std::endl;