A simple library to support serving https.
Dependents: oldheating gps motorhome heating
sha/sha256.c@24:cb43290fc439, 2020-04-01 (annotated)
- 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?
User | Revision | Line number | New 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 | } |