A simple library to support serving https.
Dependents: oldheating gps motorhome heating
sha/sha256.c@7:94ef5824c3c0, 2019-09-05 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Sep 05 12:58:41 2019 +0000
- Revision:
- 7:94ef5824c3c0
- Parent:
- 4:6a1d887f1cad
- Child:
- 14:03a0b8fd6ddc
Client handshake is now verified
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 | 3:e6a2c4579a4d | 108 | if (md->curlen > sizeof(md->buf)) 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 | 3:e6a2c4579a4d | 139 | if (md->curlen >= sizeof(md->buf)) 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 | } |