A simple library to support serving https.
Dependents: oldheating gps motorhome heating
tls/tls-response.c@13:0a80b49a5e78, 2019-09-27 (annotated)
- Committer:
- andrewboyson
- Date:
- Fri Sep 27 11:31:18 2019 +0000
- Revision:
- 13:0a80b49a5e78
- Parent:
- 10:e269fd7b9500
- Child:
- 14:03a0b8fd6ddc
Removed bug with TLS session. Unable to test as compiler has moved to v6 again (I think)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 10:e269fd7b9500 | 1 | #include "tls-defs.h" |
andrewboyson | 10:e269fd7b9500 | 2 | #include "tls-connection.h" |
andrewboyson | 10:e269fd7b9500 | 3 | #include "tls-session.h" |
andrewboyson | 10:e269fd7b9500 | 4 | #include "tls-log.h" |
andrewboyson | 10:e269fd7b9500 | 5 | #include "tls-prf.h" |
andrewboyson | 10:e269fd7b9500 | 6 | #include "ser-cer.h" |
andrewboyson | 10:e269fd7b9500 | 7 | #include "pri-key.h" |
andrewboyson | 10:e269fd7b9500 | 8 | #include "log.h" |
andrewboyson | 10:e269fd7b9500 | 9 | #include "aes128.h" |
andrewboyson | 10:e269fd7b9500 | 10 | #include "random.h" |
andrewboyson | 10:e269fd7b9500 | 11 | #include "sha1.h" |
andrewboyson | 10:e269fd7b9500 | 12 | #include "tls-mac.h" |
andrewboyson | 10:e269fd7b9500 | 13 | #include "http.h" |
andrewboyson | 10:e269fd7b9500 | 14 | |
andrewboyson | 10:e269fd7b9500 | 15 | void addSize(uint8_t** ppCurrent, int size) |
andrewboyson | 10:e269fd7b9500 | 16 | { |
andrewboyson | 10:e269fd7b9500 | 17 | uint8_t* p = *ppCurrent; |
andrewboyson | 10:e269fd7b9500 | 18 | *p++ = size >> 8; |
andrewboyson | 10:e269fd7b9500 | 19 | *p++ = size & 0xFF; |
andrewboyson | 10:e269fd7b9500 | 20 | *ppCurrent = p; |
andrewboyson | 10:e269fd7b9500 | 21 | } |
andrewboyson | 10:e269fd7b9500 | 22 | void backfillSize(uint8_t* pCurrent, uint8_t* pStart) |
andrewboyson | 10:e269fd7b9500 | 23 | { |
andrewboyson | 10:e269fd7b9500 | 24 | int size = pCurrent - pStart - 2; |
andrewboyson | 10:e269fd7b9500 | 25 | *(pStart + 0) = size >> 8; |
andrewboyson | 10:e269fd7b9500 | 26 | *(pStart + 1) = size & 0xFF; |
andrewboyson | 10:e269fd7b9500 | 27 | } |
andrewboyson | 10:e269fd7b9500 | 28 | static void sendServerHello(struct TlsConnection* pConnection, struct TlsSession* pSession, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream) |
andrewboyson | 10:e269fd7b9500 | 29 | { |
andrewboyson | 10:e269fd7b9500 | 30 | //Set up a multiple handshakes content - hello, certificate and done |
andrewboyson | 10:e269fd7b9500 | 31 | LogTime(" sending server hello\r\n"); |
andrewboyson | 10:e269fd7b9500 | 32 | uint8_t* p = pWindow; |
andrewboyson | 13:0a80b49a5e78 | 33 | *p++ = TLS_CONTENT_TYPE_HANDSHAKE; //Content is handshakes |
andrewboyson | 10:e269fd7b9500 | 34 | *p++ = 0x03; *p++ = 0x03; //Legacy TLS version |
andrewboyson | 10:e269fd7b9500 | 35 | uint8_t* pHandshakesLength = p; |
andrewboyson | 10:e269fd7b9500 | 36 | p += 2; //Handshakes Length (2 bytes) |
andrewboyson | 10:e269fd7b9500 | 37 | uint8_t* handshakesPayloadStart = p; //Record the start of the handshake payload |
andrewboyson | 10:e269fd7b9500 | 38 | |
andrewboyson | 10:e269fd7b9500 | 39 | //Server hello handshake |
andrewboyson | 13:0a80b49a5e78 | 40 | *p++ = TLS_HANDSHAKE_SERVER_HELLO; //Handshake type server hello |
andrewboyson | 10:e269fd7b9500 | 41 | *p++ = 0x00; |
andrewboyson | 10:e269fd7b9500 | 42 | uint8_t* pHandshakeHelloLength = p; |
andrewboyson | 10:e269fd7b9500 | 43 | p += 2; //Size of this handshake |
andrewboyson | 10:e269fd7b9500 | 44 | *p++ = 0x03; *p++ = 0x03; //TLS version 1.2 |
andrewboyson | 10:e269fd7b9500 | 45 | for (int i = 0; i < 32; i++) |
andrewboyson | 10:e269fd7b9500 | 46 | { |
andrewboyson | 10:e269fd7b9500 | 47 | uint8_t r = RandomGetByte(); |
andrewboyson | 10:e269fd7b9500 | 48 | pConnection->serverRandom[i] = r; |
andrewboyson | 10:e269fd7b9500 | 49 | *p++ = r; //32 bit random number |
andrewboyson | 10:e269fd7b9500 | 50 | } |
andrewboyson | 10:e269fd7b9500 | 51 | *p++ = 0x04; //SessionId length 4 |
andrewboyson | 10:e269fd7b9500 | 52 | *p++ = pConnection->sessionId >> 24; //Session id |
andrewboyson | 10:e269fd7b9500 | 53 | *p++ = pConnection->sessionId >> 16; //Session id |
andrewboyson | 10:e269fd7b9500 | 54 | *p++ = pConnection->sessionId >> 8; //Session id |
andrewboyson | 10:e269fd7b9500 | 55 | *p++ = pConnection->sessionId >> 0; //Session id |
andrewboyson | 10:e269fd7b9500 | 56 | *p++ = 0x00; *p++ = 0x2f; //Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f) |
andrewboyson | 10:e269fd7b9500 | 57 | *p++ = 0x00; //Compression method none |
andrewboyson | 10:e269fd7b9500 | 58 | *p++ = 0x00; *p++ = 0x05; //Extensions length (2 bytes) 5 bytes |
andrewboyson | 10:e269fd7b9500 | 59 | *p++ = 0xff; *p++ = 0x01; //Extension Renegotiation Info |
andrewboyson | 10:e269fd7b9500 | 60 | *p++ = 0x00; *p++ = 0x01; //1 bytes of "Renegotiation Info" extension data follows |
andrewboyson | 10:e269fd7b9500 | 61 | *p++ = 0x00; //length is zero, because this is a new connection |
andrewboyson | 10:e269fd7b9500 | 62 | backfillSize(p, pHandshakeHelloLength); |
andrewboyson | 10:e269fd7b9500 | 63 | |
andrewboyson | 10:e269fd7b9500 | 64 | //Certificate handshake |
andrewboyson | 13:0a80b49a5e78 | 65 | *p++ = TLS_HANDSHAKE_CERTIFICATE; *p++ = 0x00; //Handshake type certificate |
andrewboyson | 13:0a80b49a5e78 | 66 | addSize(&p, SerCerSize + 6); *p++ = 0x00; //Size of this handshake |
andrewboyson | 13:0a80b49a5e78 | 67 | addSize(&p, SerCerSize + 3); *p++ = 0x00; //Size of all certificates |
andrewboyson | 13:0a80b49a5e78 | 68 | addSize(&p, SerCerSize ); //Size of first certificate |
andrewboyson | 10:e269fd7b9500 | 69 | for (int i = 0; i < SerCerSize; i++) *p++ = SerCerData[i]; //Certificate |
andrewboyson | 10:e269fd7b9500 | 70 | |
andrewboyson | 10:e269fd7b9500 | 71 | //Hello done handshake |
andrewboyson | 13:0a80b49a5e78 | 72 | *p++ = TLS_HANDSHAKE_SERVER_HELLO_DONE; *p++ = 0x00; //Handshake type server hello done |
andrewboyson | 13:0a80b49a5e78 | 73 | *p++ = 0; *p++ = 0; //Size of this handshake |
andrewboyson | 10:e269fd7b9500 | 74 | backfillSize(p, pHandshakesLength); |
andrewboyson | 10:e269fd7b9500 | 75 | |
andrewboyson | 10:e269fd7b9500 | 76 | //Finalise the handshake content |
andrewboyson | 10:e269fd7b9500 | 77 | int handshakeLength = p - handshakesPayloadStart; |
andrewboyson | 10:e269fd7b9500 | 78 | Sha256Add(&pConnection->handshakeSha, handshakesPayloadStart, handshakeLength); //Add the handshake hash |
andrewboyson | 10:e269fd7b9500 | 79 | *pWindowSize = p - pWindow; |
andrewboyson | 10:e269fd7b9500 | 80 | } |
andrewboyson | 10:e269fd7b9500 | 81 | static void sendServerChange(struct TlsConnection* pConnection, struct TlsSession* pSession, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream) |
andrewboyson | 10:e269fd7b9500 | 82 | { |
andrewboyson | 10:e269fd7b9500 | 83 | LogTime(" sending server change\r\n"); |
andrewboyson | 10:e269fd7b9500 | 84 | uint8_t* p = pWindow; |
andrewboyson | 10:e269fd7b9500 | 85 | *p++ = TLS_CONTENT_TYPE_CHANGE_CIPHER; //Content is change cipher |
andrewboyson | 10:e269fd7b9500 | 86 | *p++ = 0x03; *p++ = 0x03; //Legacy TLS version |
andrewboyson | 10:e269fd7b9500 | 87 | *p++ = 0x00; *p++ = 0x01; //Change cipher Length (2 bytes) |
andrewboyson | 10:e269fd7b9500 | 88 | *p++ = 0x01; //Change cipher message 1 |
andrewboyson | 10:e269fd7b9500 | 89 | |
andrewboyson | 10:e269fd7b9500 | 90 | //Record that all incoming messages are now encrypted |
andrewboyson | 10:e269fd7b9500 | 91 | pConnection->serverEncrypted = true; |
andrewboyson | 10:e269fd7b9500 | 92 | pConnection->serverSequence = 0; |
andrewboyson | 10:e269fd7b9500 | 93 | |
andrewboyson | 10:e269fd7b9500 | 94 | LogTime(" sending server handshake finished\r\n"); |
andrewboyson | 13:0a80b49a5e78 | 95 | *p++ = TLS_CONTENT_TYPE_HANDSHAKE; //Content is handshakes |
andrewboyson | 10:e269fd7b9500 | 96 | *p++ = 0x03; *p++ = 0x03; //Legacy TLS version |
andrewboyson | 10:e269fd7b9500 | 97 | uint8_t* pHandshakesLength = p; |
andrewboyson | 10:e269fd7b9500 | 98 | p += 2; //Handshakes Length (2 bytes) |
andrewboyson | 10:e269fd7b9500 | 99 | |
andrewboyson | 10:e269fd7b9500 | 100 | //Hash over all handshake payloads exchanged so far |
andrewboyson | 10:e269fd7b9500 | 101 | uint8_t hash[32]; |
andrewboyson | 10:e269fd7b9500 | 102 | Sha256Finish(&pConnection->handshakeSha, hash); |
andrewboyson | 10:e269fd7b9500 | 103 | |
andrewboyson | 10:e269fd7b9500 | 104 | //Make verify data |
andrewboyson | 10:e269fd7b9500 | 105 | uint8_t verify[12]; |
andrewboyson | 10:e269fd7b9500 | 106 | TlsPrfServerFinished(pSession->masterSecret, hash, verify); //Hash over all handshakes |
andrewboyson | 10:e269fd7b9500 | 107 | |
andrewboyson | 10:e269fd7b9500 | 108 | //Make the 'finished' handshake |
andrewboyson | 10:e269fd7b9500 | 109 | uint8_t payload[16]; |
andrewboyson | 13:0a80b49a5e78 | 110 | payload[0] = TLS_HANDSHAKE_FINISHED; |
andrewboyson | 10:e269fd7b9500 | 111 | payload[1] = 0x00; |
andrewboyson | 10:e269fd7b9500 | 112 | payload[2] = 0x00; |
andrewboyson | 10:e269fd7b9500 | 113 | payload[3] = 0x0c; //Length 12 |
andrewboyson | 10:e269fd7b9500 | 114 | for (int i = 0; i < 12; i++) payload[i + 4] = verify[i]; |
andrewboyson | 10:e269fd7b9500 | 115 | int payloadLength = 16; |
andrewboyson | 10:e269fd7b9500 | 116 | |
andrewboyson | 10:e269fd7b9500 | 117 | uint8_t mac[SHA1_HASH_SIZE]; |
andrewboyson | 10:e269fd7b9500 | 118 | TlsMacSha1(TLS_KEY_SIZE_MAC, |
andrewboyson | 10:e269fd7b9500 | 119 | pConnection->serverMacKey, |
andrewboyson | 10:e269fd7b9500 | 120 | pConnection->serverSequence, |
andrewboyson | 13:0a80b49a5e78 | 121 | TLS_CONTENT_TYPE_HANDSHAKE, |
andrewboyson | 10:e269fd7b9500 | 122 | 0x03, |
andrewboyson | 10:e269fd7b9500 | 123 | 0x03, |
andrewboyson | 10:e269fd7b9500 | 124 | payloadLength, |
andrewboyson | 10:e269fd7b9500 | 125 | payload, |
andrewboyson | 10:e269fd7b9500 | 126 | mac); |
andrewboyson | 10:e269fd7b9500 | 127 | |
andrewboyson | 10:e269fd7b9500 | 128 | |
andrewboyson | 10:e269fd7b9500 | 129 | //plaintext |
andrewboyson | 10:e269fd7b9500 | 130 | uint8_t message[48]; |
andrewboyson | 10:e269fd7b9500 | 131 | for (int i = 0; i < 16; i++) message[i ] = payload[i]; //payload |
andrewboyson | 10:e269fd7b9500 | 132 | for (int i = 0; i < 20; i++) message[i + 16] = mac[i]; //mac |
andrewboyson | 10:e269fd7b9500 | 133 | for (int i = 0; i < 12; i++) message[i + 36] = 0x0b; //padding |
andrewboyson | 10:e269fd7b9500 | 134 | |
andrewboyson | 10:e269fd7b9500 | 135 | uint8_t iv[16]; |
andrewboyson | 10:e269fd7b9500 | 136 | for (int i = 0; i < 16; i++) iv[i] = RandomGetByte(); |
andrewboyson | 10:e269fd7b9500 | 137 | |
andrewboyson | 10:e269fd7b9500 | 138 | //Encrypt |
andrewboyson | 10:e269fd7b9500 | 139 | struct AES_ctx ctx; |
andrewboyson | 10:e269fd7b9500 | 140 | AES_init_ctx_iv(&ctx, pConnection->serverWriteKey, iv); |
andrewboyson | 10:e269fd7b9500 | 141 | AES_CBC_encrypt_buffer(&ctx, message, 48); |
andrewboyson | 10:e269fd7b9500 | 142 | |
andrewboyson | 10:e269fd7b9500 | 143 | for (int i = 0; i < 16; i++) *p++ = iv[i]; |
andrewboyson | 10:e269fd7b9500 | 144 | for (int i = 0; i < 48; i++) *p++ = message[i]; |
andrewboyson | 10:e269fd7b9500 | 145 | |
andrewboyson | 10:e269fd7b9500 | 146 | //Finalise |
andrewboyson | 10:e269fd7b9500 | 147 | backfillSize(p, pHandshakesLength); |
andrewboyson | 10:e269fd7b9500 | 148 | pConnection->serverSequence++; |
andrewboyson | 10:e269fd7b9500 | 149 | *pWindowSize = p - pWindow; |
andrewboyson | 10:e269fd7b9500 | 150 | pConnection->serverPositionInStreamOffset = positionOfWindowInStream + *pWindowSize; |
andrewboyson | 10:e269fd7b9500 | 151 | } |
andrewboyson | 10:e269fd7b9500 | 152 | static void sendFatal(char description, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream) |
andrewboyson | 10:e269fd7b9500 | 153 | { |
andrewboyson | 10:e269fd7b9500 | 154 | LogTime(" sending fatal alert: "); |
andrewboyson | 10:e269fd7b9500 | 155 | TlsLogAlertDescription(description); |
andrewboyson | 10:e269fd7b9500 | 156 | Log("\r\n"); |
andrewboyson | 10:e269fd7b9500 | 157 | uint8_t* p = pWindow; |
andrewboyson | 10:e269fd7b9500 | 158 | *p++ = TLS_CONTENT_TYPE_ALERT; //Content is alert |
andrewboyson | 10:e269fd7b9500 | 159 | *p++ = 0x03; *p++ = 0x03; //Legacy TLS version |
andrewboyson | 10:e269fd7b9500 | 160 | addSize(&p, 2); //Alert Length (2 bytes) |
andrewboyson | 10:e269fd7b9500 | 161 | |
andrewboyson | 10:e269fd7b9500 | 162 | *p++ = 2; //Fatal (level = 2) |
andrewboyson | 10:e269fd7b9500 | 163 | *p++ = description; //Description |
andrewboyson | 10:e269fd7b9500 | 164 | |
andrewboyson | 10:e269fd7b9500 | 165 | *pWindowSize = p - pWindow; |
andrewboyson | 10:e269fd7b9500 | 166 | } |
andrewboyson | 10:e269fd7b9500 | 167 | |
andrewboyson | 10:e269fd7b9500 | 168 | static bool sendContent(struct TlsConnection* pConnection, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream) |
andrewboyson | 10:e269fd7b9500 | 169 | { |
andrewboyson | 10:e269fd7b9500 | 170 | /* |
andrewboyson | 10:e269fd7b9500 | 171 | content: |
andrewboyson | 10:e269fd7b9500 | 172 | contentType * 1 |
andrewboyson | 10:e269fd7b9500 | 173 | version * 2 |
andrewboyson | 10:e269fd7b9500 | 174 | length * 2 |
andrewboyson | 10:e269fd7b9500 | 175 | iv * AES_BLOCKLEN (16) |
andrewboyson | 10:e269fd7b9500 | 176 | message: |
andrewboyson | 10:e269fd7b9500 | 177 | payload * payloadLength |
andrewboyson | 10:e269fd7b9500 | 178 | mac * SHA1_HASH_SIZE (20) |
andrewboyson | 10:e269fd7b9500 | 179 | padding * 0 to AES_BLOCKLEN - 1 (0 to 15) |
andrewboyson | 10:e269fd7b9500 | 180 | paddingLength * 1 |
andrewboyson | 10:e269fd7b9500 | 181 | */ |
andrewboyson | 10:e269fd7b9500 | 182 | #define CONTENT_MAX_OVERHEAD (5 + AES_BLOCKLEN + SHA1_HASH_SIZE + AES_BLOCKLEN - 1 + 1) |
andrewboyson | 10:e269fd7b9500 | 183 | |
andrewboyson | 10:e269fd7b9500 | 184 | //Start |
andrewboyson | 10:e269fd7b9500 | 185 | LogTime(" adding application content\r\n"); |
andrewboyson | 10:e269fd7b9500 | 186 | LogF("- available window size %d\r\n", *pWindowSize); |
andrewboyson | 10:e269fd7b9500 | 187 | LogF("- position of window in stream %d\r\n", positionOfWindowInStream); |
andrewboyson | 10:e269fd7b9500 | 188 | uint8_t* p = pWindow; |
andrewboyson | 13:0a80b49a5e78 | 189 | *p++ = TLS_CONTENT_TYPE_APPLICATION; |
andrewboyson | 10:e269fd7b9500 | 190 | *p++ = 0x03; *p++ = 0x03; |
andrewboyson | 10:e269fd7b9500 | 191 | |
andrewboyson | 10:e269fd7b9500 | 192 | //Prepare a place to backfill the size |
andrewboyson | 10:e269fd7b9500 | 193 | uint8_t* pBackfillSize = p; |
andrewboyson | 10:e269fd7b9500 | 194 | *p++ = 0; *p++ = 0; |
andrewboyson | 10:e269fd7b9500 | 195 | |
andrewboyson | 10:e269fd7b9500 | 196 | //Add the IV |
andrewboyson | 10:e269fd7b9500 | 197 | uint8_t* pIv = p; |
andrewboyson | 10:e269fd7b9500 | 198 | for (int i = 0; i < AES_BLOCKLEN; i++) *p++ = RandomGetByte(); |
andrewboyson | 10:e269fd7b9500 | 199 | |
andrewboyson | 10:e269fd7b9500 | 200 | //Add the plain payload |
andrewboyson | 10:e269fd7b9500 | 201 | uint8_t* pPayload = p; |
andrewboyson | 10:e269fd7b9500 | 202 | int payloadSize = *pWindowSize - CONTENT_MAX_OVERHEAD; |
andrewboyson | 10:e269fd7b9500 | 203 | LogF("- available payload size %d\r\n", payloadSize); |
andrewboyson | 10:e269fd7b9500 | 204 | uint32_t positionOfPayloadInStream = positionOfWindowInStream - pConnection->serverPositionInStreamOffset; |
andrewboyson | 10:e269fd7b9500 | 205 | LogF("- position of payload in stream %d\r\n", positionOfPayloadInStream); |
andrewboyson | 10:e269fd7b9500 | 206 | bool finished = HttpAdd(pConnection->id, &payloadSize, (char*)pPayload, positionOfPayloadInStream); //Return whatever HTTP would be |
andrewboyson | 10:e269fd7b9500 | 207 | LogF("- resulting payload size %d\r\n", payloadSize); |
andrewboyson | 10:e269fd7b9500 | 208 | p += payloadSize; |
andrewboyson | 10:e269fd7b9500 | 209 | |
andrewboyson | 10:e269fd7b9500 | 210 | //Add the MAC |
andrewboyson | 10:e269fd7b9500 | 211 | TlsMacSha1(TLS_KEY_SIZE_MAC, |
andrewboyson | 10:e269fd7b9500 | 212 | pConnection->serverMacKey, |
andrewboyson | 10:e269fd7b9500 | 213 | pConnection->serverSequence, |
andrewboyson | 13:0a80b49a5e78 | 214 | TLS_CONTENT_TYPE_APPLICATION, |
andrewboyson | 10:e269fd7b9500 | 215 | 0x03, |
andrewboyson | 10:e269fd7b9500 | 216 | 0x03, |
andrewboyson | 10:e269fd7b9500 | 217 | payloadSize, |
andrewboyson | 10:e269fd7b9500 | 218 | pPayload, |
andrewboyson | 10:e269fd7b9500 | 219 | p); |
andrewboyson | 10:e269fd7b9500 | 220 | p += SHA1_HASH_SIZE; |
andrewboyson | 10:e269fd7b9500 | 221 | |
andrewboyson | 10:e269fd7b9500 | 222 | //Add the padding |
andrewboyson | 10:e269fd7b9500 | 223 | int paddingSize = AES_BLOCKLEN - 1 - (payloadSize + SHA1_HASH_SIZE + 1 - 1) % AES_BLOCKLEN; |
andrewboyson | 10:e269fd7b9500 | 224 | LogF("- padding size %d\r\n", paddingSize); |
andrewboyson | 10:e269fd7b9500 | 225 | for (int i = 0; i < paddingSize; i++) *p++ = paddingSize; |
andrewboyson | 10:e269fd7b9500 | 226 | |
andrewboyson | 10:e269fd7b9500 | 227 | //Add the padding size |
andrewboyson | 10:e269fd7b9500 | 228 | *p++ = paddingSize; |
andrewboyson | 10:e269fd7b9500 | 229 | |
andrewboyson | 10:e269fd7b9500 | 230 | //Backfill the size |
andrewboyson | 10:e269fd7b9500 | 231 | backfillSize(p, pBackfillSize); |
andrewboyson | 10:e269fd7b9500 | 232 | |
andrewboyson | 10:e269fd7b9500 | 233 | //Calculate the resulting window size |
andrewboyson | 10:e269fd7b9500 | 234 | *pWindowSize = p - pWindow; |
andrewboyson | 10:e269fd7b9500 | 235 | LogF("- resulting window size %d\r\n", *pWindowSize); |
andrewboyson | 10:e269fd7b9500 | 236 | |
andrewboyson | 10:e269fd7b9500 | 237 | //Log the plain content |
andrewboyson | 10:e269fd7b9500 | 238 | Log("- plain content\r\n"); LogBytesAsHex(pWindow, *pWindowSize); Log("\r\n"); |
andrewboyson | 10:e269fd7b9500 | 239 | |
andrewboyson | 10:e269fd7b9500 | 240 | //Encrypt payload + mac + padding |
andrewboyson | 10:e269fd7b9500 | 241 | struct AES_ctx ctx; |
andrewboyson | 10:e269fd7b9500 | 242 | AES_init_ctx_iv(&ctx, pConnection->serverWriteKey, pIv); |
andrewboyson | 10:e269fd7b9500 | 243 | AES_CBC_encrypt_buffer(&ctx, pPayload, p - pPayload); |
andrewboyson | 10:e269fd7b9500 | 244 | |
andrewboyson | 10:e269fd7b9500 | 245 | //Finalise |
andrewboyson | 10:e269fd7b9500 | 246 | pConnection->serverSequence++; |
andrewboyson | 10:e269fd7b9500 | 247 | pConnection->serverPositionInStreamOffset += *pWindowSize - payloadSize; |
andrewboyson | 10:e269fd7b9500 | 248 | |
andrewboyson | 10:e269fd7b9500 | 249 | return finished; |
andrewboyson | 10:e269fd7b9500 | 250 | } |
andrewboyson | 10:e269fd7b9500 | 251 | bool TlsResponse(int connectionId, bool clientFinished, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream) |
andrewboyson | 10:e269fd7b9500 | 252 | { |
andrewboyson | 10:e269fd7b9500 | 253 | struct TlsConnection* pConnection = TlsConnectionOrNull(connectionId); |
andrewboyson | 10:e269fd7b9500 | 254 | if (!pConnection) |
andrewboyson | 10:e269fd7b9500 | 255 | { |
andrewboyson | 10:e269fd7b9500 | 256 | *pWindowSize = 0; |
andrewboyson | 10:e269fd7b9500 | 257 | return false; |
andrewboyson | 10:e269fd7b9500 | 258 | } |
andrewboyson | 10:e269fd7b9500 | 259 | |
andrewboyson | 10:e269fd7b9500 | 260 | if (!pConnection->sessionId) |
andrewboyson | 10:e269fd7b9500 | 261 | { |
andrewboyson | 10:e269fd7b9500 | 262 | *pWindowSize = 0; |
andrewboyson | 10:e269fd7b9500 | 263 | return false; |
andrewboyson | 10:e269fd7b9500 | 264 | } |
andrewboyson | 10:e269fd7b9500 | 265 | |
andrewboyson | 10:e269fd7b9500 | 266 | struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId); |
andrewboyson | 10:e269fd7b9500 | 267 | if (!pSession) |
andrewboyson | 10:e269fd7b9500 | 268 | { |
andrewboyson | 10:e269fd7b9500 | 269 | LogTimeF("TlsPoll - invalid session %u\r\n", pConnection->sessionId); |
andrewboyson | 10:e269fd7b9500 | 270 | *pWindowSize = 0; |
andrewboyson | 10:e269fd7b9500 | 271 | return false; |
andrewboyson | 10:e269fd7b9500 | 272 | } |
andrewboyson | 10:e269fd7b9500 | 273 | |
andrewboyson | 10:e269fd7b9500 | 274 | switch (pConnection->toDo) |
andrewboyson | 10:e269fd7b9500 | 275 | { |
andrewboyson | 10:e269fd7b9500 | 276 | case DO_WAIT_CLIENT_HELLO: |
andrewboyson | 10:e269fd7b9500 | 277 | case DO_WAIT_CLIENT_CHANGE: |
andrewboyson | 10:e269fd7b9500 | 278 | case DO_WAIT_DECRYPT_MASTER_SECRET: |
andrewboyson | 10:e269fd7b9500 | 279 | *pWindowSize = 0; |
andrewboyson | 10:e269fd7b9500 | 280 | if (clientFinished) return true; //The client hasn't made a request and never will so finish |
andrewboyson | 10:e269fd7b9500 | 281 | else return false; //The client hasn't made a request yet but it could. |
andrewboyson | 10:e269fd7b9500 | 282 | |
andrewboyson | 10:e269fd7b9500 | 283 | case DO_SEND_SERVER_HELLO: |
andrewboyson | 10:e269fd7b9500 | 284 | sendServerHello(pConnection, pSession, pWindowSize, pWindow, positionOfWindowInStream); |
andrewboyson | 10:e269fd7b9500 | 285 | pConnection->toDo = DO_WAIT_CLIENT_CHANGE; |
andrewboyson | 10:e269fd7b9500 | 286 | return false; //Not finished |
andrewboyson | 10:e269fd7b9500 | 287 | |
andrewboyson | 10:e269fd7b9500 | 288 | case DO_SEND_SERVER_CHANGE: |
andrewboyson | 10:e269fd7b9500 | 289 | sendServerChange(pConnection, pSession, pWindowSize, pWindow, positionOfWindowInStream); |
andrewboyson | 10:e269fd7b9500 | 290 | pConnection->toDo = DO_APPLICATION; |
andrewboyson | 10:e269fd7b9500 | 291 | return false; |
andrewboyson | 10:e269fd7b9500 | 292 | |
andrewboyson | 10:e269fd7b9500 | 293 | case DO_APPLICATION: |
andrewboyson | 10:e269fd7b9500 | 294 | { |
andrewboyson | 10:e269fd7b9500 | 295 | int status = HttpPoll(connectionId, clientFinished); |
andrewboyson | 10:e269fd7b9500 | 296 | bool finished; |
andrewboyson | 10:e269fd7b9500 | 297 | switch (status) |
andrewboyson | 10:e269fd7b9500 | 298 | { |
andrewboyson | 10:e269fd7b9500 | 299 | case HTTP_WAIT: finished = false; *pWindowSize = 0; break; |
andrewboyson | 10:e269fd7b9500 | 300 | case HTTP_FINISHED: finished = true; *pWindowSize = 0; break; |
andrewboyson | 10:e269fd7b9500 | 301 | case HTTP_HAVE_SOMETHING_TO_SEND: finished = sendContent(pConnection, pWindowSize, pWindow, positionOfWindowInStream); break; |
andrewboyson | 10:e269fd7b9500 | 302 | } |
andrewboyson | 10:e269fd7b9500 | 303 | if (finished) pConnection->toDo = DO_WAIT_CLIENT_HELLO; |
andrewboyson | 10:e269fd7b9500 | 304 | return finished; |
andrewboyson | 10:e269fd7b9500 | 305 | } |
andrewboyson | 10:e269fd7b9500 | 306 | case DO_SEND_ALERT_ILLEGAL_PARAMETER: |
andrewboyson | 10:e269fd7b9500 | 307 | sendFatal(TLS_ALERT_ILLEGAL_PARAMETER, pWindowSize, pWindow, positionOfWindowInStream); |
andrewboyson | 10:e269fd7b9500 | 308 | pConnection->toDo = DO_WAIT_CLIENT_HELLO; |
andrewboyson | 10:e269fd7b9500 | 309 | return true; //Finished |
andrewboyson | 10:e269fd7b9500 | 310 | |
andrewboyson | 10:e269fd7b9500 | 311 | case DO_SEND_ALERT_INTERNAL_ERROR: |
andrewboyson | 10:e269fd7b9500 | 312 | sendFatal(TLS_ALERT_INTERNAL_ERROR, pWindowSize, pWindow, positionOfWindowInStream); |
andrewboyson | 10:e269fd7b9500 | 313 | pConnection->toDo = DO_WAIT_CLIENT_HELLO; |
andrewboyson | 10:e269fd7b9500 | 314 | return true; //Finished |
andrewboyson | 10:e269fd7b9500 | 315 | |
andrewboyson | 10:e269fd7b9500 | 316 | default: |
andrewboyson | 10:e269fd7b9500 | 317 | LogTimeF("TlsPoll - unspecified TLS state %d\r\n", pConnection->toDo); |
andrewboyson | 10:e269fd7b9500 | 318 | sendFatal(TLS_ALERT_INTERNAL_ERROR, pWindowSize, pWindow, positionOfWindowInStream); //Internal error |
andrewboyson | 10:e269fd7b9500 | 319 | pConnection->toDo = DO_WAIT_CLIENT_HELLO; |
andrewboyson | 10:e269fd7b9500 | 320 | return true; //Finished |
andrewboyson | 10:e269fd7b9500 | 321 | } |
andrewboyson | 10:e269fd7b9500 | 322 | } |