A simple library to support serving https.
Dependents: oldheating gps motorhome heating
tls/tls-response.c@10:e269fd7b9500, 2019-09-24 (annotated)
- Committer:
- andrewboyson
- Date:
- Tue Sep 24 18:11:02 2019 +0000
- Revision:
- 10:e269fd7b9500
- Child:
- 13:0a80b49a5e78
Got padlock and some application data through. Now need to use China remainder theorem to speed up decryption and things up and the session id to avoid having to do the decryption.
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 | 10:e269fd7b9500 | 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 | 10:e269fd7b9500 | 40 | *p++ = TLS_HANDSHAKE_ServerHello; //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 | 10:e269fd7b9500 | 65 | *p++ = TLS_HANDSHAKE_Certificate; *p++ = 0x00; //Handshake type certificate |
andrewboyson | 10:e269fd7b9500 | 66 | addSize(&p, SerCerSize + 6); *p++ = 0x00; //Size of this handshake |
andrewboyson | 10:e269fd7b9500 | 67 | addSize(&p, SerCerSize + 3); *p++ = 0x00; //Size of all certificates |
andrewboyson | 10:e269fd7b9500 | 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 | 10:e269fd7b9500 | 72 | *p++ = TLS_HANDSHAKE_ServerHelloDone; *p++ = 0x00; //Handshake type server hello done |
andrewboyson | 10:e269fd7b9500 | 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 | 10:e269fd7b9500 | 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 | 10:e269fd7b9500 | 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 | 10:e269fd7b9500 | 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 | 10:e269fd7b9500 | 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 | 10:e269fd7b9500 | 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 | } |