#include "ssl.h" #include "log.h" #include #include #include #include #include #include #include #define LOG_NAME "SSL" static bool _initialized = false; static SSL_CTX* _ssl_ctx = NULL; static EVP_MD* _sha256_ctx = NULL; static const char _pkey_file_name[] = "key.pem"; static const char _cert_file_name[] = "cert.pem"; static const char _passphrase[] = "This is absolutely insecure."; static int _pem_passphrase_cb(char* buf, int size, int rwflag, void* userdata) { int len = strlen(_passphrase); memcpy(buf, _passphrase, len < size ? len : size); return len; } bool _initialize_ssl() { SSL_library_init(); SSL_load_error_strings(); _ssl_ctx = SSL_CTX_new(TLS_client_method()); if (_ssl_ctx == NULL) { fprintf(stderr, "Failed to initialize Openssl.\n"); return false; } SSL_CTX_set_verify(_ssl_ctx, SSL_VERIFY_PEER, NULL); if (!SSL_CTX_set_default_verify_paths(_ssl_ctx)) { fprintf(stderr, "Failed to set default paths for openssl.\n"); return false; } if (!SSL_CTX_set_min_proto_version(_ssl_ctx, TLS1_3_VERSION)) { fprintf(stderr, "Failed to set minimum TLS version.\n"); return false; } return true; } bool initialize_ssl() { if (!_initialized) { _initialized = _initialize_ssl(); } return _initialized; } void ssl_close_ssl() { SSL_CTX_free(_ssl_ctx); EVP_MD_free(_sha256_ctx); } SSL_CTX* ssl_get_ctx() { return _ssl_ctx; } EVP_MD* ssl_get_sha256() { return _sha256_ctx; } bool ssl_generate_cert() { EVP_PKEY* pkey = NULL; X509* cert = NULL; X509_NAME* cert_issuer; bool success = false; pkey = EVP_EC_gen("P-256"); if (pkey == NULL) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to generate private key for certificate."); goto generate_cert_cleanup; } cert = X509_new(); if (cert == NULL) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to generate certificate."); goto generate_cert_cleanup; } ASN1_INTEGER_set(X509_get_serialNumber(cert), 1); X509_gmtime_adj(X509_get_notBefore(cert), 0); X509_gmtime_adj(X509_get_notAfter(cert), 31536000L); cert_issuer = X509_get_subject_name(cert); if (cert_issuer == NULL || !( X509_NAME_add_entry_by_txt(cert_issuer, "C", MBSTRING_ASC, (unsigned char*)"AT", -1, -1, 0) && X509_NAME_add_entry_by_txt(cert_issuer, "O", MBSTRING_ASC, (unsigned char*)"me", -1, -1, 0) && X509_NAME_add_entry_by_txt(cert_issuer, "CN", MBSTRING_ASC, (unsigned char*)"localhost", -1, -1, 0))) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to create issuer name."); goto generate_cert_cleanup; } if (!X509_set_issuer_name(cert, cert_issuer)) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to set issuer name on certificate."); goto generate_cert_cleanup; } if (!X509_set_pubkey(cert, pkey)) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to set private key on certificate"); goto generate_cert_cleanup; } if (!X509_sign(cert, pkey, EVP_sha256())) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to sign certificate."); goto generate_cert_cleanup; } FILE* key_file = NULL; key_file = fopen(_pkey_file_name, "wb"); if (!PEM_write_PrivateKey(key_file, pkey, EVP_des_ede3_cbc(), (unsigned char*)_passphrase, sizeof(_passphrase), NULL, NULL)) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to write private certificate to disk."); fclose(key_file); goto generate_cert_cleanup; } fclose(key_file); key_file = fopen(_cert_file_name, "wb"); if (!PEM_write_X509(key_file, cert)) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to write certificate to disk."); fclose(key_file); goto generate_cert_cleanup; } fclose(key_file); success = true; generate_cert_cleanup: EVP_PKEY_free(pkey); X509_free(cert); X509_NAME_free(cert_issuer); return success; } bool ssl_use_ppcerts(SSL_CTX* ctx) { if (access(_cert_file_name, R_OK) != 0 && access(_pkey_file_name, R_OK) != 0) { log_log(LOG_NAME, LOG_INFO, "Could not access certificates - Generating new ones"); bool res = ssl_generate_cert(); if (!res) { log_log(LOG_NAME, LOG_ERR, "Failed to generate certificates"); return false; } } if (SSL_CTX_use_certificate_chain_file(ctx, _cert_file_name) != 1) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to load SSL certificate."); return false; } SSL_CTX_set_default_passwd_cb(ctx, _pem_passphrase_cb); if (SSL_CTX_use_PrivateKey_file(ctx, _pkey_file_name, SSL_FILETYPE_PEM) != 1) { log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to load SSL Private Key."); return false; } SSL_CTX_set_default_passwd_cb(ctx, NULL); return true; }