Kaynağa Gözat

Replace sha1 code by more recent version, and adapt to CivetWeb

bel 8 yıl önce
ebeveyn
işleme
c89b08b58f
3 değiştirilmiş dosya ile 328 ekleme ve 233 silme
  1. 1 0
      format.bat
  2. 4 3
      src/civetweb.c
  3. 323 230
      src/sha1.inl

+ 1 - 0
format.bat

@@ -4,6 +4,7 @@ clang-format -i src/main.c
 clang-format -i src/CivetServer.cpp
 clang-format -i src/civetweb_private_lua.h
 clang-format -i src/md5.inl
+clang-format -i src/sha1.inl
 clang-format -i src/mod_lua.inl
 clang-format -i src/mod_duktape.inl
 clang-format -i src/timer.inl

+ 4 - 3
src/civetweb.c

@@ -9197,6 +9197,7 @@ mg_unlock_context(struct mg_context *ctx)
 
 #if defined(USE_WEBSOCKET)
 
+#define SHA_API static
 #include "sha1.inl"
 
 static int
@@ -9214,9 +9215,9 @@ send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
 		return 0;
 	}
 
-	SHA1Init(&sha_ctx);
-	SHA1Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
-	SHA1Final((unsigned char *)sha, &sha_ctx);
+	SHA1_Init(&sha_ctx);
+	SHA1_Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
+	SHA1_Final(&sha_ctx, (unsigned char *)sha);
 	base64_encode((unsigned char *)sha, sizeof(sha), b64_sha);
 	mg_printf(conn,
 	          "HTTP/1.1 101 Switching Protocols\r\n"

+ 323 - 230
src/sha1.inl

@@ -1,230 +1,323 @@
-/* START OF SHA-1 code
- * Copyright(c) By Steve Reid <steve@edmweb.com> */
-#define SHA1HANDSOFF
-
-/* According to current tests (May 2015), the <solarisfixes.h> is not required.
- *
- * #if defined(__sun)
- * #include "solarisfixes.h"
- * #endif
- */
-
-
-static int
-is_big_endian(void)
-{
-	static const int n = 1;
-	return ((char *)&n)[0] == 0;
-}
-
-
-union char64long16 {
-	unsigned char c[64];
-	uint32_t l[16];
-};
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-
-static uint32_t
-blk0(union char64long16 *block, int i)
-{
-	/* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
-	if (!is_big_endian()) {
-		block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00)
-		              | (rol(block->l[i], 8) & 0x00FF00FF);
-	}
-	return block->l[i];
-}
-
-#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))
-#define R0(v, w, x, y, z, i)                                                   \
-	z += ((w & (x ^ y)) ^ y) + blk0(block, 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);
-
-
-typedef struct {
-	uint32_t state[5];
-	uint32_t count[2];
-	unsigned char buffer[64];
-} SHA1_CTX;
-
-
-static void
-SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
-{
-	uint32_t a, b, c, d, e;
-	union char64long16 block[1];
-
-	memcpy(block, buffer, 64);
-	a = state[0];
-	b = state[1];
-	c = state[2];
-	d = state[3];
-	e = state[4];
-	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);
-	state[0] += a;
-	state[1] += b;
-	state[2] += c;
-	state[3] += d;
-	state[4] += e;
-	a = b = c = d = e = 0;
-	memset(block, '\0', sizeof(block));
-}
-
-
-static void
-SHA1Init(SHA1_CTX *context)
-{
-	context->state[0] = 0x67452301;
-	context->state[1] = 0xEFCDAB89;
-	context->state[2] = 0x98BADCFE;
-	context->state[3] = 0x10325476;
-	context->state[4] = 0xC3D2E1F0;
-	context->count[0] = context->count[1] = 0;
-}
-
-
-static void
-SHA1Update(SHA1_CTX *context, const unsigned char *data, uint32_t len)
-{
-	uint32_t i, j;
-
-	j = context->count[0];
-	if ((context->count[0] += len << 3) < j) {
-		context->count[1]++;
-	}
-	context->count[1] += (len >> 29);
-	j = (j >> 3) & 63;
-	if ((j + len) > 63) {
-		memcpy(&context->buffer[j], data, (i = 64 - j));
-		SHA1Transform(context->state, context->buffer);
-		for (; i + 63 < len; i += 64) {
-			SHA1Transform(context->state, &data[i]);
-		}
-		j = 0;
-	} else
-		i = 0;
-	memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-static void
-SHA1Final(unsigned char digest[20], SHA1_CTX *context)
-{
-	unsigned i;
-	unsigned char finalcount[8], c;
-
-	for (i = 0; i < 8; i++) {
-		finalcount[i] = (unsigned char)((context->count[(i >= 4) ? 0 : 1]
-		                                 >> ((3 - (i & 3)) * 8)) & 255);
-	}
-	c = 0200;
-	SHA1Update(context, &c, 1);
-	while ((context->count[0] & 504) != 448) {
-		c = 0000;
-		SHA1Update(context, &c, 1);
-	}
-	SHA1Update(context, finalcount, 8);
-	for (i = 0; i < 20; i++) {
-		digest[i] = (unsigned char)((context->state[i >> 2]
-		                             >> ((3 - (i & 3)) * 8)) & 255);
-	}
-	memset(context, '\0', sizeof(*context));
-	memset(&finalcount, '\0', sizeof(finalcount));
-}
-/* END OF SHA1 CODE */
+/*
+SHA-1 in C
+By Steve Reid <sreid@sea-to-sky.net>
+100% Public Domain
+
+-----------------
+Modified 7/98
+By James H. Brown <jbrown@burgoyne.com>
+Still 100% Public Domain
+
+Corrected a problem which generated improper hash values on 16 bit machines
+Routine SHA1Update changed from
+    void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+len)
+to
+    void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+long len)
+
+The 'len' parameter was declared an int which works fine on 32 bit machines.
+However, on 16 bit machines an int is too small for the shifts being done
+against
+it.  This caused the hash function to generate incorrect values if len was
+greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
+
+Since the file IO in main() reads 16K at a time, any file 8K or larger would
+be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
+"a"s).
+
+I also changed the declaration of variables i & j in SHA1Update to
+unsigned long from unsigned int for the same reason.
+
+These changes should make no difference to any 32 bit implementations since
+an
+int and a long are the same size in those environments.
+
+--
+I also corrected a few compiler warnings generated by Borland C.
+1. Added #include <process.h> for exit() prototype
+2. Removed unused variable 'j' in SHA1Final
+3. Changed exit(0) to return(0) at end of main.
+
+ALL changes I made can be located by searching for comments containing 'JHB'
+-----------------
+Modified 8/98
+By Steve Reid <sreid@sea-to-sky.net>
+Still 100% public domain
+
+1- Removed #include <process.h> and used return() instead of exit()
+2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
+3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
+
+-----------------
+Modified 4/01
+By Saul Kravitz <Saul.Kravitz@celera.com>
+Still 100% PD
+Modified to run on Compaq Alpha hardware.
+
+-----------------
+Modified 07/2002
+By Ralph Giles <giles@ghostscript.com>
+Still 100% public domain
+modified for use with stdint types, autoconf
+code cleanup, removed attribution comments
+switched SHA1Final() argument order for consistency
+use SHA1_ prefix for public api
+move public api to sha1.h
+*/
+
+/*
+11/2016 adapted for CivetWeb:
+  include sha1.h in sha1.c,
+  rename to sha1.inl
+  remove unused #ifdef sections
+  make endian independent
+*/
+
+/*
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#include <string.h>
+#include <stdint.h>
+
+typedef struct {
+	uint32_t state[5];
+	uint32_t count[2];
+	uint8_t buffer[64];
+} SHA1_CTX;
+
+#define SHA1_DIGEST_SIZE 20
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+
+
+typedef union {
+	uint8_t c[64];
+	uint32_t l[16];
+} CHAR64LONG16;
+
+
+static uint32_t
+blk0(CHAR64LONG16 *block, int i)
+{
+	static const uint32_t n = 1u;
+	if ((*((uint8_t *)(&n))) == 1) {
+		/* little endian / intel byte order */
+		return (rol(block->l[i], 24) & 0xFF00FF00)
+		       | (rol(block->l[i], 8) & 0x00FF00FF);
+	} else {
+		/* big endian / motorola byte order */
+		return block->l[i];
+	}
+}
+
+
+#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(block, 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. */
+static void
+SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
+{
+	uint32_t a, b, c, d, e;
+	CHAR64LONG16 *block;
+
+	block = (CHAR64LONG16 *)buffer;
+
+	/* 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;
+}
+
+
+/* SHA1Init - Initialize new context */
+SHA_API void
+SHA1_Init(SHA1_CTX *context)
+{
+	/* SHA1 initialization constants */
+	context->state[0] = 0x67452301;
+	context->state[1] = 0xEFCDAB89;
+	context->state[2] = 0x98BADCFE;
+	context->state[3] = 0x10325476;
+	context->state[4] = 0xC3D2E1F0;
+	context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+SHA_API void
+SHA1_Update(SHA1_CTX *context, const uint8_t *data, const size_t len)
+{
+	size_t i, j;
+
+	j = (context->count[0] >> 3) & 63;
+	if ((context->count[0] += len << 3) < (len << 3))
+		context->count[1]++;
+	context->count[1] += (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. */
+SHA_API void
+SHA1_Final(SHA1_CTX *context, uint8_t digest[SHA1_DIGEST_SIZE])
+{
+	uint32_t i;
+	uint8_t finalcount[8];
+
+	for (i = 0; i < 8; i++) {
+		finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+		                                 >> ((3 - (i & 3)) * 8))
+		                                & 255); /* Endian independent */
+	}
+	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 a 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 */
+}