From 2c42ea909b5e333d279e08a004e6654820f814fd Mon Sep 17 00:00:00 2001 From: Ben Vanik <ben.vanik@gmail.com> Date: Wed, 6 Feb 2013 21:47:05 -0800 Subject: [PATCH] Removing the dependency on OpenSSL, as it sucks. --- .gitmodules | 3 - src/xenia/dbg/client.h | 6 +- src/xenia/dbg/content_source.h | 6 +- src/xenia/dbg/debugger.cc | 7 +- src/xenia/dbg/debugger.h | 6 +- src/xenia/dbg/listener.h | 6 +- src/xenia/dbg/simple_sha1.cc | 228 +++++++++++++++++++++++++++++++++ src/xenia/dbg/simple_sha1.h | 31 +++++ src/xenia/dbg/sources.gypi | 2 + src/xenia/dbg/ws_client.cc | 43 ++++--- src/xenia/dbg/ws_client.h | 6 +- src/xenia/dbg/ws_listener.h | 6 +- third_party/openssl | 1 - tools/xenia-run/xenia-run.cc | 2 +- xenia.gyp | 1 - 15 files changed, 310 insertions(+), 44 deletions(-) create mode 100644 src/xenia/dbg/simple_sha1.cc create mode 100644 src/xenia/dbg/simple_sha1.h delete mode 160000 third_party/openssl diff --git a/.gitmodules b/.gitmodules index 2bc3d0ba8..e27e2959d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,6 +19,3 @@ [submodule "third_party/wslay"] path = third_party/wslay url = https://github.com/benvanik/wslay.git -[submodule "third_party/openssl"] - path = third_party/openssl - url = https://github.com/benvanik/openssl.git diff --git a/src/xenia/dbg/client.h b/src/xenia/dbg/client.h index 5939468cc..0946334c7 100644 --- a/src/xenia/dbg/client.h +++ b/src/xenia/dbg/client.h @@ -7,8 +7,8 @@ ****************************************************************************** */ -#ifndef XENIA_KERNEL_DBG_CLIENT_H_ -#define XENIA_KERNEL_DBG_CLIENT_H_ +#ifndef XENIA_DBG_CLIENT_H_ +#define XENIA_DBG_CLIENT_H_ #include <xenia/common.h> #include <xenia/core.h> @@ -41,4 +41,4 @@ protected: } // namespace xe -#endif // XENIA_KERNEL_DBG_CLIENT_H_ +#endif // XENIA_DBG_CLIENT_H_ diff --git a/src/xenia/dbg/content_source.h b/src/xenia/dbg/content_source.h index 5a879823e..a063355b0 100644 --- a/src/xenia/dbg/content_source.h +++ b/src/xenia/dbg/content_source.h @@ -7,8 +7,8 @@ ****************************************************************************** */ -#ifndef XENIA_KERNEL_DBG_CONTENT_SOURCE_H_ -#define XENIA_KERNEL_DBG_CONTENT_SOURCE_H_ +#ifndef XENIA_DBG_CONTENT_SOURCE_H_ +#define XENIA_DBG_CONTENT_SOURCE_H_ #include <xenia/common.h> #include <xenia/core.h> @@ -40,4 +40,4 @@ protected: } // namespace xe -#endif // XENIA_KERNEL_DBG_CONTENT_SOURCE_H_ +#endif // XENIA_DBG_CONTENT_SOURCE_H_ diff --git a/src/xenia/dbg/debugger.cc b/src/xenia/dbg/debugger.cc index c0d89cf8b..2e41b8336 100644 --- a/src/xenia/dbg/debugger.cc +++ b/src/xenia/dbg/debugger.cc @@ -33,11 +33,12 @@ Debugger::Debugger(xe_pal_ref pal) { } Debugger::~Debugger() { - for (std::vector<Client*>::iterator it = clients_.begin(); - it != clients_.end(); ++it) { + std::vector<Client*> clients(clients_.begin(), clients_.end()); + clients_.clear(); + for (std::vector<Client*>::iterator it = clients.begin(); + it != clients.end(); ++it) { delete *it; } - clients_.clear(); for (std::map<uint32_t, ContentSource*>::iterator it = content_sources_.begin(); it != content_sources_.end(); ++it) { diff --git a/src/xenia/dbg/debugger.h b/src/xenia/dbg/debugger.h index 71453334d..158b98e6d 100644 --- a/src/xenia/dbg/debugger.h +++ b/src/xenia/dbg/debugger.h @@ -7,8 +7,8 @@ ****************************************************************************** */ -#ifndef XENIA_KERNEL_DBG_DEBUGGER_H_ -#define XENIA_KERNEL_DBG_DEBUGGER_H_ +#ifndef XENIA_DBG_DEBUGGER_H_ +#define XENIA_DBG_DEBUGGER_H_ #include <xenia/common.h> #include <xenia/core.h> @@ -58,4 +58,4 @@ private: } // namespace xe -#endif // XENIA_KERNEL_DBG_DEBUGGER_H_ +#endif // XENIA_DBG_DEBUGGER_H_ diff --git a/src/xenia/dbg/listener.h b/src/xenia/dbg/listener.h index 4c12931b1..43a160e6c 100644 --- a/src/xenia/dbg/listener.h +++ b/src/xenia/dbg/listener.h @@ -7,8 +7,8 @@ ****************************************************************************** */ -#ifndef XENIA_KERNEL_DBG_LISTENER_H_ -#define XENIA_KERNEL_DBG_LISTENER_H_ +#ifndef XENIA_DBG_LISTENER_H_ +#define XENIA_DBG_LISTENER_H_ #include <xenia/common.h> #include <xenia/core.h> @@ -39,4 +39,4 @@ protected: } // namespace xe -#endif // XENIA_KERNEL_DBG_LISTENER_H_ +#endif // XENIA_DBG_LISTENER_H_ diff --git a/src/xenia/dbg/simple_sha1.cc b/src/xenia/dbg/simple_sha1.cc new file mode 100644 index 000000000..f331b9b97 --- /dev/null +++ b/src/xenia/dbg/simple_sha1.cc @@ -0,0 +1,228 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include <xenia/dbg/simple_sha1.h> + + +using namespace xe; +using namespace xe::dbg; + + +namespace { + + +// http://git.kernel.org/?p=git/git.git;a=blob;f=block-sha1/sha1.c + +/* + * SHA1 routine optimized to do word accesses rather than byte accesses, + * and to avoid unnecessary copies into the context array. + * + * This was initially based on the Mozilla SHA1 implementation, although + * none of the original Mozilla code remains. + */ + +typedef struct { + size_t size; + uint32_t H[5]; + uint32_t W[16]; +} SHA_CTX; + +#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r))) +#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n)) +#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n) + +#define setW(x, val) (*(volatile unsigned int *)&W(x) = (val)) + +#define get_be32(p) ntohl(*(unsigned int *)(p)) +#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0) + +#define W(x) (array[(x)&15]) + +#define SHA_SRC(t) get_be32((unsigned char *) block + (t)*4) +#define SHA_MIX(t) SHA_ROL(W((t)+13) ^ W((t)+8) ^ W((t)+2) ^ W(t), 1); + +#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \ + unsigned int TEMP = input(t); setW(t, TEMP); \ + E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \ + B = SHA_ROR(B, 2); } while (0) + +#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E ) +#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E ) +#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E ) + +static void SHA1_Block(SHA_CTX *ctx, const void *block) { + uint32_t A = ctx->H[0]; + uint32_t B = ctx->H[1]; + uint32_t C = ctx->H[2]; + uint32_t D = ctx->H[3]; + uint32_t E = ctx->H[4]; + + uint32_t array[16]; + + /* Round 1 - iterations 0-16 take their input from 'block' */ + T_0_15( 0, A, B, C, D, E); + T_0_15( 1, E, A, B, C, D); + T_0_15( 2, D, E, A, B, C); + T_0_15( 3, C, D, E, A, B); + T_0_15( 4, B, C, D, E, A); + T_0_15( 5, A, B, C, D, E); + T_0_15( 6, E, A, B, C, D); + T_0_15( 7, D, E, A, B, C); + T_0_15( 8, C, D, E, A, B); + T_0_15( 9, B, C, D, E, A); + T_0_15(10, A, B, C, D, E); + T_0_15(11, E, A, B, C, D); + T_0_15(12, D, E, A, B, C); + T_0_15(13, C, D, E, A, B); + T_0_15(14, B, C, D, E, A); + T_0_15(15, A, B, C, D, E); + + /* Round 1 - tail. Input from 512-bit mixing array */ + T_16_19(16, E, A, B, C, D); + T_16_19(17, D, E, A, B, C); + T_16_19(18, C, D, E, A, B); + T_16_19(19, B, C, D, E, A); + + /* Round 2 */ + T_20_39(20, A, B, C, D, E); + T_20_39(21, E, A, B, C, D); + T_20_39(22, D, E, A, B, C); + T_20_39(23, C, D, E, A, B); + T_20_39(24, B, C, D, E, A); + T_20_39(25, A, B, C, D, E); + T_20_39(26, E, A, B, C, D); + T_20_39(27, D, E, A, B, C); + T_20_39(28, C, D, E, A, B); + T_20_39(29, B, C, D, E, A); + T_20_39(30, A, B, C, D, E); + T_20_39(31, E, A, B, C, D); + T_20_39(32, D, E, A, B, C); + T_20_39(33, C, D, E, A, B); + T_20_39(34, B, C, D, E, A); + T_20_39(35, A, B, C, D, E); + T_20_39(36, E, A, B, C, D); + T_20_39(37, D, E, A, B, C); + T_20_39(38, C, D, E, A, B); + T_20_39(39, B, C, D, E, A); + + /* Round 3 */ + T_40_59(40, A, B, C, D, E); + T_40_59(41, E, A, B, C, D); + T_40_59(42, D, E, A, B, C); + T_40_59(43, C, D, E, A, B); + T_40_59(44, B, C, D, E, A); + T_40_59(45, A, B, C, D, E); + T_40_59(46, E, A, B, C, D); + T_40_59(47, D, E, A, B, C); + T_40_59(48, C, D, E, A, B); + T_40_59(49, B, C, D, E, A); + T_40_59(50, A, B, C, D, E); + T_40_59(51, E, A, B, C, D); + T_40_59(52, D, E, A, B, C); + T_40_59(53, C, D, E, A, B); + T_40_59(54, B, C, D, E, A); + T_40_59(55, A, B, C, D, E); + T_40_59(56, E, A, B, C, D); + T_40_59(57, D, E, A, B, C); + T_40_59(58, C, D, E, A, B); + T_40_59(59, B, C, D, E, A); + + /* Round 4 */ + T_60_79(60, A, B, C, D, E); + T_60_79(61, E, A, B, C, D); + T_60_79(62, D, E, A, B, C); + T_60_79(63, C, D, E, A, B); + T_60_79(64, B, C, D, E, A); + T_60_79(65, A, B, C, D, E); + T_60_79(66, E, A, B, C, D); + T_60_79(67, D, E, A, B, C); + T_60_79(68, C, D, E, A, B); + T_60_79(69, B, C, D, E, A); + T_60_79(70, A, B, C, D, E); + T_60_79(71, E, A, B, C, D); + T_60_79(72, D, E, A, B, C); + T_60_79(73, C, D, E, A, B); + T_60_79(74, B, C, D, E, A); + T_60_79(75, A, B, C, D, E); + T_60_79(76, E, A, B, C, D); + T_60_79(77, D, E, A, B, C); + T_60_79(78, C, D, E, A, B); + T_60_79(79, B, C, D, E, A); + + ctx->H[0] += A; + ctx->H[1] += B; + ctx->H[2] += C; + ctx->H[3] += D; + ctx->H[4] += E; +} + +void SHA1_Update(SHA_CTX *ctx, const void *data, unsigned long len) +{ + uint32_t lenW = ctx->size & 63; + ctx->size += len; + + if (lenW) { + uint32_t left = 64 - lenW; + if (len < left) { + left = len; + } + memcpy(lenW + (char *)ctx->W, data, left); + lenW = (lenW + left) & 63; + len -= left; + data = ((const char *)data + left); + if (lenW) { + return; + } + SHA1_Block(ctx, ctx->W); + } + while (len >= 64) { + SHA1_Block(ctx, data); + data = ((const char *)data + 64); + len -= 64; + } + if (len) { + memcpy(ctx->W, data, len); + } +} + +} + + +void xe::dbg::SHA1(const uint8_t* data, size_t length, uint8_t out_hash[20]) { + static const uint8_t pad[64] = { 0x80 }; + + SHA_CTX ctx = { + 0, + { + 0x67452301, + 0xefcdab89, + 0x98badcfe, + 0x10325476, + 0xc3d2e1f0, + }, + { 0 } + }; + + SHA1_Update(&ctx, data, length); + + uint32_t padlen[2] = { + htonl((uint32_t)(ctx.size >> 29)), + htonl((uint32_t)(ctx.size << 3)), + }; + + size_t i = ctx.size & 63; + SHA1_Update(&ctx, pad, 1 + (63 & (55 - i))); + SHA1_Update(&ctx, padlen, 8); + + for (size_t n = 0; n < 5; n++) { + put_be32(out_hash + n * 4, ctx.H[n]); + } +} diff --git a/src/xenia/dbg/simple_sha1.h b/src/xenia/dbg/simple_sha1.h new file mode 100644 index 000000000..7ac269d2d --- /dev/null +++ b/src/xenia/dbg/simple_sha1.h @@ -0,0 +1,31 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_DBG_SIMPLE_SHA1_H_ +#define XENIA_DBG_SIMPLE_SHA1_H_ + +#include <xenia/common.h> +#include <xenia/core.h> + + +namespace xe { +namespace dbg { + + +// This is a (likely) slow SHA1 designed for use on small values such as +// Websocket security keys. If we need something more complex it'd be best +// to use a real library. +void SHA1(const uint8_t* data, size_t length, uint8_t out_hash[20]); + + +} // namespace dbg +} // namespace xe + + +#endif // XENIA_DBG_SIMPLE_SHA1_H_ diff --git a/src/xenia/dbg/sources.gypi b/src/xenia/dbg/sources.gypi index 69a745469..d379f69f1 100644 --- a/src/xenia/dbg/sources.gypi +++ b/src/xenia/dbg/sources.gypi @@ -9,6 +9,8 @@ 'debugger.h', 'listener.cc', 'listener.h', + 'simple_sha1.cc', + 'simple_sha1.h', 'ws_client.cc', 'ws_client.h', 'ws_listener.cc', diff --git a/src/xenia/dbg/ws_client.cc b/src/xenia/dbg/ws_client.cc index 3f399051b..c8e00f3eb 100644 --- a/src/xenia/dbg/ws_client.cc +++ b/src/xenia/dbg/ws_client.cc @@ -10,6 +10,7 @@ #include <xenia/dbg/ws_client.h> #include <xenia/dbg/debugger.h> +#include <xenia/dbg/simple_sha1.h> #include <fcntl.h> #include <poll.h> @@ -18,11 +19,6 @@ #include <sys/socket.h> #include <wslay/wslay.h> -#include <openssl/bio.h> -#include <openssl/buffer.h> -#include <openssl/hmac.h> -#include <openssl/sha.h> - using namespace xe; using namespace xe::dbg; @@ -152,18 +148,31 @@ void WsClientOnMsgCallback(wslay_event_context_ptr ctx, } std::string EncodeBase64(const uint8_t* input, size_t length) { - // Good god what a horrible API. - BIO* b64 = BIO_new(BIO_f_base64()); - BIO* bmem = BIO_new(BIO_s_mem()); - b64 = BIO_push(b64, bmem); - BIO_write(b64, input, length); - XEIGNORE(BIO_flush(b64)); - BUF_MEM* bptr; - BIO_get_mem_ptr(b64, &bptr); - std::string result(bptr->data, bptr->length); - BIO_free_all(b64); - // Strip the last character, which is a \n. - result.erase(result.size() - 1); + static const char b64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + std::string result; + size_t remaining = length; + size_t n = 0; + while (remaining) { + result.push_back(b64[input[n] >> 2]); + result.push_back(b64[((input[n] & 0x03) << 4) | + ((input[n + 1] & 0xf0) >> 4)]); + remaining--; + if (remaining) { + result.push_back(b64[((input[n + 1] & 0x0f) << 2) | + ((input[n + 2] & 0xc0) >> 6)]); + remaining--; + } else { + result.push_back('='); + } + if (remaining) { + result.push_back(b64[input[n + 2] & 0x3f]); + remaining--; + } else { + result.push_back('='); + } + n += 3; + } return result; } diff --git a/src/xenia/dbg/ws_client.h b/src/xenia/dbg/ws_client.h index 982370bbc..3f69186c7 100644 --- a/src/xenia/dbg/ws_client.h +++ b/src/xenia/dbg/ws_client.h @@ -7,8 +7,8 @@ ****************************************************************************** */ -#ifndef XENIA_KERNEL_DBG_WS_CLIENT_H_ -#define XENIA_KERNEL_DBG_WS_CLIENT_H_ +#ifndef XENIA_DBG_WS_CLIENT_H_ +#define XENIA_DBG_WS_CLIENT_H_ #include <xenia/common.h> #include <xenia/core.h> @@ -58,4 +58,4 @@ private: } // namespace xe -#endif // XENIA_KERNEL_DBG_WS_CLIENT_H_ +#endif // XENIA_DBG_WS_CLIENT_H_ diff --git a/src/xenia/dbg/ws_listener.h b/src/xenia/dbg/ws_listener.h index b3f05a782..afb59684d 100644 --- a/src/xenia/dbg/ws_listener.h +++ b/src/xenia/dbg/ws_listener.h @@ -7,8 +7,8 @@ ****************************************************************************** */ -#ifndef XENIA_KERNEL_DBG_WS_LISTENER_H_ -#define XENIA_KERNEL_DBG_WS_LISTENER_H_ +#ifndef XENIA_DBG_WS_LISTENER_H_ +#define XENIA_DBG_WS_LISTENER_H_ #include <xenia/common.h> #include <xenia/core.h> @@ -42,4 +42,4 @@ protected: } // namespace xe -#endif // XENIA_KERNEL_DBG_WS_LISTENER_H_ +#endif // XENIA_DBG_WS_LISTENER_H_ diff --git a/third_party/openssl b/third_party/openssl deleted file mode 160000 index d1b1f821b..000000000 --- a/third_party/openssl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d1b1f821ba7b0203e065c26a12b341eac382514d diff --git a/tools/xenia-run/xenia-run.cc b/tools/xenia-run/xenia-run.cc index ca95c027a..477a30b0d 100644 --- a/tools/xenia-run/xenia-run.cc +++ b/tools/xenia-run/xenia-run.cc @@ -106,7 +106,7 @@ int xenia_run(int argc, xechar_t **argv) { usage += "xenia-run some.xex"; google::SetUsageMessage(usage); google::SetVersionString("1.0"); - //google::ParseCommandLineFlags(&argc, &argv, true); + google::ParseCommandLineFlags(&argc, &argv, true); // Dummy call to keep the GPU code linking in to ensure it's working. do_gpu_stuff(); diff --git a/xenia.gyp b/xenia.gyp index cfa1cb34b..1cd4209a7 100644 --- a/xenia.gyp +++ b/xenia.gyp @@ -16,7 +16,6 @@ 'dependencies': [ 'gflags', 'wslay', - './third_party/openssl/openssl.gyp:openssl', ], 'export_dependent_settings': [ 'gflags',