Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Files at this revision

API Documentation at this revision

Comitter:
andrewboyson
Date:
Fri Jul 19 17:48:06 2019 +0000
Parent:
150:3366e4a0c60e
Child:
152:80a3840fc9f8
Commit message:
Removed private key and certificate from semihost storage as found to be unreliable (though secure) and moved it into flash storage (reliable, simple, but visible on mbed.

Changed in this revision

tcp/tls/base64.c Show annotated file Show diff for this revision Revisions of this file
tcp/tls/base64.h Show annotated file Show diff for this revision Revisions of this file
tcp/tls/pri-key.c Show annotated file Show diff for this revision Revisions of this file
tcp/tls/ser-cer.c Show annotated file Show diff for this revision Revisions of this file
tcp/tls/ser-cer.h Show annotated file 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp/tls/base64.c	Fri Jul 19 17:48:06 2019 +0000
@@ -0,0 +1,100 @@
+#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
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp/tls/base64.h	Fri Jul 19 17:48:06 2019 +0000
@@ -0,0 +1,5 @@
+#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	Thu Jun 27 21:19:08 2019 +0000
+++ b/tcp/tls/pri-key.c	Fri Jul 19 17:48:06 2019 +0000
@@ -1,5 +1,6 @@
-#include "semihost.h"
+#include "base64.h"
 #include "log.h"
+//#include "semihost.h"
 
 /*
 RSAPrivateKey ::= SEQUENCE {
@@ -25,125 +26,41 @@
 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[64];
+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, sizeof(buffer));
+        int bytesRead = SemihostRead(fh, buffer, BUF_SIZE);
         if (bytesRead <= 0) return -1;
         charsInBuffer += bytesRead;
     }
-    int c = buffer[sizeof(buffer) - charsInBuffer];
+    int c = buffer[BUF_SIZE - charsInBuffer];
     --charsInBuffer;
     return c;
 }
-static int get6bits()
-{
-    while (true)
-    {
-        int c = readChar();
-        if      (c ==  -1) return -1; //EOF or an error
-        else if (c == '-') return -1; //Finished
-        else if (c == '=') return -2; //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 readByte()
+*/
+
+static const char* pNext;
+static const char* buffer = 
+#include "pri-key.inc"
+;
+static char readChar()
 {
-    static int last6 = 0;
-    static int posn = 0;
-    static bool finished = false;
-    
-    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)  return -1; //EOF or an error
-            if (last6 == -2)
-            {
-                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
-            if (this6 == -2)
-            {
-                this6 = 0;
-                finished = true;
-            }
-            
-            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
-            if (this6 == -2)
-            {
-                this6 = 0;
-                finished = true;
-            }
-            
-            bits8  = last6 << 6;
-            bits8 &= 0xFF;
-            bits8 |= this6;
-            
-            posn = 0;
-            break;
-        }
-    }
-    LogF("Read %02x\r\n", bits8);
-    
-    return bits8;
-}
-static int skipLine()
-{
-    while (true)
-    {
-        int c = readChar();
-        if      (c ==  -1 ) return -1; //EOF or an error
-        else if (c == '\n') return  0; //EOL
-    }
+    char c = *pNext;
+    if (!c) return 0;
+    pNext++;
+    return c;
 }
 static int readLength()
 {
-    int c = readByte();
+    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
@@ -152,7 +69,7 @@
     for (int i = 0; i < numberOfBytes; i++)
     {
         len <<= 8;
-        c = readByte();
+        c = Base64ReadByte();
         if (c == -1) return -1; //EOF or an error
         len |= c;
     }
@@ -160,7 +77,7 @@
 }
 static int readSequence()
 {
-    int c = readByte();
+    int c = Base64ReadByte();
     if (c ==   -1) return -1;  //EOF or an error
     if (c != 0x30) return -1;  //Not SEQUENCE type
     int len = readLength();
@@ -168,17 +85,16 @@
 }
 static int readData(char* data, int size)
 {
-    int c = readByte();
+    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
     
-    LogF("Reading %d bytes into %d buffer\r\n", pemLength, size);
     int finalLength = pemLength;
     for (int i = 0; i < pemLength; i++)
     {
-        c = readByte();
+        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
         {
@@ -195,40 +111,35 @@
 }
 void PriKeyInit()
 {
-    fh = SemihostOpen("PRIVATE.PEM", OPEN_MODE_R + OPEN_MODE_B);
+    /*
+    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;
-    Log("Skipping line\r\n");
-    r = skipLine();                   if (r < 0) goto end;
-    Log("Reading sequence\r\n");
+    r = Base64SkipLine();             if (r < 0) goto end;
     r = readSequence();               if (r < 0) goto end;
-    LogF("Sequence length is %d\r\n", r);
     
-    Log("Reading v\r\n");
     r = readData(   v, sizeof(   v)); if (r < 0) goto end;
-    Log("Reading n\r\n");
     r = readData(   n, sizeof(   n)); if (r < 0) goto end;
-    Log("Reading e\r\n");
     r = readData(   e, sizeof(   e)); if (r < 0) goto end;
-    Log("Reading d\r\n");
     r = readData(   d, sizeof(   d)); if (r < 0) goto end;
-    Log("Reading p\r\n");
     r = readData(   p, sizeof(   p)); if (r < 0) goto end;
-    Log("Reading q\r\n");
     r = readData(   q, sizeof(   q)); if (r < 0) goto end;
-    Log("Reading dp\r\n");
     r = readData(  dp, sizeof(  dp)); if (r < 0) goto end;
-    Log("Reading dq\r\n");
     r = readData(  dq, sizeof(  dq)); if (r < 0) goto end;
-    Log("Reading invq\r\n");
     r = readData(invq, sizeof(invq)); if (r < 0) goto end;
     
-    Log("Logging content\r\n");
+    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");
@@ -241,6 +152,8 @@
     
     
 end:
+    ;
+/*
     SemihostClose(fh);
-
+*/
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp/tls/ser-cer.c	Fri Jul 19 17:48:06 2019 +0000
@@ -0,0 +1,79 @@
+#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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp/tls/ser-cer.h	Fri Jul 19 17:48:06 2019 +0000
@@ -0,0 +1,3 @@
+extern char SerCerData[];
+extern int  SerCerSize;
+extern void SerCerInit(void);
\ No newline at end of file
--- a/tcp/tls/tls.c	Thu Jun 27 21:19:08 2019 +0000
+++ b/tcp/tls/tls.c	Fri Jul 19 17:48:06 2019 +0000
@@ -10,6 +10,7 @@
 #include "mstimer.h"
 #include "random.h"
 #include "pri-key.h"
+#include "ser-cer.h"
 
 #define TLS_CONTENT_TYPE_ChangeCipher      20
 #define TLS_CONTENT_TYPE_Alert             21
@@ -38,16 +39,12 @@
 
 bool TlsTrace = true;
 
-static const char certificate[] = {
-#include "certificate.inc"
-};
-
 void TlsInit()
 {
+    SerCerInit();
     PriKeyInit();
 }
 
-
 struct state
 {
     int      toDo;
@@ -83,6 +80,16 @@
         default:                                LogF("%02hX", handshakeType); break;
     }
 }
+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
+    if (TlsTrace)
+    {
+        LogF("      overall   length: %d\r\n", overallLength);
+        LogF("      premaster length: %d\r\n", premasterLength);
+    }
+}
 void TlsRequest(char* pTlsState, char* pWebState, int size, char* pRequestStream, uint32_t positionInRequestStream)
 {
     struct state* pState = (struct state*)pTlsState;
@@ -90,7 +97,7 @@
     if (TlsTrace) LogF("TLS <<< %d (%u)\r\n", size, positionInRequestStream);
 
     if (size == 0) return;
-    if (positionInRequestStream != 0) return;
+    //if (positionInRequestStream != 0) return;
     char contentType = pRequestStream[0];
     char versionH    = pRequestStream[1];
     char versionL    = pRequestStream[2];
@@ -107,7 +114,16 @@
         {
             char handshakeType = pRequestStream[5];
             if (TlsTrace) { Log("      handshake type: "); logHandshakeType(handshakeType); Log("\r\n"); }
-            pState->toDo = DO_SEND_SERVER_HELLO;
+            switch (handshakeType)
+            {
+                case TLS_HANDSHAKE_ClientHello:
+                    pState->toDo = DO_SEND_SERVER_HELLO;
+                    break;
+                case TLS_HANDSHAKE_ClientKeyExchange:
+                    handleClientKeyExchange(pRequestStream + 6);
+                    pState->toDo = DO_SEND_SERVER_CHANGE;
+                    break;
+            }
             return;
         }
         case TLS_CONTENT_TYPE_Application:
@@ -135,7 +151,7 @@
     Log("     sending server hello\r\n");
     TcpBufAddChar(TLS_CONTENT_TYPE_Handshake);                                   //Content is handshakes
     TcpBufAddChar(0x03); TcpBufAddChar(0x03);                                    //Legacy TLS version
-    addSize((45 + 4) + (sizeof(certificate) + 6 + 4) + (0 + 4));                 //Handshakes Length (2 bytes)
+    addSize((45 + 4) + (SerCerSize + 6 + 4) + (0 + 4));                          //Handshakes Length (2 bytes)
     
     TcpBufAddChar(TLS_HANDSHAKE_ServerHello); TcpBufAddChar(0x00);               //Handshake type server hello
     addSize(45);                                                                 //Size of this handshake
@@ -150,10 +166,10 @@
     TcpBufAddChar(0x00);                                                         //length is zero, because this is a new connection 
     
     TcpBufAddChar(TLS_HANDSHAKE_Certificate); TcpBufAddChar(0x00);               //Handshake type certificate
-    addSize(sizeof(certificate) + 6); TcpBufAddChar(0x00);                       //Size of this handshake
-    addSize(sizeof(certificate) + 3); TcpBufAddChar(0x00);                       //Size of all certificates
-    addSize(sizeof(certificate)    );                                            //Size of first certificate
-    for (int i = 0; i < sizeof(certificate); i++) TcpBufAddChar(certificate[i]); //Certificate
+    addSize(SerCerSize + 6); TcpBufAddChar(0x00);                                //Size of this handshake
+    addSize(SerCerSize + 3); TcpBufAddChar(0x00);                                //Size of all certificates
+    addSize(SerCerSize    );                                                     //Size of first certificate
+    for (int i = 0; i < SerCerSize; i++) TcpBufAddChar(SerCerData[i]);           //Certificate
     
     TcpBufAddChar(TLS_HANDSHAKE_ServerHelloDone); TcpBufAddChar(0x00);           //Handshake type server hello done
     addSize(0);                                                                  //Size of this handshake
@@ -166,6 +182,7 @@
     switch (pState->toDo)
     {
         case DO_WAIT_CLIENT_HELLO:
+        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
@@ -178,8 +195,11 @@
     
     switch(pState->toDo)
     {
-        case DO_SEND_SERVER_HELLO: sendServerHello(); return true;
-        default:                                      return true; //Finished
+        case DO_SEND_SERVER_HELLO: sendServerHello();
+            pState->toDo = DO_WAIT_CLIENT_CHANGE;
+            return false;
+        default:
+            return true; //Finished
     }
 }
 static char encrypt(char c)