Andrew Boyson / crypto

Dependents:   oldheating gps motorhome heating

Revision:
14:03a0b8fd6ddc
Parent:
13:0a80b49a5e78
Child:
17:93feb2a51d58
--- a/tls/tls-request.c	Fri Sep 27 11:31:18 2019 +0000
+++ b/tls/tls-request.c	Wed Oct 02 20:26:04 2019 +0000
@@ -13,26 +13,28 @@
 #include "led.h"
 #include "http.h"
 
-static int handleClientHello(int length, uint8_t* pBuffer, struct TlsConnection* pConnection) //returns 0 on success; -1 on error
+static void handleClientHello(int length, uint8_t* pBuffer, struct TlsConnection* pConnection)
 {   
     //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;
+        pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
+        return;
     }
     
-    //Read in the parameters
+    //get the version
     uint8_t versionH         = *p++;
     uint8_t versionL         = *p++;
     
+    //Get the client random
     for (int i = 0; i < 32; i++) pConnection->clientRandom[i] = *p++;
     
+    //Get the session id
     int sessionIdLength = *p++;
     uint8_t* pSessionId = p;
     
-    //Handle the parameters
     if (sessionIdLength == 4)
     {
         pConnection->sessionId  = *p++;
@@ -48,9 +50,14 @@
         pConnection->sessionId = 0;
         p += sessionIdLength;
     }
-//    struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
-    struct TlsSession* pSession = NULL;
-    if (!pSession || !pSession->valid)
+    
+    //Work out from the session id if this connection can be resumed from an existing session
+    struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
+    //pSession = NULL;
+    pConnection->resume = pSession && pSession->valid;
+    
+    //If it cannot be resumed then create a new one
+    if (!pConnection->resume)
     {
         pSession = TlsSessionNew();
         pConnection->sessionId = pSession->id;
@@ -65,31 +72,40 @@
         Log ("- client random:\r\n");     LogBytesAsHex(pConnection->clientRandom, 32); Log("\r\n");
         Log ("- client session id:\r\n"); LogBytesAsHex(pSessionId, sessionIdLength); Log("\r\n");
         LogF("- session index: %u\r\n",  pConnection->sessionId);
+        if (pConnection->resume) Log ("- existing session so resume\r\n");
+        else                     Log ("- new session\r\n");
     }
-    return 0;
+    
+    if (pConnection->resume) pConnection->toDo = DO_SEND_SERVER_HELLO_RESUME;
+    else                     pConnection->toDo = DO_SEND_SERVER_HELLO_NEW;
+    
+    return;
 }
-static int handleClientKeyExchange(int length, uint8_t* pBuffer, struct TlsConnection* pConnection) //returns 0 on success; -1 on error
+static void handleClientKeyExchange(int length, uint8_t* pBuffer, struct TlsConnection* pConnection) //returns 0 on success; -1 on error
 {
     struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
     if (!pSession)
     {
         LogTimeF("handleClientKeyExchange - invalid session %u\r\n", pConnection->sessionId);
-        return -1;
+        pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
+        return;
     }
     
     if (length != 130)
     {
         LogF("TLS - %d byte client key exchange message is not 130 bytes long\r\n", length);
-        return -1;
+        pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
+        return;
     }
     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;
+        pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
+        return;
     }
     uint8_t* pEncryptedPreMasterSecret = pBuffer + 2;
-    pSession->slotPriKeyDecryption = PriKeyDecryptStart(pEncryptedPreMasterSecret);
+    pConnection->slotPriKeyDecryption = PriKeyDecryptStart(pEncryptedPreMasterSecret);
     
     if (TlsTrace)
     {
@@ -98,15 +114,17 @@
         Log("\r\n");
     }
     
-    return 0;
+    pConnection->toDo = DO_WAIT_DECRYPT_MASTER_SECRET;
+    return;
 }
-static int handleClientFinished(int length, uint8_t* pBuffer, struct TlsConnection* pConnection) //returns 0 on success; -1 on error
+static void handleClientFinished(int length, uint8_t* pBuffer, struct TlsConnection* pConnection) //returns 0 on success; -1 on error
 {
     struct TlsSession* pSession = TlsSessionOrNull(pConnection->sessionId);
     if (!pSession)
     {
         LogTimeF("handleClientKeyExchange - invalid session %u\r\n", pConnection->sessionId);
-        return -1;
+        pConnection->toDo = DO_SEND_ALERT_ILLEGAL_PARAMETER;
+        return;
     }
     
     //Calculate the verify message
@@ -116,7 +134,10 @@
     LogBytesAsHex(verify, 12);
     Log("\r\n");
     
-    return 0;
+    if (pConnection->resume) pConnection->toDo = DO_APPLICATION;
+    else                     pConnection->toDo = DO_SEND_SERVER_CHANGE;
+    
+    return;
 }
 static void changeCipher(int length, uint8_t* pBuffer, struct TlsConnection* pConnection)
 {
@@ -174,22 +195,18 @@
             LogF("- handshake length: %d\r\n", handshakeLength);
         }
         
-        int r = -1;
         switch (handshakeType)
         {
             case TLS_HANDSHAKE_CLIENT_HELLO:
-                r = handleClientHello(handshakeLength, p, pConnection);
-                pConnection->toDo = r ? DO_SEND_ALERT_ILLEGAL_PARAMETER : DO_SEND_SERVER_HELLO;
+                handleClientHello(handshakeLength, p, pConnection);
                 break;
                 
             case TLS_HANDSHAKE_CLIENT_KEY_EXCHANGE:
-                r = handleClientKeyExchange(handshakeLength, p, pConnection);
-                pConnection->toDo = r ? DO_SEND_ALERT_ILLEGAL_PARAMETER : DO_WAIT_DECRYPT_MASTER_SECRET;
+                handleClientKeyExchange(handshakeLength, p, pConnection);
                 break;
                 
             case TLS_HANDSHAKE_FINISHED:
-                r = handleClientFinished(handshakeLength, p, pConnection);
-                pConnection->toDo = r ? DO_SEND_ALERT_ILLEGAL_PARAMETER :  DO_SEND_SERVER_CHANGE;
+                handleClientFinished(handshakeLength, p, pConnection);
                 break;
                 
             default:
@@ -340,15 +357,15 @@
     
     if (pSession->valid) return;
     
-    if (!PriKeyDecryptFinished(pSession->slotPriKeyDecryption)) return;
+    if (!PriKeyDecryptFinished(pConnection->slotPriKeyDecryption)) return;
 
-    uint8_t *pPreMasterSecretMessage = PriKeyDecryptGetResult(pSession->slotPriKeyDecryption);
+    uint8_t *pPreMasterSecretMessage = PriKeyDecryptResult(pConnection->slotPriKeyDecryption);
     LogTime("Decrypted pre master secret little endian\r\n"); LogBytesAsHex(pPreMasterSecretMessage, 128); Log("\r\n");
     
     uint8_t preMasterSecret[48];
     for (int i = 0; i < 48; i++) preMasterSecret[i] = *(pPreMasterSecretMessage + 47 - i);
     LogTime("Pre master secret\r\n"); LogBytesAsHex(preMasterSecret, 48); Log("\r\n");
-    PriKeyDecryptClear(pSession->slotPriKeyDecryption);
+    PriKeyDecryptClear(pConnection->slotPriKeyDecryption);
     
     TlsPrfMasterSecret(preMasterSecret, pConnection->clientRandom, pConnection->serverRandom, pSession->masterSecret);
     
@@ -356,7 +373,7 @@
                                                                                               pConnection->serverMacKey,
                                                                                               pConnection->clientWriteKey,
                                                                                               pConnection->serverWriteKey);
-        
+
     pSession->valid = true;
     
     LogTime("Sending deferred encrypted bytes\r\n"); LogBytesAsHex(pConnection->deferredContent, TLS_DEFERRED_CONTENT_SIZE); Log("\r\n");