A simple library to support serving https.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Wed Oct 02 20:26:04 2019 +0000
Revision:
14:03a0b8fd6ddc
Parent:
13:0a80b49a5e78
Child:
15:4ddb73b5fea1
Session resume now working. TLS working quickly after the initial 5 second RSA decrypt time using the 1024 bit private key.

Who changed what in which revision?

UserRevisionLine numberNew 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 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 14:03a0b8fd6ddc 50 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 10:e269fd7b9500 58 for (int i = 0; i < 32; 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 14:03a0b8fd6ddc 93 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 14:03a0b8fd6ddc 103 LogTime(" sending handshake finished\r\n");
andrewboyson 14:03a0b8fd6ddc 104 uint8_t* p = *pp;
andrewboyson 10:e269fd7b9500 105
andrewboyson 10:e269fd7b9500 106 //Hash over all handshake payloads exchanged so far
andrewboyson 10:e269fd7b9500 107 uint8_t hash[32];
andrewboyson 10:e269fd7b9500 108 Sha256Finish(&pConnection->handshakeSha, hash);
andrewboyson 10:e269fd7b9500 109
andrewboyson 10:e269fd7b9500 110 //Make verify data
andrewboyson 10:e269fd7b9500 111 uint8_t verify[12];
andrewboyson 10:e269fd7b9500 112 TlsPrfServerFinished(pSession->masterSecret, hash, verify); //Hash over all handshakes
andrewboyson 10:e269fd7b9500 113
andrewboyson 10:e269fd7b9500 114 //Make the 'finished' handshake
andrewboyson 10:e269fd7b9500 115 uint8_t payload[16];
andrewboyson 13:0a80b49a5e78 116 payload[0] = TLS_HANDSHAKE_FINISHED;
andrewboyson 10:e269fd7b9500 117 payload[1] = 0x00;
andrewboyson 10:e269fd7b9500 118 payload[2] = 0x00;
andrewboyson 10:e269fd7b9500 119 payload[3] = 0x0c; //Length 12
andrewboyson 10:e269fd7b9500 120 for (int i = 0; i < 12; i++) payload[i + 4] = verify[i];
andrewboyson 10:e269fd7b9500 121 int payloadLength = 16;
andrewboyson 10:e269fd7b9500 122
andrewboyson 10:e269fd7b9500 123 uint8_t mac[SHA1_HASH_SIZE];
andrewboyson 10:e269fd7b9500 124 TlsMacSha1(TLS_KEY_SIZE_MAC,
andrewboyson 10:e269fd7b9500 125 pConnection->serverMacKey,
andrewboyson 10:e269fd7b9500 126 pConnection->serverSequence,
andrewboyson 13:0a80b49a5e78 127 TLS_CONTENT_TYPE_HANDSHAKE,
andrewboyson 10:e269fd7b9500 128 0x03,
andrewboyson 10:e269fd7b9500 129 0x03,
andrewboyson 10:e269fd7b9500 130 payloadLength,
andrewboyson 10:e269fd7b9500 131 payload,
andrewboyson 10:e269fd7b9500 132 mac);
andrewboyson 10:e269fd7b9500 133
andrewboyson 10:e269fd7b9500 134
andrewboyson 10:e269fd7b9500 135 //plaintext
andrewboyson 10:e269fd7b9500 136 uint8_t message[48];
andrewboyson 10:e269fd7b9500 137 for (int i = 0; i < 16; i++) message[i ] = payload[i]; //payload
andrewboyson 10:e269fd7b9500 138 for (int i = 0; i < 20; i++) message[i + 16] = mac[i]; //mac
andrewboyson 10:e269fd7b9500 139 for (int i = 0; i < 12; i++) message[i + 36] = 0x0b; //padding
andrewboyson 10:e269fd7b9500 140
andrewboyson 10:e269fd7b9500 141 uint8_t iv[16];
andrewboyson 10:e269fd7b9500 142 for (int i = 0; i < 16; i++) iv[i] = RandomGetByte();
andrewboyson 10:e269fd7b9500 143
andrewboyson 10:e269fd7b9500 144 //Encrypt
andrewboyson 10:e269fd7b9500 145 struct AES_ctx ctx;
andrewboyson 10:e269fd7b9500 146 AES_init_ctx_iv(&ctx, pConnection->serverWriteKey, iv);
andrewboyson 10:e269fd7b9500 147 AES_CBC_encrypt_buffer(&ctx, message, 48);
andrewboyson 10:e269fd7b9500 148
andrewboyson 10:e269fd7b9500 149 for (int i = 0; i < 16; i++) *p++ = iv[i];
andrewboyson 14:03a0b8fd6ddc 150 for (int i = 0; i < 48; i++) *p++ = message[i];
andrewboyson 14:03a0b8fd6ddc 151
andrewboyson 14:03a0b8fd6ddc 152 *pp = p;
andrewboyson 14:03a0b8fd6ddc 153 }
andrewboyson 14:03a0b8fd6ddc 154 static void addChangeCipher(uint8_t** pp, struct TlsConnection* pConnection)
andrewboyson 14:03a0b8fd6ddc 155 {
andrewboyson 14:03a0b8fd6ddc 156 LogTime(" sending change cipher\r\n");
andrewboyson 14:03a0b8fd6ddc 157 uint8_t* p = *pp;
andrewboyson 14:03a0b8fd6ddc 158
andrewboyson 14:03a0b8fd6ddc 159 *p++ = TLS_CONTENT_TYPE_CHANGE_CIPHER; //Content is change cipher
andrewboyson 14:03a0b8fd6ddc 160 *p++ = 0x03; *p++ = 0x03; //Legacy TLS version
andrewboyson 14:03a0b8fd6ddc 161 *p++ = 0x00; *p++ = 0x01; //Change cipher Length (2 bytes)
andrewboyson 14:03a0b8fd6ddc 162 *p++ = 0x01; //Change cipher message 1
andrewboyson 10:e269fd7b9500 163
andrewboyson 14:03a0b8fd6ddc 164 //Record that all outgoing messages are now encrypted
andrewboyson 14:03a0b8fd6ddc 165 pConnection->serverEncrypted = true;
andrewboyson 14:03a0b8fd6ddc 166 pConnection->serverSequence = 0;
andrewboyson 14:03a0b8fd6ddc 167
andrewboyson 14:03a0b8fd6ddc 168 *pp = p;
andrewboyson 14:03a0b8fd6ddc 169 }
andrewboyson 14:03a0b8fd6ddc 170 static void addAlert(uint8_t** pp, struct TlsConnection* pConnection, uint8_t level, uint8_t description)
andrewboyson 14:03a0b8fd6ddc 171 {
andrewboyson 14:03a0b8fd6ddc 172 LogTime(" sending alert\r\n");
andrewboyson 14:03a0b8fd6ddc 173 Log (" - "); TlsLogAlertLevel(level); Log(": "); TlsLogAlertDescription(description); Log("\r\n");
andrewboyson 14:03a0b8fd6ddc 174
andrewboyson 14:03a0b8fd6ddc 175 uint8_t* p = *pp;
andrewboyson 14:03a0b8fd6ddc 176
andrewboyson 14:03a0b8fd6ddc 177 *p++ = TLS_CONTENT_TYPE_ALERT;
andrewboyson 14:03a0b8fd6ddc 178 *p++ = 0x03; *p++ = 0x03;
andrewboyson 14:03a0b8fd6ddc 179 addSize(&p, 2);
andrewboyson 14:03a0b8fd6ddc 180 *p++ = level;
andrewboyson 14:03a0b8fd6ddc 181 *p++ = description;
andrewboyson 14:03a0b8fd6ddc 182
andrewboyson 10:e269fd7b9500 183 pConnection->serverSequence++;
andrewboyson 14:03a0b8fd6ddc 184
andrewboyson 14:03a0b8fd6ddc 185 *pp = p;
andrewboyson 14:03a0b8fd6ddc 186 }
andrewboyson 14:03a0b8fd6ddc 187 static void sendServerHelloNew(struct TlsConnection* pConnection, struct TlsSession* pSession, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 14:03a0b8fd6ddc 188 {
andrewboyson 14:03a0b8fd6ddc 189 uint8_t* p = pWindow;
andrewboyson 14:03a0b8fd6ddc 190
andrewboyson 14:03a0b8fd6ddc 191 addHandshakeStart (&p);
andrewboyson 14:03a0b8fd6ddc 192 addHandshakeServerHello (&p, pConnection);
andrewboyson 14:03a0b8fd6ddc 193 addHandshakeCertificate (&p);
andrewboyson 14:03a0b8fd6ddc 194 addHandshakeServerHelloDone(&p);
andrewboyson 14:03a0b8fd6ddc 195 addHandshakeEnd ( p, pConnection);
andrewboyson 14:03a0b8fd6ddc 196
andrewboyson 10:e269fd7b9500 197 *pWindowSize = p - pWindow;
andrewboyson 10:e269fd7b9500 198 pConnection->serverPositionInStreamOffset = positionOfWindowInStream + *pWindowSize;
andrewboyson 10:e269fd7b9500 199 }
andrewboyson 14:03a0b8fd6ddc 200 static void sendServerHelloResume(struct TlsConnection* pConnection, struct TlsSession* pSession, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 10:e269fd7b9500 201 {
andrewboyson 10:e269fd7b9500 202 uint8_t* p = pWindow;
andrewboyson 14:03a0b8fd6ddc 203
andrewboyson 14:03a0b8fd6ddc 204 addHandshakeStart (&p);
andrewboyson 14:03a0b8fd6ddc 205 addHandshakeServerHello(&p, pConnection);
andrewboyson 14:03a0b8fd6ddc 206 addHandshakeEnd ( p, pConnection);
andrewboyson 10:e269fd7b9500 207
andrewboyson 14:03a0b8fd6ddc 208 TlsPrfKeys (pSession->masterSecret, pConnection->clientRandom, pConnection->serverRandom, pConnection->clientMacKey,
andrewboyson 14:03a0b8fd6ddc 209 pConnection->serverMacKey,
andrewboyson 14:03a0b8fd6ddc 210 pConnection->clientWriteKey,
andrewboyson 14:03a0b8fd6ddc 211 pConnection->serverWriteKey);
andrewboyson 14:03a0b8fd6ddc 212
andrewboyson 14:03a0b8fd6ddc 213 addChangeCipher (&p, pConnection);
andrewboyson 14:03a0b8fd6ddc 214
andrewboyson 14:03a0b8fd6ddc 215 addHandshakeStart (&p);
andrewboyson 14:03a0b8fd6ddc 216 addHandshakeFinished (&p, pConnection, pSession);
andrewboyson 14:03a0b8fd6ddc 217 addHandshakeEnd ( p, pConnection);
andrewboyson 10:e269fd7b9500 218
andrewboyson 10:e269fd7b9500 219 *pWindowSize = p - pWindow;
andrewboyson 14:03a0b8fd6ddc 220 pConnection->serverPositionInStreamOffset = positionOfWindowInStream + *pWindowSize;
andrewboyson 14:03a0b8fd6ddc 221 }
andrewboyson 14:03a0b8fd6ddc 222 static void sendServerChange(struct TlsConnection* pConnection, struct TlsSession* pSession, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 14:03a0b8fd6ddc 223 {
andrewboyson 14:03a0b8fd6ddc 224 uint8_t* p = pWindow;
andrewboyson 14:03a0b8fd6ddc 225
andrewboyson 14:03a0b8fd6ddc 226 addChangeCipher(&p, pConnection);
andrewboyson 14:03a0b8fd6ddc 227
andrewboyson 14:03a0b8fd6ddc 228 addHandshakeStart (&p);
andrewboyson 14:03a0b8fd6ddc 229 addHandshakeFinished(&p, pConnection, pSession);
andrewboyson 14:03a0b8fd6ddc 230 addHandshakeEnd ( p, pConnection);
andrewboyson 14:03a0b8fd6ddc 231
andrewboyson 14:03a0b8fd6ddc 232 *pWindowSize = p - pWindow;
andrewboyson 14:03a0b8fd6ddc 233 pConnection->serverPositionInStreamOffset = positionOfWindowInStream + *pWindowSize;
andrewboyson 14:03a0b8fd6ddc 234 }
andrewboyson 14:03a0b8fd6ddc 235 static void sendFatal(uint8_t description, struct TlsConnection* pConnection, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 14:03a0b8fd6ddc 236 {
andrewboyson 14:03a0b8fd6ddc 237 uint8_t* p = pWindow;
andrewboyson 14:03a0b8fd6ddc 238
andrewboyson 14:03a0b8fd6ddc 239 addAlert(&p, pConnection, TLS_ALERT_FATAL, description);
andrewboyson 14:03a0b8fd6ddc 240
andrewboyson 14:03a0b8fd6ddc 241 *pWindowSize = p - pWindow;
andrewboyson 14:03a0b8fd6ddc 242 pConnection->serverPositionInStreamOffset = positionOfWindowInStream + *pWindowSize;
andrewboyson 10:e269fd7b9500 243 }
andrewboyson 10:e269fd7b9500 244
andrewboyson 10:e269fd7b9500 245 static bool sendContent(struct TlsConnection* pConnection, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 10:e269fd7b9500 246 {
andrewboyson 10:e269fd7b9500 247 /*
andrewboyson 10:e269fd7b9500 248 content:
andrewboyson 10:e269fd7b9500 249 contentType * 1
andrewboyson 10:e269fd7b9500 250 version * 2
andrewboyson 10:e269fd7b9500 251 length * 2
andrewboyson 10:e269fd7b9500 252 iv * AES_BLOCKLEN (16)
andrewboyson 10:e269fd7b9500 253 message:
andrewboyson 10:e269fd7b9500 254 payload * payloadLength
andrewboyson 10:e269fd7b9500 255 mac * SHA1_HASH_SIZE (20)
andrewboyson 10:e269fd7b9500 256 padding * 0 to AES_BLOCKLEN - 1 (0 to 15)
andrewboyson 10:e269fd7b9500 257 paddingLength * 1
andrewboyson 10:e269fd7b9500 258 */
andrewboyson 10:e269fd7b9500 259 #define CONTENT_MAX_OVERHEAD (5 + AES_BLOCKLEN + SHA1_HASH_SIZE + AES_BLOCKLEN - 1 + 1)
andrewboyson 10:e269fd7b9500 260
andrewboyson 10:e269fd7b9500 261 //Start
andrewboyson 10:e269fd7b9500 262 LogTime(" adding application content\r\n");
andrewboyson 10:e269fd7b9500 263 LogF("- available window size %d\r\n", *pWindowSize);
andrewboyson 10:e269fd7b9500 264 LogF("- position of window in stream %d\r\n", positionOfWindowInStream);
andrewboyson 10:e269fd7b9500 265 uint8_t* p = pWindow;
andrewboyson 13:0a80b49a5e78 266 *p++ = TLS_CONTENT_TYPE_APPLICATION;
andrewboyson 10:e269fd7b9500 267 *p++ = 0x03; *p++ = 0x03;
andrewboyson 10:e269fd7b9500 268
andrewboyson 10:e269fd7b9500 269 //Prepare a place to backfill the size
andrewboyson 10:e269fd7b9500 270 uint8_t* pBackfillSize = p;
andrewboyson 10:e269fd7b9500 271 *p++ = 0; *p++ = 0;
andrewboyson 10:e269fd7b9500 272
andrewboyson 10:e269fd7b9500 273 //Add the IV
andrewboyson 10:e269fd7b9500 274 uint8_t* pIv = p;
andrewboyson 10:e269fd7b9500 275 for (int i = 0; i < AES_BLOCKLEN; i++) *p++ = RandomGetByte();
andrewboyson 10:e269fd7b9500 276
andrewboyson 10:e269fd7b9500 277 //Add the plain payload
andrewboyson 10:e269fd7b9500 278 uint8_t* pPayload = p;
andrewboyson 10:e269fd7b9500 279 int payloadSize = *pWindowSize - CONTENT_MAX_OVERHEAD;
andrewboyson 10:e269fd7b9500 280 LogF("- available payload size %d\r\n", payloadSize);
andrewboyson 10:e269fd7b9500 281 uint32_t positionOfPayloadInStream = positionOfWindowInStream - pConnection->serverPositionInStreamOffset;
andrewboyson 10:e269fd7b9500 282 LogF("- position of payload in stream %d\r\n", positionOfPayloadInStream);
andrewboyson 10:e269fd7b9500 283 bool finished = HttpAdd(pConnection->id, &payloadSize, (char*)pPayload, positionOfPayloadInStream); //Return whatever HTTP would be
andrewboyson 10:e269fd7b9500 284 LogF("- resulting payload size %d\r\n", payloadSize);
andrewboyson 10:e269fd7b9500 285 p += payloadSize;
andrewboyson 10:e269fd7b9500 286
andrewboyson 10:e269fd7b9500 287 //Add the MAC
andrewboyson 10:e269fd7b9500 288 TlsMacSha1(TLS_KEY_SIZE_MAC,
andrewboyson 10:e269fd7b9500 289 pConnection->serverMacKey,
andrewboyson 10:e269fd7b9500 290 pConnection->serverSequence,
andrewboyson 13:0a80b49a5e78 291 TLS_CONTENT_TYPE_APPLICATION,
andrewboyson 10:e269fd7b9500 292 0x03,
andrewboyson 10:e269fd7b9500 293 0x03,
andrewboyson 10:e269fd7b9500 294 payloadSize,
andrewboyson 10:e269fd7b9500 295 pPayload,
andrewboyson 10:e269fd7b9500 296 p);
andrewboyson 10:e269fd7b9500 297 p += SHA1_HASH_SIZE;
andrewboyson 10:e269fd7b9500 298
andrewboyson 10:e269fd7b9500 299 //Add the padding
andrewboyson 10:e269fd7b9500 300 int paddingSize = AES_BLOCKLEN - 1 - (payloadSize + SHA1_HASH_SIZE + 1 - 1) % AES_BLOCKLEN;
andrewboyson 10:e269fd7b9500 301 LogF("- padding size %d\r\n", paddingSize);
andrewboyson 10:e269fd7b9500 302 for (int i = 0; i < paddingSize; i++) *p++ = paddingSize;
andrewboyson 10:e269fd7b9500 303
andrewboyson 10:e269fd7b9500 304 //Add the padding size
andrewboyson 10:e269fd7b9500 305 *p++ = paddingSize;
andrewboyson 10:e269fd7b9500 306
andrewboyson 10:e269fd7b9500 307 //Backfill the size
andrewboyson 10:e269fd7b9500 308 backfillSize(p, pBackfillSize);
andrewboyson 10:e269fd7b9500 309
andrewboyson 10:e269fd7b9500 310 //Calculate the resulting window size
andrewboyson 10:e269fd7b9500 311 *pWindowSize = p - pWindow;
andrewboyson 10:e269fd7b9500 312 LogF("- resulting window size %d\r\n", *pWindowSize);
andrewboyson 10:e269fd7b9500 313
andrewboyson 10:e269fd7b9500 314 //Log the plain content
andrewboyson 10:e269fd7b9500 315 Log("- plain content\r\n"); LogBytesAsHex(pWindow, *pWindowSize); Log("\r\n");
andrewboyson 10:e269fd7b9500 316
andrewboyson 10:e269fd7b9500 317 //Encrypt payload + mac + padding
andrewboyson 10:e269fd7b9500 318 struct AES_ctx ctx;
andrewboyson 10:e269fd7b9500 319 AES_init_ctx_iv(&ctx, pConnection->serverWriteKey, pIv);
andrewboyson 10:e269fd7b9500 320 AES_CBC_encrypt_buffer(&ctx, pPayload, p - pPayload);
andrewboyson 10:e269fd7b9500 321
andrewboyson 10:e269fd7b9500 322 //Finalise
andrewboyson 10:e269fd7b9500 323 pConnection->serverSequence++;
andrewboyson 10:e269fd7b9500 324 pConnection->serverPositionInStreamOffset += *pWindowSize - payloadSize;
andrewboyson 10:e269fd7b9500 325
andrewboyson 10:e269fd7b9500 326 return finished;
andrewboyson 10:e269fd7b9500 327 }
andrewboyson 10:e269fd7b9500 328 bool TlsResponse(int connectionId, bool clientFinished, int* pWindowSize, uint8_t* pWindow, uint32_t positionOfWindowInStream)
andrewboyson 10:e269fd7b9500 329 {
andrewboyson 10:e269fd7b9500 330 struct TlsConnection* pConnection = TlsConnectionOrNull(connectionId);
andrewboyson 10:e269fd7b9500 331 if (!pConnection)
andrewboyson 10:e269fd7b9500 332 {
andrewboyson 10:e269fd7b9500 333 *pWindowSize = 0;
andrewboyson 10:e269fd7b9500 334 return false;
andrewboyson 10:e269fd7b9500 335 }
andrewboyson 10:e269fd7b9500 336
andrewboyson 10:e269fd7b9500 337 if (!pConnection->sessionId)
andrewboyson 10:e269fd7b9500 338 {
andrewboyson 10:e269fd7b9500 339 *pWindowSize = 0;
andrewboyson 10:e269fd7b9500 340 return false;
andrewboyson 10:e269fd7b9500 341 }
andrewboyson 10:e269fd7b9500 342
andrewboyson 10:e269fd7b9500 343 struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
andrewboyson 10:e269fd7b9500 344 if (!pSession)
andrewboyson 10:e269fd7b9500 345 {
andrewboyson 10:e269fd7b9500 346 LogTimeF("TlsPoll - invalid session %u\r\n", pConnection->sessionId);
andrewboyson 10:e269fd7b9500 347 *pWindowSize = 0;
andrewboyson 10:e269fd7b9500 348 return false;
andrewboyson 10:e269fd7b9500 349 }
andrewboyson 10:e269fd7b9500 350
andrewboyson 10:e269fd7b9500 351 switch (pConnection->toDo)
andrewboyson 10:e269fd7b9500 352 {
andrewboyson 10:e269fd7b9500 353 case DO_WAIT_CLIENT_HELLO:
andrewboyson 10:e269fd7b9500 354 case DO_WAIT_CLIENT_CHANGE:
andrewboyson 10:e269fd7b9500 355 case DO_WAIT_DECRYPT_MASTER_SECRET:
andrewboyson 10:e269fd7b9500 356 *pWindowSize = 0;
andrewboyson 10:e269fd7b9500 357 if (clientFinished) return true; //The client hasn't made a request and never will so finish
andrewboyson 10:e269fd7b9500 358 else return false; //The client hasn't made a request yet but it could.
andrewboyson 10:e269fd7b9500 359
andrewboyson 14:03a0b8fd6ddc 360 case DO_SEND_SERVER_HELLO_NEW:
andrewboyson 14:03a0b8fd6ddc 361 sendServerHelloNew(pConnection, pSession, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 14:03a0b8fd6ddc 362 pConnection->toDo = DO_WAIT_CLIENT_CHANGE;
andrewboyson 14:03a0b8fd6ddc 363 return false; //Not finished
andrewboyson 14:03a0b8fd6ddc 364
andrewboyson 14:03a0b8fd6ddc 365 case DO_SEND_SERVER_HELLO_RESUME:
andrewboyson 14:03a0b8fd6ddc 366 sendServerHelloResume(pConnection, pSession, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 10:e269fd7b9500 367 pConnection->toDo = DO_WAIT_CLIENT_CHANGE;
andrewboyson 10:e269fd7b9500 368 return false; //Not finished
andrewboyson 10:e269fd7b9500 369
andrewboyson 10:e269fd7b9500 370 case DO_SEND_SERVER_CHANGE:
andrewboyson 10:e269fd7b9500 371 sendServerChange(pConnection, pSession, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 10:e269fd7b9500 372 pConnection->toDo = DO_APPLICATION;
andrewboyson 10:e269fd7b9500 373 return false;
andrewboyson 10:e269fd7b9500 374
andrewboyson 10:e269fd7b9500 375 case DO_APPLICATION:
andrewboyson 10:e269fd7b9500 376 {
andrewboyson 10:e269fd7b9500 377 int status = HttpPoll(connectionId, clientFinished);
andrewboyson 10:e269fd7b9500 378 bool finished;
andrewboyson 10:e269fd7b9500 379 switch (status)
andrewboyson 10:e269fd7b9500 380 {
andrewboyson 10:e269fd7b9500 381 case HTTP_WAIT: finished = false; *pWindowSize = 0; break;
andrewboyson 10:e269fd7b9500 382 case HTTP_FINISHED: finished = true; *pWindowSize = 0; break;
andrewboyson 10:e269fd7b9500 383 case HTTP_HAVE_SOMETHING_TO_SEND: finished = sendContent(pConnection, pWindowSize, pWindow, positionOfWindowInStream); break;
andrewboyson 10:e269fd7b9500 384 }
andrewboyson 10:e269fd7b9500 385 if (finished) pConnection->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 10:e269fd7b9500 386 return finished;
andrewboyson 10:e269fd7b9500 387 }
andrewboyson 10:e269fd7b9500 388 case DO_SEND_ALERT_ILLEGAL_PARAMETER:
andrewboyson 14:03a0b8fd6ddc 389 sendFatal(TLS_ALERT_ILLEGAL_PARAMETER, pConnection, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 10:e269fd7b9500 390 pConnection->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 10:e269fd7b9500 391 return true; //Finished
andrewboyson 10:e269fd7b9500 392
andrewboyson 10:e269fd7b9500 393 case DO_SEND_ALERT_INTERNAL_ERROR:
andrewboyson 14:03a0b8fd6ddc 394 sendFatal(TLS_ALERT_INTERNAL_ERROR, pConnection, pWindowSize, pWindow, positionOfWindowInStream);
andrewboyson 10:e269fd7b9500 395 pConnection->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 10:e269fd7b9500 396 return true; //Finished
andrewboyson 10:e269fd7b9500 397
andrewboyson 10:e269fd7b9500 398 default:
andrewboyson 10:e269fd7b9500 399 LogTimeF("TlsPoll - unspecified TLS state %d\r\n", pConnection->toDo);
andrewboyson 14:03a0b8fd6ddc 400 sendFatal(TLS_ALERT_INTERNAL_ERROR, pConnection, pWindowSize, pWindow, positionOfWindowInStream); //Internal error
andrewboyson 10:e269fd7b9500 401 pConnection->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 10:e269fd7b9500 402 return true; //Finished
andrewboyson 10:e269fd7b9500 403 }
andrewboyson 10:e269fd7b9500 404 }