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 152:80a3840fc9f8, committed 2019-07-25
- 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
--- 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
}
}