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:
17:93feb2a51d58
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 2:82268409e83f 1 #include "tls.h"
andrewboyson 2:82268409e83f 2 #include "tls-defs.h"
andrewboyson 5:ee5489ee1117 3 #include "tls-connection.h"
andrewboyson 2:82268409e83f 4 #include "tls-session.h"
andrewboyson 2:82268409e83f 5 #include "tls-log.h"
andrewboyson 8:5e66a6b4b38c 6 #include "tls-prf.h"
andrewboyson 2:82268409e83f 7 #include "mstimer.h"
andrewboyson 2:82268409e83f 8 #include "log.h"
andrewboyson 2:82268409e83f 9 #include "pri-key.h"
andrewboyson 6:819c17738dc2 10 #include "aes128.h"
andrewboyson 8:5e66a6b4b38c 11 #include "sha1.h"
andrewboyson 9:f354b4859b0b 12 #include "tls-mac.h"
andrewboyson 8:5e66a6b4b38c 13 #include "led.h"
andrewboyson 9:f354b4859b0b 14 #include "http.h"
andrewboyson 2:82268409e83f 15
andrewboyson 14:03a0b8fd6ddc 16 static void handleClientHello(int length, uint8_t* pBuffer, struct TlsConnection* pConnection)
andrewboyson 5:ee5489ee1117 17 {
andrewboyson 2:82268409e83f 18 //Check things look ok
andrewboyson 4:6a1d887f1cad 19 uint8_t* p = pBuffer;
andrewboyson 2:82268409e83f 20 if (length < 100)
andrewboyson 2:82268409e83f 21 {
andrewboyson 2:82268409e83f 22 LogF("TLS - %d byte client hello message is not at least 100 bytes long\r\n", length);
andrewboyson 14:03a0b8fd6ddc 23 pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
andrewboyson 14:03a0b8fd6ddc 24 return;
andrewboyson 2:82268409e83f 25 }
andrewboyson 4:6a1d887f1cad 26
andrewboyson 14:03a0b8fd6ddc 27 //get the version
andrewboyson 4:6a1d887f1cad 28 uint8_t versionH = *p++;
andrewboyson 4:6a1d887f1cad 29 uint8_t versionL = *p++;
andrewboyson 2:82268409e83f 30
andrewboyson 14:03a0b8fd6ddc 31 //Get the client random
andrewboyson 6:819c17738dc2 32 for (int i = 0; i < 32; i++) pConnection->clientRandom[i] = *p++;
andrewboyson 2:82268409e83f 33
andrewboyson 14:03a0b8fd6ddc 34 //Get the session id
andrewboyson 2:82268409e83f 35 int sessionIdLength = *p++;
andrewboyson 4:6a1d887f1cad 36 uint8_t* pSessionId = p;
andrewboyson 2:82268409e83f 37
andrewboyson 10:e269fd7b9500 38 if (sessionIdLength == 4)
andrewboyson 2:82268409e83f 39 {
andrewboyson 10:e269fd7b9500 40 pConnection->sessionId = *p++;
andrewboyson 10:e269fd7b9500 41 pConnection->sessionId <<= 8;
andrewboyson 10:e269fd7b9500 42 pConnection->sessionId |= *p++;
andrewboyson 10:e269fd7b9500 43 pConnection->sessionId <<= 8;
andrewboyson 10:e269fd7b9500 44 pConnection->sessionId |= *p++;
andrewboyson 10:e269fd7b9500 45 pConnection->sessionId <<= 8;
andrewboyson 10:e269fd7b9500 46 pConnection->sessionId |= *p++;
andrewboyson 2:82268409e83f 47 }
andrewboyson 10:e269fd7b9500 48 else
andrewboyson 10:e269fd7b9500 49 {
andrewboyson 10:e269fd7b9500 50 pConnection->sessionId = 0;
andrewboyson 10:e269fd7b9500 51 p += sessionIdLength;
andrewboyson 10:e269fd7b9500 52 }
andrewboyson 14:03a0b8fd6ddc 53
andrewboyson 14:03a0b8fd6ddc 54 //Work out from the session id if this connection can be resumed from an existing session
andrewboyson 14:03a0b8fd6ddc 55 struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
andrewboyson 14:03a0b8fd6ddc 56 //pSession = NULL;
andrewboyson 14:03a0b8fd6ddc 57 pConnection->resume = pSession && pSession->valid;
andrewboyson 14:03a0b8fd6ddc 58
andrewboyson 14:03a0b8fd6ddc 59 //If it cannot be resumed then create a new one
andrewboyson 14:03a0b8fd6ddc 60 if (!pConnection->resume)
andrewboyson 10:e269fd7b9500 61 {
andrewboyson 10:e269fd7b9500 62 pSession = TlsSessionNew();
andrewboyson 10:e269fd7b9500 63 pConnection->sessionId = pSession->id;
andrewboyson 10:e269fd7b9500 64 }
andrewboyson 2:82268409e83f 65
andrewboyson 2:82268409e83f 66 pSession->lastUsed = MsTimerCount;
andrewboyson 2:82268409e83f 67
andrewboyson 2:82268409e83f 68 //Log the parameters
andrewboyson 2:82268409e83f 69 if (TlsTrace)
andrewboyson 2:82268409e83f 70 {
andrewboyson 2:82268409e83f 71 LogF("- client version HH:LL: %02x:%02x\r\n", versionH, versionL);
andrewboyson 6:819c17738dc2 72 Log ("- client random:\r\n"); LogBytesAsHex(pConnection->clientRandom, 32); Log("\r\n");
andrewboyson 2:82268409e83f 73 Log ("- client session id:\r\n"); LogBytesAsHex(pSessionId, sessionIdLength); Log("\r\n");
andrewboyson 10:e269fd7b9500 74 LogF("- session index: %u\r\n", pConnection->sessionId);
andrewboyson 14:03a0b8fd6ddc 75 if (pConnection->resume) Log ("- existing session so resume\r\n");
andrewboyson 14:03a0b8fd6ddc 76 else Log ("- new session\r\n");
andrewboyson 2:82268409e83f 77 }
andrewboyson 14:03a0b8fd6ddc 78
andrewboyson 14:03a0b8fd6ddc 79 if (pConnection->resume) pConnection->toDo = DO_SEND_SERVER_HELLO_RESUME;
andrewboyson 14:03a0b8fd6ddc 80 else pConnection->toDo = DO_SEND_SERVER_HELLO_NEW;
andrewboyson 14:03a0b8fd6ddc 81
andrewboyson 14:03a0b8fd6ddc 82 return;
andrewboyson 2:82268409e83f 83 }
andrewboyson 14:03a0b8fd6ddc 84 static void handleClientKeyExchange(int length, uint8_t* pBuffer, struct TlsConnection* pConnection) //returns 0 on success; -1 on error
andrewboyson 2:82268409e83f 85 {
andrewboyson 10:e269fd7b9500 86 struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
andrewboyson 5:ee5489ee1117 87 if (!pSession)
andrewboyson 5:ee5489ee1117 88 {
andrewboyson 10:e269fd7b9500 89 LogTimeF("handleClientKeyExchange - invalid session %u\r\n", pConnection->sessionId);
andrewboyson 14:03a0b8fd6ddc 90 pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
andrewboyson 14:03a0b8fd6ddc 91 return;
andrewboyson 5:ee5489ee1117 92 }
andrewboyson 2:82268409e83f 93
andrewboyson 2:82268409e83f 94 if (length != 130)
andrewboyson 2:82268409e83f 95 {
andrewboyson 2:82268409e83f 96 LogF("TLS - %d byte client key exchange message is not 130 bytes long\r\n", length);
andrewboyson 14:03a0b8fd6ddc 97 pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
andrewboyson 14:03a0b8fd6ddc 98 return;
andrewboyson 2:82268409e83f 99 }
andrewboyson 2:82268409e83f 100 int premasterLength = pBuffer[0] << 8 | pBuffer[1]; //Overall length 2 bytes
andrewboyson 2:82268409e83f 101 if (premasterLength != 128)
andrewboyson 2:82268409e83f 102 {
andrewboyson 2:82268409e83f 103 LogF("TLS - %d byte encrypted pre master secret is not 128 bytes long\r\n", length);
andrewboyson 14:03a0b8fd6ddc 104 pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
andrewboyson 14:03a0b8fd6ddc 105 return;
andrewboyson 2:82268409e83f 106 }
andrewboyson 4:6a1d887f1cad 107 uint8_t* pEncryptedPreMasterSecret = pBuffer + 2;
andrewboyson 14:03a0b8fd6ddc 108 pConnection->slotPriKeyDecryption = PriKeyDecryptStart(pEncryptedPreMasterSecret);
andrewboyson 2:82268409e83f 109
andrewboyson 2:82268409e83f 110 if (TlsTrace)
andrewboyson 2:82268409e83f 111 {
andrewboyson 2:82268409e83f 112 LogF("- encrypted pre master\r\n", premasterLength);
andrewboyson 2:82268409e83f 113 LogBytesAsHex(pEncryptedPreMasterSecret, 128);
andrewboyson 2:82268409e83f 114 Log("\r\n");
andrewboyson 2:82268409e83f 115 }
andrewboyson 2:82268409e83f 116
andrewboyson 14:03a0b8fd6ddc 117 pConnection->toDo = DO_WAIT_DECRYPT_MASTER_SECRET;
andrewboyson 14:03a0b8fd6ddc 118 return;
andrewboyson 2:82268409e83f 119 }
andrewboyson 14:03a0b8fd6ddc 120 static void handleClientFinished(int length, uint8_t* pBuffer, struct TlsConnection* pConnection) //returns 0 on success; -1 on error
andrewboyson 8:5e66a6b4b38c 121 {
andrewboyson 10:e269fd7b9500 122 struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
andrewboyson 8:5e66a6b4b38c 123 if (!pSession)
andrewboyson 8:5e66a6b4b38c 124 {
andrewboyson 10:e269fd7b9500 125 LogTimeF("handleClientKeyExchange - invalid session %u\r\n", pConnection->sessionId);
andrewboyson 14:03a0b8fd6ddc 126 pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
andrewboyson 14:03a0b8fd6ddc 127 return;
andrewboyson 8:5e66a6b4b38c 128 }
andrewboyson 8:5e66a6b4b38c 129
andrewboyson 8:5e66a6b4b38c 130 //Calculate the verify message
andrewboyson 8:5e66a6b4b38c 131 uint8_t verify[12];
andrewboyson 8:5e66a6b4b38c 132 TlsPrfClientFinished(pSession->masterSecret, pConnection->clientHandshakeHash, verify);
andrewboyson 8:5e66a6b4b38c 133 Log("- verify handshake\r\n");
andrewboyson 8:5e66a6b4b38c 134 LogBytesAsHex(verify, 12);
andrewboyson 8:5e66a6b4b38c 135 Log("\r\n");
andrewboyson 8:5e66a6b4b38c 136
andrewboyson 14:03a0b8fd6ddc 137 if (pConnection->resume) pConnection->toDo = DO_APPLICATION;
andrewboyson 14:03a0b8fd6ddc 138 else pConnection->toDo = DO_SEND_SERVER_CHANGE;
andrewboyson 14:03a0b8fd6ddc 139
andrewboyson 14:03a0b8fd6ddc 140 return;
andrewboyson 8:5e66a6b4b38c 141 }
andrewboyson 6:819c17738dc2 142 static void changeCipher(int length, uint8_t* pBuffer, struct TlsConnection* pConnection)
andrewboyson 6:819c17738dc2 143 {
andrewboyson 6:819c17738dc2 144 uint8_t message = pBuffer[0];
andrewboyson 6:819c17738dc2 145 if (TlsTrace)
andrewboyson 6:819c17738dc2 146 {
andrewboyson 6:819c17738dc2 147 LogF("- message: %d\r\n", message);
andrewboyson 6:819c17738dc2 148 }
andrewboyson 8:5e66a6b4b38c 149
andrewboyson 8:5e66a6b4b38c 150 //Take snapshot of the handshake hash up to this point
andrewboyson 8:5e66a6b4b38c 151 struct Sha256State handshakeSha;
andrewboyson 8:5e66a6b4b38c 152 Sha256Copy (&handshakeSha, &pConnection->handshakeSha);
andrewboyson 8:5e66a6b4b38c 153 Sha256Finish(&handshakeSha, pConnection->clientHandshakeHash);
andrewboyson 8:5e66a6b4b38c 154
andrewboyson 8:5e66a6b4b38c 155 //Record that all incoming messages are now encrypted
andrewboyson 6:819c17738dc2 156 pConnection->clientEncrypted = true;
andrewboyson 8:5e66a6b4b38c 157 pConnection->clientSequence = 0;
andrewboyson 6:819c17738dc2 158 }
andrewboyson 4:6a1d887f1cad 159 static void handleAlert(int length, uint8_t* pBuffer)
andrewboyson 2:82268409e83f 160 {
andrewboyson 4:6a1d887f1cad 161 uint8_t level = pBuffer[0];
andrewboyson 4:6a1d887f1cad 162 uint8_t description = pBuffer[1];
andrewboyson 2:82268409e83f 163 if (TlsTrace)
andrewboyson 2:82268409e83f 164 {
andrewboyson 2:82268409e83f 165 Log("- alert level: "); TlsLogAlertLevel (level); Log("\r\n");
andrewboyson 2:82268409e83f 166 Log("- alert description: "); TlsLogAlertDescription(description); Log("\r\n");
andrewboyson 2:82268409e83f 167 }
andrewboyson 2:82268409e83f 168 }
andrewboyson 9:f354b4859b0b 169 static void handleApplication(int length, uint8_t* pBuffer, struct TlsConnection* pConnection)
andrewboyson 2:82268409e83f 170 {
andrewboyson 2:82268409e83f 171 if (TlsTrace)
andrewboyson 2:82268409e83f 172 {
andrewboyson 2:82268409e83f 173 Log("- application data:\r\n");
andrewboyson 2:82268409e83f 174 LogBytesAsHex(pBuffer, length);
andrewboyson 2:82268409e83f 175 Log("\r\n");
andrewboyson 9:f354b4859b0b 176 }
andrewboyson 10:e269fd7b9500 177 HttpRequest(pConnection->id, length, (char*)pBuffer, 0);
andrewboyson 2:82268409e83f 178 }
andrewboyson 5:ee5489ee1117 179
andrewboyson 5:ee5489ee1117 180 static void handleHandshake(int length, uint8_t* pBuffer, struct TlsConnection* pConnection)
andrewboyson 2:82268409e83f 181 {
andrewboyson 8:5e66a6b4b38c 182 Sha256Add(&pConnection->handshakeSha, pBuffer, length);
andrewboyson 7:94ef5824c3c0 183
andrewboyson 5:ee5489ee1117 184 uint8_t* p = pBuffer;
andrewboyson 5:ee5489ee1117 185 while (p < pBuffer + length)
andrewboyson 5:ee5489ee1117 186 {
andrewboyson 5:ee5489ee1117 187 uint8_t handshakeType = *p++;
andrewboyson 5:ee5489ee1117 188 int handshakeLength = *p++ << 16;
andrewboyson 5:ee5489ee1117 189 handshakeLength |= *p++ << 8;
andrewboyson 5:ee5489ee1117 190 handshakeLength |= *p++ ; //Handshake length 3 bytes
andrewboyson 5:ee5489ee1117 191
andrewboyson 5:ee5489ee1117 192 if (TlsTrace)
andrewboyson 5:ee5489ee1117 193 {
andrewboyson 5:ee5489ee1117 194 Log ("- handshake type: "); TlsLogHandshakeType(handshakeType); Log("\r\n");
andrewboyson 5:ee5489ee1117 195 LogF("- handshake length: %d\r\n", handshakeLength);
andrewboyson 5:ee5489ee1117 196 }
andrewboyson 5:ee5489ee1117 197
andrewboyson 5:ee5489ee1117 198 switch (handshakeType)
andrewboyson 5:ee5489ee1117 199 {
andrewboyson 13:0a80b49a5e78 200 case TLS_HANDSHAKE_CLIENT_HELLO:
andrewboyson 14:03a0b8fd6ddc 201 handleClientHello(handshakeLength, p, pConnection);
andrewboyson 5:ee5489ee1117 202 break;
andrewboyson 5:ee5489ee1117 203
andrewboyson 13:0a80b49a5e78 204 case TLS_HANDSHAKE_CLIENT_KEY_EXCHANGE:
andrewboyson 14:03a0b8fd6ddc 205 handleClientKeyExchange(handshakeLength, p, pConnection);
andrewboyson 5:ee5489ee1117 206 break;
andrewboyson 5:ee5489ee1117 207
andrewboyson 13:0a80b49a5e78 208 case TLS_HANDSHAKE_FINISHED:
andrewboyson 14:03a0b8fd6ddc 209 handleClientFinished(handshakeLength, p, pConnection);
andrewboyson 8:5e66a6b4b38c 210 break;
andrewboyson 8:5e66a6b4b38c 211
andrewboyson 5:ee5489ee1117 212 default:
andrewboyson 5:ee5489ee1117 213 LogF("TLS - ignoring handshake type ");
andrewboyson 5:ee5489ee1117 214 TlsLogHandshakeType(handshakeType);
andrewboyson 5:ee5489ee1117 215 LogF(" and skipping %d bytes\r\n", handshakeLength);
andrewboyson 5:ee5489ee1117 216 break;
andrewboyson 5:ee5489ee1117 217 }
andrewboyson 5:ee5489ee1117 218 p += handshakeLength;
andrewboyson 5:ee5489ee1117 219 }
andrewboyson 5:ee5489ee1117 220 }
andrewboyson 8:5e66a6b4b38c 221 static int handleContent(struct TlsConnection* pConnection, uint8_t* pBuffer, int available)
andrewboyson 8:5e66a6b4b38c 222 {
andrewboyson 5:ee5489ee1117 223 uint8_t contentType = *pBuffer++;
andrewboyson 5:ee5489ee1117 224 uint8_t versionH = *pBuffer++;
andrewboyson 5:ee5489ee1117 225 uint8_t versionL = *pBuffer++;
andrewboyson 5:ee5489ee1117 226 int length = *pBuffer++ << 8;
andrewboyson 5:ee5489ee1117 227 length |= *pBuffer++;
andrewboyson 5:ee5489ee1117 228 int overallLen = length + 5;
andrewboyson 5:ee5489ee1117 229
andrewboyson 2:82268409e83f 230 if (TlsTrace)
andrewboyson 2:82268409e83f 231 {
andrewboyson 2:82268409e83f 232 Log ("- content type: "); TlsLogContentType(contentType); Log("\r\n");
andrewboyson 2:82268409e83f 233 LogF("- legacy HH:LL: %02x:%02x\r\n", versionH, versionL);
andrewboyson 2:82268409e83f 234 LogF("- length : %d\r\n" , length);
andrewboyson 2:82268409e83f 235 }
andrewboyson 8:5e66a6b4b38c 236
andrewboyson 8:5e66a6b4b38c 237 if (contentType < 20 || contentType > 24) return overallLen;
andrewboyson 8:5e66a6b4b38c 238 if (versionH != 3 ) return overallLen;
andrewboyson 8:5e66a6b4b38c 239 if (overallLen > available ) return overallLen;
andrewboyson 13:0a80b49a5e78 240
andrewboyson 8:5e66a6b4b38c 241 if (pConnection->clientEncrypted)
andrewboyson 8:5e66a6b4b38c 242 {
andrewboyson 8:5e66a6b4b38c 243 //Decrypt the message
andrewboyson 8:5e66a6b4b38c 244 uint8_t* pIv = pBuffer;
andrewboyson 8:5e66a6b4b38c 245 pBuffer += 16;
andrewboyson 8:5e66a6b4b38c 246 struct AES_ctx ctx;
andrewboyson 8:5e66a6b4b38c 247 AES_init_ctx_iv(&ctx, pConnection->clientWriteKey, pIv);
andrewboyson 8:5e66a6b4b38c 248 AES_CBC_decrypt_buffer(&ctx, pBuffer, length - 16);
andrewboyson 8:5e66a6b4b38c 249 Log("- decrypted message\r\n");
andrewboyson 8:5e66a6b4b38c 250 LogBytesAsHex(pBuffer, length - 16);
andrewboyson 8:5e66a6b4b38c 251 Log("\r\n");
andrewboyson 8:5e66a6b4b38c 252 uint8_t paddingLength = *(pBuffer + length - 16 - 1);
andrewboyson 8:5e66a6b4b38c 253 LogF("- padding length %u\r\n", paddingLength);
andrewboyson 8:5e66a6b4b38c 254 int payloadLength = length - 16 - paddingLength - SHA1_HASH_SIZE - 1;
andrewboyson 8:5e66a6b4b38c 255 LogF("- payload length %d\r\n", payloadLength);
andrewboyson 8:5e66a6b4b38c 256 LogF("- sequence number %llu\r\n", pConnection->clientSequence);
andrewboyson 8:5e66a6b4b38c 257
andrewboyson 8:5e66a6b4b38c 258 uint8_t mac[SHA1_HASH_SIZE];
andrewboyson 9:f354b4859b0b 259 TlsMacSha1(TLS_KEY_SIZE_MAC,
andrewboyson 9:f354b4859b0b 260 pConnection->clientMacKey,
andrewboyson 9:f354b4859b0b 261 pConnection->clientSequence,
andrewboyson 9:f354b4859b0b 262 contentType,
andrewboyson 9:f354b4859b0b 263 versionH,
andrewboyson 9:f354b4859b0b 264 versionL,
andrewboyson 9:f354b4859b0b 265 payloadLength,
andrewboyson 9:f354b4859b0b 266 pBuffer,
andrewboyson 9:f354b4859b0b 267 mac);
andrewboyson 8:5e66a6b4b38c 268
andrewboyson 8:5e66a6b4b38c 269 Log("- verify message MAC\r\n");
andrewboyson 8:5e66a6b4b38c 270 LogBytesAsHex(mac, SHA1_HASH_SIZE);
andrewboyson 8:5e66a6b4b38c 271 Log("\r\n");
andrewboyson 8:5e66a6b4b38c 272
andrewboyson 8:5e66a6b4b38c 273 pConnection->clientSequence++;
andrewboyson 9:f354b4859b0b 274
andrewboyson 9:f354b4859b0b 275 length = payloadLength;
andrewboyson 8:5e66a6b4b38c 276 }
andrewboyson 8:5e66a6b4b38c 277
andrewboyson 2:82268409e83f 278 switch (contentType)
andrewboyson 2:82268409e83f 279 {
andrewboyson 13:0a80b49a5e78 280 case TLS_CONTENT_TYPE_HANDSHAKE:
andrewboyson 8:5e66a6b4b38c 281 handleHandshake(length, pBuffer, pConnection);
andrewboyson 6:819c17738dc2 282 break;
andrewboyson 6:819c17738dc2 283
andrewboyson 6:819c17738dc2 284 case TLS_CONTENT_TYPE_CHANGE_CIPHER:
andrewboyson 6:819c17738dc2 285 changeCipher(length, pBuffer, pConnection);
andrewboyson 5:ee5489ee1117 286 break;
andrewboyson 5:ee5489ee1117 287
andrewboyson 5:ee5489ee1117 288 case TLS_CONTENT_TYPE_ALERT:
andrewboyson 5:ee5489ee1117 289 handleAlert(length, pBuffer);
andrewboyson 5:ee5489ee1117 290 break;
andrewboyson 5:ee5489ee1117 291
andrewboyson 13:0a80b49a5e78 292 case TLS_CONTENT_TYPE_APPLICATION:
andrewboyson 9:f354b4859b0b 293 handleApplication(length, pBuffer, pConnection);
andrewboyson 5:ee5489ee1117 294 pConnection->toDo = DO_APPLICATION;
andrewboyson 5:ee5489ee1117 295 break;
andrewboyson 5:ee5489ee1117 296
andrewboyson 5:ee5489ee1117 297 default:
andrewboyson 5:ee5489ee1117 298 Log("TLS - ignoring content type ");
andrewboyson 5:ee5489ee1117 299 TlsLogContentType(contentType);
andrewboyson 5:ee5489ee1117 300 LogF(" and skipping %d bytes\r\n", overallLen);
andrewboyson 5:ee5489ee1117 301 pConnection->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 5:ee5489ee1117 302 break;
andrewboyson 5:ee5489ee1117 303 }
andrewboyson 5:ee5489ee1117 304 return overallLen;
andrewboyson 5:ee5489ee1117 305 }
andrewboyson 5:ee5489ee1117 306 void TlsRequest(int connectionId, int size, uint8_t* pRequestStream, uint32_t positionInRequestStream)
andrewboyson 6:819c17738dc2 307 {
andrewboyson 5:ee5489ee1117 308 //Log what we are doing
andrewboyson 6:819c17738dc2 309 if (TlsTrace) LogF("TLS %d <<< %d (%u)\r\n", connectionId, size, positionInRequestStream);
andrewboyson 5:ee5489ee1117 310
andrewboyson 5:ee5489ee1117 311 //Get new or existing connection information
andrewboyson 5:ee5489ee1117 312 struct TlsConnection* pConnection;
andrewboyson 5:ee5489ee1117 313 if (!positionInRequestStream)
andrewboyson 5:ee5489ee1117 314 {
andrewboyson 8:5e66a6b4b38c 315 //If this is the start of the request then open a new connection (this starts handshakeSha)
andrewboyson 5:ee5489ee1117 316 pConnection = TlsConnectionNew(connectionId);
andrewboyson 5:ee5489ee1117 317 }
andrewboyson 5:ee5489ee1117 318 else
andrewboyson 5:ee5489ee1117 319 {
andrewboyson 5:ee5489ee1117 320 //If this is in the middle of a request then open an existing connection
andrewboyson 5:ee5489ee1117 321 pConnection = TlsConnectionOrNull(connectionId);
andrewboyson 5:ee5489ee1117 322 if (!pConnection)
andrewboyson 2:82268409e83f 323 {
andrewboyson 5:ee5489ee1117 324 LogTimeF("TlsRequest - no connection corresponds to id %d\r\n", connectionId);
andrewboyson 2:82268409e83f 325 return;
andrewboyson 2:82268409e83f 326 }
andrewboyson 5:ee5489ee1117 327 }
andrewboyson 2:82268409e83f 328
andrewboyson 5:ee5489ee1117 329 //Handle each item of coalesced content
andrewboyson 5:ee5489ee1117 330 uint8_t* pNext = pRequestStream;
andrewboyson 8:5e66a6b4b38c 331 uint8_t* pDeferred = pConnection->deferredContent;
andrewboyson 8:5e66a6b4b38c 332 while (pNext < pRequestStream + size)
andrewboyson 8:5e66a6b4b38c 333 {
andrewboyson 8:5e66a6b4b38c 334 if (pConnection->clientEncrypted && pConnection->toDo == DO_WAIT_DECRYPT_MASTER_SECRET)
andrewboyson 8:5e66a6b4b38c 335 {
andrewboyson 8:5e66a6b4b38c 336 if (pDeferred >= pConnection->deferredContent + TLS_DEFERRED_CONTENT_SIZE) break;
andrewboyson 8:5e66a6b4b38c 337 *pDeferred++ = *pNext++; //Defer handling the remaining content until have master secret
andrewboyson 8:5e66a6b4b38c 338 }
andrewboyson 8:5e66a6b4b38c 339 else
andrewboyson 8:5e66a6b4b38c 340 {
andrewboyson 8:5e66a6b4b38c 341 pNext += handleContent(pConnection, pNext, size + pRequestStream - pNext);
andrewboyson 8:5e66a6b4b38c 342 }
andrewboyson 8:5e66a6b4b38c 343 }
andrewboyson 8:5e66a6b4b38c 344 }
andrewboyson 8:5e66a6b4b38c 345 void TlsAsync()
andrewboyson 8:5e66a6b4b38c 346 {
andrewboyson 8:5e66a6b4b38c 347 struct TlsConnection* pConnection = TlsConnectionGetNext();
andrewboyson 8:5e66a6b4b38c 348
andrewboyson 8:5e66a6b4b38c 349 if (pConnection->toDo != DO_WAIT_DECRYPT_MASTER_SECRET) return;
andrewboyson 8:5e66a6b4b38c 350
andrewboyson 10:e269fd7b9500 351 struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
andrewboyson 8:5e66a6b4b38c 352 if (!pSession)
andrewboyson 8:5e66a6b4b38c 353 {
andrewboyson 10:e269fd7b9500 354 LogTimeF("TlsRequestAsync - invalid session %u\r\n", pConnection->sessionId);
andrewboyson 8:5e66a6b4b38c 355 return;
andrewboyson 8:5e66a6b4b38c 356 }
andrewboyson 8:5e66a6b4b38c 357
andrewboyson 10:e269fd7b9500 358 if (pSession->valid) return;
andrewboyson 8:5e66a6b4b38c 359
andrewboyson 14:03a0b8fd6ddc 360 if (!PriKeyDecryptFinished(pConnection->slotPriKeyDecryption)) return;
andrewboyson 8:5e66a6b4b38c 361
andrewboyson 14:03a0b8fd6ddc 362 uint8_t *pPreMasterSecretMessage = PriKeyDecryptResult(pConnection->slotPriKeyDecryption);
andrewboyson 8:5e66a6b4b38c 363 LogTime("Decrypted pre master secret little endian\r\n"); LogBytesAsHex(pPreMasterSecretMessage, 128); Log("\r\n");
andrewboyson 8:5e66a6b4b38c 364
andrewboyson 8:5e66a6b4b38c 365 uint8_t preMasterSecret[48];
andrewboyson 8:5e66a6b4b38c 366 for (int i = 0; i < 48; i++) preMasterSecret[i] = *(pPreMasterSecretMessage + 47 - i);
andrewboyson 8:5e66a6b4b38c 367 LogTime("Pre master secret\r\n"); LogBytesAsHex(preMasterSecret, 48); Log("\r\n");
andrewboyson 14:03a0b8fd6ddc 368 PriKeyDecryptClear(pConnection->slotPriKeyDecryption);
andrewboyson 8:5e66a6b4b38c 369
andrewboyson 8:5e66a6b4b38c 370 TlsPrfMasterSecret(preMasterSecret, pConnection->clientRandom, pConnection->serverRandom, pSession->masterSecret);
andrewboyson 8:5e66a6b4b38c 371
andrewboyson 8:5e66a6b4b38c 372 TlsPrfKeys (pSession->masterSecret, pConnection->clientRandom, pConnection->serverRandom, pConnection->clientMacKey,
andrewboyson 8:5e66a6b4b38c 373 pConnection->serverMacKey,
andrewboyson 8:5e66a6b4b38c 374 pConnection->clientWriteKey,
andrewboyson 8:5e66a6b4b38c 375 pConnection->serverWriteKey);
andrewboyson 14:03a0b8fd6ddc 376
andrewboyson 10:e269fd7b9500 377 pSession->valid = true;
andrewboyson 8:5e66a6b4b38c 378
andrewboyson 8:5e66a6b4b38c 379 LogTime("Sending deferred encrypted bytes\r\n"); LogBytesAsHex(pConnection->deferredContent, TLS_DEFERRED_CONTENT_SIZE); Log("\r\n");
andrewboyson 8:5e66a6b4b38c 380
andrewboyson 8:5e66a6b4b38c 381 handleContent(pConnection, pConnection->deferredContent, TLS_DEFERRED_CONTENT_SIZE);
andrewboyson 2:82268409e83f 382 }
andrewboyson 5:ee5489ee1117 383 void TlsReset(int connectionId)
andrewboyson 5:ee5489ee1117 384 {
andrewboyson 5:ee5489ee1117 385 TlsConnectionReset(connectionId);
andrewboyson 10:e269fd7b9500 386 HttpReset(connectionId);
andrewboyson 5:ee5489ee1117 387 }