A simple library to support serving https.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Wed Apr 01 12:48:52 2020 +0000
Revision:
24:cb43290fc439
Parent:
14:03a0b8fd6ddc
Added check so that if the client closes the TCP connection before the TLS connection is established then respond that we have finished and the TCP connection is to be closed.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 3:e6a2c4579a4d 1 #include <stdint.h>
andrewboyson 3:e6a2c4579a4d 2 #include <string.h>
andrewboyson 3:e6a2c4579a4d 3
andrewboyson 3:e6a2c4579a4d 4 #include "sha256.h"
andrewboyson 3:e6a2c4579a4d 5
andrewboyson 3:e6a2c4579a4d 6 /**
andrewboyson 3:e6a2c4579a4d 7 * sha256_vector - SHA256 hash for data vector
andrewboyson 3:e6a2c4579a4d 8 * @num_elem: Number of elements in the data vector
andrewboyson 3:e6a2c4579a4d 9 * @addr: Pointers to the data areas
andrewboyson 3:e6a2c4579a4d 10 * @len: Lengths of the data blocks
andrewboyson 3:e6a2c4579a4d 11 * @mac: Buffer for the hash
andrewboyson 3:e6a2c4579a4d 12
andrewboyson 3:e6a2c4579a4d 13 void sha256_vector(int num_elem, const u8 *addr[], const int *len, u8 *mac)
andrewboyson 3:e6a2c4579a4d 14 {
andrewboyson 3:e6a2c4579a4d 15 struct sha256_state ctx;
andrewboyson 3:e6a2c4579a4d 16 int i;
andrewboyson 3:e6a2c4579a4d 17 sha256_init(&ctx);
andrewboyson 3:e6a2c4579a4d 18 for (i = 0; i < num_elem; i++) sha256_process(&ctx, addr[i], len[i]);
andrewboyson 3:e6a2c4579a4d 19 sha256_done(&ctx, mac);
andrewboyson 3:e6a2c4579a4d 20 }
andrewboyson 3:e6a2c4579a4d 21 */
andrewboyson 3:e6a2c4579a4d 22 /* ===== start - public domain SHA256 implementation ===== */
andrewboyson 3:e6a2c4579a4d 23 /* This is based on SHA256 implementation in LibTomCrypt that was released into
andrewboyson 3:e6a2c4579a4d 24 * public domain by Tom St Denis. */
andrewboyson 3:e6a2c4579a4d 25 /* the K array */
andrewboyson 3:e6a2c4579a4d 26 static const uint32_t K[64] =
andrewboyson 3:e6a2c4579a4d 27 {
andrewboyson 3:e6a2c4579a4d 28 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
andrewboyson 3:e6a2c4579a4d 29 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
andrewboyson 3:e6a2c4579a4d 30 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
andrewboyson 3:e6a2c4579a4d 31 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
andrewboyson 3:e6a2c4579a4d 32 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
andrewboyson 3:e6a2c4579a4d 33 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
andrewboyson 3:e6a2c4579a4d 34 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
andrewboyson 3:e6a2c4579a4d 35 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
andrewboyson 3:e6a2c4579a4d 36 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
andrewboyson 3:e6a2c4579a4d 37 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
andrewboyson 3:e6a2c4579a4d 38 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
andrewboyson 3:e6a2c4579a4d 39 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
andrewboyson 3:e6a2c4579a4d 40 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
andrewboyson 3:e6a2c4579a4d 41 };
andrewboyson 3:e6a2c4579a4d 42
andrewboyson 3:e6a2c4579a4d 43 static uint32_t rotate(uint32_t x, int count) { return x >> count | x << (32 - count); }
andrewboyson 3:e6a2c4579a4d 44
andrewboyson 3:e6a2c4579a4d 45 static int compress(struct Sha256State *md, const uint8_t *buf) // compress 512-bits
andrewboyson 3:e6a2c4579a4d 46 {
andrewboyson 3:e6a2c4579a4d 47 uint32_t s[8], w[64];
andrewboyson 3:e6a2c4579a4d 48
andrewboyson 3:e6a2c4579a4d 49 // copy state into s
andrewboyson 3:e6a2c4579a4d 50 for (int i = 0; i < 8; i++) s[i] = md->state[i];
andrewboyson 3:e6a2c4579a4d 51
andrewboyson 3:e6a2c4579a4d 52 // copy the state into 512-bits into w[0..15]
andrewboyson 3:e6a2c4579a4d 53 for (int i = 0; i < 16; i++) w[i] = (uint32_t)*(buf + 4 * i + 0) << 24 |
andrewboyson 3:e6a2c4579a4d 54 (uint32_t)*(buf + 4 * i + 1) << 16 |
andrewboyson 3:e6a2c4579a4d 55 (uint32_t)*(buf + 4 * i + 2) << 8 |
andrewboyson 3:e6a2c4579a4d 56 (uint32_t)*(buf + 4 * i + 3);
andrewboyson 3:e6a2c4579a4d 57
andrewboyson 3:e6a2c4579a4d 58 // fill w[16..63]
andrewboyson 3:e6a2c4579a4d 59 for (int i = 16; i < 64; i++)
andrewboyson 3:e6a2c4579a4d 60 {
andrewboyson 3:e6a2c4579a4d 61 const uint32_t s0 = rotate(w[i - 15], 7) ^ rotate(w[i - 15], 18) ^ (w[i - 15] >> 3);
andrewboyson 3:e6a2c4579a4d 62 const uint32_t s1 = rotate(w[i - 2], 17) ^ rotate(w[i - 2], 19) ^ (w[i - 2] >> 10);
andrewboyson 3:e6a2c4579a4d 63 w[i] = w[i - 16] + s0 + w[i - 7] + s1;
andrewboyson 3:e6a2c4579a4d 64 }
andrewboyson 3:e6a2c4579a4d 65
andrewboyson 3:e6a2c4579a4d 66 // Compress
andrewboyson 3:e6a2c4579a4d 67 for (int i = 0; i < 64; ++i)
andrewboyson 3:e6a2c4579a4d 68 {
andrewboyson 3:e6a2c4579a4d 69 const uint32_t s1 = rotate(s[4], 6) ^ rotate(s[4], 11) ^ rotate(s[4], 25);
andrewboyson 3:e6a2c4579a4d 70 const uint32_t ch = (s[4] & s[5]) ^ (~s[4] & s[6]);
andrewboyson 3:e6a2c4579a4d 71 const uint32_t t0 = s[7] + s1 + ch + K[i] + w[i];
andrewboyson 3:e6a2c4579a4d 72 const uint32_t s0 = rotate(s[0], 2) ^ rotate(s[0], 13) ^ rotate(s[0], 22);
andrewboyson 3:e6a2c4579a4d 73 const uint32_t maj = (s[0] & s[1]) ^ (s[0] & s[2]) ^ (s[1] & s[2]);
andrewboyson 3:e6a2c4579a4d 74 const uint32_t t1 = s0 + maj;
andrewboyson 3:e6a2c4579a4d 75
andrewboyson 3:e6a2c4579a4d 76 s[7] = s[6];
andrewboyson 3:e6a2c4579a4d 77 s[6] = s[5];
andrewboyson 3:e6a2c4579a4d 78 s[5] = s[4];
andrewboyson 3:e6a2c4579a4d 79 s[4] = s[3] + t0;
andrewboyson 3:e6a2c4579a4d 80 s[3] = s[2];
andrewboyson 3:e6a2c4579a4d 81 s[2] = s[1];
andrewboyson 3:e6a2c4579a4d 82 s[1] = s[0];
andrewboyson 3:e6a2c4579a4d 83 s[0] = t0 + t1;
andrewboyson 3:e6a2c4579a4d 84 }
andrewboyson 3:e6a2c4579a4d 85
andrewboyson 3:e6a2c4579a4d 86 // feedback
andrewboyson 3:e6a2c4579a4d 87 for (int i = 0; i < 8; i++) md->state[i] = md->state[i] + s[i];
andrewboyson 3:e6a2c4579a4d 88
andrewboyson 3:e6a2c4579a4d 89 return 0;
andrewboyson 3:e6a2c4579a4d 90 }
andrewboyson 3:e6a2c4579a4d 91
andrewboyson 3:e6a2c4579a4d 92 void Sha256Start(struct Sha256State *md) // Initialize the hash state
andrewboyson 3:e6a2c4579a4d 93 {
andrewboyson 3:e6a2c4579a4d 94 md->curlen = 0;
andrewboyson 3:e6a2c4579a4d 95 md->length = 0;
andrewboyson 3:e6a2c4579a4d 96 md->state[0] = 0x6A09E667UL;
andrewboyson 3:e6a2c4579a4d 97 md->state[1] = 0xBB67AE85UL;
andrewboyson 3:e6a2c4579a4d 98 md->state[2] = 0x3C6EF372UL;
andrewboyson 3:e6a2c4579a4d 99 md->state[3] = 0xA54FF53AUL;
andrewboyson 3:e6a2c4579a4d 100 md->state[4] = 0x510E527FUL;
andrewboyson 3:e6a2c4579a4d 101 md->state[5] = 0x9B05688CUL;
andrewboyson 3:e6a2c4579a4d 102 md->state[6] = 0x1F83D9ABUL;
andrewboyson 3:e6a2c4579a4d 103 md->state[7] = 0x5BE0CD19UL;
andrewboyson 3:e6a2c4579a4d 104 }
andrewboyson 3:e6a2c4579a4d 105
andrewboyson 3:e6a2c4579a4d 106 int Sha256Add(struct Sha256State *md, const uint8_t *in, int inlen) //Return 0 if ok; -1 on error
andrewboyson 3:e6a2c4579a4d 107 {
andrewboyson 14:03a0b8fd6ddc 108 if (md->curlen > SHA256_BLOCK_SIZE) return -1;
andrewboyson 3:e6a2c4579a4d 109
andrewboyson 3:e6a2c4579a4d 110 while (inlen > 0)
andrewboyson 3:e6a2c4579a4d 111 {
andrewboyson 7:94ef5824c3c0 112 if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE)
andrewboyson 3:e6a2c4579a4d 113 {
andrewboyson 3:e6a2c4579a4d 114 if (compress(md, in) < 0) return -1;
andrewboyson 7:94ef5824c3c0 115 md->length += SHA256_BLOCK_SIZE * 8;
andrewboyson 7:94ef5824c3c0 116 in += SHA256_BLOCK_SIZE;
andrewboyson 7:94ef5824c3c0 117 inlen -= SHA256_BLOCK_SIZE;
andrewboyson 3:e6a2c4579a4d 118 }
andrewboyson 3:e6a2c4579a4d 119 else
andrewboyson 3:e6a2c4579a4d 120 {
andrewboyson 7:94ef5824c3c0 121 int n = inlen < SHA256_BLOCK_SIZE - md->curlen ? inlen : SHA256_BLOCK_SIZE - md->curlen;
andrewboyson 3:e6a2c4579a4d 122 memcpy(md->buf + md->curlen, in, n);
andrewboyson 3:e6a2c4579a4d 123 md->curlen += n;
andrewboyson 3:e6a2c4579a4d 124 in += n;
andrewboyson 3:e6a2c4579a4d 125 inlen -= n;
andrewboyson 7:94ef5824c3c0 126 if (md->curlen == SHA256_BLOCK_SIZE)
andrewboyson 3:e6a2c4579a4d 127 {
andrewboyson 3:e6a2c4579a4d 128 if (compress(md, md->buf) < 0) return -1;
andrewboyson 7:94ef5824c3c0 129 md->length += 8 * SHA256_BLOCK_SIZE;
andrewboyson 3:e6a2c4579a4d 130 md->curlen = 0;
andrewboyson 3:e6a2c4579a4d 131 }
andrewboyson 3:e6a2c4579a4d 132 }
andrewboyson 3:e6a2c4579a4d 133 }
andrewboyson 3:e6a2c4579a4d 134 return 0;
andrewboyson 3:e6a2c4579a4d 135 }
andrewboyson 3:e6a2c4579a4d 136
andrewboyson 3:e6a2c4579a4d 137 int Sha256Finish(struct Sha256State *md, uint8_t *out) //returns 0 on success; -1 on failure
andrewboyson 3:e6a2c4579a4d 138 {
andrewboyson 14:03a0b8fd6ddc 139 if (md->curlen >= SHA256_BLOCK_SIZE) return -1;
andrewboyson 3:e6a2c4579a4d 140
andrewboyson 3:e6a2c4579a4d 141 // increase the length of the message
andrewboyson 3:e6a2c4579a4d 142 md->length += md->curlen * 8;
andrewboyson 3:e6a2c4579a4d 143
andrewboyson 3:e6a2c4579a4d 144 // append the '1' bit
andrewboyson 3:e6a2c4579a4d 145 md->buf[md->curlen++] = 0x80;
andrewboyson 3:e6a2c4579a4d 146
andrewboyson 3:e6a2c4579a4d 147 /* if the length is currently above 56 bytes we append zeros
andrewboyson 3:e6a2c4579a4d 148 * then compress. Then we can fall back to padding zeros and length
andrewboyson 3:e6a2c4579a4d 149 * encoding like normal.
andrewboyson 3:e6a2c4579a4d 150 */
andrewboyson 3:e6a2c4579a4d 151 if (md->curlen > 56)
andrewboyson 3:e6a2c4579a4d 152 {
andrewboyson 3:e6a2c4579a4d 153 while (md->curlen < 64) md->buf[md->curlen++] = 0;
andrewboyson 3:e6a2c4579a4d 154 compress(md, md->buf);
andrewboyson 3:e6a2c4579a4d 155 md->curlen = 0;
andrewboyson 3:e6a2c4579a4d 156 }
andrewboyson 3:e6a2c4579a4d 157 // pad upto 56 bytes of zeroes
andrewboyson 3:e6a2c4579a4d 158 while (md->curlen < 56) md->buf[md->curlen++] = 0;
andrewboyson 3:e6a2c4579a4d 159
andrewboyson 3:e6a2c4579a4d 160 // store length
andrewboyson 3:e6a2c4579a4d 161 *(md->buf + 56 + 0) = (uint8_t) (md->length >> 56);
andrewboyson 3:e6a2c4579a4d 162 *(md->buf + 56 + 1) = (uint8_t) (md->length >> 48);
andrewboyson 3:e6a2c4579a4d 163 *(md->buf + 56 + 2) = (uint8_t) (md->length >> 40);
andrewboyson 3:e6a2c4579a4d 164 *(md->buf + 56 + 3) = (uint8_t) (md->length >> 32);
andrewboyson 3:e6a2c4579a4d 165 *(md->buf + 56 + 4) = (uint8_t) (md->length >> 24);
andrewboyson 3:e6a2c4579a4d 166 *(md->buf + 56 + 5) = (uint8_t) (md->length >> 16);
andrewboyson 3:e6a2c4579a4d 167 *(md->buf + 56 + 6) = (uint8_t) (md->length >> 8);
andrewboyson 3:e6a2c4579a4d 168 *(md->buf + 56 + 7) = (uint8_t) (md->length >> 0);
andrewboyson 3:e6a2c4579a4d 169
andrewboyson 3:e6a2c4579a4d 170
andrewboyson 3:e6a2c4579a4d 171 compress(md, md->buf);
andrewboyson 3:e6a2c4579a4d 172
andrewboyson 3:e6a2c4579a4d 173 // copy output
andrewboyson 3:e6a2c4579a4d 174 for (int i = 0; i < 8; i++)
andrewboyson 3:e6a2c4579a4d 175 {
andrewboyson 3:e6a2c4579a4d 176 *(out + 4 * i + 0) = (uint8_t) (md->state[i] >> 24);
andrewboyson 3:e6a2c4579a4d 177 *(out + 4 * i + 1) = (uint8_t) (md->state[i] >> 16);
andrewboyson 3:e6a2c4579a4d 178 *(out + 4 * i + 2) = (uint8_t) (md->state[i] >> 8);
andrewboyson 3:e6a2c4579a4d 179 *(out + 4 * i + 3) = (uint8_t) (md->state[i] >> 0);
andrewboyson 3:e6a2c4579a4d 180 }
andrewboyson 3:e6a2c4579a4d 181
andrewboyson 3:e6a2c4579a4d 182 return 0;
andrewboyson 3:e6a2c4579a4d 183 }
andrewboyson 4:6a1d887f1cad 184 void Sha256(const uint8_t* in, int inlen, uint8_t* hash)
andrewboyson 4:6a1d887f1cad 185 {
andrewboyson 4:6a1d887f1cad 186 struct Sha256State md;
andrewboyson 4:6a1d887f1cad 187 Sha256Start (&md);
andrewboyson 4:6a1d887f1cad 188 Sha256Add (&md, in, inlen);
andrewboyson 4:6a1d887f1cad 189 Sha256Finish(&md, hash);
andrewboyson 7:94ef5824c3c0 190 }
andrewboyson 7:94ef5824c3c0 191
andrewboyson 7:94ef5824c3c0 192 void Sha256Copy(struct Sha256State* pTo, struct Sha256State* pFrom)
andrewboyson 7:94ef5824c3c0 193 {
andrewboyson 7:94ef5824c3c0 194 pTo->length = pFrom->length;
andrewboyson 7:94ef5824c3c0 195 pTo->curlen = pFrom->curlen;
andrewboyson 7:94ef5824c3c0 196 for (int i = 0; i < SHA256_HASH_SIZE / 4; i++) pTo->state[i] = pFrom->state[i];
andrewboyson 7:94ef5824c3c0 197 for (int i = 0; i < SHA256_BLOCK_SIZE; i++) pTo->buf[i] = pFrom->buf[i];
andrewboyson 4:6a1d887f1cad 198 }