From 5d2e5dab8b9a3059b0fad678d7f46f1c7145327e Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Tue, 17 Sep 2019 00:52:04 -0700 Subject: [PATCH] Added compile switch to support SSL/TLS key export for debug --- microscript/ILibDuktape_HttpStream.c | 21 +++++++++++++++++++++ microscript/ILibDuktape_net.c | 23 +++++++++++++++++++++++ microstack/ILibCrypto.c | 26 ++++++++++++++++++++++++++ microstack/ILibCrypto.h | 4 ++++ 4 files changed, 74 insertions(+) diff --git a/microscript/ILibDuktape_HttpStream.c b/microscript/ILibDuktape_HttpStream.c index 872f6d7..11db8b6 100644 --- a/microscript/ILibDuktape_HttpStream.c +++ b/microscript/ILibDuktape_HttpStream.c @@ -4146,6 +4146,24 @@ duk_ret_t ILibDuktape_httpStream_webSocketStream_encoded_Finalizer(duk_context * return(0); } +#ifdef _SSL_KEYS_EXPORTABLE +duk_ret_t ILibDuktape_httpStream_webSocket_exportKeys(duk_context *ctx) +{ + duk_push_this(ctx); + duk_get_prop_string(ctx, -1, ILibDuktape_WSDEC2WS); + + ILibDuktape_WebSocket_State *state = (ILibDuktape_WebSocket_State*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_WebSocket_StatePtr); + if (state->encodedStream->writableStream->pipedReadable != NULL) + { + duk_push_heapptr(ctx, state->encodedStream->writableStream->pipedReadable); // [readable] + duk_get_prop_string(ctx, -1, "_exportKeys"); // [readable][exportKeys] + duk_swap_top(ctx, -2); // [exportKeys][this] + duk_call_method(ctx, 0); // [ret] + return(1); + } + return(ILibDuktape_Error(ctx, "Error exporting keys")); +} +#endif duk_ret_t ILibDuktape_httpStream_webSocketStream_new(duk_context *ctx) { ILibDuktape_WebSocket_State *state; @@ -4176,6 +4194,9 @@ duk_ret_t ILibDuktape_httpStream_webSocketStream_new(duk_context *ctx) ILibDuktape_EventEmitter_CreateEventEx(ILibDuktape_EventEmitter_GetEmitter(ctx, -1), "pong"); ILibDuktape_CreateProperty_InstanceMethod(ctx, "ping", ILibDuktape_httpStream_webSocketStream_sendPing, DUK_VARARGS); ILibDuktape_CreateProperty_InstanceMethod(ctx, "pong", ILibDuktape_httpStream_webSocketStream_sendPong, DUK_VARARGS); +#ifdef _SSL_KEYS_EXPORTABLE + ILibDuktape_CreateInstanceMethod(ctx, "_exportKeys", ILibDuktape_httpStream_webSocket_exportKeys, 0); +#endif ILibDuktape_CreateReadonlyProperty(ctx, "decoded"); // [WebSocket] ILibDuktape_CreateFinalizer(ctx, ILibDuktape_httpStream_webSocketStream_finalizer); diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index 272d970..d686fce 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -1732,6 +1732,25 @@ void ILibDuktape_TLS_connect_resolveError(duk_context *ctx, void ** args, int ar if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "tls.socket.OnError(): "); } duk_pop(ctx); } +#ifdef _SSL_KEYS_EXPORTABLE +duk_ret_t ILibDuktape_TLS_exportKeys(duk_context *ctx) +{ + char buffer[2000]; + int bufferLen; + + ILibDuktape_net_socket *data; + duk_push_this(ctx); // [socket] + + data = (ILibDuktape_net_socket*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_net_socket_ptr); + if (data != NULL) + { + bufferLen = util_exportkeys(data->ssl, buffer, sizeof(buffer)); + duk_push_lstring(ctx, buffer, bufferLen); + return(1); + } + return(ILibDuktape_Error(ctx, "Error exporting OpenSSL Keys")); +} +#endif duk_ret_t ILibDuktape_TLS_connect(duk_context *ctx) { int nargs = duk_get_top(ctx), i; @@ -1785,6 +1804,10 @@ duk_ret_t ILibDuktape_TLS_connect(duk_context *ctx) ILibDuktape_net_socket_PUSH(ctx, module); // [socket] ILibDuktape_WriteID(ctx, "tls.socket"); +#ifdef _SSL_KEYS_EXPORTABLE + ILibDuktape_CreateInstanceMethod(ctx, "_exportKeys", ILibDuktape_TLS_exportKeys, 0); +#endif + duk_dup(ctx, 0); // [socket][options] if (duk_has_prop_string(ctx, -1, "secureContext")) { diff --git a/microstack/ILibCrypto.c b/microstack/ILibCrypto.c index 78c7e5c..d9a5315 100644 --- a/microstack/ILibCrypto.c +++ b/microstack/ILibCrypto.c @@ -1046,6 +1046,32 @@ int __fastcall util_rsaverify(X509 *cert, char* data, int datalen, char* sign, i return r; } +#ifdef _SSL_KEYS_EXPORTABLE +int __fastcall util_exportkeys(SSL* ssl, char *buffer, size_t bufferSize) +{ + int len = 0; + char clientRandom[32], serverRandom[32], sessionSecret[48], clientRandomHex[65], serverRandomHex[65], sessionSecretHex[97]; + + // Get the client random and session key. + if (ssl == NULL) return(0); + if (SSL_get_client_random(ssl, (unsigned char*)clientRandom, 32) != 32) return(0); + if (SSL_get_server_random(ssl, (unsigned char*)serverRandom, 32) != 32) return(0); + if (SSL_SESSION_get_master_key(SSL_get_session(ssl), (unsigned char*)sessionSecret, 48) != 48) return(0); + + // Convert the randoms and key into hex + util_tohex(clientRandom, 32, clientRandomHex); + util_tohex(serverRandom, 32, serverRandomHex); + util_tohex(sessionSecret, 48, sessionSecretHex); + + // Append the client random and key to the log file. + if (buffer != NULL && bufferSize > 0) + { + len = sprintf_s(buffer, bufferSize, "CLIENT_RANDOM %s %s\r\nCLIENT_RANDOM %s %s\r\n", clientRandomHex, sessionSecretHex, serverRandomHex, sessionSecretHex); + } + return(len); +} +#endif + #ifdef _DEBUG // Saves the SSL/TLS session private keys to file. // Because we do lots of DTLS, we will be saving both client and server randoms pointing to the same key. diff --git a/microstack/ILibCrypto.h b/microstack/ILibCrypto.h index 7f7fea9..b3d545b 100644 --- a/microstack/ILibCrypto.h +++ b/microstack/ILibCrypto.h @@ -172,6 +172,10 @@ int __fastcall util_rsaencrypt(X509 *cert, char* data, int datalen, char** enc int __fastcall util_rsadecrypt(struct util_cert cert, char* data, int datalen, char** decdata); int __fastcall util_rsaverify(X509 *cert, char* data, int datalen, char* sign, int signlen); +#ifdef _SSL_KEYS_EXPORTABLE +int __fastcall util_exportkeys(SSL* ssl, char *buffer, size_t bufferSize); +#endif + #ifdef _DEBUG void __fastcall util_savekeys(SSL* ssl); #endif