Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
Revision 151:bde6f7da1755, committed 2019-07-19
- 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
--- /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)