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',