A simple library to support serving https.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Wed Apr 01 12:48:52 2020 +0000
Revision:
24:cb43290fc439
Parent:
23:e93d5529b7a6
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?

UserRevisionLine numberNew contents of line
andrewboyson 21:a6d6e26dd742 1 #include "tls.h"
andrewboyson 10:e269fd7b9500 2 #include "tls-defs.h"
andrewboyson 10:e269fd7b9500 3 #include "tls-connection.h"
andrewboyson 10:e269fd7b9500 4 #include "tls-session.h"
andrewboyson 10:e269fd7b9500 5 #include "tls-log.h"
andrewboyson 10:e269fd7b9500 6 #include "tls-prf.h"
andrewboyson 10:e269fd7b9500 7 #include "ser-cer.h"
andrewboyson 10:e269fd7b9500 8 #include "pri-key.h"
andrewboyson 10:e269fd7b9500 9 #include "log.h"
andrewboyson 18:e3cf22ba2a06 10 #include "tls-aes128cbc-sha.h"
andrewboyson 10:e269fd7b9500 11 #include "random.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 backfillSize(uint8_t* pCurrent, uint8_t* pStart)
andrewboyson 10:e269fd7b9500 16 {
andrewboyson 10:e269fd7b9500 17 int size = pCurrent - pStart - 2;
andrewboyson 10:e269fd7b9500 18 *(pStart + 0) = size >> 8;
andrewboyson 10:e269fd7b9500 19 *(pStart + 1) = size & 0xFF;
andrewboyson 10:e269fd7b9500 20 }
andrewboyson 14:03a0b8fd6ddc 21 void addSize(uint8_t** pp, int size)
andrewboyson 14:03a0b8fd6ddc 22 {
andrewboyson 14:03a0b8fd6ddc 23 uint8_t* p = *pp;
andrewboyson 14:03a0b8fd6ddc 24 *p++ = size >> 8;
andrewboyson 14:03a0b8fd6ddc 25 *p++ = size & 0xFF;
andrewboyson 14:03a0b8fd6ddc 26 *pp = p;
andrewboyson 14:03a0b8fd6ddc 27 }
andrewboyson 14:03a0b8fd6ddc 28 static uint8_t* pHandshakeSize;
andrewboyson 14:03a0b8fd6ddc 29 static uint8_t* pHandshakePayload;
andrewboyson 14:03a0b8fd6ddc 30 static void addHandshakeStart(uint8_t** pp)
andrewboyson 10:e269fd7b9500 31 {
andrewboyson 14:03a0b8fd6ddc 32 uint8_t* p = *pp;
andrewboyson 14:03a0b8fd6ddc 33
andrewboyson 14:03a0b8fd6ddc 34 *p++ = TLS_CONTENT_TYPE_HANDSHAKE;
andrewboyson 14:03a0b8fd6ddc 35 *p++ = 0x03; *p++ = 0x03;
andrewboyson 14:03a0b8fd6ddc 36 pHandshakeSize = p; //Store the position to backfill the handshake size
andrewboyson 14:03a0b8fd6ddc 37 p += 2; //Leave room to backfill the handshake size
andrewboyson 14:03a0b8fd6ddc 38 pHandshakePayload = p; //Record the position of the handshake payload to later calculate the hash
andrewboyson 10:e269fd7b9500 39
andrewboyson 14:03a0b8fd6ddc 40 *pp = p;
andrewboyson 14:03a0b8fd6ddc 41 }
andrewboyson 14:03a0b8fd6ddc 42 static void addHandshakeEnd(uint8_t* p, struct TlsConnection* pConnection)
andrewboyson 14:03a0b8fd6ddc 43 {
andrewboyson 14:03a0b8fd6ddc 44 backfillSize(p, pHandshakeSize);
andrewboyson 14:03a0b8fd6ddc 45 Sha256Add(&pConnection->handshakeSha, pHandshakePayload, p - pHandshakePayload); //Add the handshake hash
andrewboyson 14:03a0b8fd6ddc 46 pConnection->serverSequence++;
andrewboyson 14:03a0b8fd6ddc 47 }
andrewboyson 14:03a0b8fd6ddc 48 static void addHandshakeServerHello(uint8_t** pp, struct TlsConnection* pConnection)
andrewboyson 14:03a0b8fd6ddc 49 {
andrewboyson 21:a6d6e26dd742 50 if (TlsTrace) Log(" sending handshake server hello\r\n");
andrewboyson 14:03a0b8fd6ddc 51 uint8_t* p = *pp;
andrewboyson 14:03a0b8fd6ddc 52
andrewboyson 14:03a0b8fd6ddc 53 *p++ = TLS_HANDSHAKE_SERVER_HELLO;
andrewboyson 10:e269fd7b9500 54 *p++ = 0x00;
andrewboyson 14:03a0b8fd6ddc 55 uint8_t* pSize = p;
andrewboyson 14:03a0b8fd6ddc 56 p += 2;
andrewboyson 14:03a0b8fd6ddc 57 *p++ = 0x03; *p++ = 0x03;
andrewboyson 17:93feb2a51d58 58 for (int i = 0; i < TLS_LENGTH_RANDOM; i++)
andrewboyson 10:e269fd7b9500 59 {
andrewboyson 10:e269fd7b9500 60 uint8_t r = RandomGetByte();
andrewboyson 10:e269fd7b9500 61 pConnection->serverRandom[i] = r;
andrewboyson 14:03a0b8fd6ddc 62 *p++ = r; //32 bit random number
andrewboyson 10:e269fd7b9500 63 }
andrewboyson 14:03a0b8fd6ddc 64 *p++ = 0x04; //SessionId length 4
andrewboyson 14:03a0b8fd6ddc 65 *p++ = pConnection->sessionId >> 24; //Session id
andrewboyson 14:03a0b8fd6ddc 66 *p++ = pConnection->sessionId >> 16; //Session id
andrewboyson 14:03a0b8fd6ddc 67 *p++ = pConnection->sessionId >> 8; //Session id
andrewboyson 14:03a0b8fd6ddc 68 *p++ = pConnection->sessionId >> 0; //Session id
andrewboyson 14:03a0b8fd6ddc 69 *p++ = 0x00; *p++ = 0x2f; //Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
andrewboyson 14:03a0b8fd6ddc 70 *p++ = 0x00; //Compression method none
andrewboyson 14:03a0b8fd6ddc 71 *p++ = 0x00; *p++ = 0x05; //Extensions length (2 bytes) 5 bytes
andrewboyson 14:03a0b8fd6ddc 72 *p++ = 0xff; *p++ = 0x01; //Extension Renegotiation Info
andrewboyson 14:03a0b8fd6ddc 73 *p++ = 0x00; *p++ = 0x01; //1 bytes of "Renegotiation Info" extension data follows
andrewboyson 14:03a0b8fd6ddc 74 *p++ = 0x00; //length is zero, because this is a new connection
andrewboyson 14:03a0b8fd6ddc 75 backfillSize(p, pSize);
andrewboyson 10:e269fd7b9500 76
andrewboyson 14:03a0b8fd6ddc 77 *pp = p;
andrewboyson 14:03a0b8fd6ddc 78 }
andrewboyson 14:03a0b8fd6ddc 79 static void addHandshakeCertificate(uint8_t** pp)
andrewboyson 14:03a0b8fd6ddc 80 {
andrewboyson 14:03a0b8fd6ddc 81 uint8_t* p = *pp;
andrewboyson 14:03a0b8fd6ddc 82
andrewboyson 14:03a0b8fd6ddc 83 *p++ = TLS_HANDSHAKE_CERTIFICATE; *p++ = 0x00;
andrewboyson 13:0a80b49a5e78 84 addSize(&p, SerCerSize + 6); *p++ = 0x00; //Size of this handshake
andrewboyson 13:0a80b49a5e78 85 addSize(&p, SerCerSize + 3); *p++ = 0x00; //Size of all certificates
andrewboyson 13:0a80b49a5e78 86 addSize(&p, SerCerSize ); //Size of first certificate
andrewboyson 10:e269fd7b9500 87 for (int i = 0; i < SerCerSize; i++) *p++ = SerCerData[i]; //Certificate
andrewboyson 10:e269fd7b9500 88
andrewboyson 14:03a0b8fd6ddc 89 *pp = p;
andrewboyson 14:03a0b8fd6ddc 90 }
andrewboyson 14:03a0b8fd6ddc 91 static void addHandshakeServerHelloDone(uint8_t** pp)
andrewboyson 14:03a0b8fd6ddc 92 {
andrewboyson 21:a6d6e26dd742 93 if (TlsTrace) LogTime(" sending handshake server hello done\r\n");
andrewboyson 14:03a0b8fd6ddc 94 uint8_t* p = *pp;
andrewboyson 10:e269fd7b9500 95
andrewboyson 14:03a0b8fd6ddc 96 *p++ = TLS_HANDSHAKE_SERVER_HELLO_DONE; *p++ = 0x00;
andrewboyson 14:03a0b8fd6ddc 97 addSize(&p, 0);
andrewboyson 14:03a0b8fd6ddc 98
andrewboyson 14:03a0b8fd6ddc 99 *pp = p;
andrewboyson 10:e269fd7b9500 100 }
andrewboyson 14:03a0b8fd6ddc 101 static void addHandshakeFinished(uint8_t** pp, struct TlsConnection* pConnection, struct TlsSession* pSession)
andrewboyson 10:e269fd7b9500 102 {
andrewboyson 21:a6d6e26dd742 103 if (TlsTrace) LogTime(" sending handshake finished\r\n");
andrewboyson 14:03a0b8fd6ddc 104 uint8_t* p = *pp;
andrewboyson 10:e269fd7b9500 105
andrewboyson 18:e3cf22ba2a06 106 TlsAes128CbcSha1EncryptStart(&p);
andrewboyson 15:4ddb73b5fea1 107
andrewboyson 16:7eeb5f6626ad 108 //Make the 'finished' handshake which is part of the payload to be encrypted
andrewboyson 15:4ddb73b5fea1 109 *p++ = TLS_HANDSHAKE_FINISHED;
andrewboyson 15:4ddb73b5fea1 110 *p++ = 0x00;
andrewboyson 15:4ddb73b5fea1 111 *p++ = 0x00;
andrewboyson 17:93feb2a51d58 112 *p++ = TLS_LENGTH_VERIFY; //Length 12
andrewboyson 15:4ddb73b5fea1 113
andrewboyson 10:e269fd7b9500 114 //Hash over all handshake payloads exchanged so far
andrewboyson 17:93feb2a51d58 115 uint8_t hash[SHA256_HASH_SIZE];
andrewboyson 10:e269fd7b9500 116 Sha256Finish(&pConnection->handshakeSha, hash);
andrewboyson 10:e269fd7b9500 117
andrewboyson 10:e269fd7b9500 118 //Make verify data
andrewboyson 15:4ddb73b5fea1 119 TlsPrfServerFinished(pSession->masterSecret, hash, p); //Hash over all handshakes
andrewboyson 17:93feb2a51d58 120 p += TLS_LENGTH_VERIFY;
andrewboyson 10:e269fd7b9500 121
andrewboyson 18:e3cf22ba2a06 122 TlsAes128CbcSha1EncryptEnd(&p, pConnection, TLS_CONTENT_TYPE_HANDSHAKE);
andrewboyson 14:03a0b8fd6ddc 123
andrewboyson 14:03a0b8fd6ddc 124 *pp = p;
andrewboyson 14:03a0b8fd6ddc 125 }
andrewboyson 14:03a0b8fd6ddc 126 static void addChangeCipher(uint8_t** pp, struct TlsConnection* pConnection)
andrewboyson 14:03a0b8fd6ddc 127 {
andrewboyson 21:a6d6e26dd742 128 if (TlsTrace) LogTime(" sending change cipher\r\n");
andrewboyson 14:03a0b8fd6ddc 129 uint8_t* p = *pp;
andrewboyson 14:03a0b8fd6ddc 130
andrewboyson 14:03a0b8fd6ddc 131 *p++ = TLS_CONTENT_TYPE_CHANGE_CIPHER; //Content is change cipher
andrewboyson 14:03a0b8fd6ddc 132 *p++ = 0x03; *p++ = 0x03; //Legacy TLS version
andrewboyson 14:03a0b8fd6ddc 133 *p++ = 0x00; *p++ = 0x01; //Change cipher Length (2 bytes)
andrewboyson 14:03a0b8fd6ddc 134 *p++ = 0x01; //Change cipher message 1
andrewboyson 10:e269fd7b9500 135
andrewboyson 14:03a0b8fd6ddc 136 //Record that all outgoing messages are now encrypted
andrewboyson 14:03a0b8fd6ddc 137 pConnection->serverEncrypted = true;
andrewboyson 14:03a0b8fd6ddc 138 pConnection->serverSequence = 0;
andrewboyson 14:03a0b8fd6ddc 139
andrewboyson 14:03a0b8fd6ddc 140 *pp = p;
andrewboyson 14:03a0b8fd6ddc 141 }
andrewboyson 14:03a0b8fd6ddc 142 static void addAlert(uint8_t** pp, struct TlsConnection* pConnection, uint8_t level, uint8_t description)
andrewboyson 14:03a0b8fd6ddc 143 {
andrewboyson 21:a6d6e26dd742 144 if (TlsTrace) LogTime(" sending alert\r\n");
andrewboyson 14:03a0b8fd6ddc 145 Log (" - "); TlsLogAlertLevel(level); Log(": "); TlsLogAlertDescription(description); Log("\r\n");
andrewboyson 14:03a0b8fd6ddc 146
andrewboyson 14:03a0b8fd6ddc 147 uint8_t* p = *pp;
andrewboyson 14:03a0b8fd6ddc 148
andrewboyson 14:03a0b8fd6ddc 149 *p++ = TLS_CONTENT_TYPE_ALERT;
andrewboyson 14:03a0b8fd6ddc 150 *p++ = 0x03; *p++ = 0x03;
andrewboyson 14:03a0b8fd6ddc 151 addSize(&p, 2);
andrewboyson 14:03a0b8fd6ddc 152 *p++ = level;
andrewboyson 14:03a0b8fd6ddc 153 *p++ = description;
andrewboyson 14:03a0b8fd6ddc 154
andrewboyson 10:e269fd7b9500 155 pConnection->serverSequence++;
andrewboyson 14:03a0b8fd6ddc 156
andrewboyson 14:03a0b8fd6ddc 157 *pp = p;
andrewboyson 14:03a0b8fd6ddc 158 }
andrewboyson 14:03a0b8fd6ddc 159 static void sendServerHelloNew(struct TlsConnection* pConnection, struct TlsSession* pSession, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 14:03a0b8fd6ddc 160 {
andrewboyson 14:03a0b8fd6ddc 161 uint8_t* p = pWindow;
andrewboyson 14:03a0b8fd6ddc 162
andrewboyson 14:03a0b8fd6ddc 163 addHandshakeStart (&p);
andrewboyson 14:03a0b8fd6ddc 164 addHandshakeServerHello (&p, pConnection);
andrewboyson 14:03a0b8fd6ddc 165 addHandshakeCertificate (&p);
andrewboyson 14:03a0b8fd6ddc 166 addHandshakeServerHelloDone(&p);
andrewboyson 14:03a0b8fd6ddc 167 addHandshakeEnd ( p, pConnection);
andrewboyson 14:03a0b8fd6ddc 168
andrewboyson 10:e269fd7b9500 169 *pWindowSize = p - pWindow;
andrewboyson 10:e269fd7b9500 170 pConnection->serverPositionInStreamOffset = positionOfWindowInStream + *pWindowSize;
andrewboyson 10:e269fd7b9500 171 }
andrewboyson 14:03a0b8fd6ddc 172 static void sendServerHelloResume(struct TlsConnection* pConnection, struct TlsSession* pSession, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 10:e269fd7b9500 173 {
andrewboyson 10:e269fd7b9500 174 uint8_t* p = pWindow;
andrewboyson 14:03a0b8fd6ddc 175
andrewboyson 14:03a0b8fd6ddc 176 addHandshakeStart (&p);
andrewboyson 14:03a0b8fd6ddc 177 addHandshakeServerHello(&p, pConnection);
andrewboyson 14:03a0b8fd6ddc 178 addHandshakeEnd ( p, pConnection);
andrewboyson 10:e269fd7b9500 179
andrewboyson 19:f22327e8be7b 180 TlsPrfKeysAes128Sha1(pSession->masterSecret, pConnection->clientRandom, pConnection->serverRandom, pConnection->clientMacKey,
andrewboyson 19:f22327e8be7b 181 pConnection->serverMacKey,
andrewboyson 19:f22327e8be7b 182 pConnection->clientWriteKey,
andrewboyson 19:f22327e8be7b 183 pConnection->serverWriteKey);
andrewboyson 14:03a0b8fd6ddc 184
andrewboyson 14:03a0b8fd6ddc 185 addChangeCipher (&p, pConnection);
andrewboyson 14:03a0b8fd6ddc 186
andrewboyson 14:03a0b8fd6ddc 187 addHandshakeStart (&p);
andrewboyson 14:03a0b8fd6ddc 188 addHandshakeFinished (&p, pConnection, pSession);
andrewboyson 14:03a0b8fd6ddc 189 addHandshakeEnd ( p, pConnection);
andrewboyson 10:e269fd7b9500 190
andrewboyson 10:e269fd7b9500 191 *pWindowSize = p - pWindow;
andrewboyson 14:03a0b8fd6ddc 192 pConnection->serverPositionInStreamOffset = positionOfWindowInStream + *pWindowSize;
andrewboyson 14:03a0b8fd6ddc 193 }
andrewboyson 14:03a0b8fd6ddc 194 static void sendServerChange(struct TlsConnection* pConnection, struct TlsSession* pSession, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 14:03a0b8fd6ddc 195 {
andrewboyson 14:03a0b8fd6ddc 196 uint8_t* p = pWindow;
andrewboyson 14:03a0b8fd6ddc 197
andrewboyson 14:03a0b8fd6ddc 198 addChangeCipher(&p, pConnection);
andrewboyson 14:03a0b8fd6ddc 199
andrewboyson 14:03a0b8fd6ddc 200 addHandshakeStart (&p);
andrewboyson 14:03a0b8fd6ddc 201 addHandshakeFinished(&p, pConnection, pSession);
andrewboyson 14:03a0b8fd6ddc 202 addHandshakeEnd ( p, pConnection);
andrewboyson 14:03a0b8fd6ddc 203
andrewboyson 14:03a0b8fd6ddc 204 *pWindowSize = p - pWindow;
andrewboyson 14:03a0b8fd6ddc 205 pConnection->serverPositionInStreamOffset = positionOfWindowInStream + *pWindowSize;
andrewboyson 14:03a0b8fd6ddc 206 }
andrewboyson 14:03a0b8fd6ddc 207 static void sendFatal(uint8_t description, struct TlsConnection* pConnection, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 14:03a0b8fd6ddc 208 {
andrewboyson 14:03a0b8fd6ddc 209 uint8_t* p = pWindow;
andrewboyson 14:03a0b8fd6ddc 210
andrewboyson 14:03a0b8fd6ddc 211 addAlert(&p, pConnection, TLS_ALERT_FATAL, description);
andrewboyson 14:03a0b8fd6ddc 212
andrewboyson 14:03a0b8fd6ddc 213 *pWindowSize = p - pWindow;
andrewboyson 14:03a0b8fd6ddc 214 pConnection->serverPositionInStreamOffset = positionOfWindowInStream + *pWindowSize;
andrewboyson 10:e269fd7b9500 215 }
andrewboyson 10:e269fd7b9500 216 static bool sendContent(struct TlsConnection* pConnection, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 10:e269fd7b9500 217 {
andrewboyson 10:e269fd7b9500 218 //Start
andrewboyson 21:a6d6e26dd742 219 if (TlsTrace)
andrewboyson 21:a6d6e26dd742 220 {
andrewboyson 21:a6d6e26dd742 221 LogTime(" adding application content\r\n");
andrewboyson 21:a6d6e26dd742 222 LogF("- available window size %d\r\n", *pWindowSize);
andrewboyson 21:a6d6e26dd742 223 LogF("- position of window in stream %d\r\n", positionOfWindowInStream);
andrewboyson 21:a6d6e26dd742 224 }
andrewboyson 10:e269fd7b9500 225 uint8_t* p = pWindow;
andrewboyson 13:0a80b49a5e78 226 *p++ = TLS_CONTENT_TYPE_APPLICATION;
andrewboyson 10:e269fd7b9500 227 *p++ = 0x03; *p++ = 0x03;
andrewboyson 10:e269fd7b9500 228
andrewboyson 10:e269fd7b9500 229 //Prepare a place to backfill the size
andrewboyson 10:e269fd7b9500 230 uint8_t* pBackfillSize = p;
andrewboyson 10:e269fd7b9500 231 *p++ = 0; *p++ = 0;
andrewboyson 10:e269fd7b9500 232
andrewboyson 18:e3cf22ba2a06 233 TlsAes128CbcSha1EncryptStart(&p);
andrewboyson 10:e269fd7b9500 234
andrewboyson 10:e269fd7b9500 235 //Add the plain payload
andrewboyson 18:e3cf22ba2a06 236 int payloadSize = *pWindowSize - 5 - TLS_AES_128_CBC_SHA1_MAX_OVERHEAD;
andrewboyson 21:a6d6e26dd742 237 if (TlsTrace) LogF("- available payload size %d\r\n", payloadSize);
andrewboyson 10:e269fd7b9500 238 uint32_t positionOfPayloadInStream = positionOfWindowInStream - pConnection->serverPositionInStreamOffset;
andrewboyson 21:a6d6e26dd742 239 if (TlsTrace) LogF("- position of payload in stream %d\r\n", positionOfPayloadInStream);
andrewboyson 16:7eeb5f6626ad 240 bool finished = HttpAdd(pConnection->id, &payloadSize, (char*)p, positionOfPayloadInStream); //Return whatever HTTP would be
andrewboyson 21:a6d6e26dd742 241 if (TlsTrace) LogF("- resulting payload size %d\r\n", payloadSize);
andrewboyson 16:7eeb5f6626ad 242 p += payloadSize;
andrewboyson 10:e269fd7b9500 243
andrewboyson 18:e3cf22ba2a06 244 TlsAes128CbcSha1EncryptEnd(&p, pConnection, TLS_CONTENT_TYPE_APPLICATION);
andrewboyson 10:e269fd7b9500 245
andrewboyson 10:e269fd7b9500 246 //Backfill the size
andrewboyson 10:e269fd7b9500 247 backfillSize(p, pBackfillSize);
andrewboyson 10:e269fd7b9500 248
andrewboyson 16:7eeb5f6626ad 249 //Finalise
andrewboyson 16:7eeb5f6626ad 250 pConnection->serverSequence++;
andrewboyson 10:e269fd7b9500 251 *pWindowSize = p - pWindow;
andrewboyson 21:a6d6e26dd742 252 if (TlsTrace) LogF("- resulting window size %d\r\n", *pWindowSize);
andrewboyson 16:7eeb5f6626ad 253 pConnection->serverPositionInStreamOffset += *pWindowSize - payloadSize;
andrewboyson 10:e269fd7b9500 254
andrewboyson 10:e269fd7b9500 255 return finished;
andrewboyson 10:e269fd7b9500 256 }
andrewboyson 10:e269fd7b9500 257 bool TlsResponse(int connectionId, bool clientFinished, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 10:e269fd7b9500 258 {
andrewboyson 10:e269fd7b9500 259 struct TlsConnection* pConnection = TlsConnectionOrNull(connectionId);
andrewboyson 10:e269fd7b9500 260 if (!pConnection)
andrewboyson 10:e269fd7b9500 261 {
andrewboyson 10:e269fd7b9500 262 *pWindowSize = 0;
andrewboyson 24:cb43290fc439 263 return clientFinished; //Ignore empty connections in poll
andrewboyson 10:e269fd7b9500 264 }
andrewboyson 10:e269fd7b9500 265
andrewboyson 10:e269fd7b9500 266 if (!pConnection->sessionId)
andrewboyson 10:e269fd7b9500 267 {
andrewboyson 10:e269fd7b9500 268 *pWindowSize = 0;
andrewboyson 24:cb43290fc439 269 return clientFinished; //Ignore empty sessions in poll
andrewboyson 10:e269fd7b9500 270 }
andrewboyson 10:e269fd7b9500 271
andrewboyson 10:e269fd7b9500 272 struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
andrewboyson 10:e269fd7b9500 273 if (!pSession)
andrewboyson 10:e269fd7b9500 274 {
andrewboyson 23:e93d5529b7a6 275 pConnection->toDo = DO_SEND_ALERT_INTERNAL_ERROR; //Abort invalid sessions
andrewboyson 23:e93d5529b7a6 276 LogTimeF("TlsPoll - invalid session %u - sending internal error\r\n", pConnection->sessionId);
andrewboyson 10:e269fd7b9500 277 }
andrewboyson 10:e269fd7b9500 278
andrewboyson 10:e269fd7b9500 279 switch (pConnection->toDo)
andrewboyson 10:e269fd7b9500 280 {
andrewboyson 10:e269fd7b9500 281 case DO_WAIT_CLIENT_HELLO:
andrewboyson 10:e269fd7b9500 282 case DO_WAIT_CLIENT_CHANGE:
andrewboyson 10:e269fd7b9500 283 case DO_WAIT_DECRYPT_MASTER_SECRET:
andrewboyson 10:e269fd7b9500 284 *pWindowSize = 0;
andrewboyson 10:e269fd7b9500 285 if (clientFinished) return true; //The client hasn't made a request and never will so finish
andrewboyson 10:e269fd7b9500 286 else return false; //The client hasn't made a request yet but it could.
andrewboyson 10:e269fd7b9500 287
andrewboyson 14:03a0b8fd6ddc 288 case DO_SEND_SERVER_HELLO_NEW:
andrewboyson 14:03a0b8fd6ddc 289 sendServerHelloNew(pConnection, pSession, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 14:03a0b8fd6ddc 290 pConnection->toDo = DO_WAIT_CLIENT_CHANGE;
andrewboyson 14:03a0b8fd6ddc 291 return false; //Not finished
andrewboyson 14:03a0b8fd6ddc 292
andrewboyson 14:03a0b8fd6ddc 293 case DO_SEND_SERVER_HELLO_RESUME:
andrewboyson 14:03a0b8fd6ddc 294 sendServerHelloResume(pConnection, pSession, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 10:e269fd7b9500 295 pConnection->toDo = DO_WAIT_CLIENT_CHANGE;
andrewboyson 10:e269fd7b9500 296 return false; //Not finished
andrewboyson 10:e269fd7b9500 297
andrewboyson 10:e269fd7b9500 298 case DO_SEND_SERVER_CHANGE:
andrewboyson 10:e269fd7b9500 299 sendServerChange(pConnection, pSession, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 10:e269fd7b9500 300 pConnection->toDo = DO_APPLICATION;
andrewboyson 10:e269fd7b9500 301 return false;
andrewboyson 10:e269fd7b9500 302
andrewboyson 10:e269fd7b9500 303 case DO_APPLICATION:
andrewboyson 10:e269fd7b9500 304 {
andrewboyson 10:e269fd7b9500 305 int status = HttpPoll(connectionId, clientFinished);
andrewboyson 10:e269fd7b9500 306 bool finished;
andrewboyson 10:e269fd7b9500 307 switch (status)
andrewboyson 10:e269fd7b9500 308 {
andrewboyson 10:e269fd7b9500 309 case HTTP_WAIT: finished = false; *pWindowSize = 0; break;
andrewboyson 10:e269fd7b9500 310 case HTTP_FINISHED: finished = true; *pWindowSize = 0; break;
andrewboyson 10:e269fd7b9500 311 case HTTP_HAVE_SOMETHING_TO_SEND: finished = sendContent(pConnection, pWindowSize, pWindow, positionOfWindowInStream); break;
andrewboyson 10:e269fd7b9500 312 }
andrewboyson 10:e269fd7b9500 313 if (finished) pConnection->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 10:e269fd7b9500 314 return finished;
andrewboyson 10:e269fd7b9500 315 }
andrewboyson 10:e269fd7b9500 316 case DO_SEND_ALERT_ILLEGAL_PARAMETER:
andrewboyson 14:03a0b8fd6ddc 317 sendFatal(TLS_ALERT_ILLEGAL_PARAMETER, pConnection, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 10:e269fd7b9500 318 pConnection->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 10:e269fd7b9500 319 return true; //Finished
andrewboyson 10:e269fd7b9500 320
andrewboyson 10:e269fd7b9500 321 case DO_SEND_ALERT_INTERNAL_ERROR:
andrewboyson 14:03a0b8fd6ddc 322 sendFatal(TLS_ALERT_INTERNAL_ERROR, pConnection, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 10:e269fd7b9500 323 pConnection->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 10:e269fd7b9500 324 return true; //Finished
andrewboyson 10:e269fd7b9500 325
andrewboyson 10:e269fd7b9500 326 default:
andrewboyson 10:e269fd7b9500 327 LogTimeF("TlsPoll - unspecified TLS state %d\r\n", pConnection->toDo);
andrewboyson 14:03a0b8fd6ddc 328 sendFatal(TLS_ALERT_INTERNAL_ERROR, pConnection, pWindowSize, pWindow, positionOfWindowInStream); //Internal error
andrewboyson 10:e269fd7b9500 329 pConnection->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 10:e269fd7b9500 330 return true; //Finished
andrewboyson 10:e269fd7b9500 331 }
andrewboyson 10:e269fd7b9500 332 }