Generate Private Key and Certificate if none exist
This commit is contained in:
parent
1b49a9661e
commit
f06f5dde2f
6 changed files with 150 additions and 53 deletions
|
|
@ -1,22 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDsTCCApmgAwIBAgIULnRRHDUzdg4a9dwWi0/yV5LADLIwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwaDELMAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
|
||||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEhMB8GCSqGSIb3DQEJARYSbG9raUBm
|
|
||||||
YWtlZW1haWwuY29tMB4XDTE5MDYwMzEwMzY0N1oXDTI5MDUzMTEwMzY0N1owaDEL
|
|
||||||
MAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVy
|
|
||||||
bmV0IFdpZGdpdHMgUHR5IEx0ZDEhMB8GCSqGSIb3DQEJARYSbG9raUBmYWtlZW1h
|
|
||||||
aWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4cyNQ7uH6tAE
|
|
||||||
EAD99oxR1CVYlOgRDEUqJCjkpIoVF5uE3/kfuvEJ+l7/WL51lqbq35uL5ta7EbJH
|
|
||||||
BvVyNH00FN2D/Yl0n/X+TlhRP88MS5F0d0rwyQEAh4wEGcUhdSoW9TfybmLaHeCC
|
|
||||||
bZlxC3kBWxr0e6YDlV9deM6j+OjCerQwkiiGwgE9dVrVCj1dLyzBhWnYGpYBvY+3
|
|
||||||
6kEy0Vmf2spGCB6meCAMrAMz75fUDuk8YRF0umb+SLA44AB/U6d6GXU2EjpTuPww
|
|
||||||
OMkUr8EmdbAI3l1tmWJTAkhFQ7681AyIWYOspc1biXZdBrvNBTV8kbDGlomNj19V
|
|
||||||
QhhN44d4ywIDAQABo1MwUTAdBgNVHQ4EFgQUFRktN33zyW4MR9Cy1Vcn+B+EdYAw
|
|
||||||
HwYDVR0jBBgwFoAUFRktN33zyW4MR9Cy1Vcn+B+EdYAwDwYDVR0TAQH/BAUwAwEB
|
|
||||||
/zANBgkqhkiG9w0BAQsFAAOCAQEAkpU+ALElNz+5jOnVAPyYXYsJKfevmKK9uK4v
|
|
||||||
V+l7GrFLIEhC2qr26S8Nd2pLkrgesCD4xfoOONiVOceU5igh9acFA3+NyOSFLdRN
|
|
||||||
bSdy0jvCuoiK46ieDAagQtdt0G7HGV4u+jWz0jaKUQI9zJqznOHdJV6RZFIqTYLG
|
|
||||||
KHnGP+mtXjW3E1djU9vFreYcB6UY+Ai1KB33dnBK9Es2fIQhikKZUPTh6BYsRZT6
|
|
||||||
U7c6fh+01fRhRPo/SCFmY993857NtoOHMeP0M2V65CG4VjpAPR0msChVQVv7csca
|
|
||||||
TvBvB23dFRTLbo5PUSWC9bhBrMjzJ7yylt1CNBBHv7ycw8yIPw==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDhzI1Du4fq0AQQ
|
|
||||||
AP32jFHUJViU6BEMRSokKOSkihUXm4Tf+R+68Qn6Xv9YvnWWpurfm4vm1rsRskcG
|
|
||||||
9XI0fTQU3YP9iXSf9f5OWFE/zwxLkXR3SvDJAQCHjAQZxSF1Khb1N/JuYtod4IJt
|
|
||||||
mXELeQFbGvR7pgOVX114zqP46MJ6tDCSKIbCAT11WtUKPV0vLMGFadgalgG9j7fq
|
|
||||||
QTLRWZ/aykYIHqZ4IAysAzPvl9QO6TxhEXS6Zv5IsDjgAH9Tp3oZdTYSOlO4/DA4
|
|
||||||
yRSvwSZ1sAjeXW2ZYlMCSEVDvrzUDIhZg6ylzVuJdl0Gu80FNXyRsMaWiY2PX1VC
|
|
||||||
GE3jh3jLAgMBAAECggEAdnHgoGkc8RXRK7v5fH0653f3sZTSbIdThchVt+IfElUo
|
|
||||||
LHz4Ig4S191BQQIXmMFSb52ek6aMVsoX7BSQpewPh+pzNGoIXWiiz+IQLNKldnaE
|
|
||||||
i5cqG6aE6pWOCR6ZYGaFyHhimXkNRaLhiDB3VjdReML5AGujcZWm6Jos9YLTkZ07
|
|
||||||
pYXs2S+/5oNbfDdAE8dgdD7vD9lNGrbtmJ9+J+VvgPOYM/4LaEAfZU0ALDm2Hl3n
|
|
||||||
CqkZCp+eWbQK3MC2+6Y4yS+jo7e5/nKX1De9StkX6KumAEIpxkHPZF2EnWXW64oD
|
|
||||||
k40tKXT+oMXF1RLb4scnv+J+uR4bdl+Xq/VTzKrtsQKBgQDyoOjrv+g5l0s0KKDJ
|
|
||||||
qPkLQNRCJpzU7Km3CjPuk8DOlmBCr4KUeVfjbYPxQQMkeNL9zFz/QYBmabTCE6Ih
|
|
||||||
E8BbzT/RQzVPSOOh//Hh4eN4umrYaOIkY4Bv2R2X3H0ELFq+G7pKdvTAkusGHcWu
|
|
||||||
OAUb2HO5rTiRYq8DvHy8b+qH7wKBgQDuPjR+DCVtkBXmBNf0FZkl7OW/EUQBq4+T
|
|
||||||
WoaYleq8Gd7ubJgz2Gud+0+L41VjFD9W3hkJAb/3wkASseQ+2hk3Sv/BzpAIdS9e
|
|
||||||
tN/xxp/8NK7tJGL63m6tAfX+Hi/kSDEp45Zp3PoOD08MEK0yIrpf7S8uJ++u49K4
|
|
||||||
tKXkGCIg5QKBgFujvPW2AQ8nfqcPpVMleBLxBHqLvPaLALr6poy4z7z3fRoS0j4j
|
|
||||||
6rcimRAZHwe6fu6PLpzWb5m+2R/obHcTz7acujreqJbuj9OTKRfIyrLBrjNYwfk+
|
|
||||||
f7c/CPdftvRJkGh3bpBLh7vogc5Ilm5sCDnxMhxyOYhn/nRpz68YkjuPAoGBAOQX
|
|
||||||
6DfZtyfLcDvV3U/SMdsOkPO6OwsCTya73+tMdP18I2TP0XSpunb5ebIrh7+hTfcE
|
|
||||||
EqH96+XwM1nyuNy4ALZgdrb95gZC84RP1axsBxX29pcSZDVdKkc3fmW6Tw3XVEKP
|
|
||||||
o51dNIarf3nEqZ07hIZ81dPx5lbhxgiS49SaimpFAoGBAKamKZFAfUHlaHV/Na1C
|
|
||||||
3SZji7PaDSj1EFmRkCySK9VqD7Tbh1abrpC2ImdhYHn5TcQQE2eidB+F0Nf6IhKN
|
|
||||||
upBTofg0ebaslo+BYAqAsRKnUQGDToGIIIdXJ6DnO3wxWu9GY4nKdl3jxqAv2A2x
|
|
||||||
d8SETw4wqlFFRO33opycuFS5
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
|
|
@ -8,9 +8,9 @@
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define CA_DIR SUNSHINE_ASSETS_DIR "/demoCA"
|
#define CA_DIR "credentials"
|
||||||
#define PRIVATE_KEY_FILE CA_DIR "/cakey.pem"
|
#define PRIVATE_KEY_FILE CA_DIR "/cakey.pem"
|
||||||
#define CERTIFICATE_FILE CA_DIR "/cacert.pem"
|
#define CERTIFICATE_FILE CA_DIR "/cacert.pem"
|
||||||
|
|
||||||
#define APPS_JSON_PATH SUNSHINE_ASSETS_DIR "/" APPS_JSON
|
#define APPS_JSON_PATH SUNSHINE_ASSETS_DIR "/" APPS_JSON
|
||||||
namespace config {
|
namespace config {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,10 @@
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
namespace crypto {
|
namespace crypto {
|
||||||
|
using big_num_t = util::safe_ptr<BIGNUM, BN_free>;
|
||||||
|
//using rsa_t = util::safe_ptr<RSA, RSA_free>;
|
||||||
|
using asn1_string_t = util::safe_ptr<ASN1_STRING, ASN1_STRING_free>;
|
||||||
|
|
||||||
cert_chain_t::cert_chain_t() : _certs {}, _cert_ctx {X509_STORE_CTX_new() } {}
|
cert_chain_t::cert_chain_t() : _certs {}, _cert_ctx {X509_STORE_CTX_new() } {}
|
||||||
void cert_chain_t::add(x509_t &&cert) {
|
void cert_chain_t::add(x509_t &&cert) {
|
||||||
x509_store_t x509_store { X509_STORE_new() };
|
x509_store_t x509_store { X509_STORE_new() };
|
||||||
|
|
@ -200,6 +204,25 @@ pkey_t pkey(const std::string_view &k) {
|
||||||
return pkey_t { p };
|
return pkey_t { p };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string pem(x509_t &x509) {
|
||||||
|
bio_t bio { BIO_new(BIO_s_mem()) };
|
||||||
|
|
||||||
|
PEM_write_bio_X509(bio.get(), x509.get());
|
||||||
|
BUF_MEM *mem_ptr;
|
||||||
|
BIO_get_mem_ptr(bio.get(), &mem_ptr);
|
||||||
|
|
||||||
|
return { mem_ptr->data, mem_ptr->length };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string pem(pkey_t &pkey) {
|
||||||
|
bio_t bio { BIO_new(BIO_s_mem()) };
|
||||||
|
|
||||||
|
PEM_write_bio_PrivateKey(bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr);
|
||||||
|
BUF_MEM *mem_ptr;
|
||||||
|
BIO_get_mem_ptr(bio.get(), &mem_ptr);
|
||||||
|
|
||||||
|
return { mem_ptr->data, mem_ptr->length };
|
||||||
|
}
|
||||||
|
|
||||||
std::string_view signature(const x509_t &x) {
|
std::string_view signature(const x509_t &x) {
|
||||||
// X509_ALGOR *_ = nullptr;
|
// X509_ALGOR *_ = nullptr;
|
||||||
|
|
@ -242,6 +265,48 @@ std::vector<uint8_t> sign(const pkey_t &pkey, const std::string_view &data, cons
|
||||||
return digest;
|
return digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
creds_t gen_creds(const std::string_view &cn, std::uint32_t key_bits) {
|
||||||
|
x509_t x509 { X509_new() };
|
||||||
|
pkey_t pkey { EVP_PKEY_new() };
|
||||||
|
|
||||||
|
big_num_t big_num { BN_new() };
|
||||||
|
BN_set_word(big_num.get(), RSA_F4);
|
||||||
|
|
||||||
|
auto rsa = RSA_new();
|
||||||
|
RSA_generate_key_ex(rsa, key_bits, big_num.get(), nullptr);
|
||||||
|
EVP_PKEY_assign_RSA(pkey.get(), rsa);
|
||||||
|
|
||||||
|
X509_set_version(x509.get(), 2);
|
||||||
|
ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), 0);
|
||||||
|
|
||||||
|
constexpr auto year = 60 * 60 * 24 * 365;
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
X509_gmtime_adj(X509_get_notBefore(x509.get()), 0);
|
||||||
|
X509_gmtime_adj(X509_get_notAfter(x509.get()), 20 * year);
|
||||||
|
#else
|
||||||
|
asn1_string_t not_before { ASN1_STRING_dup(X509_get0_notBefore(x509.get())) };
|
||||||
|
asn1_string_t not_after { ASN1_STRING_dup(X509_get0_notAfter(x509.get())) };
|
||||||
|
|
||||||
|
X509_gmtime_adj(not_before.get(), 0);
|
||||||
|
X509_gmtime_adj(not_after.get(), 20 * year);
|
||||||
|
|
||||||
|
X509_set1_notBefore(x509.get(), not_before.get());
|
||||||
|
X509_set1_notAfter(x509.get(), not_after.get());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
X509_set_pubkey(x509.get(), pkey.get());
|
||||||
|
|
||||||
|
auto name = X509_get_subject_name(x509.get());
|
||||||
|
X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC,
|
||||||
|
(const std::uint8_t*)cn.data(), cn.size(),
|
||||||
|
-1, 0);
|
||||||
|
|
||||||
|
X509_set_issuer_name(x509.get(), name);
|
||||||
|
X509_sign(x509.get(), pkey.get(), EVP_sha256());
|
||||||
|
|
||||||
|
return { pem(x509), pem(pkey) };
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> sign256(const pkey_t &pkey, const std::string_view &data) {
|
std::vector<uint8_t> sign256(const pkey_t &pkey, const std::string_view &data) {
|
||||||
return sign(pkey, data, EVP_sha256());
|
return sign(pkey, data, EVP_sha256());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,10 @@
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
namespace crypto {
|
namespace crypto {
|
||||||
|
struct creds_t {
|
||||||
|
std::string x509;
|
||||||
|
std::string pkey;
|
||||||
|
};
|
||||||
constexpr std::size_t digest_size = 256;
|
constexpr std::size_t digest_size = 256;
|
||||||
|
|
||||||
void md_ctx_destroy(EVP_MD_CTX *);
|
void md_ctx_destroy(EVP_MD_CTX *);
|
||||||
|
|
@ -35,10 +39,13 @@ aes_t gen_aes_key(const std::array<uint8_t, 16> &salt, const std::string_view &p
|
||||||
|
|
||||||
x509_t x509(const std::string_view &x);
|
x509_t x509(const std::string_view &x);
|
||||||
pkey_t pkey(const std::string_view &k);
|
pkey_t pkey(const std::string_view &k);
|
||||||
|
std::string pem(x509_t &x509);
|
||||||
|
std::string pem(pkey_t &pkey);
|
||||||
|
|
||||||
std::vector<uint8_t> sign256(const pkey_t &pkey, const std::string_view &data);
|
std::vector<uint8_t> sign256(const pkey_t &pkey, const std::string_view &data);
|
||||||
bool verify256(const x509_t &x509, const std::string_view &data, const std::string_view &signature);
|
bool verify256(const x509_t &x509, const std::string_view &data, const std::string_view &signature);
|
||||||
|
|
||||||
|
creds_t gen_creds(const std::string_view &cn, std::uint32_t key_bits);
|
||||||
|
|
||||||
std::string_view signature(const x509_t &x);
|
std::string_view signature(const x509_t &x);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ namespace fs = std::filesystem;
|
||||||
namespace pt = boost::property_tree;
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
std::string read_file(const char *path);
|
std::string read_file(const char *path);
|
||||||
|
int write_file(const char *path, const std::string_view &contents);
|
||||||
|
|
||||||
using https_server_t = SimpleWeb::Server<SimpleWeb::HTTPS>;
|
using https_server_t = SimpleWeb::Server<SimpleWeb::HTTPS>;
|
||||||
using http_server_t = SimpleWeb::Server<SimpleWeb::HTTP>;
|
using http_server_t = SimpleWeb::Server<SimpleWeb::HTTP>;
|
||||||
|
|
@ -652,7 +653,69 @@ void appasset(resp_https_t response, req_https_t request) {
|
||||||
response->write(SimpleWeb::StatusCode::success_ok, in);
|
response->write(SimpleWeb::StatusCode::success_ok, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int create_creds(const std::string &pkey, const std::string &cert) {
|
||||||
|
fs::path pkey_path = pkey;
|
||||||
|
fs::path cert_path = cert;
|
||||||
|
|
||||||
|
auto creds = crypto::gen_creds("Sunshine Gamestream Host"sv, 2048);
|
||||||
|
|
||||||
|
auto pkey_dir = pkey_path;
|
||||||
|
auto cert_dir = cert_path;
|
||||||
|
pkey_dir.remove_filename();
|
||||||
|
cert_dir.remove_filename();
|
||||||
|
|
||||||
|
std::error_code err_code{};
|
||||||
|
fs::create_directories(pkey_dir, err_code);
|
||||||
|
if (err_code) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't create directory ["sv << pkey_dir << "] :"sv << err_code.message();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::create_directories(cert_dir, err_code);
|
||||||
|
if (err_code) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't create directory ["sv << cert_dir << "] :"sv << err_code.message();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_file(pkey.c_str(), creds.pkey)) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't open ["sv << config::nvhttp.pkey << ']';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_file(cert.c_str(), creds.x509)) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't open ["sv << config::nvhttp.cert << ']';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::permissions(pkey_path,
|
||||||
|
fs::perms::owner_read | fs::perms::owner_write,
|
||||||
|
fs::perm_options::replace, err_code);
|
||||||
|
|
||||||
|
if (err_code) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't change permissions of ["sv << config::nvhttp.pkey << "] :"sv << err_code.message();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::permissions(cert_path,
|
||||||
|
fs::perms::owner_read | fs::perms::group_read | fs::perms::others_read | fs::perms::owner_write,
|
||||||
|
fs::perm_options::replace, err_code);
|
||||||
|
|
||||||
|
if (err_code) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't change permissions of ["sv << config::nvhttp.cert << "] :"sv << err_code.message();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void start(std::shared_ptr<safe::event_t<bool>> shutdown_event) {
|
void start(std::shared_ptr<safe::event_t<bool>> shutdown_event) {
|
||||||
|
if(!fs::exists(config::nvhttp.pkey) || !fs::exists(config::nvhttp.cert)) {
|
||||||
|
if(create_creds(config::nvhttp.pkey, config::nvhttp.cert)) {
|
||||||
|
shutdown_event->raise(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed);
|
origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed);
|
||||||
load_state();
|
load_state();
|
||||||
|
|
||||||
|
|
@ -748,6 +811,18 @@ void start(std::shared_ptr<safe::event_t<bool>> shutdown_event) {
|
||||||
tcp.join();
|
tcp.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int write_file(const char *path, const std::string_view &contents) {
|
||||||
|
std::ofstream out(path);
|
||||||
|
|
||||||
|
if(!out.is_open()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << contents;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::string read_file(const char *path) {
|
std::string read_file(const char *path) {
|
||||||
std::ifstream in(path);
|
std::ifstream in(path);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue