A simple library to support serving https.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Fri Jul 26 13:49:52 2019 +0000
Revision:
1:9c66a551a67e
Child:
2:82268409e83f
Moved TLS module from net library to crypto library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 1:9c66a551a67e 1 #include <stdbool.h>
andrewboyson 1:9c66a551a67e 2
andrewboyson 1:9c66a551a67e 3 #include "http.h"
andrewboyson 1:9c66a551a67e 4 #include "tcpbuf.h"
andrewboyson 1:9c66a551a67e 5 #include "action.h"
andrewboyson 1:9c66a551a67e 6 #include "net.h"
andrewboyson 1:9c66a551a67e 7 #include "log.h"
andrewboyson 1:9c66a551a67e 8 #include "led.h"
andrewboyson 1:9c66a551a67e 9 #include "restart.h"
andrewboyson 1:9c66a551a67e 10 #include "mstimer.h"
andrewboyson 1:9c66a551a67e 11 #include "random.h"
andrewboyson 1:9c66a551a67e 12 #include "pri-key.h"
andrewboyson 1:9c66a551a67e 13 #include "ser-cer.h"
andrewboyson 1:9c66a551a67e 14 #include "tls-prf.h"
andrewboyson 1:9c66a551a67e 15
andrewboyson 1:9c66a551a67e 16 #define TLS_CONTENT_TYPE_ChangeCipher 20
andrewboyson 1:9c66a551a67e 17 #define TLS_CONTENT_TYPE_Alert 21
andrewboyson 1:9c66a551a67e 18 #define TLS_CONTENT_TYPE_Handshake 22
andrewboyson 1:9c66a551a67e 19 #define TLS_CONTENT_TYPE_Application 23
andrewboyson 1:9c66a551a67e 20 #define TLS_CONTENT_TYPE_Heartbeat 24
andrewboyson 1:9c66a551a67e 21
andrewboyson 1:9c66a551a67e 22 #define TLS_HANDSHAKE_HelloRequest 0
andrewboyson 1:9c66a551a67e 23 #define TLS_HANDSHAKE_ClientHello 1
andrewboyson 1:9c66a551a67e 24 #define TLS_HANDSHAKE_ServerHello 2
andrewboyson 1:9c66a551a67e 25 #define TLS_HANDSHAKE_NewSessionTicket 4
andrewboyson 1:9c66a551a67e 26 #define TLS_HANDSHAKE_EncryptedExtensions 8
andrewboyson 1:9c66a551a67e 27 #define TLS_HANDSHAKE_Certificate 11
andrewboyson 1:9c66a551a67e 28 #define TLS_HANDSHAKE_ServerKeyExchange 12
andrewboyson 1:9c66a551a67e 29 #define TLS_HANDSHAKE_CertificateRequest 13
andrewboyson 1:9c66a551a67e 30 #define TLS_HANDSHAKE_ServerHelloDone 14
andrewboyson 1:9c66a551a67e 31 #define TLS_HANDSHAKE_CertificateVerify 15
andrewboyson 1:9c66a551a67e 32 #define TLS_HANDSHAKE_ClientKeyExchange 16
andrewboyson 1:9c66a551a67e 33 #define TLS_HANDSHAKE_Finished 20
andrewboyson 1:9c66a551a67e 34
andrewboyson 1:9c66a551a67e 35 #define DO_WAIT_CLIENT_HELLO 0
andrewboyson 1:9c66a551a67e 36 #define DO_SEND_SERVER_HELLO 1
andrewboyson 1:9c66a551a67e 37 #define DO_WAIT_CLIENT_CHANGE 2
andrewboyson 1:9c66a551a67e 38 #define DO_WAIT_DECRYPT_MASTER_SECRET 3
andrewboyson 1:9c66a551a67e 39 #define DO_SEND_SERVER_CHANGE 4
andrewboyson 1:9c66a551a67e 40 #define DO_APPLICATION 5
andrewboyson 1:9c66a551a67e 41 #define DO_SEND_ALERT_ILLEGAL_PARAMETER 6
andrewboyson 1:9c66a551a67e 42 #define DO_SEND_ALERT_INTERNAL_ERROR 7
andrewboyson 1:9c66a551a67e 43
andrewboyson 1:9c66a551a67e 44 bool TlsTrace = true;
andrewboyson 1:9c66a551a67e 45
andrewboyson 1:9c66a551a67e 46 char paddedMasterSecret[128];
andrewboyson 1:9c66a551a67e 47 char clientHelloRandom[32];
andrewboyson 1:9c66a551a67e 48
andrewboyson 1:9c66a551a67e 49 void TlsInit()
andrewboyson 1:9c66a551a67e 50 {
andrewboyson 1:9c66a551a67e 51 SerCerInit();
andrewboyson 1:9c66a551a67e 52 PriKeyInit();
andrewboyson 1:9c66a551a67e 53 TlsPrfTest();
andrewboyson 1:9c66a551a67e 54 }
andrewboyson 1:9c66a551a67e 55
andrewboyson 1:9c66a551a67e 56 struct state
andrewboyson 1:9c66a551a67e 57 {
andrewboyson 1:9c66a551a67e 58 int toDo;
andrewboyson 1:9c66a551a67e 59 };
andrewboyson 1:9c66a551a67e 60 static void logContentType(char contentType)
andrewboyson 1:9c66a551a67e 61 {
andrewboyson 1:9c66a551a67e 62 switch (contentType)
andrewboyson 1:9c66a551a67e 63 {
andrewboyson 1:9c66a551a67e 64 case TLS_CONTENT_TYPE_ChangeCipher: Log ("Change cipher" ); break;
andrewboyson 1:9c66a551a67e 65 case TLS_CONTENT_TYPE_Alert: Log ("Alert" ); break;
andrewboyson 1:9c66a551a67e 66 case TLS_CONTENT_TYPE_Handshake: Log ("Handshake" ); break;
andrewboyson 1:9c66a551a67e 67 case TLS_CONTENT_TYPE_Application: Log ("Application" ); break;
andrewboyson 1:9c66a551a67e 68 case TLS_CONTENT_TYPE_Heartbeat: Log ("Heartbeat" ); break;
andrewboyson 1:9c66a551a67e 69 default: LogF("%02hX", contentType); break;
andrewboyson 1:9c66a551a67e 70 }
andrewboyson 1:9c66a551a67e 71 }
andrewboyson 1:9c66a551a67e 72 static void logHandshakeType(char handshakeType)
andrewboyson 1:9c66a551a67e 73 {
andrewboyson 1:9c66a551a67e 74 switch (handshakeType)
andrewboyson 1:9c66a551a67e 75 {
andrewboyson 1:9c66a551a67e 76 case TLS_HANDSHAKE_HelloRequest: Log ("Hello request" ); break;
andrewboyson 1:9c66a551a67e 77 case TLS_HANDSHAKE_ClientHello: Log ("Client hello" ); break;
andrewboyson 1:9c66a551a67e 78 case TLS_HANDSHAKE_ServerHello: Log ("Server hello" ); break;
andrewboyson 1:9c66a551a67e 79 case TLS_HANDSHAKE_NewSessionTicket: Log ("New session ticket" ); break;
andrewboyson 1:9c66a551a67e 80 case TLS_HANDSHAKE_EncryptedExtensions: Log ("Encrypted extensions"); break;
andrewboyson 1:9c66a551a67e 81 case TLS_HANDSHAKE_Certificate: Log ("Certificate" ); break;
andrewboyson 1:9c66a551a67e 82 case TLS_HANDSHAKE_ServerKeyExchange: Log ("Server key exchange" ); break;
andrewboyson 1:9c66a551a67e 83 case TLS_HANDSHAKE_CertificateRequest: Log ("Certificate request" ); break;
andrewboyson 1:9c66a551a67e 84 case TLS_HANDSHAKE_ServerHelloDone: Log ("Server hello done" ); break;
andrewboyson 1:9c66a551a67e 85 case TLS_HANDSHAKE_CertificateVerify: Log ("Certificate verify" ); break;
andrewboyson 1:9c66a551a67e 86 case TLS_HANDSHAKE_ClientKeyExchange: Log ("Client key exchange" ); break;
andrewboyson 1:9c66a551a67e 87 case TLS_HANDSHAKE_Finished: Log ("Finished" ); break;
andrewboyson 1:9c66a551a67e 88 default: LogF("%02hX", handshakeType); break;
andrewboyson 1:9c66a551a67e 89 }
andrewboyson 1:9c66a551a67e 90 }
andrewboyson 1:9c66a551a67e 91 static void logAlertLevel(char level)
andrewboyson 1:9c66a551a67e 92 {
andrewboyson 1:9c66a551a67e 93 switch (level)
andrewboyson 1:9c66a551a67e 94 {
andrewboyson 1:9c66a551a67e 95 case 1: Log ("Warning" ); break;
andrewboyson 1:9c66a551a67e 96 case 2: Log ("Fatal" ); break;
andrewboyson 1:9c66a551a67e 97 default: LogF("%d", level); break;
andrewboyson 1:9c66a551a67e 98 }
andrewboyson 1:9c66a551a67e 99 }
andrewboyson 1:9c66a551a67e 100 static void logAlertDescription(char description)
andrewboyson 1:9c66a551a67e 101 {
andrewboyson 1:9c66a551a67e 102 switch (description)
andrewboyson 1:9c66a551a67e 103 {
andrewboyson 1:9c66a551a67e 104 case 0: Log("Close notify" ); break;
andrewboyson 1:9c66a551a67e 105 case 10: Log("Unexpected message" ); break;
andrewboyson 1:9c66a551a67e 106 case 20: Log("Bad record MAC" ); break;
andrewboyson 1:9c66a551a67e 107 case 21: Log("Decryption failed" ); break;
andrewboyson 1:9c66a551a67e 108 case 22: Log("Record overflow" ); break;
andrewboyson 1:9c66a551a67e 109 case 30: Log("Decompression failure" ); break;
andrewboyson 1:9c66a551a67e 110 case 40: Log("Handshake failure" ); break;
andrewboyson 1:9c66a551a67e 111 case 41: Log("No certificate" ); break;
andrewboyson 1:9c66a551a67e 112 case 42: Log("Bad certificate" ); break;
andrewboyson 1:9c66a551a67e 113 case 43: Log("Unsupported certificate" ); break;
andrewboyson 1:9c66a551a67e 114 case 44: Log("Certificate revoked" ); break;
andrewboyson 1:9c66a551a67e 115 case 45: Log("Certificate expired" ); break;
andrewboyson 1:9c66a551a67e 116 case 46: Log("Certificate unknown" ); break;
andrewboyson 1:9c66a551a67e 117 case 47: Log("Illegal parameter" ); break;
andrewboyson 1:9c66a551a67e 118 case 48: Log("Unknown CA" ); break;
andrewboyson 1:9c66a551a67e 119 case 49: Log("Access denied" ); break;
andrewboyson 1:9c66a551a67e 120 case 50: Log("Decode error" ); break;
andrewboyson 1:9c66a551a67e 121 case 51: Log("Decrypt error" ); break;
andrewboyson 1:9c66a551a67e 122 case 60: Log("Export restriction" ); break;
andrewboyson 1:9c66a551a67e 123 case 70: Log("Protocol version" ); break;
andrewboyson 1:9c66a551a67e 124 case 71: Log("Insufficient security" ); break;
andrewboyson 1:9c66a551a67e 125 case 80: Log("Internal error" ); break;
andrewboyson 1:9c66a551a67e 126 case 86: Log("Inappropriate Fallback" ); break;
andrewboyson 1:9c66a551a67e 127 case 90: Log("User cancelled" ); break;
andrewboyson 1:9c66a551a67e 128 case 100: Log("No renegotiation" ); break;
andrewboyson 1:9c66a551a67e 129 case 110: Log("Unsupported extension" ); break;
andrewboyson 1:9c66a551a67e 130 case 111: Log("Certificate unobtainable" ); break;
andrewboyson 1:9c66a551a67e 131 case 112: Log("Unrecognized name" ); break;
andrewboyson 1:9c66a551a67e 132 case 113: Log("Bad certificate status response"); break;
andrewboyson 1:9c66a551a67e 133 case 114: Log("Bad certificate hash value" ); break;
andrewboyson 1:9c66a551a67e 134 case 115: Log("Unknown PSK identity" ); break;
andrewboyson 1:9c66a551a67e 135 case 120: Log("No Application Protocol" ); break;
andrewboyson 1:9c66a551a67e 136 default: LogF("%d", description ); break;
andrewboyson 1:9c66a551a67e 137 }
andrewboyson 1:9c66a551a67e 138 }
andrewboyson 1:9c66a551a67e 139 static int handleClientHello(int length, char* pBuffer) //returns 0 on success; -1 on error
andrewboyson 1:9c66a551a67e 140 {
andrewboyson 1:9c66a551a67e 141 if (length != 32)
andrewboyson 1:9c66a551a67e 142 {
andrewboyson 1:9c66a551a67e 143 LogF("TLS - %d byte client hello message is not 32 bytes long\r\n", length);
andrewboyson 1:9c66a551a67e 144 return -1;
andrewboyson 1:9c66a551a67e 145 }
andrewboyson 1:9c66a551a67e 146 for (int i = 0; i < 32; i++) clientHelloRandom[i] = pBuffer[i];
andrewboyson 1:9c66a551a67e 147 if (TlsTrace)
andrewboyson 1:9c66a551a67e 148 {
andrewboyson 1:9c66a551a67e 149 Log("- random:\r\n");
andrewboyson 1:9c66a551a67e 150 LogBytesAsHex(clientHelloRandom, 32);
andrewboyson 1:9c66a551a67e 151 Log("\r\n");
andrewboyson 1:9c66a551a67e 152 }
andrewboyson 1:9c66a551a67e 153 return 0;
andrewboyson 1:9c66a551a67e 154 }
andrewboyson 1:9c66a551a67e 155 static int handleClientKeyExchange(int length, char* pBuffer) //returns 0 on success; -1 on error
andrewboyson 1:9c66a551a67e 156 {
andrewboyson 1:9c66a551a67e 157 if (length != 130)
andrewboyson 1:9c66a551a67e 158 {
andrewboyson 1:9c66a551a67e 159 LogF("TLS - %d byte client key exchange message is not 130 bytes long\r\n", length);
andrewboyson 1:9c66a551a67e 160 return -1;
andrewboyson 1:9c66a551a67e 161 }
andrewboyson 1:9c66a551a67e 162 int premasterLength = pBuffer[0] << 8 | pBuffer[1]; //Overall length 2 bytes
andrewboyson 1:9c66a551a67e 163 if (premasterLength != 128)
andrewboyson 1:9c66a551a67e 164 {
andrewboyson 1:9c66a551a67e 165 LogF("TLS - %d byte encrypted pre master secret is not 128 bytes long\r\n", length);
andrewboyson 1:9c66a551a67e 166 return -1;
andrewboyson 1:9c66a551a67e 167 }
andrewboyson 1:9c66a551a67e 168 char* pEncryptedPreMasterSecret = pBuffer + 2;
andrewboyson 1:9c66a551a67e 169 PriKeyDecryptStart(pEncryptedPreMasterSecret, paddedMasterSecret);
andrewboyson 1:9c66a551a67e 170
andrewboyson 1:9c66a551a67e 171 if (TlsTrace)
andrewboyson 1:9c66a551a67e 172 {
andrewboyson 1:9c66a551a67e 173 LogF("- encrypted premaster (%d bytes little endian)\r\n", premasterLength);
andrewboyson 1:9c66a551a67e 174 LogBytesAsHex(pEncryptedPreMasterSecret, 128);
andrewboyson 1:9c66a551a67e 175 Log("\r\n");
andrewboyson 1:9c66a551a67e 176 }
andrewboyson 1:9c66a551a67e 177
andrewboyson 1:9c66a551a67e 178 return 0;
andrewboyson 1:9c66a551a67e 179 }
andrewboyson 1:9c66a551a67e 180 static void handleHandshake(int length, char* pBuffer, int* pToDo)
andrewboyson 1:9c66a551a67e 181 {
andrewboyson 1:9c66a551a67e 182 char* p = pBuffer;
andrewboyson 1:9c66a551a67e 183 while (p < pBuffer + length)
andrewboyson 1:9c66a551a67e 184 {
andrewboyson 1:9c66a551a67e 185 char handshakeType = *p++;
andrewboyson 1:9c66a551a67e 186 int handshakeLength = *p++ << 16 | *p++ << 8 | *p++; //Handshake length 3 bytes
andrewboyson 1:9c66a551a67e 187 if (TlsTrace)
andrewboyson 1:9c66a551a67e 188 {
andrewboyson 1:9c66a551a67e 189 Log ("- handshake type: "); logHandshakeType(handshakeType); Log("\r\n");
andrewboyson 1:9c66a551a67e 190 LogF("- handshake length: %d\r\n", handshakeLength);
andrewboyson 1:9c66a551a67e 191 }
andrewboyson 1:9c66a551a67e 192 int r = -1;
andrewboyson 1:9c66a551a67e 193 switch (handshakeType)
andrewboyson 1:9c66a551a67e 194 {
andrewboyson 1:9c66a551a67e 195 case TLS_HANDSHAKE_ClientHello:
andrewboyson 1:9c66a551a67e 196 r = handleClientHello(handshakeLength, p);
andrewboyson 1:9c66a551a67e 197 *pToDo = r ? DO_SEND_ALERT_ILLEGAL_PARAMETER : DO_SEND_SERVER_HELLO;
andrewboyson 1:9c66a551a67e 198 break;
andrewboyson 1:9c66a551a67e 199
andrewboyson 1:9c66a551a67e 200 case TLS_HANDSHAKE_ClientKeyExchange:
andrewboyson 1:9c66a551a67e 201 r = handleClientKeyExchange(handshakeLength, p);
andrewboyson 1:9c66a551a67e 202 *pToDo = r ? DO_SEND_ALERT_ILLEGAL_PARAMETER : DO_WAIT_DECRYPT_MASTER_SECRET;
andrewboyson 1:9c66a551a67e 203 break;
andrewboyson 1:9c66a551a67e 204
andrewboyson 1:9c66a551a67e 205 default:
andrewboyson 1:9c66a551a67e 206 LogF("TLS - ignoring untreated %d byte handshake type ", handshakeLength);
andrewboyson 1:9c66a551a67e 207 logHandshakeType(handshakeType);
andrewboyson 1:9c66a551a67e 208 Log("\r\n");
andrewboyson 1:9c66a551a67e 209 break;
andrewboyson 1:9c66a551a67e 210 }
andrewboyson 1:9c66a551a67e 211 p += handshakeLength;
andrewboyson 1:9c66a551a67e 212 }
andrewboyson 1:9c66a551a67e 213 }
andrewboyson 1:9c66a551a67e 214 static void handleAlert(int length, char* pBuffer)
andrewboyson 1:9c66a551a67e 215 {
andrewboyson 1:9c66a551a67e 216 char level = pBuffer[0];
andrewboyson 1:9c66a551a67e 217 char description = pBuffer[1];
andrewboyson 1:9c66a551a67e 218 if (TlsTrace)
andrewboyson 1:9c66a551a67e 219 {
andrewboyson 1:9c66a551a67e 220 Log("- alert level: "); logAlertLevel (level); Log("\r\n");
andrewboyson 1:9c66a551a67e 221 Log("- alert description: "); logAlertDescription(description); Log("\r\n");
andrewboyson 1:9c66a551a67e 222 }
andrewboyson 1:9c66a551a67e 223 }
andrewboyson 1:9c66a551a67e 224 static void handleApplication(int length, char* pBuffer)
andrewboyson 1:9c66a551a67e 225 {
andrewboyson 1:9c66a551a67e 226 if (TlsTrace)
andrewboyson 1:9c66a551a67e 227 {
andrewboyson 1:9c66a551a67e 228 Log("- application data:\r\n");
andrewboyson 1:9c66a551a67e 229 LogBytesAsHex(pBuffer, length);
andrewboyson 1:9c66a551a67e 230 Log("\r\n");
andrewboyson 1:9c66a551a67e 231 }
andrewboyson 1:9c66a551a67e 232 }
andrewboyson 1:9c66a551a67e 233 void TlsRequest(char* pTlsState, char* pWebState, int size, char* pRequestStream, uint32_t positionInRequestStream)
andrewboyson 1:9c66a551a67e 234 {
andrewboyson 1:9c66a551a67e 235 struct state* pState = (struct state*)pTlsState;
andrewboyson 1:9c66a551a67e 236
andrewboyson 1:9c66a551a67e 237 if (TlsTrace) LogF("TLS <<< %d (%u)\r\n", size, positionInRequestStream);
andrewboyson 1:9c66a551a67e 238
andrewboyson 1:9c66a551a67e 239 if (size == 0) return;
andrewboyson 1:9c66a551a67e 240 //if (positionInRequestStream != 0) return;
andrewboyson 1:9c66a551a67e 241 char contentType = pRequestStream[0];
andrewboyson 1:9c66a551a67e 242 char versionH = pRequestStream[1];
andrewboyson 1:9c66a551a67e 243 char versionL = pRequestStream[2];
andrewboyson 1:9c66a551a67e 244 int length = pRequestStream[3] << 8 | pRequestStream[4]; //Length (2 bytes)
andrewboyson 1:9c66a551a67e 245 if (TlsTrace)
andrewboyson 1:9c66a551a67e 246 {
andrewboyson 1:9c66a551a67e 247 Log ("- content type: "); logContentType(contentType); Log("\r\n");
andrewboyson 1:9c66a551a67e 248 LogF("- legacy HH:LL: %02x:%02x\r\n", versionH, versionL);
andrewboyson 1:9c66a551a67e 249 LogF("- length : %d\r\n" , length);
andrewboyson 1:9c66a551a67e 250 }
andrewboyson 1:9c66a551a67e 251 switch (contentType)
andrewboyson 1:9c66a551a67e 252 {
andrewboyson 1:9c66a551a67e 253 case TLS_CONTENT_TYPE_Handshake:
andrewboyson 1:9c66a551a67e 254 {
andrewboyson 1:9c66a551a67e 255 handleHandshake(length, pRequestStream + 5, &pState->toDo);
andrewboyson 1:9c66a551a67e 256 return;
andrewboyson 1:9c66a551a67e 257 }
andrewboyson 1:9c66a551a67e 258 case TLS_CONTENT_TYPE_Alert:
andrewboyson 1:9c66a551a67e 259 {
andrewboyson 1:9c66a551a67e 260 handleAlert(length, pRequestStream + 5);
andrewboyson 1:9c66a551a67e 261 return;
andrewboyson 1:9c66a551a67e 262 }
andrewboyson 1:9c66a551a67e 263 case TLS_CONTENT_TYPE_Application:
andrewboyson 1:9c66a551a67e 264 {
andrewboyson 1:9c66a551a67e 265 handleApplication(length, pRequestStream + 5);
andrewboyson 1:9c66a551a67e 266 pState->toDo = DO_APPLICATION;
andrewboyson 1:9c66a551a67e 267 return;
andrewboyson 1:9c66a551a67e 268 }
andrewboyson 1:9c66a551a67e 269
andrewboyson 1:9c66a551a67e 270 default:
andrewboyson 1:9c66a551a67e 271 Log("TLS - untreated content type "); logContentType(contentType); Log("\r\n");
andrewboyson 1:9c66a551a67e 272 pState->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 1:9c66a551a67e 273 return;
andrewboyson 1:9c66a551a67e 274 }
andrewboyson 1:9c66a551a67e 275 }
andrewboyson 1:9c66a551a67e 276 char lengthH(int size) { return size >> 8;}
andrewboyson 1:9c66a551a67e 277 char lengthL(int size) { return size & 0xFF; }
andrewboyson 1:9c66a551a67e 278 void addSize(int size)
andrewboyson 1:9c66a551a67e 279 {
andrewboyson 1:9c66a551a67e 280 TcpBufAddChar(size >> 8 );
andrewboyson 1:9c66a551a67e 281 TcpBufAddChar(size & 0xFF);
andrewboyson 1:9c66a551a67e 282 }
andrewboyson 1:9c66a551a67e 283
andrewboyson 1:9c66a551a67e 284 static void sendServerHello()
andrewboyson 1:9c66a551a67e 285 {
andrewboyson 1:9c66a551a67e 286 Log(" sending server hello\r\n");
andrewboyson 1:9c66a551a67e 287 TcpBufAddChar(TLS_CONTENT_TYPE_Handshake); //Content is handshakes
andrewboyson 1:9c66a551a67e 288 TcpBufAddChar(0x03); TcpBufAddChar(0x03); //Legacy TLS version
andrewboyson 1:9c66a551a67e 289 addSize((45 + 4) + (SerCerSize + 6 + 4) + (0 + 4)); //Handshakes Length (2 bytes)
andrewboyson 1:9c66a551a67e 290
andrewboyson 1:9c66a551a67e 291 TcpBufAddChar(TLS_HANDSHAKE_ServerHello); TcpBufAddChar(0x00); //Handshake type server hello
andrewboyson 1:9c66a551a67e 292 addSize(45); //Size of this handshake
andrewboyson 1:9c66a551a67e 293 TcpBufAddChar(0x03); TcpBufAddChar(0x03); //TLS version 1.2
andrewboyson 1:9c66a551a67e 294 for (int i = 0; i < 32; i++) TcpBufAddChar(RandomGetByte()); //32 bit random number
andrewboyson 1:9c66a551a67e 295 TcpBufAddChar(0x00); //SessionId length 0
andrewboyson 1:9c66a551a67e 296 TcpBufAddChar(0x00); TcpBufAddChar(0x2f); //Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
andrewboyson 1:9c66a551a67e 297 TcpBufAddChar(0x00); //Compression method none
andrewboyson 1:9c66a551a67e 298 TcpBufAddChar(0x00); TcpBufAddChar(0x05); //Extensions length (2 bytes) 5 bytes
andrewboyson 1:9c66a551a67e 299 TcpBufAddChar(0xff); TcpBufAddChar(0x01); //Extension Renegotiation Info
andrewboyson 1:9c66a551a67e 300 TcpBufAddChar(0x00); TcpBufAddChar(0x01); //1 bytes of "Renegotiation Info" extension data follows
andrewboyson 1:9c66a551a67e 301 TcpBufAddChar(0x00); //length is zero, because this is a new connection
andrewboyson 1:9c66a551a67e 302
andrewboyson 1:9c66a551a67e 303 TcpBufAddChar(TLS_HANDSHAKE_Certificate); TcpBufAddChar(0x00); //Handshake type certificate
andrewboyson 1:9c66a551a67e 304 addSize(SerCerSize + 6); TcpBufAddChar(0x00); //Size of this handshake
andrewboyson 1:9c66a551a67e 305 addSize(SerCerSize + 3); TcpBufAddChar(0x00); //Size of all certificates
andrewboyson 1:9c66a551a67e 306 addSize(SerCerSize ); //Size of first certificate
andrewboyson 1:9c66a551a67e 307 for (int i = 0; i < SerCerSize; i++) TcpBufAddChar(SerCerData[i]); //Certificate
andrewboyson 1:9c66a551a67e 308
andrewboyson 1:9c66a551a67e 309 TcpBufAddChar(TLS_HANDSHAKE_ServerHelloDone); TcpBufAddChar(0x00); //Handshake type server hello done
andrewboyson 1:9c66a551a67e 310 addSize(0); //Size of this handshake
andrewboyson 1:9c66a551a67e 311 }
andrewboyson 1:9c66a551a67e 312 static void sendServerChange()
andrewboyson 1:9c66a551a67e 313 {
andrewboyson 1:9c66a551a67e 314 Log(" sending server change\r\n");
andrewboyson 1:9c66a551a67e 315 }
andrewboyson 1:9c66a551a67e 316 static void sendFatal(char description)
andrewboyson 1:9c66a551a67e 317 {
andrewboyson 1:9c66a551a67e 318 Log(" sending fatal alert: ");
andrewboyson 1:9c66a551a67e 319 logAlertDescription(description);
andrewboyson 1:9c66a551a67e 320 Log("\r\n");
andrewboyson 1:9c66a551a67e 321 TcpBufAddChar(TLS_CONTENT_TYPE_Alert); //Content is alert
andrewboyson 1:9c66a551a67e 322 TcpBufAddChar(0x03); TcpBufAddChar(0x03); //Legacy TLS version
andrewboyson 1:9c66a551a67e 323 addSize(2); //Alert Length (2 bytes)
andrewboyson 1:9c66a551a67e 324
andrewboyson 1:9c66a551a67e 325 TcpBufAddChar(2); //Fatal (level = 2)
andrewboyson 1:9c66a551a67e 326 TcpBufAddChar(description); //Description
andrewboyson 1:9c66a551a67e 327
andrewboyson 1:9c66a551a67e 328 }
andrewboyson 1:9c66a551a67e 329 int TlsPoll(char* pTlsState, char* pWebState, bool clientFinished)
andrewboyson 1:9c66a551a67e 330 {
andrewboyson 1:9c66a551a67e 331 struct state* pState = (struct state*)pTlsState;
andrewboyson 1:9c66a551a67e 332
andrewboyson 1:9c66a551a67e 333 switch (pState->toDo)
andrewboyson 1:9c66a551a67e 334 {
andrewboyson 1:9c66a551a67e 335 case DO_WAIT_CLIENT_HELLO:
andrewboyson 1:9c66a551a67e 336 case DO_WAIT_CLIENT_CHANGE:
andrewboyson 1:9c66a551a67e 337 if (clientFinished) return -1; //The client hasn't made a request and never will so finish
andrewboyson 1:9c66a551a67e 338 else return 0; //The client hasn't made a request yet but it could.
andrewboyson 1:9c66a551a67e 339
andrewboyson 1:9c66a551a67e 340 case DO_WAIT_DECRYPT_MASTER_SECRET:
andrewboyson 1:9c66a551a67e 341 if (PriKeyDecryptFinished())
andrewboyson 1:9c66a551a67e 342 {
andrewboyson 1:9c66a551a67e 343 Log("Master secret\r\n");
andrewboyson 1:9c66a551a67e 344 LogBytesAsHex(paddedMasterSecret, sizeof(paddedMasterSecret));
andrewboyson 1:9c66a551a67e 345 Log("\r\n");
andrewboyson 1:9c66a551a67e 346 pState->toDo = DO_SEND_SERVER_CHANGE;
andrewboyson 1:9c66a551a67e 347 return 1; //Call TlsReply to do the send
andrewboyson 1:9c66a551a67e 348 }
andrewboyson 1:9c66a551a67e 349 else
andrewboyson 1:9c66a551a67e 350 {
andrewboyson 1:9c66a551a67e 351 if (clientFinished) return -1; //The client hasn't made a request and never will so finish
andrewboyson 1:9c66a551a67e 352 else return 0; //The client hasn't made a request yet but it could.
andrewboyson 1:9c66a551a67e 353 }
andrewboyson 1:9c66a551a67e 354
andrewboyson 1:9c66a551a67e 355 case DO_APPLICATION:
andrewboyson 1:9c66a551a67e 356 return HttpPollFunction(pWebState, clientFinished); //Return whatever HTTP would be
andrewboyson 1:9c66a551a67e 357
andrewboyson 1:9c66a551a67e 358 case DO_SEND_SERVER_HELLO:
andrewboyson 1:9c66a551a67e 359 case DO_SEND_ALERT_ILLEGAL_PARAMETER:
andrewboyson 1:9c66a551a67e 360 case DO_SEND_ALERT_INTERNAL_ERROR:
andrewboyson 1:9c66a551a67e 361 return 1;
andrewboyson 1:9c66a551a67e 362
andrewboyson 1:9c66a551a67e 363 default:
andrewboyson 1:9c66a551a67e 364 LogTimeF("TlsPoll - unspecified TLS state %d\r\n", pState->toDo);
andrewboyson 1:9c66a551a67e 365 return -1; //Finish
andrewboyson 1:9c66a551a67e 366 }
andrewboyson 1:9c66a551a67e 367 }
andrewboyson 1:9c66a551a67e 368 bool TlsReply(char* pTlsState, char* pWebState)
andrewboyson 1:9c66a551a67e 369 {
andrewboyson 1:9c66a551a67e 370 struct state* pState = (struct state*)pTlsState;
andrewboyson 1:9c66a551a67e 371
andrewboyson 1:9c66a551a67e 372 switch(pState->toDo)
andrewboyson 1:9c66a551a67e 373 {
andrewboyson 1:9c66a551a67e 374 case DO_SEND_SERVER_HELLO:
andrewboyson 1:9c66a551a67e 375 sendServerHello();
andrewboyson 1:9c66a551a67e 376 pState->toDo = DO_WAIT_CLIENT_CHANGE;
andrewboyson 1:9c66a551a67e 377 return false; //Not finished
andrewboyson 1:9c66a551a67e 378
andrewboyson 1:9c66a551a67e 379 case DO_SEND_SERVER_CHANGE:
andrewboyson 1:9c66a551a67e 380 sendServerChange();
andrewboyson 1:9c66a551a67e 381 pState->toDo = DO_APPLICATION;
andrewboyson 1:9c66a551a67e 382 return false; //Not finished
andrewboyson 1:9c66a551a67e 383
andrewboyson 1:9c66a551a67e 384 case DO_APPLICATION:
andrewboyson 1:9c66a551a67e 385 return HttpReplyFunction(pWebState); //Return whatever HTTP would be
andrewboyson 1:9c66a551a67e 386
andrewboyson 1:9c66a551a67e 387 case DO_SEND_ALERT_ILLEGAL_PARAMETER:
andrewboyson 1:9c66a551a67e 388 sendFatal(47);
andrewboyson 1:9c66a551a67e 389 pState->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 1:9c66a551a67e 390 return true; //Finished
andrewboyson 1:9c66a551a67e 391
andrewboyson 1:9c66a551a67e 392 case DO_SEND_ALERT_INTERNAL_ERROR:
andrewboyson 1:9c66a551a67e 393 sendFatal(80);
andrewboyson 1:9c66a551a67e 394 pState->toDo = DO_WAIT_CLIENT_HELLO;
andrewboyson 1:9c66a551a67e 395 return true; //Finished
andrewboyson 1:9c66a551a67e 396
andrewboyson 1:9c66a551a67e 397 default:
andrewboyson 1:9c66a551a67e 398 LogTimeF("TlsReply - unspecified TLS state %d\r\n", pState->toDo);
andrewboyson 1:9c66a551a67e 399 return true; //Finished
andrewboyson 1:9c66a551a67e 400 }
andrewboyson 1:9c66a551a67e 401 }
andrewboyson 1:9c66a551a67e 402 static char encrypt(char c)
andrewboyson 1:9c66a551a67e 403 {
andrewboyson 1:9c66a551a67e 404 return c; //Implement encryption
andrewboyson 1:9c66a551a67e 405 }
andrewboyson 1:9c66a551a67e 406 void TlsAddChar(char c)
andrewboyson 1:9c66a551a67e 407 {
andrewboyson 1:9c66a551a67e 408 char e = encrypt(c);
andrewboyson 1:9c66a551a67e 409 TcpBufAddChar(e);
andrewboyson 1:9c66a551a67e 410 }