mirror of
https://github.com/rock88/moonlight-nx
synced 2024-11-23 03:53:07 +00:00
Reimplemet CryptoManager for use mbedtls, other fixes...
This commit is contained in:
parent
246f4abd4d
commit
d12e1090f8
18 changed files with 594 additions and 381 deletions
|
@ -39,7 +39,8 @@ include $(DEVKITPRO)/libnx/switch_rules
|
|||
#---------------------------------------------------------------------------------
|
||||
TARGET := moonlight
|
||||
BUILD := build
|
||||
SOURCES := libgamestream src/nanogui_resources src src/streaming src/streaming/ffmpeg src/streaming/video src/ui/windows src/ui/buttons src/ui \
|
||||
SOURCES := libgamestream src/nanogui_resources src src/streaming src/streaming/ffmpeg \
|
||||
src/crypto src/streaming/video src/ui/windows src/ui/buttons src/ui \
|
||||
third_party/moonlight-common-c/enet third_party/moonlight-common-c/reedsolomon third_party/moonlight-common-c/src \
|
||||
third_party/nanogui/ext/nanovg/src third_party/nanogui/src
|
||||
DATA := data
|
||||
|
@ -52,7 +53,7 @@ INCLUDES := include
|
|||
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
||||
|
||||
M_INCLUDES := \
|
||||
-I$(TOPDIR)/src -I$(TOPDIR)/src/streaming \
|
||||
-I$(TOPDIR)/src -I$(TOPDIR)/src/streaming -I$(TOPDIR)/src/crypto -I$(TOPDIR)/src/crypto/keys \
|
||||
-I$(TOPDIR)/src/streaming/ffmpeg -I$(TOPDIR)/src/streaming/video -I$(TOPDIR)/src/streaming/audio \
|
||||
-I$(TOPDIR)/src/nanogui_resources \
|
||||
-I$(TOPDIR)/src/ui -I$(TOPDIR)/src/ui/buttons -I$(TOPDIR)/src/ui/windows \
|
||||
|
@ -62,10 +63,11 @@ M_INCLUDES := \
|
|||
-I$(TOPDIR)/third_party/moonlight-common-c/enet/include \
|
||||
-I$(TOPDIR)/third_party/nanogui/include \
|
||||
-I$(TOPDIR)/third_party/nanogui/ext/nanovg/src \
|
||||
-I$(TOPDIR)/third_party/json/single_include/nlohmann
|
||||
-I$(TOPDIR)/third_party/json/single_include/nlohmann \
|
||||
-I/Users/rock88/Downloads/moonlight-switch-master/dependencies/include
|
||||
|
||||
DEFINES := -DNANOGUI_USE_OPENGL -DNVG_STB_IMAGE_IMPLEMENTATION -DNANOGUI_NO_GLFW \
|
||||
-DHAS_SOCKLEN_T -DHAS_POLL -DHAS_FCNTL -D_GNU_SOURCE
|
||||
-DHAS_SOCKLEN_T -DHAS_POLL -DHAS_FCNTL -D_GNU_SOURCE -DUSE_MBEDTLS_CRYPTO
|
||||
|
||||
CFLAGS := -g -Wall -O0 -ffunction-sections \
|
||||
$(ARCH) $(DEFINES)
|
||||
|
@ -81,14 +83,15 @@ LIBS := -lcurl -lmbedtls -lmbedx509 -lmbedcrypto \
|
|||
-lavcodec -lavutil -lopus -lssl -lcrypto -lbz2 -lz -lexpat -lm \
|
||||
-lglad -lEGL -lglapi -ldrm_nouveau -lglfw3 \
|
||||
-lnx -lwebp -lswresample -lavformat -lvpx \
|
||||
-L/Users/rock88/Documents/Projects/Switch/moonlight-switch-new/deps/lib
|
||||
-L/Users/rock88/Downloads/moonlight-switch-master/dependencies/lib
|
||||
|
||||
LIBGAMESTREAM_SOURCES = \
|
||||
client.c \
|
||||
http.c \
|
||||
mkcert.c \
|
||||
LIBGAMESTREAM_C_SOURCES = \
|
||||
xml.c
|
||||
|
||||
LIBGAMESTREAM_CPP_SOURCES = \
|
||||
client.cpp \
|
||||
http.cpp
|
||||
|
||||
MOONLIGHT_LIBRETRO_C_SOURCES = \
|
||||
nanogui_resources.c \
|
||||
moonlight_libnx.c \
|
||||
|
@ -111,7 +114,9 @@ MOONLIGHT_LIBRETRO_CXX_SOURCES = \
|
|||
InputController.cpp \
|
||||
MoonlightSession.cpp \
|
||||
FFmpegVideoDecoder.cpp \
|
||||
GLVideoRenderer.cpp
|
||||
GLVideoRenderer.cpp \
|
||||
Data.cpp \
|
||||
MbedTLSCryptoManager.cpp
|
||||
|
||||
MOONLIGHT_COMMON_C_SOURCES = \
|
||||
callbacks.c \
|
||||
|
@ -202,8 +207,8 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(LIBGAMESTREAM_SOURCES) $(MOONLIGHT_LIBRETRO_C_SOURCES) $(MOONLIGHT_COMMON_C_SOURCES) $(NANOGUI_C_SOURCES)
|
||||
CPPFILES := $(MOONLIGHT_LIBRETRO_CXX_SOURCES) $(NANOGUI_CXX_SOURCES)
|
||||
CFILES := $(LIBGAMESTREAM_C_SOURCES) $(MOONLIGHT_LIBRETRO_C_SOURCES) $(MOONLIGHT_COMMON_C_SOURCES) $(NANOGUI_C_SOURCES)
|
||||
CPPFILES := $(LIBGAMESTREAM_CPP_SOURCES) $(MOONLIGHT_LIBRETRO_CXX_SOURCES) $(NANOGUI_CXX_SOURCES)
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
#include "http.h"
|
||||
#include "mkcert.h"
|
||||
#include "client.h"
|
||||
#include "errors.h"
|
||||
#include "limits.h"
|
||||
|
@ -40,10 +39,6 @@
|
|||
static char* unique_id = "0123456789ABCDEF";
|
||||
const char* gs_error;
|
||||
|
||||
uid_t getuid() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mkdirtree(const char* directory) {
|
||||
char buffer[PATH_MAX];
|
||||
char* p = buffer;
|
||||
|
@ -207,10 +202,10 @@ static int gs_pair_validate(Data &data, char** result) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (strcmp(*result, "1") != 0) {
|
||||
gs_error = "Pairing failed";
|
||||
ret = GS_FAILED;
|
||||
}
|
||||
// if (strcmp(*result, "1") != 0) {
|
||||
// gs_error = "Pairing failed";
|
||||
// ret = GS_FAILED;
|
||||
// }
|
||||
|
||||
if (*result) {
|
||||
free(*result);
|
||||
|
@ -252,7 +247,7 @@ int gs_pair(PSERVER_DATA server, char* pin) {
|
|||
Data salted_pin = salt.append(Data(pin, strlen(pin)));
|
||||
LOG_FMT("PIN: %s, salt %s\n", pin, salt.hex().bytes());
|
||||
|
||||
snprintf(url, sizeof(url), "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", server->serverInfo.address, unique_id, salt.hex().bytes(), CryptoManager::read_cert_from_file().hex().bytes());
|
||||
snprintf(url, sizeof(url), "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", server->serverInfo.address, unique_id, salt.hex().bytes(), CryptoManager::cert_data().hex().bytes());
|
||||
|
||||
if ((ret = http_request(url, &data)) != GS_OK) {
|
||||
return gs_pair_cleanup(ret, server, &result);
|
||||
|
@ -308,7 +303,7 @@ int gs_pair(PSERVER_DATA server, char* pin) {
|
|||
Data serverChallenge = decServerChallengeResp.subdata(hashLength, 16);
|
||||
|
||||
Data clientSecret = Data::random_bytes(16);
|
||||
Data challengeRespHashInput = serverChallenge.append(CryptoManager::get_signature_from_cert(CryptoManager::read_cert_from_file())).append(clientSecret);
|
||||
Data challengeRespHashInput = serverChallenge.append(CryptoManager::signature(CryptoManager::cert_data())).append(clientSecret);
|
||||
|
||||
Data challengeRespHash;
|
||||
|
||||
|
@ -347,7 +342,7 @@ int gs_pair(PSERVER_DATA server, char* pin) {
|
|||
return gs_pair_cleanup(ret, server, &result);
|
||||
}
|
||||
|
||||
Data serverChallengeRespHashInput = randomChallenge.append(CryptoManager::get_signature_from_cert(plainCert.hex_to_bytes())).append(serverSecret);
|
||||
Data serverChallengeRespHashInput = randomChallenge.append(CryptoManager::signature(plainCert.hex_to_bytes())).append(serverSecret);
|
||||
Data serverChallengeRespHash;
|
||||
if (server->serverMajorVersion >= 7) {
|
||||
serverChallengeRespHash = CryptoManager::SHA256_hash_data(serverChallengeRespHashInput);
|
||||
|
@ -356,7 +351,7 @@ int gs_pair(PSERVER_DATA server, char* pin) {
|
|||
serverChallengeRespHash = CryptoManager::SHA1_hash_data(serverChallengeRespHashInput);
|
||||
}
|
||||
|
||||
Data clientPairingSecret = clientSecret.append(CryptoManager::sign_data(clientSecret, CryptoManager::read_key_from_file()));
|
||||
Data clientPairingSecret = clientSecret.append(CryptoManager::sign_data(clientSecret, CryptoManager::key_data()));
|
||||
|
||||
snprintf(url, sizeof(url), "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", server->serverInfo.address, unique_id, clientPairingSecret.hex().bytes());
|
||||
if ((ret = http_request(url, &data)) != GS_OK) {
|
||||
|
@ -512,16 +507,16 @@ cleanup:
|
|||
}
|
||||
|
||||
int gs_init(PSERVER_DATA server, char *address, const char *keyDirectory, int log_level, bool unsupported) {
|
||||
if (!CryptoManager::certs_exists()) {
|
||||
if (!CryptoManager::load_cert_key_pair()) {
|
||||
LOG("No certs, generate new...\n");
|
||||
|
||||
if (!CryptoManager::generate_certs()) {
|
||||
if (!CryptoManager::generate_new_cert_key_pair()) {
|
||||
LOG("Failed to generate certs...\n");
|
||||
return GS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
http_init(keyDirectory, log_level);
|
||||
http_init(keyDirectory, 2);
|
||||
|
||||
LiInitializeServerInformation(&server->serverInfo);
|
||||
server->serverInfo.address = address;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "http.h"
|
||||
#include "errors.h"
|
||||
#include "CryptoManager.hpp"
|
||||
#include "Log.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
@ -47,6 +49,13 @@ static size_t _write_curl(void *contents, size_t size, size_t nmemb, void *userp
|
|||
}
|
||||
|
||||
int http_init(const char* key_directory, int log_level) {
|
||||
if (!curl) {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
LOG_FMT("Curl version: %s\n", curl_version());
|
||||
} else {
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
curl = curl_easy_init();
|
||||
debug = log_level >= 2;
|
||||
|
||||
|
@ -59,9 +68,12 @@ int http_init(const char* key_directory, int log_level) {
|
|||
char keyFilePath[4096];
|
||||
sprintf(&keyFilePath[0], "%s/%s", key_directory, KEY_FILE_NAME);
|
||||
|
||||
LOG_FMT("certificateFilePath: %s\n", certificateFilePath);
|
||||
LOG_FMT("keyFilePath: %s\n", keyFilePath);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE,"PEM");
|
||||
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
|
||||
curl_easy_setopt(curl, CURLOPT_SSLCERT, certificateFilePath);
|
||||
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
|
||||
curl_easy_setopt(curl, CURLOPT_SSLKEY, keyFilePath);
|
||||
|
@ -75,7 +87,7 @@ int http_init(const char* key_directory, int log_level) {
|
|||
|
||||
int http_request(char* url, Data* data) {
|
||||
if (debug)
|
||||
printf("Request %s\n", url);
|
||||
LOG_FMT("Request %s\n", url);
|
||||
|
||||
HTTP_DATA* http_data = (HTTP_DATA*)malloc(sizeof(HTTP_DATA));
|
||||
http_data->memory = (char*)malloc(1);
|
||||
|
@ -88,19 +100,20 @@ int http_request(char* url, Data* data) {
|
|||
|
||||
if (res != CURLE_OK) {
|
||||
gs_error = curl_easy_strerror(res);
|
||||
LOG_FMT("Curl error: %s\n", gs_error);
|
||||
return GS_FAILED;
|
||||
} else if (http_data->memory == NULL) {
|
||||
LOG("Curl error: memory = NULL\n");
|
||||
return GS_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
*data = Data(http_data->memory, http_data->size);
|
||||
|
||||
if (debug)
|
||||
LOG_FMT("Response:\n%s\n\n", http_data->memory);
|
||||
|
||||
free(http_data->memory);
|
||||
free(http_data);
|
||||
|
||||
if (debug)
|
||||
printf("Response:\n%s\n\n", http_data->memory);
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,5 @@
|
|||
|
||||
#include "Data.hpp"
|
||||
|
||||
#define CERTIFICATE_FILE_NAME "client.pem"
|
||||
#define KEY_FILE_NAME "key.pem"
|
||||
|
||||
int http_init(const char* key_directory, int log_level);
|
||||
int http_request(char* url, Data* data);
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Moonlight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mkcert.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/pkcs12.h>
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
static const int NUM_BITS = 2048;
|
||||
static const int SERIAL = 0;
|
||||
static const int NUM_YEARS = 10;
|
||||
|
||||
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years);
|
||||
|
||||
CERT_KEY_PAIR mkcert_generate() {
|
||||
BIO *bio_err;
|
||||
X509 *x509 = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
PKCS12 *p12 = NULL;
|
||||
|
||||
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
|
||||
bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
|
||||
|
||||
mkcert(&x509, &pkey, NUM_BITS, SERIAL, NUM_YEARS);
|
||||
|
||||
p12 = PKCS12_create("limelight", "GameStream", pkey, x509, NULL, 0, 0, 0, 0, 0);
|
||||
if (p12 == NULL) {
|
||||
printf("Error generating a valid PKCS12 certificate.\n");
|
||||
}
|
||||
|
||||
BIO_free(bio_err);
|
||||
|
||||
return (CERT_KEY_PAIR){x509, pkey, p12};
|
||||
}
|
||||
|
||||
void mkcert_free(CERT_KEY_PAIR certKeyPair) {
|
||||
X509_free(certKeyPair.x509);
|
||||
EVP_PKEY_free(certKeyPair.pkey);
|
||||
PKCS12_free(certKeyPair.p12);
|
||||
}
|
||||
|
||||
void mkcert_save(const char* certFile, const char* p12File, const char* keyPairFile, CERT_KEY_PAIR certKeyPair) {
|
||||
FILE* certFilePtr = fopen(certFile, "w");
|
||||
FILE* keyPairFilePtr = fopen(keyPairFile, "w");
|
||||
FILE* p12FilePtr = fopen(p12File, "wb");
|
||||
|
||||
//TODO: error check
|
||||
PEM_write_PrivateKey(keyPairFilePtr, certKeyPair.pkey, NULL, NULL, 0, NULL, NULL);
|
||||
PEM_write_X509(certFilePtr, certKeyPair.x509);
|
||||
i2d_PKCS12_fp(p12FilePtr, certKeyPair.p12);
|
||||
|
||||
fclose(p12FilePtr);
|
||||
fclose(certFilePtr);
|
||||
fclose(keyPairFilePtr);
|
||||
}
|
||||
|
||||
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
||||
X509* cert = X509_new();
|
||||
EVP_PKEY* pk = EVP_PKEY_new();
|
||||
BIGNUM* bne = BN_new();
|
||||
RSA* rsa = RSA_new();
|
||||
|
||||
BN_set_word(bne, RSA_F4);
|
||||
RSA_generate_key_ex(rsa, bits, bne, NULL);
|
||||
|
||||
EVP_PKEY_assign_RSA(pk, rsa);
|
||||
|
||||
X509_set_version(cert, 2);
|
||||
ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
X509_gmtime_adj(X509_get_notBefore(cert), 0);
|
||||
X509_gmtime_adj(X509_get_notAfter(cert), 60 * 60 * 24 * 365 * years);
|
||||
#else
|
||||
ASN1_TIME* before = ASN1_STRING_dup(X509_get0_notBefore(cert));
|
||||
ASN1_TIME* after = ASN1_STRING_dup(X509_get0_notAfter(cert));
|
||||
|
||||
X509_gmtime_adj(before, 0);
|
||||
X509_gmtime_adj(after, 60 * 60 * 24 * 365 * years);
|
||||
|
||||
X509_set1_notBefore(cert, before);
|
||||
X509_set1_notAfter(cert, after);
|
||||
|
||||
ASN1_STRING_free(before);
|
||||
ASN1_STRING_free(after);
|
||||
#endif
|
||||
|
||||
X509_set_pubkey(cert, pk);
|
||||
|
||||
X509_NAME* name = X509_get_subject_name(cert);
|
||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
|
||||
(const unsigned char*)"NVIDIA GameStream Client",
|
||||
-1, -1, 0);
|
||||
X509_set_issuer_name(cert, name);
|
||||
|
||||
X509_sign(cert, pk, EVP_sha256());
|
||||
|
||||
BN_free(bne);
|
||||
|
||||
*x509p = cert;
|
||||
*pkeyp = pk;
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Created by Diego Waxemberg on 10/16/14.
|
||||
* Copyright (c) 2014 Limelight Stream. All rights reserved.
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Moonlight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/pkcs12.h>
|
||||
|
||||
typedef struct _CERT_KEY_PAIR {
|
||||
X509 *x509;
|
||||
EVP_PKEY *pkey;
|
||||
PKCS12 *p12;
|
||||
} CERT_KEY_PAIR, *PCERT_KEY_PAIR;
|
||||
|
||||
CERT_KEY_PAIR mkcert_generate();
|
||||
void mkcert_free(CERT_KEY_PAIR);
|
||||
void mkcert_save(const char* certFile, const char* p12File, const char* keyPairFile, CERT_KEY_PAIR certKeyPair);
|
|
@ -11,6 +11,8 @@
|
|||
3602C3BA245DB3C800368900 /* AppListWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3602C3B8245DB3C800368900 /* AppListWindow.cpp */; };
|
||||
3602C3BD245DBA9100368900 /* AppButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3602C3BB245DBA9100368900 /* AppButton.cpp */; };
|
||||
3603E93C246316400051287D /* InputController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3603E93A246316400051287D /* InputController.cpp */; };
|
||||
363898332471B7C500F99920 /* OpenSSLCryptoManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 363898302471B7C500F99920 /* OpenSSLCryptoManager.cpp */; };
|
||||
363898342471B7C500F99920 /* MbedTLSCryptoManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 363898312471B7C500F99920 /* MbedTLSCryptoManager.cpp */; };
|
||||
3652EFCD245B3B00001FABF3 /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF0F245B3B00001FABF3 /* widget.cpp */; };
|
||||
3652EFCE245B3B00001FABF3 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF10245B3B00001FABF3 /* common.cpp */; };
|
||||
3652EFCF245B3B00001FABF3 /* checkbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF11245B3B00001FABF3 /* checkbox.cpp */; };
|
||||
|
@ -50,7 +52,6 @@
|
|||
3652F005245C28C6001FABF3 /* GameStreamClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652F003245C28C6001FABF3 /* GameStreamClient.cpp */; };
|
||||
3652F010245C2919001FABF3 /* xml.c in Sources */ = {isa = PBXBuildFile; fileRef = 3652F008245C2918001FABF3 /* xml.c */; };
|
||||
3652F011245C2919001FABF3 /* client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652F00C245C2918001FABF3 /* client.cpp */; };
|
||||
3652F012245C2919001FABF3 /* mkcert.c in Sources */ = {isa = PBXBuildFile; fileRef = 3652F00D245C2918001FABF3 /* mkcert.c */; };
|
||||
3652F013245C2919001FABF3 /* http.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652F00F245C2918001FABF3 /* http.cpp */; };
|
||||
3652F065245C292B001FABF3 /* list.c in Sources */ = {isa = PBXBuildFile; fileRef = 3652F017245C292B001FABF3 /* list.c */; };
|
||||
3652F066245C292B001FABF3 /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = 3652F01B245C292B001FABF3 /* compress.c */; };
|
||||
|
@ -100,7 +101,6 @@
|
|||
36DFE0CE2459FAB100FC51CE /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 36DBDEA22450C2640057C8D3 /* OpenGL.framework */; };
|
||||
36DFE217245A278700FC51CE /* glsym_gl.c in Sources */ = {isa = PBXBuildFile; fileRef = 36DFE0DB245A1FEC00FC51CE /* glsym_gl.c */; };
|
||||
36DFE218245A278900FC51CE /* rglgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 36DFE0DE245A1FEC00FC51CE /* rglgen.c */; };
|
||||
36E6378C246FFFF30032F5FB /* CryptoManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36E6378A246FFFF30032F5FB /* CryptoManager.cpp */; };
|
||||
36E63790247010C70032F5FB /* Data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36E6378E247010C70032F5FB /* Data.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -126,6 +126,10 @@
|
|||
3602C3C0245DC7E300368900 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
||||
3603E93A246316400051287D /* InputController.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InputController.cpp; sourceTree = "<group>"; };
|
||||
3603E93B246316400051287D /* InputController.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = InputController.hpp; sourceTree = "<group>"; };
|
||||
3638982F2471B7C500F99920 /* MbedTLSCryptoManager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MbedTLSCryptoManager.hpp; sourceTree = "<group>"; };
|
||||
363898302471B7C500F99920 /* OpenSSLCryptoManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenSSLCryptoManager.cpp; sourceTree = "<group>"; };
|
||||
363898312471B7C500F99920 /* MbedTLSCryptoManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MbedTLSCryptoManager.cpp; sourceTree = "<group>"; };
|
||||
363898322471B7C500F99920 /* OpenSSLCryptoManager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OpenSSLCryptoManager.hpp; sourceTree = "<group>"; };
|
||||
3652ECE8245B3AFF001FABF3 /* colorpicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colorpicker.h; sourceTree = "<group>"; };
|
||||
3652ECE9245B3AFF001FABF3 /* renderpass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = renderpass.h; sourceTree = "<group>"; };
|
||||
3652ECEA245B3AFF001FABF3 /* theme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = theme.h; sourceTree = "<group>"; };
|
||||
|
@ -212,13 +216,11 @@
|
|||
3652F001245B6961001FABF3 /* AddHostWindow.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AddHostWindow.hpp; sourceTree = "<group>"; };
|
||||
3652F003245C28C6001FABF3 /* GameStreamClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GameStreamClient.cpp; sourceTree = "<group>"; };
|
||||
3652F004245C28C6001FABF3 /* GameStreamClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = GameStreamClient.hpp; sourceTree = "<group>"; };
|
||||
3652F007245C2918001FABF3 /* mkcert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mkcert.h; sourceTree = "<group>"; };
|
||||
3652F008245C2918001FABF3 /* xml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xml.c; sourceTree = "<group>"; };
|
||||
3652F009245C2918001FABF3 /* client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = client.h; sourceTree = "<group>"; };
|
||||
3652F00A245C2918001FABF3 /* http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http.h; sourceTree = "<group>"; };
|
||||
3652F00B245C2918001FABF3 /* errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = errors.h; sourceTree = "<group>"; };
|
||||
3652F00C245C2918001FABF3 /* client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = client.cpp; sourceTree = "<group>"; };
|
||||
3652F00D245C2918001FABF3 /* mkcert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mkcert.c; sourceTree = "<group>"; };
|
||||
3652F00E245C2918001FABF3 /* xml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xml.h; sourceTree = "<group>"; };
|
||||
3652F00F245C2918001FABF3 /* http.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http.cpp; sourceTree = "<group>"; };
|
||||
3652F017245C292B001FABF3 /* list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = list.c; sourceTree = "<group>"; };
|
||||
|
@ -301,6 +303,7 @@
|
|||
36D3F8432469B5C400CDEF9B /* MoonlightSession.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MoonlightSession.hpp; sourceTree = "<group>"; };
|
||||
36D3F8452469C6BC00CDEF9B /* Log.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Log.h; sourceTree = "<group>"; };
|
||||
36D3F8492469CC2600CDEF9B /* IAudioRenderer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IAudioRenderer.hpp; sourceTree = "<group>"; };
|
||||
36D461BE24709B8F00A543B4 /* build.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = build.sh; path = "../../../../Downloads/openssl-1.1.1g/build.sh"; sourceTree = "<group>"; };
|
||||
36DBDE8E2450BB7E0057C8D3 /* moonlight */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = moonlight; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
36DBDE992450BCD50057C8D3 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||
36DBDE9B2450BCD90057C8D3 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
|
@ -320,7 +323,6 @@
|
|||
36DFE0DF245A1FEC00FC51CE /* rglgen_headers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = rglgen_headers.h; sourceTree = "<group>"; };
|
||||
36DFE0E1245A1FEC00FC51CE /* glsym_es3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = glsym_es3.h; sourceTree = "<group>"; };
|
||||
36DFE0E3245A1FEC00FC51CE /* glsym_gl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = glsym_gl.h; sourceTree = "<group>"; };
|
||||
36E6378A246FFFF30032F5FB /* CryptoManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CryptoManager.cpp; sourceTree = "<group>"; };
|
||||
36E6378B246FFFF30032F5FB /* CryptoManager.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CryptoManager.hpp; sourceTree = "<group>"; };
|
||||
36E6378E247010C70032F5FB /* Data.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Data.cpp; sourceTree = "<group>"; };
|
||||
36E6378F247010C70032F5FB /* Data.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Data.hpp; sourceTree = "<group>"; };
|
||||
|
@ -515,8 +517,6 @@
|
|||
3652F009245C2918001FABF3 /* client.h */,
|
||||
3652F00F245C2918001FABF3 /* http.cpp */,
|
||||
3652F00A245C2918001FABF3 /* http.h */,
|
||||
3652F00D245C2918001FABF3 /* mkcert.c */,
|
||||
3652F007245C2918001FABF3 /* mkcert.h */,
|
||||
3652F008245C2918001FABF3 /* xml.c */,
|
||||
3652F00E245C2918001FABF3 /* xml.h */,
|
||||
3652F00B245C2918001FABF3 /* errors.h */,
|
||||
|
@ -689,6 +689,7 @@
|
|||
36DBDE852450BB7E0057C8D3 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
36D461BE24709B8F00A543B4 /* build.sh */,
|
||||
3602C3C0245DC7E300368900 /* Makefile */,
|
||||
369445A82466CE2700786D0A /* Makefile.libnx */,
|
||||
36A0C03E2461FFF10083289C /* build_opus_lakka_switch.sh */,
|
||||
|
@ -771,10 +772,13 @@
|
|||
36E63789246FFFDC0032F5FB /* crypto */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
36E6378B246FFFF30032F5FB /* CryptoManager.hpp */,
|
||||
363898312471B7C500F99920 /* MbedTLSCryptoManager.cpp */,
|
||||
3638982F2471B7C500F99920 /* MbedTLSCryptoManager.hpp */,
|
||||
363898302471B7C500F99920 /* OpenSSLCryptoManager.cpp */,
|
||||
363898322471B7C500F99920 /* OpenSSLCryptoManager.hpp */,
|
||||
36E6378E247010C70032F5FB /* Data.cpp */,
|
||||
36E6378F247010C70032F5FB /* Data.hpp */,
|
||||
36E6378A246FFFF30032F5FB /* CryptoManager.cpp */,
|
||||
36E6378B246FFFF30032F5FB /* CryptoManager.hpp */,
|
||||
);
|
||||
path = crypto;
|
||||
sourceTree = "<group>";
|
||||
|
@ -867,6 +871,7 @@
|
|||
36DFE0CD2459FA3F00FC51CE /* nanogui_resources.cpp in Sources */,
|
||||
36DFE217245A278700FC51CE /* glsym_gl.c in Sources */,
|
||||
3652F06A245C292B001FABF3 /* protocol.c in Sources */,
|
||||
363898332471B7C500F99920 /* OpenSSLCryptoManager.cpp in Sources */,
|
||||
3652EFFC245B6434001FABF3 /* MainWindow.cpp in Sources */,
|
||||
3652F086245C6CFC001FABF3 /* moonlight_libretro.cpp in Sources */,
|
||||
3652EFD3245B3B00001FABF3 /* button.cpp in Sources */,
|
||||
|
@ -892,6 +897,7 @@
|
|||
3652EFF6245B3CF2001FABF3 /* nanovg.c in Sources */,
|
||||
3652F067245C292B001FABF3 /* packet.c in Sources */,
|
||||
3661D2F92469D1940060EE24 /* FFmpegVideoDecoder.cpp in Sources */,
|
||||
363898342471B7C500F99920 /* MbedTLSCryptoManager.cpp in Sources */,
|
||||
3652F072245C292B001FABF3 /* RtspConnection.c in Sources */,
|
||||
3652F005245C28C6001FABF3 /* GameStreamClient.cpp in Sources */,
|
||||
3652EFE8245B3B00001FABF3 /* opengl.cpp in Sources */,
|
||||
|
@ -900,7 +906,6 @@
|
|||
3652EFF5245B3B00001FABF3 /* popupbutton.cpp in Sources */,
|
||||
3652EFF0245B3B00001FABF3 /* colorwheel.cpp in Sources */,
|
||||
3652F068245C292B001FABF3 /* unix.c in Sources */,
|
||||
36E6378C246FFFF30032F5FB /* CryptoManager.cpp in Sources */,
|
||||
3652F07B245C292B001FABF3 /* RtspParser.c in Sources */,
|
||||
3652EFCF245B3B00001FABF3 /* checkbox.cpp in Sources */,
|
||||
36A0C03A2461E4C00083289C /* SettingsWindow.cpp in Sources */,
|
||||
|
@ -925,7 +930,6 @@
|
|||
3602C3B7245D903000368900 /* HostButton.cpp in Sources */,
|
||||
3652EFD0245B3B00001FABF3 /* vscrollpanel.cpp in Sources */,
|
||||
3652F06D245C292B001FABF3 /* win32.c in Sources */,
|
||||
3652F012245C2919001FABF3 /* mkcert.c in Sources */,
|
||||
3652F002245B6961001FABF3 /* AddHostWindow.cpp in Sources */,
|
||||
3652EFF8245B4EE2001FABF3 /* Application.cpp in Sources */,
|
||||
3652F07E245C292B001FABF3 /* AudioStream.c in Sources */,
|
||||
|
@ -1031,6 +1035,7 @@
|
|||
"-DHAS_POLL",
|
||||
"-DHAS_FCNTL",
|
||||
"-DHAVE_PULSE",
|
||||
"-DUSE_MBEDTLS_CRYPTO",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-lglfw3",
|
||||
|
@ -1044,6 +1049,9 @@
|
|||
"-lavdevice",
|
||||
"-lz",
|
||||
"-lopus",
|
||||
"-lmbedtls",
|
||||
"-lmbedx509",
|
||||
"-lmbedcrypto",
|
||||
);
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
|
@ -1120,6 +1128,7 @@
|
|||
"-DHAS_POLL",
|
||||
"-DHAS_FCNTL",
|
||||
"-DHAVE_PULSE",
|
||||
"-DUSE_MBEDTLS_CRYPTO",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-lglfw3",
|
||||
|
@ -1133,6 +1142,9 @@
|
|||
"-lavdevice",
|
||||
"-lz",
|
||||
"-lopus",
|
||||
"-lmbedtls",
|
||||
"-lmbedx509",
|
||||
"-lmbedcrypto",
|
||||
);
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
|
|
1
run.sh
1
run.sh
|
@ -1,4 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
rm -fr moonlight.nro moonlight.elf moonlight.nacp
|
||||
make -f Makefile.libnx
|
||||
/opt/devkitpro/tools/bin/nxlink -s moonlight.nro
|
||||
|
|
|
@ -15,22 +15,28 @@ static std::vector<std::function<void()>> m_tasks;
|
|||
|
||||
#ifdef __SWITCH__
|
||||
#include <switch.h>
|
||||
static Thread thread;
|
||||
static bool run = true;
|
||||
void terminate_gamestream_thread() {
|
||||
run = false;
|
||||
threadWaitForExit(&thread);
|
||||
}
|
||||
|
||||
static void task_loop() {
|
||||
Thread thread;
|
||||
threadCreate(
|
||||
&thread,
|
||||
[](void* a) {
|
||||
while (1) {
|
||||
while (run) {
|
||||
std::vector<std::function<void()>> m_tasks_copy; {
|
||||
std::lock_guard<std::mutex> guard(m_async_mutex);
|
||||
m_tasks_copy = m_tasks;
|
||||
m_tasks.clear();
|
||||
}
|
||||
|
||||
|
||||
for (auto task: m_tasks_copy) {
|
||||
task();
|
||||
}
|
||||
|
||||
|
||||
usleep(500'000);
|
||||
}
|
||||
},
|
||||
|
@ -41,7 +47,6 @@ static void task_loop() {
|
|||
-2
|
||||
);
|
||||
threadStart(&thread);
|
||||
|
||||
}
|
||||
#else
|
||||
static void task_loop() {
|
||||
|
|
|
@ -1,38 +1,16 @@
|
|||
#include <stdio.h>
|
||||
#include "Data.hpp"
|
||||
#include "client.h"
|
||||
|
||||
extern "C" {
|
||||
#include "mkcert.h"
|
||||
}
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CERTIFICATE_FILE_NAME "client.pem"
|
||||
#define P12_FILE_NAME "client.p12"
|
||||
#define KEY_FILE_NAME "key.pem"
|
||||
#if defined(USE_OPENSSL_CRYPTO)
|
||||
|
||||
class CryptoManager {
|
||||
public:
|
||||
static bool certs_exists();
|
||||
static bool load_certs();
|
||||
static bool generate_certs();
|
||||
|
||||
static Data read_cert_from_file();
|
||||
static Data read_p12_from_file();
|
||||
static Data read_key_from_file();
|
||||
|
||||
static Data SHA1_hash_data(Data data);
|
||||
static Data SHA256_hash_data(Data data);
|
||||
static Data create_AES_key_from_salt_SHA1(Data salted_pin);
|
||||
static Data create_AES_key_from_salt_SHA256(Data salted_pin);
|
||||
static Data aes_encrypt(Data data, Data key);
|
||||
static Data aes_decrypt(Data data, Data key);
|
||||
static Data pem_to_der(Data pem_cert_bytes);
|
||||
static bool verify_signature(Data data, Data signature, Data cert);
|
||||
static Data sign_data(Data data, Data key);
|
||||
static Data get_signature_from_cert(Data cert);
|
||||
static Data get_key_from_cert_key_pair(PCERT_KEY_PAIR cert_key_pair);
|
||||
static Data get_p12_from_cert_key_pair(PCERT_KEY_PAIR cert_key_pair);
|
||||
static Data get_cert_from_cert_key_pair(PCERT_KEY_PAIR cert_key_pair);
|
||||
};
|
||||
#include "OpenSSLCryptoManager.hpp"
|
||||
#define CryptoManager OpenSSLCryptoManager
|
||||
|
||||
#elif defined(USE_MBEDTLS_CRYPTO)
|
||||
|
||||
#include "MbedTLSCryptoManager.hpp"
|
||||
#define CryptoManager MbedTLSCryptoManager
|
||||
|
||||
#else
|
||||
#error Select crypto!
|
||||
#endif
|
||||
|
|
|
@ -5,18 +5,18 @@
|
|||
|
||||
Data::Data(unsigned char* bytes, size_t size) {
|
||||
if (bytes && size > 0) {
|
||||
m_bytes = (unsigned char *)malloc(size);
|
||||
m_bytes = (unsigned char *)malloc(size + 1);
|
||||
m_bytes[size] = '\0';
|
||||
memcpy(m_bytes, bytes, size);
|
||||
m_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
Data::Data(size_t capacity) {
|
||||
if (capacity > 0) {
|
||||
m_bytes = (unsigned char *)malloc(capacity + 1);
|
||||
m_bytes[capacity] = '\0';
|
||||
m_size = capacity;
|
||||
}
|
||||
m_bytes = (unsigned char *)malloc(capacity + 1);
|
||||
memset(m_bytes, 0, capacity + 1);
|
||||
m_bytes[capacity] = '\0';
|
||||
m_size = capacity;
|
||||
}
|
||||
|
||||
Data::~Data() {
|
||||
|
@ -45,9 +45,14 @@ Data Data::append(Data other) {
|
|||
}
|
||||
|
||||
Data::Data(const Data& that): Data(0) {
|
||||
m_bytes = (unsigned char *)malloc(that.size());
|
||||
memcpy(m_bytes, that.bytes(), that.size());
|
||||
m_size = that.size();
|
||||
if (m_bytes) {
|
||||
free(m_bytes);
|
||||
}
|
||||
|
||||
m_bytes = (unsigned char *)malloc(that.size() + 1);
|
||||
memcpy(m_bytes, that.m_bytes, that.m_size);
|
||||
m_bytes[that.m_size] = '\0';
|
||||
m_size = that.m_size;
|
||||
}
|
||||
|
||||
Data& Data::operator=(const Data& that) {
|
||||
|
@ -56,8 +61,9 @@ Data& Data::operator=(const Data& that) {
|
|||
free(m_bytes);
|
||||
}
|
||||
|
||||
m_bytes = (unsigned char *)malloc(that.m_size);
|
||||
m_bytes = (unsigned char *)malloc(that.m_size + 1);
|
||||
memcpy(m_bytes, that.m_bytes, that.m_size);
|
||||
m_bytes[that.m_size] = '\0';
|
||||
m_size = that.m_size;
|
||||
}
|
||||
return *this;
|
||||
|
@ -65,7 +71,12 @@ Data& Data::operator=(const Data& that) {
|
|||
|
||||
Data Data::random_bytes(size_t size) {
|
||||
unsigned char* bytes = (unsigned char*)malloc(sizeof(char) * size);
|
||||
arc4random_buf(bytes, size);
|
||||
srand(time(NULL));
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
bytes[i] = rand() % 255;
|
||||
}
|
||||
|
||||
Data random_data(size);
|
||||
memcpy(random_data.m_bytes, bytes, size);
|
||||
free(bytes);
|
||||
|
@ -81,6 +92,7 @@ Data Data::read_from_file(std::string path) {
|
|||
|
||||
char* buffer = (char*)malloc(size);
|
||||
fread(buffer, 1, size, f);
|
||||
|
||||
Data data(buffer, size);
|
||||
free(buffer);
|
||||
fclose(f);
|
||||
|
@ -89,6 +101,16 @@ Data Data::read_from_file(std::string path) {
|
|||
return Data();
|
||||
}
|
||||
|
||||
void Data::write_to_file(std::string path) {
|
||||
FILE *f = fopen(path.c_str(), "w");
|
||||
if (f) {
|
||||
fwrite(m_bytes, m_size, 1, f);
|
||||
fclose(f);
|
||||
} else {
|
||||
LOG_FMT("Path not found: %s\n", path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Data Data::hex_to_bytes() const {
|
||||
Data data(m_size / 2);
|
||||
char byte_chars[3] = {'\0','\0','\0'};
|
||||
|
@ -105,6 +127,11 @@ Data Data::hex_to_bytes() const {
|
|||
}
|
||||
|
||||
Data Data::hex() const {
|
||||
if (!m_size) {
|
||||
char end = '\n';
|
||||
return Data(&end, 1);
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
Data hex(m_size * 2);
|
||||
char fmt[3] = {'\0','\0','\0'};
|
||||
|
@ -116,9 +143,3 @@ Data Data::hex() const {
|
|||
hex.m_bytes[m_size * 2] = '\0';
|
||||
return hex;
|
||||
}
|
||||
|
||||
void Data::write_to_file(std::string path) {
|
||||
FILE *f = fopen(path.c_str(), "w");
|
||||
fwrite(m_bytes, m_size, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
|
||||
static Data random_bytes(size_t size);
|
||||
static Data read_from_file(std::string path);
|
||||
void write_to_file(std::string path);
|
||||
|
||||
Data hex_to_bytes() const;
|
||||
Data hex() const;
|
||||
|
@ -35,8 +36,6 @@ public:
|
|||
return m_size == 0;
|
||||
}
|
||||
|
||||
void write_to_file(std::string path);
|
||||
|
||||
private:
|
||||
unsigned char* m_bytes = nullptr;
|
||||
size_t m_size = 0;
|
||||
|
|
258
src/crypto/MbedTLSCryptoManager.cpp
Normal file
258
src/crypto/MbedTLSCryptoManager.cpp
Normal file
|
@ -0,0 +1,258 @@
|
|||
#include "MbedTLSCryptoManager.hpp"
|
||||
#include "Settings.hpp"
|
||||
#include "client.h"
|
||||
#include <string.h>
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/x509.h>
|
||||
#include <mbedtls/x509_crt.h>
|
||||
#include <mbedtls/error.h>
|
||||
|
||||
static Data m_cert;
|
||||
static Data m_key;
|
||||
|
||||
static bool _generate_new_cert_key_pair();
|
||||
|
||||
bool MbedTLSCryptoManager::load_cert_key_pair() {
|
||||
if (m_key.is_empty() || m_cert.is_empty()) {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
Data cert = Data::read_from_file(key_dir + CERTIFICATE_FILE_NAME);
|
||||
Data key = Data::read_from_file(key_dir + KEY_FILE_NAME);
|
||||
|
||||
if (!cert.is_empty() && !key.is_empty()) {
|
||||
m_cert = cert;
|
||||
m_key = key;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MbedTLSCryptoManager::generate_new_cert_key_pair() {
|
||||
if (_generate_new_cert_key_pair()) {
|
||||
if (!m_cert.is_empty() && !m_key.is_empty()) {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
mkdirtree(key_dir.c_str());
|
||||
m_cert.write_to_file(key_dir + CERTIFICATE_FILE_NAME);
|
||||
m_key.write_to_file(key_dir + KEY_FILE_NAME);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MbedTLSCryptoManager::remove_cert_key_pair() {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
remove((key_dir + CERTIFICATE_FILE_NAME).c_str());
|
||||
remove((key_dir + KEY_FILE_NAME).c_str());
|
||||
m_cert = Data();
|
||||
m_key = Data();
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::cert_data() {
|
||||
return m_cert;
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::key_data() {
|
||||
return m_key;
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::SHA1_hash_data(Data data) {
|
||||
mbedtls_sha1_context ctx;
|
||||
unsigned char sha1[20];
|
||||
mbedtls_sha1_init(&ctx);
|
||||
mbedtls_sha1_ret(data.bytes(), data.size(), sha1);
|
||||
mbedtls_sha1_free(&ctx);
|
||||
return Data(sha1, sizeof(sha1));
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::SHA256_hash_data(Data data) {
|
||||
mbedtls_sha256_context ctx;
|
||||
unsigned char sha256[32];
|
||||
mbedtls_sha256_init(&ctx);
|
||||
mbedtls_sha256_ret(data.bytes(), data.size(), sha256, 0);
|
||||
mbedtls_sha256_free(&ctx);
|
||||
return Data(sha256, sizeof(sha256));
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::create_AES_key_from_salt_SHA1(Data salted_pin) {
|
||||
return SHA1_hash_data(salted_pin).subdata(0, 16);
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::create_AES_key_from_salt_SHA256(Data salted_pin) {
|
||||
return SHA256_hash_data(salted_pin).subdata(0, 16);
|
||||
}
|
||||
|
||||
static int get_encrypt_size(Data data) {
|
||||
// the size is the length of the data ceiling to the nearest 16 bytes
|
||||
return (((int)data.size() + 15) / 16) * 16;
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::aes_encrypt(Data data, Data key) {
|
||||
mbedtls_aes_context ctx;
|
||||
mbedtls_aes_init(&ctx);
|
||||
mbedtls_aes_setkey_enc(&ctx, key.bytes(), 128);
|
||||
|
||||
int size = get_encrypt_size(data);
|
||||
unsigned char* buffer = (unsigned char*)malloc(size);
|
||||
unsigned char* block_rounded_buffer = (unsigned char*)calloc(1, size);
|
||||
memcpy(block_rounded_buffer, data.bytes(), data.size());
|
||||
|
||||
int block_offset = 0;
|
||||
while (block_offset < size) {
|
||||
mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, block_rounded_buffer + block_offset, buffer + block_offset);
|
||||
block_offset += 16;
|
||||
}
|
||||
|
||||
Data encrypted_data = Data((char*)buffer, size);
|
||||
mbedtls_aes_free(&ctx);
|
||||
free(buffer);
|
||||
free(block_rounded_buffer);
|
||||
return encrypted_data;
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::aes_decrypt(Data data, Data key) {
|
||||
mbedtls_aes_context ctx;
|
||||
mbedtls_aes_init(&ctx);
|
||||
mbedtls_aes_setkey_dec(&ctx, key.bytes(), 128);
|
||||
unsigned char* buffer = (unsigned char*)malloc(data.size());
|
||||
|
||||
int block_offset = 0;
|
||||
while (block_offset < data.size()) {
|
||||
mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, data.bytes() + block_offset, buffer + block_offset);
|
||||
block_offset += 16;
|
||||
}
|
||||
|
||||
Data decrypted_data = Data(buffer, data.size());
|
||||
mbedtls_aes_free(&ctx);
|
||||
free(buffer);
|
||||
return decrypted_data;
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::signature(Data cert) {
|
||||
mbedtls_x509_crt x509;
|
||||
mbedtls_x509_crt_init(&x509);
|
||||
|
||||
mbedtls_x509_crt_parse(&x509, cert.bytes(), cert.size() + 1);
|
||||
|
||||
Data data(x509.sig.p, x509.sig.len);
|
||||
mbedtls_x509_crt_free(&x509);
|
||||
return data;
|
||||
}
|
||||
|
||||
bool MbedTLSCryptoManager::verify_signature(Data data, Data signature, Data cert) {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
Data MbedTLSCryptoManager::sign_data(Data data, Data key) {
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
|
||||
unsigned char hash[32];
|
||||
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
|
||||
size_t size = 0;
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
mbedtls_pk_init(&pk);
|
||||
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
|
||||
|
||||
mbedtls_pk_parse_key(&pk, key.bytes(), key.size() + 1, NULL, 0);
|
||||
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), data.bytes(), data.size(), hash);
|
||||
mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, hash, 0, buf, &size, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
|
||||
mbedtls_pk_free(&pk);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
|
||||
if (size > 0) {
|
||||
return Data(buf, size);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// Cert and key generator
|
||||
|
||||
static void _generate_key(mbedtls_pk_context* key) {
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
|
||||
|
||||
mbedtls_pk_init(key);
|
||||
|
||||
mbedtls_pk_setup(key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
|
||||
mbedtls_rsa_gen_key(mbedtls_pk_rsa(*key), mbedtls_ctr_drbg_random, &ctr_drbg, 2048, 65537);
|
||||
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
}
|
||||
|
||||
static void _generate_cert(mbedtls_x509write_cert* cert, mbedtls_pk_context* key) {
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_mpi serial;
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
|
||||
mbedtls_mpi_init(&serial);
|
||||
mbedtls_mpi_lset(&serial, 1);
|
||||
|
||||
mbedtls_x509write_crt_init(cert);
|
||||
|
||||
mbedtls_x509write_crt_set_version(cert, MBEDTLS_X509_CRT_VERSION_3);
|
||||
mbedtls_x509write_crt_set_subject_name(cert, "CN=NVIDIA GameStream Client");
|
||||
mbedtls_x509write_crt_set_issuer_name(cert, "CN=NVIDIA GameStream Client");
|
||||
mbedtls_x509write_crt_set_subject_key(cert, key);
|
||||
mbedtls_x509write_crt_set_issuer_key(cert, key);
|
||||
mbedtls_x509write_crt_set_md_alg(cert, MBEDTLS_MD_SHA256);
|
||||
mbedtls_x509write_crt_set_validity(cert, "20200101000000", "20300101000000");
|
||||
mbedtls_x509write_crt_set_serial(cert, &serial);
|
||||
|
||||
mbedtls_mpi_free(&serial);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
}
|
||||
|
||||
static bool _generate_new_cert_key_pair() {
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
|
||||
|
||||
mbedtls_x509write_cert cert;
|
||||
mbedtls_pk_context key;
|
||||
|
||||
_generate_key(&key);
|
||||
_generate_cert(&cert, &key);
|
||||
|
||||
unsigned char tmp[4096];
|
||||
memset(tmp, 0, 4096);
|
||||
size_t len = 0;
|
||||
int i = mbedtls_pk_write_key_pem(&key, tmp, 4096);
|
||||
|
||||
len = strlen((char *)tmp);
|
||||
m_key = Data(tmp, len);
|
||||
memset(tmp, 0, 4096);
|
||||
|
||||
i = mbedtls_x509write_crt_pem(&cert, tmp, 4096, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
len = strlen((char *)tmp);
|
||||
m_cert = Data(tmp, len);
|
||||
|
||||
mbedtls_x509write_crt_free(&cert);
|
||||
mbedtls_pk_free(&key);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
return true;
|
||||
}
|
28
src/crypto/MbedTLSCryptoManager.hpp
Normal file
28
src/crypto/MbedTLSCryptoManager.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include <stdio.h>
|
||||
#include "Data.hpp"
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CERTIFICATE_FILE_NAME "client.pem"
|
||||
#define KEY_FILE_NAME "key.pem"
|
||||
|
||||
class MbedTLSCryptoManager {
|
||||
public:
|
||||
static bool load_cert_key_pair();
|
||||
static bool generate_new_cert_key_pair();
|
||||
static void remove_cert_key_pair();
|
||||
|
||||
static Data cert_data();
|
||||
static Data key_data();
|
||||
|
||||
static Data SHA1_hash_data(Data data);
|
||||
static Data SHA256_hash_data(Data data);
|
||||
static Data create_AES_key_from_salt_SHA1(Data salted_pin);
|
||||
static Data create_AES_key_from_salt_SHA256(Data salted_pin);
|
||||
static Data aes_encrypt(Data data, Data key);
|
||||
static Data aes_decrypt(Data data, Data key);
|
||||
|
||||
static Data signature(Data cert);
|
||||
static bool verify_signature(Data data, Data signature, Data cert);
|
||||
static Data sign_data(Data data, Data key);
|
||||
};
|
|
@ -1,5 +1,6 @@
|
|||
#include "CryptoManager.hpp"
|
||||
#include "OpenSSLCryptoManager.hpp"
|
||||
#include "Settings.hpp"
|
||||
#include "client.h"
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
#include <openssl/aes.h>
|
||||
|
@ -7,95 +8,80 @@
|
|||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <openssl/pkcs12.h>
|
||||
#include "Log.h"
|
||||
|
||||
static const int SHA1_HASH_LENGTH = 20;
|
||||
static const int SHA256_HASH_LENGTH = 32;
|
||||
|
||||
static Data m_cert;
|
||||
static Data m_p12;
|
||||
static Data m_key;
|
||||
|
||||
bool CryptoManager::certs_exists() {
|
||||
if (load_certs()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static const int NUM_BITS = 2048;
|
||||
static const int SERIAL = 0;
|
||||
static const int NUM_YEARS = 10;
|
||||
|
||||
bool CryptoManager::load_certs() {
|
||||
if (m_key.is_empty() || m_cert.is_empty() || m_p12.is_empty()) {
|
||||
static bool _generate_new_cert_key_pair();
|
||||
|
||||
bool OpenSSLCryptoManager::load_cert_key_pair() {
|
||||
if (m_key.is_empty() || m_cert.is_empty()) {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
mkdirtree(key_dir.c_str());
|
||||
|
||||
Data cert = Data::read_from_file(key_dir + CERTIFICATE_FILE_NAME);
|
||||
Data p12 = Data::read_from_file(key_dir + P12_FILE_NAME);
|
||||
Data key = Data::read_from_file(key_dir + KEY_FILE_NAME);
|
||||
|
||||
if (!cert.is_empty() && !p12.is_empty() && !key.is_empty()) {
|
||||
if (!cert.is_empty() && !key.is_empty()) {
|
||||
m_cert = cert;
|
||||
m_p12 = p12;
|
||||
m_key = key;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CryptoManager::generate_certs() {
|
||||
auto cert_key_pair = mkcert_generate();
|
||||
|
||||
Data cert = get_cert_from_cert_key_pair(&cert_key_pair);
|
||||
Data p12 = get_p12_from_cert_key_pair(&cert_key_pair);
|
||||
Data key = get_key_from_cert_key_pair(&cert_key_pair);
|
||||
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
mkdirtree(key_dir.c_str());
|
||||
|
||||
if (!cert.is_empty() && !p12.is_empty() && !key.is_empty()) {
|
||||
cert.write_to_file(key_dir + CERTIFICATE_FILE_NAME);
|
||||
p12.write_to_file(key_dir + P12_FILE_NAME);
|
||||
key.write_to_file(key_dir + KEY_FILE_NAME);
|
||||
m_cert = cert;
|
||||
m_p12 = p12;
|
||||
m_key = key;
|
||||
return true;
|
||||
bool OpenSSLCryptoManager::generate_new_cert_key_pair() {
|
||||
if (_generate_new_cert_key_pair()) {
|
||||
if (!m_cert.is_empty() && !m_key.is_empty()) {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
mkdirtree(key_dir.c_str());
|
||||
m_cert.write_to_file(key_dir + CERTIFICATE_FILE_NAME);
|
||||
m_key.write_to_file(key_dir + KEY_FILE_NAME);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Data CryptoManager::read_cert_from_file() {
|
||||
void OpenSSLCryptoManager::remove_cert_key_pair() {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
remove((key_dir + CERTIFICATE_FILE_NAME).c_str());
|
||||
remove((key_dir + KEY_FILE_NAME).c_str());
|
||||
m_cert = Data();
|
||||
m_key = Data();
|
||||
}
|
||||
|
||||
Data OpenSSLCryptoManager::cert_data() {
|
||||
return m_cert;
|
||||
}
|
||||
|
||||
Data CryptoManager::read_p12_from_file() {
|
||||
return m_p12;
|
||||
}
|
||||
|
||||
Data CryptoManager::read_key_from_file() {
|
||||
Data OpenSSLCryptoManager::key_data() {
|
||||
return m_key;
|
||||
}
|
||||
|
||||
Data CryptoManager::SHA1_hash_data(Data data) {
|
||||
unsigned char sha1[SHA1_HASH_LENGTH];
|
||||
Data OpenSSLCryptoManager::SHA1_hash_data(Data data) {
|
||||
unsigned char sha1[20];
|
||||
SHA1(data.bytes(), data.size(), sha1);
|
||||
return Data(sha1, sizeof(sha1));
|
||||
}
|
||||
|
||||
Data CryptoManager::SHA256_hash_data(Data data) {
|
||||
unsigned char sha256[SHA256_HASH_LENGTH];
|
||||
Data OpenSSLCryptoManager::SHA256_hash_data(Data data) {
|
||||
unsigned char sha256[32];
|
||||
SHA256(data.bytes(), data.size(), sha256);
|
||||
return Data(sha256, sizeof(sha256));
|
||||
}
|
||||
|
||||
Data CryptoManager::create_AES_key_from_salt_SHA1(Data salted_pin) {
|
||||
Data OpenSSLCryptoManager::create_AES_key_from_salt_SHA1(Data salted_pin) {
|
||||
return SHA1_hash_data(salted_pin).subdata(0, 16);
|
||||
}
|
||||
|
||||
Data CryptoManager::create_AES_key_from_salt_SHA256(Data salted_pin) {
|
||||
Data OpenSSLCryptoManager::create_AES_key_from_salt_SHA256(Data salted_pin) {
|
||||
return SHA256_hash_data(salted_pin).subdata(0, 16);
|
||||
}
|
||||
|
||||
|
@ -104,7 +90,7 @@ static int get_encrypt_size(Data data) {
|
|||
return (((int)data.size() + 15) / 16) * 16;
|
||||
}
|
||||
|
||||
Data CryptoManager::aes_encrypt(Data data, Data key) {
|
||||
Data OpenSSLCryptoManager::aes_encrypt(Data data, Data key) {
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key((unsigned char*)key.bytes(), 128, &aes_key);
|
||||
int size = get_encrypt_size(data);
|
||||
|
@ -125,7 +111,7 @@ Data CryptoManager::aes_encrypt(Data data, Data key) {
|
|||
return encrypted_data;
|
||||
}
|
||||
|
||||
Data CryptoManager::aes_decrypt(Data data, Data key) {
|
||||
Data OpenSSLCryptoManager::aes_decrypt(Data data, Data key) {
|
||||
AES_KEY aes_key;
|
||||
AES_set_decrypt_key(key.bytes(), 128, &aes_key);
|
||||
unsigned char* buffer = (unsigned char*)malloc(data.size());
|
||||
|
@ -142,25 +128,31 @@ Data CryptoManager::aes_decrypt(Data data, Data key) {
|
|||
return decrypted_data;
|
||||
}
|
||||
|
||||
Data CryptoManager::pem_to_der(Data pem_cert_bytes) {
|
||||
X509* x509;
|
||||
Data OpenSSLCryptoManager::signature(Data cert) {
|
||||
BIO* bio = BIO_new_mem_buf(cert.bytes(), cert.size());
|
||||
X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||
|
||||
BIO* bio = BIO_new_mem_buf(pem_cert_bytes.bytes(), pem_cert_bytes.size());
|
||||
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||
BIO_free(bio);
|
||||
if (!x509) {
|
||||
LOG("Unable to parse certificate in memory!\n");
|
||||
return Data();
|
||||
}
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
i2d_X509_bio(bio, x509);
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10002000L)
|
||||
ASN1_BIT_STRING *asn_signature = x509->signature;
|
||||
#elif (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
ASN1_BIT_STRING *asn_signature;
|
||||
X509_get0_signature(&asn_signature, NULL, x509);
|
||||
#else
|
||||
const ASN1_BIT_STRING *asn_signature;
|
||||
X509_get0_signature(&asn_signature, NULL, x509);
|
||||
#endif
|
||||
|
||||
BUF_MEM* mem;
|
||||
BIO_get_mem_ptr(bio, &mem);
|
||||
|
||||
Data ret = Data(mem->data, mem->length);
|
||||
BIO_free(bio);
|
||||
return ret;
|
||||
Data sig = Data(asn_signature->data, asn_signature->length);
|
||||
X509_free(x509);
|
||||
return sig;
|
||||
}
|
||||
|
||||
bool CryptoManager::verify_signature(Data data, Data signature, Data cert) {
|
||||
bool OpenSSLCryptoManager::verify_signature(Data data, Data signature, Data cert) {
|
||||
BIO* bio = BIO_new_mem_buf(cert.bytes(), cert.size());
|
||||
X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||
|
||||
|
@ -184,14 +176,14 @@ bool CryptoManager::verify_signature(Data data, Data signature, Data cert) {
|
|||
return result > 0;
|
||||
}
|
||||
|
||||
Data CryptoManager::sign_data(Data data, Data key) {
|
||||
Data OpenSSLCryptoManager::sign_data(Data data, Data key) {
|
||||
BIO* bio = BIO_new_mem_buf(key.bytes(), key.size());
|
||||
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
||||
|
||||
BIO_free(bio);
|
||||
|
||||
if (!pkey) {
|
||||
LOG("Unable to parse private key in memory!");
|
||||
LOG("Unable to parse private key in memory...\n");
|
||||
return Data();
|
||||
}
|
||||
|
||||
|
@ -208,8 +200,8 @@ Data CryptoManager::sign_data(Data data, Data key) {
|
|||
|
||||
if (result <= 0) {
|
||||
free(signature);
|
||||
LOG("Unable to sign data!");
|
||||
exit(-1);
|
||||
LOG("Unable to sign data...\n");
|
||||
Data();
|
||||
}
|
||||
|
||||
Data signed_data = Data(signature, slen);
|
||||
|
@ -217,37 +209,27 @@ Data CryptoManager::sign_data(Data data, Data key) {
|
|||
return signed_data;
|
||||
}
|
||||
|
||||
Data CryptoManager::get_signature_from_cert(Data cert) {
|
||||
BIO* bio = BIO_new_mem_buf(cert.bytes(), cert.size());
|
||||
X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||
// Cert and key generator
|
||||
|
||||
static Data _cert_data(X509* cert) {
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!x509) {
|
||||
LOG("Unable to parse certificate in memory!\n");
|
||||
exit(-1);
|
||||
}
|
||||
PEM_write_bio_X509(bio, cert);
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10002000L)
|
||||
ASN1_BIT_STRING *asn_signature = x509->signature;
|
||||
#elif (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
ASN1_BIT_STRING *asn_signature;
|
||||
X509_get0_signature(&asn_signature, NULL, x509);
|
||||
#else
|
||||
const ASN1_BIT_STRING *asn_signature;
|
||||
X509_get0_signature(&asn_signature, NULL, x509);
|
||||
#endif
|
||||
|
||||
Data sig = Data(asn_signature->data, asn_signature->length);
|
||||
X509_free(x509);
|
||||
return sig;
|
||||
BUF_MEM* mem;
|
||||
BIO_get_mem_ptr(bio, &mem);
|
||||
Data data = Data(mem->data, mem->length);
|
||||
BIO_free(bio);
|
||||
return data;
|
||||
}
|
||||
|
||||
Data CryptoManager::get_key_from_cert_key_pair(PCERT_KEY_PAIR cert_key_pair) {
|
||||
static Data _key_data(EVP_PKEY* pk) {
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
PEM_write_bio_PrivateKey(bio, cert_key_pair->pkey, NULL, NULL, 0, NULL, NULL);
|
||||
PEM_write_bio_PrivateKey(bio, pk, NULL, NULL, 0, NULL, NULL);
|
||||
#else
|
||||
PEM_write_bio_PrivateKey_traditional(bio, cert_key_pair->pkey, NULL, NULL, 0, NULL, NULL);
|
||||
PEM_write_bio_PrivateKey_traditional(bio, pk, NULL, NULL, 0, NULL, NULL);
|
||||
#endif
|
||||
|
||||
BUF_MEM* mem;
|
||||
|
@ -257,26 +239,55 @@ Data CryptoManager::get_key_from_cert_key_pair(PCERT_KEY_PAIR cert_key_pair) {
|
|||
return data;
|
||||
}
|
||||
|
||||
Data CryptoManager::get_p12_from_cert_key_pair(PCERT_KEY_PAIR cert_key_pair) {
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
static bool _generate_new_cert_key_pair() {
|
||||
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
|
||||
BIO *bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
|
||||
|
||||
i2d_PKCS12_bio(bio, cert_key_pair->p12);
|
||||
X509* cert = X509_new();
|
||||
EVP_PKEY* pk = EVP_PKEY_new();
|
||||
BIGNUM* bne = BN_new();
|
||||
RSA* rsa = RSA_new();
|
||||
|
||||
BUF_MEM* mem;
|
||||
BIO_get_mem_ptr(bio, &mem);
|
||||
Data data = Data(mem->data, mem->length);
|
||||
BIO_free(bio);
|
||||
return data;
|
||||
}
|
||||
|
||||
Data CryptoManager::get_cert_from_cert_key_pair(PCERT_KEY_PAIR cert_key_pair) {
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
|
||||
PEM_write_bio_X509(bio, cert_key_pair->x509);
|
||||
|
||||
BUF_MEM* mem;
|
||||
BIO_get_mem_ptr(bio, &mem);
|
||||
Data data = Data(mem->data, mem->length);
|
||||
BIO_free(bio);
|
||||
return data;
|
||||
BN_set_word(bne, RSA_F4);
|
||||
RSA_generate_key_ex(rsa, NUM_BITS, bne, NULL);
|
||||
|
||||
EVP_PKEY_assign_RSA(pk, rsa);
|
||||
|
||||
X509_set_version(cert, 2);
|
||||
ASN1_INTEGER_set(X509_get_serialNumber(cert), SERIAL);
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
X509_gmtime_adj(X509_get_notBefore(cert), 0);
|
||||
X509_gmtime_adj(X509_get_notAfter(cert), 60 * 60 * 24 * 365 * NUM_YEARS);
|
||||
#else
|
||||
ASN1_TIME* before = ASN1_STRING_dup(X509_get0_notBefore(cert));
|
||||
ASN1_TIME* after = ASN1_STRING_dup(X509_get0_notAfter(cert));
|
||||
|
||||
X509_gmtime_adj(before, 0);
|
||||
X509_gmtime_adj(after, 60 * 60 * 24 * 365 * NUM_YEARS);
|
||||
|
||||
X509_set1_notBefore(cert, before);
|
||||
X509_set1_notAfter(cert, after);
|
||||
|
||||
ASN1_STRING_free(before);
|
||||
ASN1_STRING_free(after);
|
||||
#endif
|
||||
|
||||
X509_set_pubkey(cert, pk);
|
||||
|
||||
X509_NAME* name = X509_get_subject_name(cert);
|
||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char*)"NVIDIA GameStream Client", -1, -1, 0);
|
||||
X509_set_issuer_name(cert, name);
|
||||
|
||||
X509_sign(cert, pk, EVP_sha256());
|
||||
|
||||
BN_free(bne);
|
||||
|
||||
BIO_free(bio_err);
|
||||
|
||||
m_cert = _cert_data(cert);
|
||||
m_key = _key_data(pk);
|
||||
|
||||
X509_free(cert);
|
||||
EVP_PKEY_free(pk);
|
||||
return true;
|
||||
}
|
28
src/crypto/OpenSSLCryptoManager.hpp
Normal file
28
src/crypto/OpenSSLCryptoManager.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include <stdio.h>
|
||||
#include "Data.hpp"
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CERTIFICATE_FILE_NAME "client.pem"
|
||||
#define KEY_FILE_NAME "key.pem"
|
||||
|
||||
class OpenSSLCryptoManager {
|
||||
public:
|
||||
static bool load_cert_key_pair();
|
||||
static bool generate_new_cert_key_pair();
|
||||
static void remove_cert_key_pair();
|
||||
|
||||
static Data cert_data();
|
||||
static Data key_data();
|
||||
|
||||
static Data SHA1_hash_data(Data data);
|
||||
static Data SHA256_hash_data(Data data);
|
||||
static Data create_AES_key_from_salt_SHA1(Data salted_pin);
|
||||
static Data create_AES_key_from_salt_SHA256(Data salted_pin);
|
||||
static Data aes_encrypt(Data data, Data key);
|
||||
static Data aes_decrypt(Data data, Data key);
|
||||
|
||||
static Data signature(Data cert);
|
||||
static bool verify_signature(Data data, Data signature, Data cert);
|
||||
static Data sign_data(Data data, Data key);
|
||||
};
|
|
@ -5,8 +5,6 @@
|
|||
#include "Limelight.h"
|
||||
#include "libretro.h"
|
||||
#include "InputController.hpp"
|
||||
#include <curl/curl.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#ifdef __SWITCH__
|
||||
#include <glad/glad.h>
|
||||
|
@ -55,12 +53,11 @@ static int16_t glfw_input_state_cb(unsigned port, unsigned device, unsigned inde
|
|||
return 0;
|
||||
}
|
||||
|
||||
#include "CryptoManager.hpp"
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
input_state_cb = glfw_input_state_cb;
|
||||
|
||||
OpenSSL_add_all_algorithms();
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
glfwInit();
|
||||
|
||||
glfwSetErrorCallback([](int i, const char *error) {
|
||||
|
@ -140,6 +137,12 @@ int main(int argc, const char * argv[]) {
|
|||
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
#ifdef __SWITCH__
|
||||
extern void terminate_gamestream_thread();
|
||||
terminate_gamestream_thread();
|
||||
#endif
|
||||
//nanogui::shutdown();
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,22 @@ uint16_t ntohs(uint16_t netshort) {
|
|||
return __builtin_bswap16(netshort);
|
||||
}
|
||||
|
||||
uid_t getuid() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uid_t geteuid() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
gid_t getgid(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
gid_t getegid(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sigaction(int a, const struct sigaction* b, struct sigaction* c) {
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue