A simple library to support serving https.
Dependents: oldheating gps motorhome heating
tls/tls-request.c
- Committer:
- andrewboyson
- Date:
- 2019-08-20
- Revision:
- 4:6a1d887f1cad
- Parent:
- 2:82268409e83f
- Child:
- 5:ee5489ee1117
File content as of revision 4:6a1d887f1cad:
#include "tls.h" #include "tls-defs.h" #include "tls-state.h" #include "tls-session.h" #include "tls-log.h" #include "mstimer.h" #include "random.h" #include "log.h" #include "pri-key.h" static int handleClientHello(int length, uint8_t* pBuffer, struct TlsState* pState) //returns 0 on success; -1 on error { //Check things look ok uint8_t* p = pBuffer; if (length < 100) { LogF("TLS - %d byte client hello message is not at least 100 bytes long\r\n", length); return -1; } //Start and add the handshake hash Sha256Start(&pState->handshakeHash); Sha256Add (&pState->handshakeHash, pBuffer, length); //Read in the parameters uint8_t versionH = *p++; uint8_t versionL = *p++; uint8_t* pRandom = p; p += 32; int sessionIdLength = *p++; uint8_t* pSessionId = p; //Handle the parameters pState->session = -1; if (sessionIdLength == 1) pState->session = *pSessionId; struct TlsSession* pSession = TlsSessionGetFromIndex(pState->session); if (!pSession || pSession->state != TLS_SESSION_STATE_VALID) { pSession = TlsSessionGetOldest(); pSession->state = TLS_SESSION_STATE_STARTED; } pState->session = TlsSessionGetIndex(pSession); pSession->lastUsed = MsTimerCount; for (int i = 0; i < 32; i++) pSession->clientRandom[i] = *pRandom++; for (int i = 0; i < 32; i++) pSession->serverRandom[i] = RandomGetByte(); //Log the parameters if (TlsTrace) { LogF("- client version HH:LL: %02x:%02x\r\n", versionH, versionL); Log ("- client random:\r\n"); LogBytesAsHex(pRandom, 32); Log("\r\n"); Log ("- client session id:\r\n"); LogBytesAsHex(pSessionId, sessionIdLength); Log("\r\n"); LogF("- session index: %d\r\n", pState->session); } return 0; } static int handleClientKeyExchange(int length, uint8_t* pBuffer, struct TlsState* pState) //returns 0 on success; -1 on error { struct TlsSession* pSession = TlsSessionGetFromIndex(pState->session); Sha256Add (&pState->handshakeHash, pBuffer, length); if (length != 130) { LogF("TLS - %d byte client key exchange message is not 130 bytes long\r\n", length); return -1; } int premasterLength = pBuffer[0] << 8 | pBuffer[1]; //Overall length 2 bytes if (premasterLength != 128) { LogF("TLS - %d byte encrypted pre master secret is not 128 bytes long\r\n", length); return -1; } uint8_t* pEncryptedPreMasterSecret = pBuffer + 2; pSession->slotPriKeyDecryption = PriKeyDecryptStart(pEncryptedPreMasterSecret); if (TlsTrace) { LogF("- encrypted pre master\r\n", premasterLength); LogBytesAsHex(pEncryptedPreMasterSecret, 128); Log("\r\n"); } return 0; } static void handleHandshake(int length, uint8_t* pBuffer, struct TlsState* pState) { uint8_t* p = pBuffer; while (p < pBuffer + length) { uint8_t handshakeType = *p++; int handshakeLength = *p++ << 16; handshakeLength |= *p++ << 8; handshakeLength |= *p++ ; //Handshake length 3 bytes if (TlsTrace) { Log ("- handshake type: "); TlsLogHandshakeType(handshakeType); Log("\r\n"); LogF("- handshake length: %d\r\n", handshakeLength); } int r = -1; switch (handshakeType) { case TLS_HANDSHAKE_ClientHello: r = handleClientHello(handshakeLength, p, pState); pState->toDo = r ? DO_SEND_ALERT_ILLEGAL_PARAMETER : DO_SEND_SERVER_HELLO; break; case TLS_HANDSHAKE_ClientKeyExchange: r = handleClientKeyExchange(handshakeLength, p, pState); pState->toDo = r ? DO_SEND_ALERT_ILLEGAL_PARAMETER : DO_WAIT_DECRYPT_MASTER_SECRET; break; default: LogF("TLS - ignoring untreated %d byte handshake type ", handshakeLength); TlsLogHandshakeType(handshakeType); Log("\r\n"); break; } p += handshakeLength; } } static void handleAlert(int length, uint8_t* pBuffer) { uint8_t level = pBuffer[0]; uint8_t description = pBuffer[1]; if (TlsTrace) { Log("- alert level: "); TlsLogAlertLevel (level); Log("\r\n"); Log("- alert description: "); TlsLogAlertDescription(description); Log("\r\n"); } } static void handleApplication(int length, uint8_t* pBuffer) { if (TlsTrace) { Log("- application data:\r\n"); LogBytesAsHex(pBuffer, length); Log("\r\n"); } } void TlsRequest(char* pTlsState, char* pWebState, int size, uint8_t* pRequestStream, uint32_t positionInRequestStream) { struct TlsState* pState = (struct TlsState*)pTlsState; if (TlsTrace) LogF("TLS <<< %d (%u)\r\n", size, positionInRequestStream); if (size == 0) return; //if (positionInRequestStream != 0) return; uint8_t contentType = pRequestStream[0]; uint8_t versionH = pRequestStream[1]; uint8_t versionL = pRequestStream[2]; int length = pRequestStream[3] << 8 | pRequestStream[4]; //Length (2 bytes) if (TlsTrace) { Log ("- content type: "); TlsLogContentType(contentType); Log("\r\n"); LogF("- legacy HH:LL: %02x:%02x\r\n", versionH, versionL); LogF("- length : %d\r\n" , length); } switch (contentType) { case TLS_CONTENT_TYPE_Handshake: { handleHandshake(length, pRequestStream + 5, pState); return; } case TLS_CONTENT_TYPE_ALERT: { handleAlert(length, pRequestStream + 5); return; } case TLS_CONTENT_TYPE_Application: { handleApplication(length, pRequestStream + 5); pState->toDo = DO_APPLICATION; return; } default: Log("TLS - untreated content type "); TlsLogContentType(contentType); Log("\r\n"); pState->toDo = DO_WAIT_CLIENT_HELLO; return; } }