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