A simple library to support serving https.
Dependents: oldheating gps motorhome heating
sha/sha1.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 | 6:819c17738dc2 | 1 | #include <string.h> |
andrewboyson | 6:819c17738dc2 | 2 | #include "sha1.h" |
andrewboyson | 6:819c17738dc2 | 3 | |
andrewboyson | 6:819c17738dc2 | 4 | static uint32_t ror27(uint32_t val) |
andrewboyson | 6:819c17738dc2 | 5 | { |
andrewboyson | 6:819c17738dc2 | 6 | return (val >> 27) | (val << 5); |
andrewboyson | 6:819c17738dc2 | 7 | } |
andrewboyson | 6:819c17738dc2 | 8 | static uint32_t ror2(uint32_t val) |
andrewboyson | 6:819c17738dc2 | 9 | { |
andrewboyson | 6:819c17738dc2 | 10 | return (val >> 2) | (val << 30); |
andrewboyson | 6:819c17738dc2 | 11 | } |
andrewboyson | 6:819c17738dc2 | 12 | static uint32_t ror31(uint32_t val) |
andrewboyson | 6:819c17738dc2 | 13 | { |
andrewboyson | 6:819c17738dc2 | 14 | return (val >> 31) | (val << 1); |
andrewboyson | 6:819c17738dc2 | 15 | } |
andrewboyson | 7:94ef5824c3c0 | 16 | static void sha1_transform(struct Sha1State *ctx) |
andrewboyson | 6:819c17738dc2 | 17 | { |
andrewboyson | 6:819c17738dc2 | 18 | uint32_t W[80]; |
andrewboyson | 6:819c17738dc2 | 19 | register uint32_t A, B, C, D, E; |
andrewboyson | 6:819c17738dc2 | 20 | int t; |
andrewboyson | 6:819c17738dc2 | 21 | A = ctx->state[0]; |
andrewboyson | 6:819c17738dc2 | 22 | B = ctx->state[1]; |
andrewboyson | 6:819c17738dc2 | 23 | C = ctx->state[2]; |
andrewboyson | 6:819c17738dc2 | 24 | D = ctx->state[3]; |
andrewboyson | 6:819c17738dc2 | 25 | E = ctx->state[4]; |
andrewboyson | 6:819c17738dc2 | 26 | #define SHA_F1(A, B, C, D, E, t) \ |
andrewboyson | 6:819c17738dc2 | 27 | E += ror27(A) + \ |
andrewboyson | 6:819c17738dc2 | 28 | (W[t] = __builtin_bswap32(ctx->buf.w[t])) + \ |
andrewboyson | 6:819c17738dc2 | 29 | (D^(B&(C^D))) + 0x5A827999; \ |
andrewboyson | 6:819c17738dc2 | 30 | B = ror2(B); |
andrewboyson | 6:819c17738dc2 | 31 | for (t = 0; t < 15; t += 5) { |
andrewboyson | 6:819c17738dc2 | 32 | SHA_F1(A, B, C, D, E, t + 0); |
andrewboyson | 6:819c17738dc2 | 33 | SHA_F1(E, A, B, C, D, t + 1); |
andrewboyson | 6:819c17738dc2 | 34 | SHA_F1(D, E, A, B, C, t + 2); |
andrewboyson | 6:819c17738dc2 | 35 | SHA_F1(C, D, E, A, B, t + 3); |
andrewboyson | 6:819c17738dc2 | 36 | SHA_F1(B, C, D, E, A, t + 4); |
andrewboyson | 6:819c17738dc2 | 37 | } |
andrewboyson | 6:819c17738dc2 | 38 | SHA_F1(A, B, C, D, E, t + 0); /* 16th one, t == 15 */ |
andrewboyson | 6:819c17738dc2 | 39 | #undef SHA_F1 |
andrewboyson | 6:819c17738dc2 | 40 | #define SHA_F1(A, B, C, D, E, t) \ |
andrewboyson | 6:819c17738dc2 | 41 | E += ror27(A) + \ |
andrewboyson | 6:819c17738dc2 | 42 | (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ |
andrewboyson | 6:819c17738dc2 | 43 | (D^(B&(C^D))) + 0x5A827999; \ |
andrewboyson | 6:819c17738dc2 | 44 | B = ror2(B); |
andrewboyson | 6:819c17738dc2 | 45 | SHA_F1(E, A, B, C, D, t + 1); |
andrewboyson | 6:819c17738dc2 | 46 | SHA_F1(D, E, A, B, C, t + 2); |
andrewboyson | 6:819c17738dc2 | 47 | SHA_F1(C, D, E, A, B, t + 3); |
andrewboyson | 6:819c17738dc2 | 48 | SHA_F1(B, C, D, E, A, t + 4); |
andrewboyson | 6:819c17738dc2 | 49 | #undef SHA_F1 |
andrewboyson | 6:819c17738dc2 | 50 | #define SHA_F2(A, B, C, D, E, t) \ |
andrewboyson | 6:819c17738dc2 | 51 | E += ror27(A) + \ |
andrewboyson | 6:819c17738dc2 | 52 | (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ |
andrewboyson | 6:819c17738dc2 | 53 | (B^C^D) + 0x6ED9EBA1; \ |
andrewboyson | 6:819c17738dc2 | 54 | B = ror2(B); |
andrewboyson | 6:819c17738dc2 | 55 | for (t = 20; t < 40; t += 5) { |
andrewboyson | 6:819c17738dc2 | 56 | SHA_F2(A, B, C, D, E, t + 0); |
andrewboyson | 6:819c17738dc2 | 57 | SHA_F2(E, A, B, C, D, t + 1); |
andrewboyson | 6:819c17738dc2 | 58 | SHA_F2(D, E, A, B, C, t + 2); |
andrewboyson | 6:819c17738dc2 | 59 | SHA_F2(C, D, E, A, B, t + 3); |
andrewboyson | 6:819c17738dc2 | 60 | SHA_F2(B, C, D, E, A, t + 4); |
andrewboyson | 6:819c17738dc2 | 61 | } |
andrewboyson | 6:819c17738dc2 | 62 | #undef SHA_F2 |
andrewboyson | 6:819c17738dc2 | 63 | #define SHA_F3(A, B, C, D, E, t) \ |
andrewboyson | 6:819c17738dc2 | 64 | E += ror27(A) + \ |
andrewboyson | 6:819c17738dc2 | 65 | (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ |
andrewboyson | 6:819c17738dc2 | 66 | ((B&C)|(D&(B|C))) + 0x8F1BBCDC; \ |
andrewboyson | 6:819c17738dc2 | 67 | B = ror2(B); |
andrewboyson | 6:819c17738dc2 | 68 | for (; t < 60; t += 5) { |
andrewboyson | 6:819c17738dc2 | 69 | SHA_F3(A, B, C, D, E, t + 0); |
andrewboyson | 6:819c17738dc2 | 70 | SHA_F3(E, A, B, C, D, t + 1); |
andrewboyson | 6:819c17738dc2 | 71 | SHA_F3(D, E, A, B, C, t + 2); |
andrewboyson | 6:819c17738dc2 | 72 | SHA_F3(C, D, E, A, B, t + 3); |
andrewboyson | 6:819c17738dc2 | 73 | SHA_F3(B, C, D, E, A, t + 4); |
andrewboyson | 6:819c17738dc2 | 74 | } |
andrewboyson | 6:819c17738dc2 | 75 | #undef SHA_F3 |
andrewboyson | 6:819c17738dc2 | 76 | #define SHA_F4(A, B, C, D, E, t) \ |
andrewboyson | 6:819c17738dc2 | 77 | E += ror27(A) + \ |
andrewboyson | 6:819c17738dc2 | 78 | (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ |
andrewboyson | 6:819c17738dc2 | 79 | (B^C^D) + 0xCA62C1D6; \ |
andrewboyson | 6:819c17738dc2 | 80 | B = ror2(B); |
andrewboyson | 6:819c17738dc2 | 81 | for (; t < 80; t += 5) { |
andrewboyson | 6:819c17738dc2 | 82 | SHA_F4(A, B, C, D, E, t + 0); |
andrewboyson | 6:819c17738dc2 | 83 | SHA_F4(E, A, B, C, D, t + 1); |
andrewboyson | 6:819c17738dc2 | 84 | SHA_F4(D, E, A, B, C, t + 2); |
andrewboyson | 6:819c17738dc2 | 85 | SHA_F4(C, D, E, A, B, t + 3); |
andrewboyson | 6:819c17738dc2 | 86 | SHA_F4(B, C, D, E, A, t + 4); |
andrewboyson | 6:819c17738dc2 | 87 | } |
andrewboyson | 6:819c17738dc2 | 88 | #undef SHA_F4 |
andrewboyson | 6:819c17738dc2 | 89 | ctx->state[0] += A; |
andrewboyson | 6:819c17738dc2 | 90 | ctx->state[1] += B; |
andrewboyson | 6:819c17738dc2 | 91 | ctx->state[2] += C; |
andrewboyson | 6:819c17738dc2 | 92 | ctx->state[3] += D; |
andrewboyson | 6:819c17738dc2 | 93 | ctx->state[4] += E; |
andrewboyson | 6:819c17738dc2 | 94 | } |
andrewboyson | 7:94ef5824c3c0 | 95 | void Sha1Add(struct Sha1State *ctx, const uint8_t *data, int len) |
andrewboyson | 6:819c17738dc2 | 96 | { |
andrewboyson | 14:03a0b8fd6ddc | 97 | int i = ctx->count % SHA1_BLOCK_SIZE; |
andrewboyson | 6:819c17738dc2 | 98 | const uint8_t *p = (const uint8_t *)data; |
andrewboyson | 6:819c17738dc2 | 99 | ctx->count += len; |
andrewboyson | 14:03a0b8fd6ddc | 100 | while (len > SHA1_BLOCK_SIZE - i) |
andrewboyson | 6:819c17738dc2 | 101 | { |
andrewboyson | 14:03a0b8fd6ddc | 102 | memcpy(&ctx->buf.b[i], p, SHA1_BLOCK_SIZE - i); |
andrewboyson | 14:03a0b8fd6ddc | 103 | len -= SHA1_BLOCK_SIZE - i; |
andrewboyson | 14:03a0b8fd6ddc | 104 | p += SHA1_BLOCK_SIZE - i; |
andrewboyson | 6:819c17738dc2 | 105 | sha1_transform(ctx); |
andrewboyson | 6:819c17738dc2 | 106 | i = 0; |
andrewboyson | 6:819c17738dc2 | 107 | } |
andrewboyson | 6:819c17738dc2 | 108 | while (len--) { |
andrewboyson | 6:819c17738dc2 | 109 | ctx->buf.b[i++] = *p++; |
andrewboyson | 14:03a0b8fd6ddc | 110 | if (i == SHA1_BLOCK_SIZE) { |
andrewboyson | 6:819c17738dc2 | 111 | sha1_transform(ctx); |
andrewboyson | 6:819c17738dc2 | 112 | i = 0; |
andrewboyson | 6:819c17738dc2 | 113 | } |
andrewboyson | 6:819c17738dc2 | 114 | } |
andrewboyson | 6:819c17738dc2 | 115 | } |
andrewboyson | 7:94ef5824c3c0 | 116 | void Sha1Finish(struct Sha1State *ctx, uint8_t *out) |
andrewboyson | 6:819c17738dc2 | 117 | { |
andrewboyson | 6:819c17738dc2 | 118 | uint32_t cnt = ctx->count * 8; |
andrewboyson | 6:819c17738dc2 | 119 | int i; |
andrewboyson | 7:94ef5824c3c0 | 120 | Sha1Add(ctx, (uint8_t *)"\x80", 1); |
andrewboyson | 14:03a0b8fd6ddc | 121 | while ((ctx->count % SHA1_BLOCK_SIZE) != (SHA1_BLOCK_SIZE - 8)) |
andrewboyson | 7:94ef5824c3c0 | 122 | Sha1Add(ctx, (uint8_t *)"\0", 1); |
andrewboyson | 6:819c17738dc2 | 123 | for (i = 0; i < 8; ++i) { |
andrewboyson | 6:819c17738dc2 | 124 | uint8_t tmp = cnt >> ((7 - i) * 8); |
andrewboyson | 7:94ef5824c3c0 | 125 | Sha1Add(ctx, &tmp, 1); |
andrewboyson | 6:819c17738dc2 | 126 | } |
andrewboyson | 7:94ef5824c3c0 | 127 | for (i = 0; i < 5; i++) ctx->buf.w[i] = __builtin_bswap32(ctx->state[i]); |
andrewboyson | 7:94ef5824c3c0 | 128 | for (i = 0; i < 20; i++) out[i] = ctx->buf.b[i]; |
andrewboyson | 6:819c17738dc2 | 129 | } |
andrewboyson | 7:94ef5824c3c0 | 130 | void Sha1Start(struct Sha1State *ctx) |
andrewboyson | 6:819c17738dc2 | 131 | { |
andrewboyson | 6:819c17738dc2 | 132 | ctx->state[0] = 0x67452301; |
andrewboyson | 6:819c17738dc2 | 133 | ctx->state[1] = 0xEFCDAB89; |
andrewboyson | 6:819c17738dc2 | 134 | ctx->state[2] = 0x98BADCFE; |
andrewboyson | 6:819c17738dc2 | 135 | ctx->state[3] = 0x10325476; |
andrewboyson | 6:819c17738dc2 | 136 | ctx->state[4] = 0xC3D2E1F0; |
andrewboyson | 6:819c17738dc2 | 137 | ctx->count = 0; |
andrewboyson | 7:94ef5824c3c0 | 138 | } |
andrewboyson | 7:94ef5824c3c0 | 139 | |
andrewboyson | 7:94ef5824c3c0 | 140 | void Sha1(const uint8_t* in, int inlen, uint8_t* hash) |
andrewboyson | 7:94ef5824c3c0 | 141 | { |
andrewboyson | 7:94ef5824c3c0 | 142 | struct Sha1State md; |
andrewboyson | 7:94ef5824c3c0 | 143 | Sha1Start (&md); |
andrewboyson | 7:94ef5824c3c0 | 144 | Sha1Add (&md, in, inlen); |
andrewboyson | 7:94ef5824c3c0 | 145 | Sha1Finish(&md, hash); |
andrewboyson | 6:819c17738dc2 | 146 | } |