Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Files at this revision

API Documentation at this revision

Comitter:
andrewboyson
Date:
Thu Jul 25 21:11:37 2019 +0000
Parent:
151:bde6f7da1755
Child:
153:638c21b06d3e
Commit message:
Pulled a lot of the crypto stuff out into a separate library.

Changed in this revision

tcp/http/http.h Show annotated file Show diff for this revision Revisions of this file
tcp/http/httpadd.c Show annotated file Show diff for this revision Revisions of this file
tcp/tls/base64.c Show diff for this revision Revisions of this file
tcp/tls/base64.h Show diff for this revision Revisions of this file
tcp/tls/pri-key.c Show diff for this revision Revisions of this file
tcp/tls/pri-key.h Show diff for this revision Revisions of this file
tcp/tls/ser-cer.c Show diff for this revision Revisions of this file
tcp/tls/ser-cer.h Show diff for this revision Revisions of this file
tcp/tls/tls.c Show annotated file Show diff for this revision Revisions of this file
--- a/tcp/http/http.h	Fri Jul 19 17:48:06 2019 +0000
+++ b/tcp/http/http.h	Thu Jul 25 21:11:37 2019 +0000
@@ -16,6 +16,9 @@
 extern void   HttpAddInt16AsHex (int value);
 extern void   HttpAddInt32AsHex (int value);
 extern void   HttpAddInt64AsHex (int64_t value);
+extern void   HttpAddBytesAsHex (const char* value, int size);
+extern void   HttpAddBytesAsHexRev(const char* value, int size);
+
 extern void   HttpAddTm         (struct tm* ptm);
 extern bool   HttpBufFilled     (void);
 
--- a/tcp/http/httpadd.c	Fri Jul 19 17:48:06 2019 +0000
+++ b/tcp/http/httpadd.c	Thu Jul 25 21:11:37 2019 +0000
@@ -122,6 +122,30 @@
     HttpAddNibbleAsHex(value >>  4);
     HttpAddNibbleAsHex(value >>  0);
 }
+void HttpAddBytesAsHex(const char* value, int size)
+{
+    int i = 0;
+    while(true)
+    {
+        HttpAddByteAsHex(value[i]);
+        i++;
+        if (i >= size) break;
+        if (i % 16 == 0) HttpAddText("\r\n");
+        else             HttpAddChar(' ');
+    }
+}
+void HttpAddBytesAsHexRev(const char* value, int size)
+{
+    int i = 0;
+    while(true)
+    {
+        HttpAddByteAsHex(value[size - i - 1]);
+        i++;
+        if (i >= size) break;
+        if (i % 16 == 0) HttpAddText("\r\n");
+        else             HttpAddChar(' ');
+    }
+}
 void HttpAddTm(struct tm* ptm)
 {
     HttpAddF("%d-%02d-%02d ", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday);
--- a/tcp/tls/base64.c	Fri Jul 19 17:48:06 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-#include <stdbool.h>
-#include <stdio.h>
-#include "base64.h"
-
-char (*Base64ReadNextCharFunctionPointer)(void) = NULL;
-
-static int get6bits()
-{
-    while (true)
-    {
-        char c = Base64ReadNextCharFunctionPointer();
-        if      (c ==  0 ) return -1; //EOF or an error
-        else if (c == '-') return -1; //Finished
-        else if (c == '=') return -1; //Padding  
-        else if (c == '/') return 63;
-        else if (c == '+') return 62;
-        else if (c >= 'a') return c - 'a' + 26;
-        else if (c >= 'A') return c - 'A' +  0;
-        else if (c >= '0') return c - '0' + 52;
-        else continue;
-    }
-}
-
-static int last6 = 0;
-static int posn = 0;
-static bool finished = false;
-int Base64ReadByte()
-{
-    if (finished) return -1;
-    
-    /*
-    L = last
-    T = this
-                out
-    case 0    TTTTTTLL
-    case 1    LLLLTTTT
-    case 2    LLTTTTTT
-    */
-    int this6 = 0;
-    int bits8 = 0;
-    
-    switch (posn)
-    {
-        case 0: //We have no bits leftover
-        {
-            this6 = get6bits(); if (this6 == -1)  return -1; //EOF or an error
-            last6 = get6bits();
-            if (last6 == -1)
-            {
-                last6 = 0;
-                finished = true;
-            }
-            bits8  = this6 << 2;
-            bits8 &= 0xFF;
-            bits8 |= last6 >> 4;
-            
-            posn = 1;
-            break;
-        }
-        case 1: //We have 4 bits leftover
-        {
-            this6 = get6bits(); if (this6 == -1)  return -1; //EOF or an error
-            
-            bits8  = last6 << 4;
-            bits8 &= 0xFF;
-            bits8 |= this6 >> 2;
-            
-            last6 = this6;
-            
-            posn = 2;
-            break;
-        }
-        case 2: //We have 2 bits leftover
-        {
-            this6 = get6bits(); if (this6 == -1)  return -1; //EOF or an error
-            
-            bits8  = last6 << 6;
-            bits8 &= 0xFF;
-            bits8 |= this6;
-            
-            posn = 0;
-            break;
-        }
-    }
-    
-    return bits8;
-}
-int Base64SkipLine()
-{
-    last6 = 0;
-    posn = 0;
-    finished = false;
-    
-    while (true)
-    {
-        char c = Base64ReadNextCharFunctionPointer();
-        if      (c ==   0 ) return -1; //EOF or an error
-        else if (c == '\n') return  0; //EOL
-    }
-}
--- a/tcp/tls/base64.h	Fri Jul 19 17:48:06 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-#include <stdio.h>
-
-extern char (*Base64ReadNextCharFunctionPointer)(void);
-extern int    Base64ReadByte(void);
-extern int    Base64SkipLine(void);
\ No newline at end of file
--- a/tcp/tls/pri-key.c	Fri Jul 19 17:48:06 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-#include "base64.h"
-#include "log.h"
-//#include "semihost.h"
-
-/*
-RSAPrivateKey ::= SEQUENCE {
-      version           INTEGER,
-      modulus           INTEGER,  -- n
-      publicExponent    INTEGER,  -- e
-      privateExponent   INTEGER,  -- d
-      prime1            INTEGER,  -- p
-      prime2            INTEGER,  -- q
-      exponent1         INTEGER,  -- d mod (p-1)
-      exponent2         INTEGER,  -- d mod (q-1)
-      coefficient       INTEGER,  -- (inverse of q) mod p
-      otherPrimeInfos   OtherPrimeInfos OPTIONAL
-*/
-
-char v   [  4]; //version
-char n   [128]; //modulus
-char e   [  4]; //publicExponent
-char d   [128]; //privateExponent
-char p   [ 64]; //prime1
-char q   [ 64]; //prime2
-char dp  [ 64]; //exponent1 -- d mod (p-1)
-char dq  [ 64]; //exponent2 -- d mod (q-1)
-char invq[ 64]; //coefficient -- (inverse of q) mod p
-
-/*
-#define BUF_SIZE 64
-static FILEHANDLE fh;
-static char*      buffer;       //Allocated during init and only valid during the read
-
-static char charsInBuffer = 0; //Number of characters left in the buffer
-
-static int readChar()
-{
-    if (charsInBuffer <= 0)
-    {
-        int bytesRead = SemihostRead(fh, buffer, BUF_SIZE);
-        if (bytesRead <= 0) return -1;
-        charsInBuffer += bytesRead;
-    }
-    int c = buffer[BUF_SIZE - charsInBuffer];
-    --charsInBuffer;
-    return c;
-}
-*/
-
-static const char* pNext;
-static const char* buffer = 
-#include "pri-key.inc"
-;
-static char readChar()
-{
-    char c = *pNext;
-    if (!c) return 0;
-    pNext++;
-    return c;
-}
-static int readLength()
-{
-    int c = Base64ReadByte();
-    if (c ==   -1) return -1; //EOF or an error
-    if (c  < 0x80) return  c; //Single byte length
-    if (c == 0x80) return -1; //indefinite form - do not use
-    int numberOfBytes = c - 0x80;
-    int len = 0;
-    for (int i = 0; i < numberOfBytes; i++)
-    {
-        len <<= 8;
-        c = Base64ReadByte();
-        if (c == -1) return -1; //EOF or an error
-        len |= c;
-    }
-    return len;
-}
-static int readSequence()
-{
-    int c = Base64ReadByte();
-    if (c ==   -1) return -1;  //EOF or an error
-    if (c != 0x30) return -1;  //Not SEQUENCE type
-    int len = readLength();
-    return len;
-}
-static int readData(char* data, int size)
-{
-    int c = Base64ReadByte();
-    if (c ==   -1) return -1;            //EOF or an error
-    if (c != 0x02) return -1;            //Not INTEGER type
-    int pemLength = readLength();
-    if (pemLength == -1)   return -1;    //EOF or an error
-    
-    int finalLength = pemLength;
-    for (int i = 0; i < pemLength; i++)
-    {
-        c = Base64ReadByte();
-        if (c == -1) return -1;          //EOF or an error
-        if (!i && !c)                    //Don't add if this is the msb and that byte is zero but reduce the final length by 1
-        {
-            finalLength--;
-        }
-        else
-        {
-            data[pemLength - 1 - i] = c; //If pemLength is one too big then 'i' will also be one too big so the result is correct
-        }
-    }
-    for (int i = finalLength; i < size; i++) data[i] = 0;
-    
-    return finalLength + 1;
-}
-void PriKeyInit()
-{
-    /*
-    fh = SemihostOpen("PRIVATE.KEY", OPEN_MODE_R + OPEN_MODE_B);
-    if (fh <= 0)
-    {
-        LogTimeF("PriKeyInit - open file for read error\r\n");
-        return;
-    }
-    
-    buffer = alloca(BUF_SIZE);
-    charsInBuffer = 0;
-    */
-    pNext = buffer;
-    Base64ReadNextCharFunctionPointer = readChar;
-    
-    int r = 0;
-    r = Base64SkipLine();             if (r < 0) goto end;
-    r = readSequence();               if (r < 0) goto end;
-    
-    r = readData(   v, sizeof(   v)); if (r < 0) goto end;
-    r = readData(   n, sizeof(   n)); if (r < 0) goto end;
-    r = readData(   e, sizeof(   e)); if (r < 0) goto end;
-    r = readData(   d, sizeof(   d)); if (r < 0) goto end;
-    r = readData(   p, sizeof(   p)); if (r < 0) goto end;
-    r = readData(   q, sizeof(   q)); if (r < 0) goto end;
-    r = readData(  dp, sizeof(  dp)); if (r < 0) goto end;
-    r = readData(  dq, sizeof(  dq)); if (r < 0) goto end;
-    r = readData(invq, sizeof(invq)); if (r < 0) goto end;
-    
-    Log("Primary key content\r\n");
-    LogBytesAsHex(   v, sizeof(   v)); Log("\n\n");
-    LogBytesAsHex(   n, sizeof(   n)); Log("\n\n");
-    LogBytesAsHex(   e, sizeof(   e)); Log("\n\n");
-    LogBytesAsHex(   d, sizeof(   d)); Log("\n\n");
-    LogBytesAsHex(   p, sizeof(   p)); Log("\n\n");
-    LogBytesAsHex(   q, sizeof(   q)); Log("\n\n");
-    LogBytesAsHex(  dp, sizeof(  dp)); Log("\n\n");
-    LogBytesAsHex(  dq, sizeof(  dq)); Log("\n\n");
-    LogBytesAsHex(invq, sizeof(invq)); Log("\n\n");
-    
-    
-end:
-    ;
-/*
-    SemihostClose(fh);
-*/
-}
\ No newline at end of file
--- a/tcp/tls/pri-key.h	Fri Jul 19 17:48:06 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-extern void PriKeyInit(void);
\ No newline at end of file
--- a/tcp/tls/ser-cer.c	Fri Jul 19 17:48:06 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-#include "base64.h"
-//#include "ser-cer.h"
-//#include "semihost.h"
-#include "log.h"
-
-char SerCerData[1024];
-int  SerCerSize = 0;
-/*
-#define BUF_SIZE 64
-static FILEHANDLE fh;
-static char*      buffer;       //Allocated during init and only valid during the read
-
-static char charsInBuffer = 0; //Number of characters left in the buffer
-
-static char readChar()
-{
-    if (charsInBuffer <= 0)
-    {
-        int bytesRead = SemihostRead(fh, buffer, BUF_SIZE);
-        if (bytesRead <= 0) return 0;
-        charsInBuffer += bytesRead;
-    }
-    char c = buffer[BUF_SIZE - charsInBuffer];
-    --charsInBuffer;
-    return c;
-}
-*/
-
-static const char* pNext;
-static const char* buffer = 
-#include "ser-cer.inc"
-;
-static char readChar()
-{
-    char c = *pNext;
-    if (!c) return 0;
-    pNext++;
-    return c;
-}
-static void readData()
-{
-    SerCerSize = 0;
-    while (true)
-    {
-        int c = Base64ReadByte();
-        if (c == -1) return;       //EOF or an error
-        SerCerData[SerCerSize] = c;
-        SerCerSize++;
-    }
-}
-void SerCerInit()
-{
-    /*
-    fh = SemihostOpen("SERVER.CER", OPEN_MODE_R + OPEN_MODE_B);
-    if (fh <= 0)
-    {
-        LogTimeF("SerCerInit - open file for read error\r\n");
-        return;
-    }
-    
-    buffer = alloca(BUF_SIZE);
-    charsInBuffer = 0;
-    */
-    
-    pNext = buffer;
-    Base64ReadNextCharFunctionPointer = readChar;
-    
-    int r = Base64SkipLine();
-    if (r < 0) goto end;
-    
-    readData();
-    
-    LogF("Server certificate content - %d bytes\r\n", SerCerSize);
-    LogBytesAsHex(SerCerData, SerCerSize); Log("\n\n");
-    
-end:
-    ;
-//    SemihostClose(fh);
-}
\ No newline at end of file
--- a/tcp/tls/ser-cer.h	Fri Jul 19 17:48:06 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-extern char SerCerData[];
-extern int  SerCerSize;
-extern void SerCerInit(void);
\ No newline at end of file
--- a/tcp/tls/tls.c	Fri Jul 19 17:48:06 2019 +0000
+++ b/tcp/tls/tls.c	Thu Jul 25 21:11:37 2019 +0000
@@ -11,6 +11,7 @@
 #include "random.h"
 #include "pri-key.h"
 #include "ser-cer.h"
+#include "tls-prf.h"
 
 #define TLS_CONTENT_TYPE_ChangeCipher      20
 #define TLS_CONTENT_TYPE_Alert             21
@@ -31,18 +32,22 @@
 #define TLS_HANDSHAKE_ClientKeyExchange    16
 #define TLS_HANDSHAKE_Finished             20
 
-#define DO_WAIT_CLIENT_HELLO  0
-#define DO_SEND_SERVER_HELLO  1
-#define DO_WAIT_CLIENT_CHANGE 2
-#define DO_SEND_SERVER_CHANGE 3
-#define DO_APPLICATION        4
+#define DO_WAIT_CLIENT_HELLO          0
+#define DO_SEND_SERVER_HELLO          1
+#define DO_WAIT_CLIENT_CHANGE         2
+#define DO_WAIT_DECRYPT_MASTER_SECRET 3
+#define DO_SEND_SERVER_CHANGE         4
+#define DO_APPLICATION                5
 
 bool TlsTrace = true;
 
+char paddedMasterSecret[128];
+
 void TlsInit()
 {
     SerCerInit();
     PriKeyInit();
+    TlsPrfTest();
 }
 
 struct state
@@ -82,13 +87,16 @@
 }
 static void handleClientKeyExchange(char* pBuffer)
 {
-    int  overallLength = pBuffer[0] << 16 | pBuffer[1] << 8 | pBuffer[2]; //Overall length 3 bytes
-    int premasterLength = pBuffer[3] <<  8 | pBuffer[4]; //Overall length 3 bytes
+    int   overallLength = pBuffer[0] << 16 | pBuffer[1] << 8 | pBuffer[2]; //Overall length 3 bytes
+    int premasterLength =                    pBuffer[3] << 8 | pBuffer[4]; //Overall length 2 bytes
     if (TlsTrace)
     {
         LogF("      overall   length: %d\r\n", overallLength);
         LogF("      premaster length: %d\r\n", premasterLength);
     }
+    char pms[128];
+    for (int i = 0; i < 128; i++) pms[127 - i] = pBuffer[i + 5];
+    PriKeyDecryptStart(pms, paddedMasterSecret);
 }
 void TlsRequest(char* pTlsState, char* pWebState, int size, char* pRequestStream, uint32_t positionInRequestStream)
 {
@@ -121,7 +129,7 @@
                     break;
                 case TLS_HANDSHAKE_ClientKeyExchange:
                     handleClientKeyExchange(pRequestStream + 6);
-                    pState->toDo = DO_SEND_SERVER_CHANGE;
+                    pState->toDo = DO_WAIT_DECRYPT_MASTER_SECRET;
                     break;
             }
             return;
@@ -174,6 +182,10 @@
     TcpBufAddChar(TLS_HANDSHAKE_ServerHelloDone); TcpBufAddChar(0x00);           //Handshake type server hello done
     addSize(0);                                                                  //Size of this handshake
 }
+static void sendServerChange()
+{
+    Log("     sending server change\r\n");
+}
 
 int TlsPoll(char* pTlsState, char* pWebState, bool clientFinished)
 {
@@ -185,8 +197,31 @@
         case DO_WAIT_CLIENT_CHANGE:
             if (clientFinished) return -1; //The client hasn't made a request and never will so finish
             else                return  0; //The client hasn't made a request yet but it could.
-        case DO_APPLICATION:    return HttpPollFunction(pWebState, clientFinished); //Return whatever HTTP would be
-        default:                return  1; //The client has made a request so do it
+        
+        case DO_WAIT_DECRYPT_MASTER_SECRET:
+            if (PriKeyDecryptFinished())
+            {
+                Log("Master secret\r\n");
+                LogBytesAsHex(paddedMasterSecret, sizeof(paddedMasterSecret));
+                Log("\r\n");
+                pState->toDo = DO_SEND_SERVER_CHANGE;
+                return 1;                  //Call TlsReply to do the send
+            }
+            else
+            {
+                if (clientFinished) return -1; //The client hasn't made a request and never will so finish
+                else                return  0; //The client hasn't made a request yet but it could.
+            }
+            
+        case DO_APPLICATION:
+            return HttpPollFunction(pWebState, clientFinished); //Return whatever HTTP would be
+            
+        case DO_SEND_SERVER_HELLO:
+            return 1;
+            
+        default:
+            LogTimeF("TlsPoll - unspecified TLS state %d\r\n", pState->toDo);
+            return -1; //Finish
     }
 }
 bool TlsReply(char* pTlsState, char* pWebState)
@@ -195,10 +230,21 @@
     
     switch(pState->toDo)
     {
-        case DO_SEND_SERVER_HELLO: sendServerHello();
+        case DO_SEND_SERVER_HELLO:
+            sendServerHello();
             pState->toDo = DO_WAIT_CLIENT_CHANGE;
-            return false;
+            return false; //Not finished
+            
+        case DO_SEND_SERVER_CHANGE:
+            sendServerChange();
+            pState->toDo = DO_APPLICATION;
+            return false; //Not finished
+            
+        case DO_APPLICATION:
+            return HttpReplyFunction(pWebState); //Return whatever HTTP would be
+            
         default:
+            LogTimeF("TlsReply - unspecified TLS state %d\r\n", pState->toDo);
             return true; //Finished
     }
 }