A simple library to support serving https.
Dependents: oldheating gps motorhome heating
tls/tls-request.c@22:af0b5ceb556e, 2019-10-23 (annotated)
- Committer:
- andrewboyson
- Date:
- Wed Oct 23 08:44:50 2019 +0000
- Revision:
- 22:af0b5ceb556e
- Parent:
- 21:a6d6e26dd742
Removed error if passing a 0 id to TlsSessionGetFromIdOrNull; now it just returns NULL without complaining.
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 | } |