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