Merge pull request #1125 from pjsg/ssl-verify

Adds support for verifying the certificate offered by an SSL server.
This commit is contained in:
Johny Mattsson 2016-03-10 14:02:16 +11:00
commit 3490ffb285
11 changed files with 538 additions and 18 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
sdk/
cache/
user_config.h
server-ca.crt

View File

@ -132,7 +132,7 @@ CCFLAGS += \
# -Wall
ifneq ($(wildcard $(TOP_DIR)/user_config.h),)
INCLUDES := $(INCLUDES) -include "$(TOP_DIR)/user_config.h"
INCLUDES += -include "$(TOP_DIR)/user_config.h"
endif
CFLAGS = $(CCFLAGS) $(DEFINES) $(EXTRA_CCFLAGS) $(STD_CFLAGS) $(INCLUDES)
@ -175,7 +175,7 @@ $(BINODIR)/%.bin: $(IMAGEODIR)/%.out
# Should be done in top-level makefile only
#
all: sdk_extracted .subdirs $(OBJS) $(OLIBS) $(OIMAGES) $(OBINS) $(SPECIAL_MKTARGETS)
all: sdk_extracted pre_build .subdirs $(OBJS) $(OLIBS) $(OIMAGES) $(OBINS) $(SPECIAL_MKTARGETS)
.PHONY: sdk_extracted
@ -222,6 +222,17 @@ endif
endif
endif
.PHONY: pre_build
pre_build:
ifneq ($(wildcard $(TOP_DIR)/server-ca.crt),)
python $(TOP_DIR)/tools/make_server_cert.py $(TOP_DIR)/server-ca.crt > $(TOP_DIR)/app/modules/server-ca.crt.h
DEFINES += -DHAVE_SSL_SERVER_CRT=\"server-ca.crt.h\"
else
@-rm -f $(TOP_DIR)/app/modules/server-ca.crt.h
endif
$(OBJODIR)/%.o: %.c
@mkdir -p $(OBJODIR);
$(CC) $(if $(findstring $<,$(DSRCS)),$(DFLAGS),$(CFLAGS)) $(COPTS_$(*F)) -o $@ -c $<

View File

@ -437,10 +437,10 @@ static void ICACHE_FLASH_ATTR http_dns_callback( const char * hostname, ip_addr_
{
HTTPCLIENT_DEBUG( "DNS found %s " IPSTR "\n", hostname, IP2STR( addr ) );
struct espconn * conn = (struct espconn *) os_malloc( sizeof(struct espconn) );
struct espconn * conn = (struct espconn *) os_zalloc( sizeof(struct espconn) );
conn->type = ESPCONN_TCP;
conn->state = ESPCONN_NONE;
conn->proto.tcp = (esp_tcp *) os_malloc( sizeof(esp_tcp) );
conn->proto.tcp = (esp_tcp *) os_zalloc( sizeof(esp_tcp) );
conn->proto.tcp->local_port = espconn_port();
conn->proto.tcp->remote_port = req->port;
conn->reverse = req;
@ -473,7 +473,7 @@ void ICACHE_FLASH_ATTR http_raw_request( const char * hostname, int port, bool s
{
HTTPCLIENT_DEBUG( "DNS request\n" );
request_args_t * req = (request_args_t *) os_malloc( sizeof(request_args_t) );
request_args_t * req = (request_args_t *) os_zalloc( sizeof(request_args_t) );
req->hostname = esp_strdup( hostname );
req->port = port;
req->secure = secure;
@ -558,6 +558,11 @@ void ICACHE_FLASH_ATTR http_request( const char * url, const char * method, cons
colon = NULL; /* Limit the search to characters before the path. */
}
if (path - url >= sizeof(hostname)) {
HTTPCLIENT_DEBUG( "hostname is too long %s\n", url );
return;
}
if ( colon == NULL ) /* The port is not present. */
{
os_memcpy( hostname, url, path - url );

1
app/modules/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
server-ca.crt.h

View File

@ -3,6 +3,7 @@
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "lmem.h"
#include "c_string.h"
#include "c_stdlib.h"
@ -13,18 +14,19 @@
#include "espconn.h"
#include "lwip/dns.h"
#ifdef CLIENT_SSL_ENABLE
unsigned char *default_certificate;
unsigned int default_certificate_len = 0;
unsigned char *default_private_key;
unsigned int default_private_key_len = 0;
#endif
#define TCP ESPCONN_TCP
#define UDP ESPCONN_UDP
static ip_addr_t host_ip; // for dns
#ifdef HAVE_SSL_SERVER_CRT
#include HAVE_SSL_SERVER_CRT
#else
__attribute__((section(".servercert.flash"))) unsigned char net_server_cert_area[INTERNAL_FLASH_SECTOR_SIZE];
#endif
__attribute__((section(".clientcert.flash"))) unsigned char net_client_cert_area[INTERNAL_FLASH_SECTOR_SIZE];
#if 0
static int expose_array(lua_State* L, char *array, unsigned short len);
#endif
@ -1432,6 +1434,201 @@ static int net_multicastLeave( lua_State* L )
return net_multicastJoinLeave(L,0);
}
// Returns NULL on success, error message otherwise
static const char *append_pem_blob(const char *pem, const char *type, uint8_t **buffer_p, uint8_t *buffer_limit, const char *name) {
char unb64[256];
memset(unb64, 0xff, sizeof(unb64));
int i;
for (i = 0; i < 64; i++) {
unb64["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;
}
if (!pem) {
return "No PEM blob";
}
// Scan for -----BEGIN CERT
pem = strstr(pem, "-----BEGIN ");
if (!pem) {
return "No PEM header";
}
if (strncmp(pem + 11, type, strlen(type))) {
return "Wrong PEM type";
}
pem = strchr(pem, '\n');
if (!pem) {
return "Incorrect PEM format";
}
//
// Base64 encoded data starts here
// Get all the base64 data into a single buffer....
// We will use the back end of the buffer....
//
uint8_t *buffer = *buffer_p;
uint8_t *dest = buffer + 32 + 2; // Leave space for name and length
int bitcount = 0;
int accumulator = 0;
for (; *pem && dest < buffer_limit; pem++) {
int val = unb64[*(uint8_t*) pem];
if (val & 0xC0) {
// not a base64 character
if (isspace(*(uint8_t*) pem)) {
continue;
}
if (*pem == '=') {
// just ignore -- at the end
bitcount = 0;
continue;
}
if (*pem == '-') {
break;
}
return "Invalid character in PEM";
} else {
bitcount += 6;
accumulator = (accumulator << 6) + val;
if (bitcount >= 8) {
bitcount -= 8;
*dest++ = accumulator >> bitcount;
}
}
}
if (dest >= buffer_limit || strncmp(pem, "-----END ", 9) || strncmp(pem + 9, type, strlen(type)) || bitcount) {
return "Invalid PEM format data";
}
size_t len = dest - (buffer + 32 + 2);
memset(buffer, 0, 32);
strcpy(buffer, name);
buffer[32] = len & 0xff;
buffer[33] = (len >> 8) & 0xff;
*buffer_p = dest;
return NULL;
}
static const char *fill_page_with_pem(lua_State *L, const unsigned char *flash_memory, int flash_offset, const char **types, const char **names)
{
uint8_t *buffer = luaM_malloc(L, INTERNAL_FLASH_SECTOR_SIZE);
uint8_t *buffer_base = buffer;
uint8_t *buffer_limit = buffer + INTERNAL_FLASH_SECTOR_SIZE;
int argno;
for (argno = 1; argno <= lua_gettop(L) && types[argno - 1]; argno++) {
const char *pem = lua_tostring(L, argno);
const char *error = append_pem_blob(pem, types[argno - 1], &buffer, buffer_limit, names[argno - 1]);
if (error) {
luaM_free(L, buffer_base);
return error;
}
}
memset(buffer, 0xff, buffer_limit - buffer);
// Lets see if it matches what is already there....
if (c_memcmp(buffer_base, flash_memory, INTERNAL_FLASH_SECTOR_SIZE) != 0) {
// Starts being dangerous
if (platform_flash_erase_sector(flash_offset / INTERNAL_FLASH_SECTOR_SIZE) != PLATFORM_OK) {
luaM_free(L, buffer_base);
return "Failed to erase sector";
}
if (platform_s_flash_write(buffer_base, flash_offset, INTERNAL_FLASH_SECTOR_SIZE) != INTERNAL_FLASH_SECTOR_SIZE) {
luaM_free(L, buffer_base);
return "Failed to write sector";
}
// ends being dangerous
}
luaM_free(L, buffer_base);
return NULL;
}
// Lua: net.cert.auth(true / false | PEM data [, PEM data] )
static int net_cert_auth(lua_State *L)
{
int enable;
uint32_t flash_offset = platform_flash_mapped2phys((uint32_t) &net_client_cert_area[0]);
if ((flash_offset & 0xfff) || flash_offset > 0xff000 || INTERNAL_FLASH_SECTOR_SIZE != 0x1000) {
// THis should never happen
return luaL_error( L, "bad offset" );
}
if (lua_type(L, 1) == LUA_TSTRING) {
const char *types[3] = { "CERTIFICATE", "RSA PRIVATE KEY", NULL };
const char *names[2] = { "certificate", "private_key" };
const char *error = fill_page_with_pem(L, &net_client_cert_area[0], flash_offset, types, names);
if (error) {
return luaL_error(L, error);
}
enable = 1;
} else {
enable = lua_toboolean(L, 1);
}
bool rc;
if (enable) {
// See if there is a cert there
if (net_client_cert_area[0] == 0x00 || net_client_cert_area[0] == 0xff) {
return luaL_error( L, "no certificates found" );
}
rc = espconn_secure_cert_req_enable(1, flash_offset / INTERNAL_FLASH_SECTOR_SIZE);
} else {
rc = espconn_secure_cert_req_disable(1);
}
lua_pushboolean(L, rc);
return 1;
}
// Lua: net.cert.verify(true / false | PEM data [, PEM data] )
static int net_cert_verify(lua_State *L)
{
int enable;
uint32_t flash_offset = platform_flash_mapped2phys((uint32_t) &net_server_cert_area[0]);
if ((flash_offset & 0xfff) || flash_offset > 0xff000 || INTERNAL_FLASH_SECTOR_SIZE != 0x1000) {
// THis should never happen
return luaL_error( L, "bad offset" );
}
if (lua_type(L, 1) == LUA_TSTRING) {
const char *types[2] = { "CERTIFICATE", NULL };
const char *names[1] = { "certificate" };
const char *error = fill_page_with_pem(L, &net_server_cert_area[0], flash_offset, types, names);
if (error) {
return luaL_error(L, error);
}
enable = 1;
} else {
enable = lua_toboolean(L, 1);
}
bool rc;
if (enable) {
// See if there is a cert there
if (net_server_cert_area[0] == 0x00 || net_server_cert_area[0] == 0xff) {
return luaL_error( L, "no certificates found" );
}
rc = espconn_secure_ca_enable(1, flash_offset / INTERNAL_FLASH_SECTOR_SIZE);
} else {
rc = espconn_secure_ca_disable(1);
}
lua_pushboolean(L, rc);
return 1;
}
// Lua: s = net.dns.setdnsserver(ip_addr, [index])
static int net_setdnsserver( lua_State* L )
@ -1539,6 +1736,14 @@ static const LUA_REG_TYPE net_array_map[] = {
};
#endif
static const LUA_REG_TYPE net_cert_map[] = {
{ LSTRKEY( "verify" ), LFUNCVAL( net_cert_verify ) },
#ifdef CLIENT_SSL_CERT_AUTH_ENABLE
{ LSTRKEY( "auth" ), LFUNCVAL( net_cert_auth ) },
#endif
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE net_dns_map[] = {
{ LSTRKEY( "setdnsserver" ), LFUNCVAL( net_setdnsserver ) },
{ LSTRKEY( "getdnsserver" ), LFUNCVAL( net_getdnsserver ) },
@ -1552,6 +1757,9 @@ static const LUA_REG_TYPE net_map[] = {
{ LSTRKEY( "multicastJoin"), LFUNCVAL( net_multicastJoin ) },
{ LSTRKEY( "multicastLeave"), LFUNCVAL( net_multicastLeave ) },
{ LSTRKEY( "dns" ), LROVAL( net_dns_map ) },
#ifdef CLIENT_SSL_ENABLE
{ LSTRKEY( "cert" ), LROVAL(net_cert_map) },
#endif
{ LSTRKEY( "TCP" ), LNUMVAL( TCP ) },
{ LSTRKEY( "UDP" ), LNUMVAL( UDP ) },
{ LSTRKEY( "__metatable" ), LROVAL( net_map ) },

View File

@ -286,3 +286,100 @@ Sets the IP of the DNS server used to resolve hostnames. Default: resolver1.open
#### See also
[`net.dns:getdnsserver()`](#netdnsgetdnsserver)
# net.cert Module
This controls certificate verification when SSL is in use.
## net.cert.verify()
Controls the vertificate verification process when the Nodemcu makes a secure connection.
#### Syntax
`net.cert.verify(enable)`
`net.cert.verify(pemdata)`
#### Parameters
- `enable` A boolean which indicates whether verification should be enabled or not. The default at boot is `false`.
- `pemdata` A string containing the CA certificate to use for verification.
#### Returns
`true` if it worked.
Can throw a number of errors if invalid data is supplied.
#### Example
Make a secure https connection and verify that the certificate chain is valid.
```
net.cert.verify(true)
http.get("https://example.com/info", nil, function (code, resp) print(code, resp) end)
```
Load a certificate into the flash chip and make a request. This is the [startssl](https://startssl.com) root certificate. They provide free
certificates.
```
net.cert.verify([[
-----BEGIN CERTIFICATE-----
MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
-----END CERTIFICATE-----
]])
http.get("https://pskreporter.info/gen404", nil, function (code, resp) print(code, resp) end)
```
#### Notes
The certificate needed for verification is stored in the flash chip. The `net.cert.verify` call with `true`
enables verification against the value stored in the flash.
The certificate can be loaded into the flash chip in two ways -- one at firmware build time, and the other at initial boot
of the firmware. In order to load the certificate at build time, just place a file containing the CA certificate (in PEM format)
at `server-ca.crt` in the root of the nodemcu-firmware build tree. The build scripts will incorporate this into the resulting
firmware image.
The alternative approach is easier for development, and that is to supply the PEM data as a string value to `net.cert.verify`. This
will store the certificate into the flash chip and turn on verification for that certificate. Subsequent boots of the nodemcu can then
use `net.cert.verify(true)` and use the stored certificate.

View File

@ -71,9 +71,11 @@ SECTIONS
_dport0_data_end = ABSOLUTE(.);
} >dport0_0_seg :dport0_0_phdr
.irom0.text : ALIGN(4)
.irom0.text : ALIGN(0x1000)
{
_irom0_text_start = ABSOLUTE(.);
*(.servercert.flash)
*(.clientcert.flash)
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
*(.literal.* .text.*)
*(.rodata*)
@ -95,7 +97,7 @@ SECTIONS
_irom0_text_end = ABSOLUTE(.);
_flash_used_end = ABSOLUTE(.);
} >irom0_0_seg :irom0_0_phdr
} >irom0_0_seg :irom0_0_phdr =0xffffffff
.data : ALIGN(4)
{

3
tools/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
TLS.*
private_key.h
cert.h

42
tools/make_cert.py Normal file
View File

@ -0,0 +1,42 @@
import os
class Cert(object):
def __init__(self, name, buff):
self.name = name
self.len = len(buff)
self.buff = buff
pass
def __str__(self):
out_str = ['\0']*32
for i in range(len(self.name)):
out_str[i] = self.name[i]
out_str = "".join(out_str)
out_str += str(chr(self.len & 0xFF))
out_str += str(chr((self.len & 0xFF00) >> 8))
out_str += self.buff
return out_str
pass
def main():
cert_list = []
file_list = os.listdir(os.getcwd())
cert_file_list = []
for _file in file_list:
pos = _file.find(".cer")
if pos != -1:
cert_file_list.append(_file[:pos])
for cert_file in cert_file_list:
with open(cert_file+".cer", 'rb') as f:
buff = f.read()
cert_list.append(Cert(cert_file, buff))
with open('esp_ca_cert.bin', 'wb+') as f:
for _cert in cert_list:
f.write("%s" % _cert)
pass
if __name__ == '__main__':
main()

69
tools/make_server_cert.py Normal file
View File

@ -0,0 +1,69 @@
import os
import argparse
import base64
import re
import sys
class Cert(object):
def __init__(self, name, buff):
self.name = name
self.len = len(buff)
self.buff = buff
pass
def __str__(self):
out_str = ['\0']*32
for i in range(len(self.name)):
out_str[i] = self.name[i]
out_str = "".join(out_str)
out_str += str(chr(self.len & 0xFF))
out_str += str(chr((self.len & 0xFF00) >> 8))
out_str += self.buff
return out_str
def main():
parser = argparse.ArgumentParser(description='Convert PEM file(s) into C source file.')
parser.add_argument('--section',
default='.servercert.flash',
help='specify the section for the data (default is .servercert.flash)')
parser.add_argument('--name',
default='net_server_cert_area',
help='specify the variable name for the data (default is net_server_cert_area)')
parser.add_argument('file', nargs='+',
help='One or more PEM files')
args = parser.parse_args()
cert_list = []
cert_file_list = []
for cert_file in args.file:
with open(cert_file, 'r') as f:
buff = f.read()
m = re.search(r"-----BEGIN ([A-Z ]+)-----([^-]+?)-----END \1-----", buff, flags=re.DOTALL)
if not m:
sys.exit("Input file was not in PEM format")
if "----BEGIN" in buff[m.end(0):]:
sys.exit("Input file contains more than one PEM object")
cert_list.append(Cert(m.group(1), base64.b64decode(''.join(m.group(2).split()))))
print '__attribute__((section("%s"))) unsigned char %s[INTERNAL_FLASH_SECTOR_SIZE] = {' % (args.section, args.name)
for _cert in cert_list:
col = 0
for ch in str(_cert):
print ("0x%02x," % ord(ch)),
if col & 15 == 15:
print
col = col + 1
print '\n0xff};\n'
if __name__ == '__main__':
main()

89
tools/makefile.sh Executable file → Normal file
View File

@ -1,11 +1,92 @@
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the axTLS project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# Generate the certificates and keys for testing.
#
PROJECT_NAME="Nodemcu Project"
# Generate the openssl configuration files.
cat > ca_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Dodgy Certificate Authority
EOF
cat > certs.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME
CN = Nodemcu Client cert
EOF
cat > device_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Device Certificate
EOF
# private key generation
openssl genrsa -out TLS.ca_key.pem 2048
openssl genrsa -out TLS.key_2048.pem 2048
# convert private keys into DER format
openssl rsa -in TLS.key_2048.pem -out TLS.key_2048 -outform DER
# cert requests
openssl req -out TLS.ca_x509.req -sha256 -key TLS.ca_key.pem -new \
-config ./ca_cert.conf
openssl req -out TLS.x509_2048.req -sha256 -key TLS.key_2048.pem -new \
-config ./certs.conf
# generate the actual certs.
openssl x509 -req -in TLS.ca_x509.req -sha256 -out TLS.ca_x509.pem \
-sha1 -days 5000 -signkey TLS.ca_key.pem
openssl x509 -req -in TLS.x509_2048.req -sha256 -out TLS.x509_2048.pem \
-sha1 -CAcreateserial -days 5000 \
-CA TLS.ca_x509.pem -CAkey TLS.ca_key.pem
# some cleanup
rm TLS*.req
rm *.conf
openssl x509 -in TLS.ca_x509.pem -outform DER -out TLS.ca_x509.cer
openssl x509 -in TLS.x509_2048.pem -outform DER -out TLS.x509_2048.cer
#
# Generate the certificates and keys for encrypt.
#
# set default cert for use in the client
xxd -i client.cer | sed -e \
"s/client_cer/default_certificate/" > cert.h
xxd -i TLS.x509_2048.cer | sed -e \
"s/TLS_x509_2048_cer/default_certificate/" > cert.h
# set default key for use in the server
xxd -i server.key_1024 | sed -e \
"s/server_key_1024/default_private_key/" > private_key.h
xxd -i TLS.key_2048 | sed -e \
"s/TLS_key_2048/default_private_key/" > private_key.h