From 0858f1b7c1a92e5af7dd768b77199afa3128ba04 Mon Sep 17 00:00:00 2001
From: simon987 <me@simon987.net>
Date: Sat, 28 Mar 2020 10:37:05 -0400
Subject: [PATCH] Embed SHA1

---
 .gitignore              |   3 +-
 ngx_http_js_challenge.c | 267 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 268 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index 0db7952..75576c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ cmake-build-debug
 CMakeCache.txt
 *.so
 Makefile
-.idea/
\ No newline at end of file
+.idea/
+CMakeLists.txt
\ No newline at end of file
diff --git a/ngx_http_js_challenge.c b/ngx_http_js_challenge.c
index bbed29f..9b5b907 100644
--- a/ngx_http_js_challenge.c
+++ b/ngx_http_js_challenge.c
@@ -235,6 +235,8 @@ int serve_challenge(ngx_http_request_t *r, const char *challenge, const char *ht
     return ngx_http_output_filter(r, &out);
 }
 
+unsigned char *_sha1(const unsigned char *d, size_t n, unsigned char *md);
+
 /**
  * @param out 40 bytes long string!
  */
@@ -242,7 +244,7 @@ void get_challenge_string(int32_t bucket, ngx_str_t addr, ngx_str_t secret, char
     char buf[4096];
     unsigned char md[SHA1_MD_LEN];
 
-    char * p = (char*)&bucket;
+    char *p = (char *) &bucket;
     /*
      * Challenge= hex( SHA1( concat(bucket, addr, secret) ) )
      */
@@ -250,7 +252,11 @@ void get_challenge_string(int32_t bucket, ngx_str_t addr, ngx_str_t secret, char
     memcpy((buf + sizeof(int32_t)), addr.data, addr.len);
     memcpy((buf + sizeof(int32_t) + addr.len), secret.data, secret.len);
 
+#ifndef HEADER_SHA_H
+    _sha1((unsigned char *) buf, (size_t) (sizeof(int32_t) + addr.len + secret.len), md);
+#else
     SHA1((unsigned char *) buf, (size_t) (sizeof(int32_t) + addr.len + secret.len), md);
+#endif
     buf2hex(md, SHA1_MD_LEN, out);
 }
 
@@ -370,3 +376,262 @@ static ngx_int_t ngx_http_js_challenge(ngx_conf_t *cf) {
     return NGX_OK;
 }
 
+/**
+ * By Steve Reid <sreid@sea-to-sky.net>
+ * 100% Public Domain
+ */
+#ifndef HEADER_SHA_H
+
+#define SHA1HANDSOFF (1)
+
+#include <stdint.h>
+
+#include <stdio.h>
+#include <string.h>
+
+void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+#if defined (BYTE_ORDER) && defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN)
+#define WORDS_BIGENDIAN 1
+#endif
+#ifdef _BIG_ENDIAN
+#define WORDS_BIGENDIAN 1
+#endif
+
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+/* FIXME: can we do this in an endian-proof way? */
+#ifdef WORDS_BIGENDIAN
+#define blk0(i) block->l[i]
+#else
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xff00ff00) \
+         |(rol(block->l[i],8)&0x00ff00ff))
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+                     ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v, w, x, y, z, i) \
+    z+=((w&(x^y))^y)+blk0(i)+0x5a827999+rol(v,5);w=rol(w,30);
+#define R1(v, w, x, y, z, i) \
+    z+=((w&(x^y))^y)+blk(i)+0x5a827999+rol(v,5);w=rol(w,30);
+#define R2(v, w, x, y, z, i) \
+    z+=(w^x^y)+blk(i)+0x6ed9eba1+rol(v,5);w=rol(w,30);
+#define R3(v, w, x, y, z, i) \
+    z+=(((w|x)&y)|(w&x))+blk(i)+0x8f1bbcdc+rol(v,5);w=rol(w,30);
+#define R4(v, w, x, y, z, i) \
+    z+=(w^x^y)+blk(i)+0xca62c1d6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]) {
+    uint32_t a, b, c, d, e;
+    typedef union {
+        uint8_t c[64];
+        uint32_t l[16];
+    } CHAR64LONG16;
+    CHAR64LONG16 *block;
+
+#ifdef SHA1HANDSOFF
+    CHAR64LONG16 workspace;
+    block = &workspace;
+    memcpy(block, buffer, 64);
+#else
+    block = (CHAR64LONG16*)buffer;
+#endif
+
+    /* Copy context->state[] to working vars */
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    e = state[4];
+
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a, b, c, d, e, 0);
+    R0(e, a, b, c, d, 1);
+    R0(d, e, a, b, c, 2);
+    R0(c, d, e, a, b, 3);
+    R0(b, c, d, e, a, 4);
+    R0(a, b, c, d, e, 5);
+    R0(e, a, b, c, d, 6);
+    R0(d, e, a, b, c, 7);
+    R0(c, d, e, a, b, 8);
+    R0(b, c, d, e, a, 9);
+    R0(a, b, c, d, e, 10);
+    R0(e, a, b, c, d, 11);
+    R0(d, e, a, b, c, 12);
+    R0(c, d, e, a, b, 13);
+    R0(b, c, d, e, a, 14);
+    R0(a, b, c, d, e, 15);
+    R1(e, a, b, c, d, 16);
+    R1(d, e, a, b, c, 17);
+    R1(c, d, e, a, b, 18);
+    R1(b, c, d, e, a, 19);
+    R2(a, b, c, d, e, 20);
+    R2(e, a, b, c, d, 21);
+    R2(d, e, a, b, c, 22);
+    R2(c, d, e, a, b, 23);
+    R2(b, c, d, e, a, 24);
+    R2(a, b, c, d, e, 25);
+    R2(e, a, b, c, d, 26);
+    R2(d, e, a, b, c, 27);
+    R2(c, d, e, a, b, 28);
+    R2(b, c, d, e, a, 29);
+    R2(a, b, c, d, e, 30);
+    R2(e, a, b, c, d, 31);
+    R2(d, e, a, b, c, 32);
+    R2(c, d, e, a, b, 33);
+    R2(b, c, d, e, a, 34);
+    R2(a, b, c, d, e, 35);
+    R2(e, a, b, c, d, 36);
+    R2(d, e, a, b, c, 37);
+    R2(c, d, e, a, b, 38);
+    R2(b, c, d, e, a, 39);
+    R3(a, b, c, d, e, 40);
+    R3(e, a, b, c, d, 41);
+    R3(d, e, a, b, c, 42);
+    R3(c, d, e, a, b, 43);
+    R3(b, c, d, e, a, 44);
+    R3(a, b, c, d, e, 45);
+    R3(e, a, b, c, d, 46);
+    R3(d, e, a, b, c, 47);
+    R3(c, d, e, a, b, 48);
+    R3(b, c, d, e, a, 49);
+    R3(a, b, c, d, e, 50);
+    R3(e, a, b, c, d, 51);
+    R3(d, e, a, b, c, 52);
+    R3(c, d, e, a, b, 53);
+    R3(b, c, d, e, a, 54);
+    R3(a, b, c, d, e, 55);
+    R3(e, a, b, c, d, 56);
+    R3(d, e, a, b, c, 57);
+    R3(c, d, e, a, b, 58);
+    R3(b, c, d, e, a, 59);
+    R4(a, b, c, d, e, 60);
+    R4(e, a, b, c, d, 61);
+    R4(d, e, a, b, c, 62);
+    R4(c, d, e, a, b, 63);
+    R4(b, c, d, e, a, 64);
+    R4(a, b, c, d, e, 65);
+    R4(e, a, b, c, d, 66);
+    R4(d, e, a, b, c, 67);
+    R4(c, d, e, a, b, 68);
+    R4(b, c, d, e, a, 69);
+    R4(a, b, c, d, e, 70);
+    R4(e, a, b, c, d, 71);
+    R4(d, e, a, b, c, 72);
+    R4(c, d, e, a, b, 73);
+    R4(b, c, d, e, a, 74);
+    R4(a, b, c, d, e, 75);
+    R4(e, a, b, c, d, 76);
+    R4(d, e, a, b, c, 77);
+    R4(c, d, e, a, b, 78);
+    R4(b, c, d, e, a, 79);
+
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+
+    /* Wipe variables */
+    a = b = c = d = e = 0;
+}
+
+/** SHA-1 Context */
+typedef struct {
+    uint32_t state[5];
+    /**< Context state */
+    uint32_t count[2];
+    /**< Counter       */
+    uint8_t buffer[64]; /**< SHA-1 buffer  */
+} SHA1_CTX;
+
+/** SHA-1 Digest size in bytes */
+#define SHA1_DIGEST_SIZE 20
+
+void SHA1_Init(SHA1_CTX *context);
+
+void SHA1_Update(SHA1_CTX *context, const void *p, size_t len);
+
+void SHA1_Final(uint8_t digest[SHA1_DIGEST_SIZE], SHA1_CTX *context);
+
+/**
+* Run your data through this
+*
+* @param context SHA1-Context
+* @param p       Buffer to run SHA1 on
+* @param len     Number of bytes
+*/
+void SHA1_Update(SHA1_CTX *context, const void *p, size_t len) {
+    const uint8_t *data = p;
+    size_t i, j;
+
+    j = (context->count[0] >> 3) & 63;
+    if ((context->count[0] += (uint32_t) (len << 3)) < (len << 3)) {
+        context->count[1]++;
+    }
+    context->count[1] += (uint32_t) (len >> 29);
+    if ((j + len) > 63) {
+        memcpy(&context->buffer[j], data, (i = 64 - j));
+        SHA1_Transform(context->state, context->buffer);
+        for (; i + 63 < len; i += 64) {
+            SHA1_Transform(context->state, data + i);
+        }
+        j = 0;
+    } else i = 0;
+    memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/**
+* Add padding and return the message digest
+*
+* @param digest  Generated message digest
+* @param context SHA1-Context
+*/
+void SHA1_Final(uint8_t digest[SHA1_DIGEST_SIZE], SHA1_CTX *context) {
+    uint32_t i;
+    uint8_t finalcount[8];
+
+    for (i = 0; i < 8; i++) {
+        finalcount[i] = (uint8_t) ((context->count[(i >= 4 ? 0 : 1)]
+                >> ((3 - (i & 3)) * 8)) & 255);
+    }
+    SHA1_Update(context, (uint8_t *) "\200", 1);
+    while ((context->count[0] & 504) != 448) {
+        SHA1_Update(context, (uint8_t *) "\0", 1);
+    }
+    SHA1_Update(context, finalcount, 8); /* Should cause SHA1_Transform */
+    for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
+        digest[i] = (uint8_t)
+                ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
+    }
+
+    /* Wipe variables */
+    i = 0;
+    memset(context->buffer, 0, 64);
+    memset(context->state, 0, 20);
+    memset(context->count, 0, 8);
+    memset(finalcount, 0, 8);    /* SWR */
+
+#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite its own static vars */
+    SHA1_Transform(context->state, context->buffer);
+#endif
+}
+
+unsigned char *_sha1(const unsigned char *d, size_t n, unsigned char *md) {
+    SHA1_CTX c;
+    SHA1_Init(&c);
+    SHA1_Update(&c, d, n);
+    SHA1_Final(md, &c);
+    return md;
+}
+
+#endif
+