From 3661c54000182992d486cc8645c4979bd4744eeb Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 30 Aug 2015 13:39:31 +0300 Subject: [PATCH 01/29] Add makefile --- .gitignore | 5 +++ Makefile | 69 ++++++++++++++++++++++++++++++++++++++++ Makefile.local.template | 3 ++ crypto/aes.o | Bin 35312 -> 0 bytes crypto/bigint.o | Bin 94704 -> 0 bytes crypto/hmac.o | Bin 10444 -> 0 bytes crypto/md2.o | Bin 9808 -> 0 bytes crypto/md5.o | Bin 19348 -> 0 bytes crypto/rc4.o | Bin 6232 -> 0 bytes crypto/rsa.o | Bin 25612 -> 0 bytes crypto/sha1.o | Bin 13688 -> 0 bytes ssl/asn1.o | Bin 48176 -> 0 bytes ssl/gen_cert.o | Bin 828 -> 0 bytes ssl/loader.o | Bin 38320 -> 0 bytes ssl/os_port.o | Bin 13424 -> 0 bytes ssl/p12.o | Bin 1812 -> 0 bytes 16 files changed, 77 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 Makefile.local.template delete mode 100644 crypto/aes.o delete mode 100644 crypto/bigint.o delete mode 100644 crypto/hmac.o delete mode 100644 crypto/md2.o delete mode 100644 crypto/md5.o delete mode 100644 crypto/rc4.o delete mode 100644 crypto/rsa.o delete mode 100644 crypto/sha1.o delete mode 100644 ssl/asn1.o delete mode 100644 ssl/gen_cert.o delete mode 100644 ssl/loader.o delete mode 100644 ssl/os_port.o delete mode 100644 ssl/p12.o diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..03ba8b58a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +bin/ +Makefile.local +.DS_Store + diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..3af715f09 --- /dev/null +++ b/Makefile @@ -0,0 +1,69 @@ +include Makefile.local + +TOOLCHAIN_PREFIX := xtensa-lx106-elf- +CC := $(TOOLCHAIN_PREFIX)gcc +AR := $(TOOLCHAIN_PREFIX)ar +LD := $(TOOLCHAIN_PREFIX)gcc +OBJCOPY := $(TOOLCHAIN_PREFIX)objcopy + + +XTENSA_LIBS ?= $(shell $(CC) -print-sysroot) + + +OBJ_FILES := \ + crypto/aes.o \ + crypto/bigint.o \ + crypto/hmac.o \ + crypto/md2.o \ + crypto/md5.o \ + crypto/rc4.o \ + crypto/rsa.o \ + crypto/sha1.o \ + ssl/asn1.o \ + ssl/gen_cert.o \ + ssl/loader.o \ + ssl/os_port.o \ + ssl/p12.o \ + ssl/tls1.o \ + ssl/tls1_clnt.o \ + ssl/tls1_svr.o \ + ssl/x509.o \ + crypto/crypto_misc.o \ + + +CPPFLAGS += -I$(XTENSA_LIBS)/include \ + -I$(SDK_BASE)/include \ + -Icrypto \ + -Issl + +LDFLAGS += -L$(XTENSA_LIBS)/lib \ + -L$(XTENSA_LIBS)/arch/lib \ + -L$(SDK_BASE)/lib + +CFLAGS+=-std=c99 -DESP8266 + +CFLAGS += -Os -g -O2 -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mno-text-section-literals -D__ets__ -DICACHE_FLASH +BIN_DIR := bin +AXTLS_AR := $(BIN_DIR)/libaxtls.a + +all: $(AXTLS_AR) + +$(AXTLS_AR): | $(BIN_DIR) + +$(AXTLS_AR): $(OBJ_FILES) + for file in $(OBJ_FILES); do \ + $(OBJCOPY) \ + --rename-section .text=.irom0.text \ + --rename-section .literal=.irom0.literal \ + $$file; \ + done + $(AR) cru $@ $^ + +$(BIN_DIR): + mkdir -p $(BIN_DIR) + +clean: + rm -rf $(OBJ_FILES) $(LWIP_AR) + + +.PHONY: all clean diff --git a/Makefile.local.template b/Makefile.local.template new file mode 100644 index 000000000..937027f99 --- /dev/null +++ b/Makefile.local.template @@ -0,0 +1,3 @@ +# Set this to SDK path and save as Makefile.local +SDK_BASE := $(HOME)/esp8266/sdk + diff --git a/crypto/aes.o b/crypto/aes.o deleted file mode 100644 index 2d10e6d61b32126958a595851154435673e62722..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35312 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 A^8f$< diff --git a/crypto/hmac.o b/crypto/hmac.o deleted file mode 100644 index 69cf2c4ffaf1b84ac3c043ffcfffe464d200d0bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10444 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 diff --git a/crypto/md5.o b/crypto/md5.o deleted file mode 100644 index 3bb00b7a4309c39bc8e25351f7642c3b8f4a74bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19348 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 diff --git a/crypto/rc4.o b/crypto/rc4.o deleted file mode 100644 index 104525ceec999c31adb503b09319f55875470aae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6232 zcma)=YiwM_6~|}pKD_Jo+XNDvs_XD*9_+4dg^&aS#CC|CLQ;R9`&Dxw%g2viDEMMYcGRstz%(^jnztyDlNAQePu`9LW}w5dq{|G6{k zV?b(;GjfTaagNXsuijsGSsVvdi92f z);y}#?_aY+b*!0u|DO$!RQ#D&^ey@12~QoUR_fHD>7$be5Bi4|&eW-n(KEg3#7?;G zyh1lbe*DlYjqf35+Y9f#()p|IcUoWa)VQZNR32Z^cgxx1FFug$xcB&R|Lafm)T^x~ z$f;-IYU|&g*`?li)bANoPhRs-SoMTd*OsoHe$~Y#qKM4H;Oima& zp87^S&0Kw#I^@|PQ=X3Ypup3yMp!&AlAz|*rJ#kvkwVE=Ubyb3EQ>`r3tp`59J6p_ z9X-Q!ZyT+ygPD$fj4b>*9-;MD;TiF?H}(`DIHUneUp0r>vF7jy)E4%$Im~D43KkEz70?eSOrHkW zCp}a@Q=LL7d-NQf>&tUKR7QLiYMbfez;@tyBzAHa6;3Ie-ff!xVk5@5n{8EKZ^Q_V z@;xf(uTg$aW!x(7LqX%M`iiFZM5w8wsa3Z{TQ0#&Uak^}>tVvWSd3wvE>@wYt%++B zgY8(UcAbb&(NLm|DijM!c&h5O9&D#Q)~N>DGqA+d`i50Otq@)w_x=^^sat z4=pEzx>Dgh)|&L7Hf~(z+$2<#HaDZ!>|4u~Xcja6nT=vLMNl+pgu7X*A!gh)A+>PV zqA9?m9?9%>)wRf+TNl2a$ZkN2s)|}rs~5@rNOjPX6}4uO3WGTZU`<%rLpTF;jpMx?{YG6yPJjWT--DWvA~BEf|- zCD4_+9f@(+apvDds#89i99g|cSZple6LEyk`09P_;ha)QG2f&A_U2m4#WqtTLn3e5INxOjXKk2PNt3>};m5T=MfJRNIw3 zlFdw`(jD1K-UZ2(XB=kya=BQ|%)`5yO%><6yEdir#mP?_3Z-0eZX%EA%WX{OFo7!Q zbb6Xx^(SzNgUtj)%rmq>hr)4;E~MiT^Tc~5ucUR z-T)4n`d?v9)C!_3MVvSGdSj0n&u~0m^K|~KduKdq+m6!P_5!VaqCXy^7~5U7-g>nf zrnk0+i*hvHg81=xGoHpXbc}5Uy+t%Eb}(I;VEX1t)xuOMKatE~ZB(&bno8D8d>dA$ z%N2jQY3I$O$-d;q^yYL=GBv|0xoojm1((VxKR@rMs@N!naw%0T`1wkfMN`StUSxYw z11q#Gw`EH*H3|1ZsaPoGQJ1?Kf&imLJ`EIqWYo@cG?lCr{zj+KjFC5ML z3$yuPP{xk~GUFWT+c?%Yvd@l=W?Ia|7^>#|x!ItinFKjS`O=h+lfJXBZ)w>8<-!Ms@F{FKFSC0*rCd+Dcc*ofG-r>D_Mn`sx?HL@|F|>Wp z@V2h{?Y)EBx_MVy39k(xxVnQY{34jvAax>LX1O0Z*45Z~!BS$V%gggpBpw0YHrFGu zE-#B#%kEZ)L09SO!i=9CNA6dGeA-bZU(BYtv?@K3^|LBHUahLMu}L6f^X`MPvW`{gZ4U5ET)B-UqH1JadN=cg&A^zUxu>>u|9%h(X5>x8 zdjo}xSBK={jeuPpIqIw*)ETTYxfSY zY^Hai8m3;lD!EdB_7^8_o- z?>YyF z3O-1-ZB3GG{6kGM)1pm-xADU<*uI`gBut3nPWENn0JKZ zq+sqVXLoxECUdVk`!&MnTERO7?-smI@RtP73ibuxDfqbHdj#Jv__W|h1V1kLNx{zv z=00)bIxCoa#@SyL{F>mm1ivHrykK6OE>09{_k(#~k$HBDmig}B-k^OHJa3ujn0tfv+rW2Qz8(CajV!79ua&{a8dAo0Urm0#Q*>R diff --git a/crypto/rsa.o b/crypto/rsa.o deleted file mode 100644 index 320410453e6cc58e9a49c78d923a2f93303eb47c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25612 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 An*aa+ diff --git a/ssl/asn1.o b/ssl/asn1.o deleted file mode 100644 index 7f8f449c11af05a9cbd3901e0328945bdcecc67b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48176 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 i=ChFHm5MojV vCMH2%N!fA?@n?^V~EdL)ENaHa8 diff --git a/ssl/gen_cert.o b/ssl/gen_cert.o deleted file mode 100644 index d31834c7a965f77cc907f6522e6a8bbeb4d37f31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 828 zcma)4O-sW-5S^I%RXyn0OY~v|UDDEn2tBkVmO@alt?0#&##jq&0?i8btb&oFqDq zCnpyjtEy_YvX88~I#o5=hT8(U(~SG(cSORylyx7l%;8!D% yexfB7>m~a9k~&B8*92J?Z^F8GB5S@)4wF`Mfz14Q1&gxDlNyDQ7lbpd0{R9ra6;1n diff --git a/ssl/loader.o b/ssl/loader.o deleted file mode 100644 index 17758504edd98f44158f57f73a8403e39913fddd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38320 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%0D-mkXXHxLz>-!;DFH znc$UzZx(!~;Clo=Ab7LjCj|4ko=J=U(8lnqg8Bb#jQoh;j|86-{H5Sig83ZK*f}FO z0?)sUoX-ah#|VxU+*NQ7!O4RA3C6Jx2)o|!F;A^?8FN0D!7MWKHoI@=J_U;W2`|!o-25yVE&sr6PM3D4F?4C|J50JjbQ#S z93x*Qc%|T*1>Y`stziBW9b@M)!A}W(RxtmejnRKq@BzVx1b-m-pMv?nZ;YMq1pgwK zFTEL^7{RfE`Cn^{PG7;eX0x`8rQ)zY!%SS=7yKWrhnV{O7R+yB zxc#IV%irqT7Rvb^BG*aC{3M~hX4X?@&0Ht$uDL(Br)GW+(pPgnnCm38QwY9T^X1?{ znz?2?OmhHSpt%Y>PV+o)iRSs>t2EyTp00T%c!uU%!8Mw11JBcZ2Y9LG4d7LpH-Yce zycxVf^V48{zr+0VeMY|fP2K_Csd+b;-}O+w56pEB@^SDX%_qQo|BdpKV6KOd`CSR$ zg(Js;xgJ7}2lKr+at`=M&HV3^d`FIQuF-lt4o?U3eL2c&z%iQnJ|o|qqx=qVH_iMf zk$jJia()}awGlG^0VLn4BOeCy-EuP5LAg#s=DUqtCn0|UF4WAm&+(f1O~ypc{1)SC z&0OycXy*4CGd1)7FV<=v3g)ll(*79i^ELCkt;L%8e!>l!OTqk}iuwWUTvs8NW4}vt z4fuY|A@C;6T>E@f^BV9In)yuz-(RO4u6^#%%paNGrFlD;@7Ys_-(T<_2$TPc{T{IrRI;o-)TMp{zdbbU^nj5X`jC?j9+F{debX0qnq;8e|Azs%M=3OrCV$6T)F$zZ-qPx~ByTyG&y1s7=!fG2C_ zw;IzlSA+R{l=`#4*J!Qf+u{J7>!@Y9;PzW8U&Twi=iGvD*wt9dl|4b2n42Q{-_b8UxpG7HT2UCFgzuI-Td zZRIDL8^K>`4uQYd%;)>RXy&tc3u_3B%lCr0**rn(%`mTX%sHLcIfi=*=Jkw`^SZ?_ zuUicB`o!>b!8L-L1Ya+BwcvGv9~Qh#@J_*R2tF+MBf(z@{zb44=N^-1o;wZm+-bO< zV4g>fJWuch!BYfR2@VNfB6yWxKF2in`Rvm06M}iJHS+y}4+%adnCDuf|D#}@YmJ=G z77ce3oGh5n6OB%;V4h!%oaa=-6@nWC^SPnXQQsiI&+T?0UoUuzV4g2c+&zL12tFeC zq+njJnz$C`T*JIZHO%W$!@L$X%rBHu&l#RBnAecz-IXT6*9%@P`2PX* CP`p_H diff --git a/ssl/os_port.o b/ssl/os_port.o deleted file mode 100644 index 6c20927b3dc431d559f8956458439137b6d48b39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13424 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 fpJNgyCnGo8Dq)d From 6030371051fb340be1ccf5b7dee883e7e9fcee89 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 31 Aug 2015 09:05:04 +0300 Subject: [PATCH 02/29] Initial compilation fixes --- Makefile | 8 ++++---- ssl/os_port.h | 13 +++++++++++-- ssl/tls1.c | 4 ++++ util/time.h | 11 +++++++++++ 4 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 util/time.h diff --git a/Makefile b/Makefile index 3af715f09..c2c2469f5 100644 --- a/Makefile +++ b/Makefile @@ -28,17 +28,17 @@ OBJ_FILES := \ ssl/tls1_clnt.o \ ssl/tls1_svr.o \ ssl/x509.o \ - crypto/crypto_misc.o \ +# crypto/crypto_misc.o \ CPPFLAGS += -I$(XTENSA_LIBS)/include \ - -I$(SDK_BASE)/include \ -Icrypto \ - -Issl + -Issl \ + -I. LDFLAGS += -L$(XTENSA_LIBS)/lib \ -L$(XTENSA_LIBS)/arch/lib \ - -L$(SDK_BASE)/lib + CFLAGS+=-std=c99 -DESP8266 diff --git a/ssl/os_port.h b/ssl/os_port.h index d63a48ddc..f2195eed7 100644 --- a/ssl/os_port.h +++ b/ssl/os_port.h @@ -62,8 +62,17 @@ extern "C" { #if defined(ESP8266) - - +#include "util/time.h" +#define alloca(size) __builtin_alloca(size) +#define TTY_FLUSH() +#ifdef putc +#undef putc +#endif +#define putc(x, f) ets_putc(x) +#ifdef printf +#undef printf +#endif +#define printf(...) ets_printf(__VA_ARGS__) #elif defined(WIN32) diff --git a/ssl/tls1.c b/ssl/tls1.c index 428c9ea56..2aaeb5b75 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -943,6 +943,7 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt) return NULL; /* its all gone wrong */ } +#ifndef ESP8266 /** * Send a packet over the socket. */ @@ -1004,6 +1005,7 @@ static int send_raw_packet(SSL *ssl, uint8_t protocol) return ret; } +#endif /** * Send an encrypted packet with padding bytes if necessary. @@ -1190,6 +1192,7 @@ static int set_key_block(SSL *ssl, int is_write) return 0; } +#ifndef ESP8266 /** * Read the SSL connection. */ @@ -1385,6 +1388,7 @@ error: return ret; } +#endif /** * Do some basic checking of data and then perform the appropriate handshaking. diff --git a/util/time.h b/util/time.h new file mode 100644 index 000000000..78e37b1d3 --- /dev/null +++ b/util/time.h @@ -0,0 +1,11 @@ +#ifndef TIME_H +#define TIME_H + +struct timeval +{ + time_t tv_sec; + long tv_usec; +}; + + +#endif //TIME_H From 6c91aa10fca36ebee76b13fd36189c1a0dd0bf6b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 31 Aug 2015 09:22:23 +0300 Subject: [PATCH 03/29] Create README.md --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..04779e8de --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +Replacement for Espressif's libssl, kept as close as possible to [axTLS](http://axtls.sourceforge.net/) source. +Currently based on axTLS 1.4.9, will be upgraded to 1.5.3. + +This is not a self-sufficient library. Application has to provide the following symbols (list not complete yet): +``` +malloc +calloc +free +abort +gettimeofday +time +ctime +printf +vprintf +``` + +Additionally, functions for non-blocking TCP socket reads and writes have to be provided (details TBD). + +To build, add xtensa toolchain to your path, and run `make`. + +See [LICENSE](LICENSE) file for axTLS license. From 6095fde37e72933f0f0c38e49d98e5879c8829e2 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 1 Sep 2015 15:59:34 +0300 Subject: [PATCH 04/29] Allocation debugging, reduce SSL structure size. --- Makefile | 4 +-- crypto/crypto_misc.c | 8 +++-- crypto/rsa.c | 4 +-- ssl/config.h | 2 +- ssl/gen_cert.c | 14 +++++--- ssl/os_port.c | 85 +++++++------------------------------------- ssl/os_port.h | 62 ++++++++++++++++++++------------ ssl/tls1.c | 13 ++++--- ssl/tls1.h | 2 +- ssl/x509.c | 4 +-- 10 files changed, 82 insertions(+), 116 deletions(-) diff --git a/Makefile b/Makefile index c2c2469f5..2f9d349bf 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ OBJ_FILES := \ ssl/tls1_clnt.o \ ssl/tls1_svr.o \ ssl/x509.o \ -# crypto/crypto_misc.o \ + crypto/crypto_misc.o \ CPPFLAGS += -I$(XTENSA_LIBS)/include \ @@ -63,7 +63,7 @@ $(BIN_DIR): mkdir -p $(BIN_DIR) clean: - rm -rf $(OBJ_FILES) $(LWIP_AR) + rm -rf $(OBJ_FILES) $(AXTLS_AR) .PHONY: all clean diff --git a/crypto/crypto_misc.c b/crypto/crypto_misc.c index 62eb6fe70..9a85ee82b 100644 --- a/crypto/crypto_misc.c +++ b/crypto/crypto_misc.c @@ -42,7 +42,11 @@ #include "wincrypt.h" #endif -#ifndef WIN32 +#ifdef ESP8266 +#define CONFIG_SSL_SKELETON_MODE 1 +#endif + +#if defined(CONFIG_USE_DEV_URANDOM) static int rng_fd = -1; #elif defined(CONFIG_WIN32_USE_CRYPTO_LIB) static HCRYPTPROV gCryptProv; @@ -146,7 +150,7 @@ EXP_FUNC void STDCALL RNG_custom_init(const uint8_t *seed_buf, int size) */ EXP_FUNC void STDCALL RNG_terminate(void) { -#ifndef WIN32 +#if defined(CONFIG_USE_DEV_URANDOM) close(rng_fd); #elif defined(CONFIG_WIN32_USE_CRYPTO_LIB) CryptReleaseContext(gCryptProv, 0); diff --git a/crypto/rsa.c b/crypto/rsa.c index 143e66add..9d52c062f 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -146,7 +146,7 @@ int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, const int byte_size = ctx->num_octets; int i, size; bigint *decrypted_bi, *dat_bi; - uint8_t *block = (uint8_t *)alloca(byte_size); + uint8_t *block = (uint8_t *)malloc(byte_size); memset(out_data, 0, byte_size); /* initialise */ @@ -182,7 +182,7 @@ int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, /* get only the bit we want */ if (size > 0) memcpy(out_data, &block[i], size); - + free(block); return size ? size : -1; } diff --git a/ssl/config.h b/ssl/config.h index 3404b5be5..1bb1de6df 100644 --- a/ssl/config.h +++ b/ssl/config.h @@ -48,7 +48,7 @@ #define CONFIG_X509_MAX_CA_CERTS 150 #define CONFIG_SSL_MAX_CERTS 3 #undef CONFIG_SSL_CTX_MUTEXING -//#define CONFIG_USE_DEV_URANDOM 1 +#undef CONFIG_USE_DEV_URANDOM #undef CONFIG_WIN32_USE_CRYPTO_LIB #undef CONFIG_OPENSSL_COMPATIBLE #undef CONFIG_PERFORMANCE_TESTING diff --git a/ssl/gen_cert.c b/ssl/gen_cert.c index c2fe381eb..ef223b27b 100644 --- a/ssl/gen_cert.c +++ b/ssl/gen_cert.c @@ -214,14 +214,14 @@ static void gen_utc_time(uint8_t *buf, int *offset) static void gen_pub_key2(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset) { - static const uint8_t pub_key_seq[] = + static const uint8_t pub_key_seq[] = { ASN1_INTEGER, 0x03, 0x01, 0x00, 0x01 /* INTEGER 65537 */ }; int seq_offset; int pub_key_size = rsa_ctx->num_octets; - uint8_t *block = (uint8_t *)alloca(pub_key_size); + uint8_t *block = (uint8_t *)malloc(pub_key_size); int seq_size = pre_adjust_with_size( ASN1_SEQUENCE, &seq_offset, buf, offset); buf[(*offset)++] = ASN1_INTEGER; @@ -236,6 +236,7 @@ static void gen_pub_key2(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset) set_gen_length(pub_key_size, buf, offset); memcpy(&buf[*offset], block, pub_key_size); + free(block); *offset += pub_key_size; memcpy(&buf[*offset], pub_key_seq, sizeof(pub_key_seq)); *offset += sizeof(pub_key_seq); @@ -282,8 +283,8 @@ static void gen_signature(const RSA_CTX *rsa_ctx, const uint8_t *sha_dgst, ASN1_NULL, 0x00, ASN1_OCTET_STRING, 0x14 }; - uint8_t *enc_block = (uint8_t *)alloca(rsa_ctx->num_octets); - uint8_t *block = (uint8_t *)alloca(sizeof(asn1_sig) + SHA1_SIZE); + uint8_t *enc_block = (uint8_t *)malloc(rsa_ctx->num_octets); + uint8_t *block = (uint8_t *)malloc(sizeof(asn1_sig) + SHA1_SIZE); int sig_size; /* add the digest as an embedded asn.1 sequence */ @@ -297,6 +298,8 @@ static void gen_signature(const RSA_CTX *rsa_ctx, const uint8_t *sha_dgst, set_gen_length(sig_size+1, buf, offset); buf[(*offset)++] = 0; /* bit string is multiple of 8 */ memcpy(&buf[*offset], enc_block, sig_size); + free(enc_block); + free(block); *offset += sig_size; } @@ -342,7 +345,7 @@ EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const c { int ret = X509_OK, offset = 0, seq_offset; /* allocate enough space to load a new certificate */ - uint8_t *buf = (uint8_t *)alloca(ssl_ctx->rsa_ctx->num_octets*2 + 512); + uint8_t *buf = (uint8_t *)malloc(ssl_ctx->rsa_ctx->num_octets*2 + 512); uint8_t sha_dgst[SHA1_SIZE]; int seq_size = pre_adjust_with_size(ASN1_SEQUENCE, &seq_offset, buf, &offset); @@ -357,6 +360,7 @@ EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const c memcpy(*cert_data, buf, offset); error: + free(buf); return ret < 0 ? ret : offset; } diff --git a/ssl/os_port.c b/ssl/os_port.c index 6a71000b4..b8a2b19a8 100644 --- a/ssl/os_port.c +++ b/ssl/os_port.c @@ -1,18 +1,18 @@ /* * Copyright (c) 2007, Cameron Rich - * + * * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without + * + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * * Redistributions of source code must retain the above copyright notice, + * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * * 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 + * * 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 @@ -37,17 +37,18 @@ #include #include #include +#include #include "os_port.h" #ifdef WIN32 /** - * gettimeofday() not in Win32 + * gettimeofday() not in Win32 */ EXP_FUNC void STDCALL gettimeofday(struct timeval* t, void* timezone) -{ +{ #if defined(_WIN32_WCE) t->tv_sec = time(NULL); - t->tv_usec = 0; /* 1sec precision only */ + t->tv_usec = 0; /* 1sec precision only */ #else struct _timeb timebuffer; _ftime(&timebuffer); @@ -86,7 +87,7 @@ EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size) RegQueryValueEx(hKey, "Domain", NULL, &datatype, buf, &bufferlength); RegCloseKey(hKey); - return 0; + return 0; } #endif @@ -96,63 +97,3 @@ EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size) static const char * out_of_mem_str = "out of memory"; static const char * file_open_str = "Could not open file \"%s\""; - -/* - * Some functions that call display some error trace and then call abort(). - * This just makes life much easier on embedded systems, since we're - * suffering major trauma... - */ -EXP_FUNC void * STDCALL ax_malloc(size_t s) -{ - void *x; - - if ((x = malloc(s)) == NULL) - exit_now(out_of_mem_str); - - return x; -} - -EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s) -{ - void *x; - - if ((x = realloc(y, s)) == NULL) - exit_now(out_of_mem_str); - - return x; -} - -EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s) -{ - void *x; - - if ((x = calloc(n, s)) == NULL) - exit_now(out_of_mem_str); - - return x; -} - -EXP_FUNC int STDCALL ax_open(const char *pathname, int flags) -{ - int x; - - if ((x = open(pathname, flags)) < 0) - exit_now(file_open_str, pathname); - - return x; -} - -/** - * This is a call which will deliberately exit an application, but will - * display some information before dying. - */ -void exit_now(const char *format, ...) -{ - va_list argp; - - va_start(argp, format); - vfprintf(stderr, format, argp); - va_end(argp); - abort(); -} - diff --git a/ssl/os_port.h b/ssl/os_port.h index f2195eed7..73a0e917b 100644 --- a/ssl/os_port.h +++ b/ssl/os_port.h @@ -1,18 +1,18 @@ /* * Copyright (c) 2007, Cameron Rich - * + * * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without + * + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * * Redistributions of source code must retain the above copyright notice, + * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * * 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 + * * 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 @@ -44,9 +44,6 @@ extern "C" { #include "os_int.h" #include - - - #ifdef WIN32 #define STDCALL __stdcall #define EXP_FUNC __declspec(dllexport) @@ -63,7 +60,8 @@ extern "C" { #if defined(ESP8266) #include "util/time.h" -#define alloca(size) __builtin_alloca(size) +#include +// #define alloca(size) __builtin_alloca(size) #define TTY_FLUSH() #ifdef putc #undef putc @@ -74,6 +72,15 @@ extern "C" { #endif #define printf(...) ets_printf(__VA_ARGS__) +#define SOCKET_READ(A,B,C) ax_port_read(A,B,C) +#define SOCKET_WRITE(A,B,C) ax_port_write(A,B,C) +#define SOCKET_CLOSE(A) ax_port_close(A) +#define get_file ax_get_file +#define EWOULDBLOCK EAGAIN + +#define hmac_sha1 ax_hmac_sha1 +#define hmac_md5 ax_hmac_md5 + #elif defined(WIN32) /* Windows CE stuff */ @@ -122,7 +129,7 @@ extern "C" { /* This fix gets around a problem where a win32 application on a cygwin xterm doesn't display regular output (until a certain buffer limit) - but it works - fine under a normal DOS window. This is a hack to get around the issue - + fine under a normal DOS window. This is a hack to get around the issue - see http://www.khngai.com/emacs/tty.php */ #define TTY_FLUSH() if (!_isatty(_fileno(stdout))) fflush(stdout); @@ -161,16 +168,27 @@ EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size); #endif /* Not Win32 */ /* some functions to mutate the way these work */ -#define malloc(A) ax_malloc(A) +#define malloc(A) ax_port_malloc(A, __FILE__, __LINE__) #ifndef realloc -#define realloc(A,B) ax_realloc(A,B) +#define realloc(A,B) ax_port_realloc(A,B, __FILE__, __LINE__) #endif -#define calloc(A,B) ax_calloc(A,B) +#define calloc(A,B) ax_port_calloc(A,B, __FILE__, __LINE__) +#define free(x) ax_port_free(x) -EXP_FUNC void * STDCALL ax_malloc(size_t s); -EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s); -EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s); -EXP_FUNC int STDCALL ax_open(const char *pathname, int flags); +EXP_FUNC void * STDCALL ax_port_malloc(size_t s, const char*, int); +EXP_FUNC void * STDCALL ax_port_realloc(void *y, size_t s, const char*, int); +EXP_FUNC void * STDCALL ax_port_calloc(size_t n, size_t s, const char*, int); +EXP_FUNC void * STDCALL ax_port_free(void*); +EXP_FUNC int STDCALL ax_open(const char *pathname, int flags); + +inline uint32_t htonl(uint32_t n){ + return ((n & 0xff) << 24) | + ((n & 0xff00) << 8) | + ((n & 0xff0000UL) >> 8) | + ((n & 0xff000000UL) >> 24); +} + +#define ntohl htonl #ifdef CONFIG_PLATFORM_LINUX void exit_now(const char *format, ...) __attribute((noreturn)); @@ -186,7 +204,7 @@ void exit_now(const char *format, ...); #define SSL_CTX_MUTEX_DESTROY(A) CloseHandle(A) #define SSL_CTX_LOCK(A) WaitForSingleObject(A, INFINITE) #define SSL_CTX_UNLOCK(A) ReleaseMutex(A) -#else +#else #include #define SSL_CTX_MUTEX_TYPE pthread_mutex_t #define SSL_CTX_MUTEX_INIT(A) pthread_mutex_init(&A, NULL) @@ -205,4 +223,4 @@ void exit_now(const char *format, ...); } #endif -#endif +#endif diff --git a/ssl/tls1.c b/ssl/tls1.c index 2aaeb5b75..a5b9f014f 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -647,7 +647,7 @@ static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header, const uint8_t *buf, int buf_len, uint8_t *hmac_buf) { int hmac_len = buf_len + 8 + SSL_RECORD_SIZE; - uint8_t *t_buf = (uint8_t *)alloca(hmac_len+10); + uint8_t *t_buf = (uint8_t *)malloc(hmac_len+10); memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ? ssl->write_sequence : ssl->read_sequence, 8); @@ -659,6 +659,7 @@ static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header, ssl->server_mac : ssl->client_mac, ssl->cipher_info->digest_size, hmac_buf); + free(t_buf); #if 0 print_blob("record", hmac_header, SSL_RECORD_SIZE); print_blob("buf", buf, buf_len); @@ -943,7 +944,6 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt) return NULL; /* its all gone wrong */ } -#ifndef ESP8266 /** * Send a packet over the socket. */ @@ -980,7 +980,7 @@ static int send_raw_packet(SSL *ssl, uint8_t protocol) #endif return SSL_ERROR_CONN_LOST; } - +#ifndef ESP8266 /* keep going until the write buffer has some space */ if (sent != pkt_size) { @@ -992,6 +992,7 @@ static int send_raw_packet(SSL *ssl, uint8_t protocol) if (select(ssl->client_fd + 1, NULL, &wfds, NULL, NULL) < 0) return SSL_ERROR_CONN_LOST; } +#endif } SET_SSL_FLAG(SSL_NEED_RECORD); /* reset for next time */ @@ -1005,7 +1006,6 @@ static int send_raw_packet(SSL *ssl, uint8_t protocol) return ret; } -#endif /** * Send an encrypted packet with padding bytes if necessary. @@ -1075,11 +1075,12 @@ int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length) ssl->cipher_info->iv_size) { uint8_t iv_size = ssl->cipher_info->iv_size; - uint8_t *t_buf = alloca(msg_length + iv_size); + uint8_t *t_buf = malloc(msg_length + iv_size); memcpy(t_buf + iv_size, ssl->bm_data, msg_length); get_random(iv_size, t_buf); msg_length += iv_size; memcpy(ssl->bm_data, t_buf, msg_length); + free(t_buf); } /* now encrypt the packet */ @@ -1192,7 +1193,6 @@ static int set_key_block(SSL *ssl, int is_write) return 0; } -#ifndef ESP8266 /** * Read the SSL connection. */ @@ -1388,7 +1388,6 @@ error: return ret; } -#endif /** * Do some basic checking of data and then perform the appropriate handshaking. diff --git a/ssl/tls1.h b/ssl/tls1.h index 414a17343..4dcb9b503 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -75,7 +75,7 @@ extern "C" { #define IS_SET_SSL_FLAG(A) (ssl->flag & A) #define MAX_KEY_BYTE_SIZE 512 /* for a 4096 bit key */ -#define RT_MAX_PLAIN_LENGTH 16384 +#define RT_MAX_PLAIN_LENGTH 4096 #define RT_EXTRA 1024 #define BM_RECORD_OFFSET 5 diff --git a/ssl/x509.c b/ssl/x509.c index cb007fbbc..0b092111f 100644 --- a/ssl/x509.c +++ b/ssl/x509.c @@ -270,7 +270,7 @@ static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, int i, size; bigint *decrypted_bi, *dat_bi; bigint *bir = NULL; - uint8_t *block = (uint8_t *)alloca(sig_len); + uint8_t *block = (uint8_t *)malloc(sig_len); /* decrypt */ dat_bi = bi_import(ctx, sig, sig_len); @@ -297,7 +297,7 @@ static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, bir = bi_import(ctx, sig_ptr, len); } } - + free(block); /* save a few bytes of memory */ bi_clear_cache(ctx); return bir; From ad9780684a698fad10baad7c1720d214d17ef2a9 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 14 Sep 2015 08:51:13 +0300 Subject: [PATCH 05/29] Calculate SHA-1 fingerprint when loading the certificate --- ssl/crypto_misc.h | 1 + ssl/x509.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/ssl/crypto_misc.h b/ssl/crypto_misc.h index 1fd514eeb..5b08d36e4 100644 --- a/ssl/crypto_misc.h +++ b/ssl/crypto_misc.h @@ -76,6 +76,7 @@ struct _x509_ctx uint8_t sig_type; RSA_CTX *rsa_ctx; bigint *digest; + bigint *fingerprint; struct _x509_ctx *next; }; diff --git a/ssl/x509.c b/ssl/x509.c index 0b092111f..7402a4d79 100644 --- a/ssl/x509.c +++ b/ssl/x509.c @@ -119,6 +119,13 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) bi_ctx = x509_ctx->rsa_ctx->bi_ctx; + SHA1_CTX sha_fp_ctx; + uint8_t sha_fp_dgst[SHA1_SIZE]; + SHA1_Init(&sha_fp_ctx); + SHA1_Update(&sha_fp_ctx, &cert[0], cert_size); + SHA1_Final(sha_fp_dgst, &sha_fp_ctx); + x509_ctx->fingerprint = bi_import(bi_ctx, sha_fp_dgst, SHA1_SIZE); + #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ /* use the appropriate signature algorithm (SHA1/MD5/MD2) */ if (x509_ctx->sig_type == SIG_TYPE_MD5) @@ -245,6 +252,11 @@ void x509_free(X509_CTX *x509_ctx) bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest); } + if (x509_ctx->fingerprint) + { + bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->fingerprint); + } + if (x509_ctx->subject_alt_dnsnames) { for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i) From a069bc0eb6523aaf2f53031d5f93a50f42b64a58 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 14 Sep 2015 10:24:51 +0300 Subject: [PATCH 06/29] Add function to match certificate fingerprint --- ssl/ssl.h | 9 +++++++++ ssl/tls1.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/ssl/ssl.h b/ssl/ssl.h index 198efc689..97e87d495 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -371,6 +371,15 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code); */ EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl); +/** + * @brief Check if certificate fingerprint (SHA1) matches the one given. + * + * @param ssl [in] An SSL object reference. + * @param fp [in] SHA1 fingerprint to match against + * @return SSL_OK if the certificate is verified. + */ +EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp); + /** * @brief Retrieve an X.509 distinguished name component. * diff --git a/ssl/tls1.c b/ssl/tls1.c index a5b9f014f..c2895ea5f 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -1887,6 +1887,15 @@ error: return ret; } +EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp) +{ + uint8_t cert_fp[SHA1_SIZE]; + X509_CTX* x509 = ssl->x509_ctx; + + bi_export(x509->rsa_ctx->bi_ctx, x509->fingerprint, cert_fp, SHA1_SIZE); + return memcmp(cert_fp, fp, SHA1_SIZE); +} + #endif /* CONFIG_SSL_CERT_VERIFICATION */ /** From 6f48f0d11462dba88aa14e0fcd5b5c6abdb5e660 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 18 Sep 2015 12:38:27 +0300 Subject: [PATCH 07/29] Store fingerprint as raw byte array --- ssl/crypto_misc.h | 2 +- ssl/tls1.c | 3 +-- ssl/x509.c | 7 +++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ssl/crypto_misc.h b/ssl/crypto_misc.h index 5b08d36e4..0201f5b5e 100644 --- a/ssl/crypto_misc.h +++ b/ssl/crypto_misc.h @@ -76,7 +76,7 @@ struct _x509_ctx uint8_t sig_type; RSA_CTX *rsa_ctx; bigint *digest; - bigint *fingerprint; + uint8_t *fingerprint; struct _x509_ctx *next; }; diff --git a/ssl/tls1.c b/ssl/tls1.c index c2895ea5f..f0b527676 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -1892,8 +1892,7 @@ EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp) uint8_t cert_fp[SHA1_SIZE]; X509_CTX* x509 = ssl->x509_ctx; - bi_export(x509->rsa_ctx->bi_ctx, x509->fingerprint, cert_fp, SHA1_SIZE); - return memcmp(cert_fp, fp, SHA1_SIZE); + return memcmp(x509->fingerprint, fp, SHA1_SIZE); } #endif /* CONFIG_SSL_CERT_VERIFICATION */ diff --git a/ssl/x509.c b/ssl/x509.c index 7402a4d79..a291f2012 100644 --- a/ssl/x509.c +++ b/ssl/x509.c @@ -119,12 +119,11 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) bi_ctx = x509_ctx->rsa_ctx->bi_ctx; + x509_ctx->fingerprint = malloc(SHA1_SIZE); SHA1_CTX sha_fp_ctx; - uint8_t sha_fp_dgst[SHA1_SIZE]; SHA1_Init(&sha_fp_ctx); SHA1_Update(&sha_fp_ctx, &cert[0], cert_size); - SHA1_Final(sha_fp_dgst, &sha_fp_ctx); - x509_ctx->fingerprint = bi_import(bi_ctx, sha_fp_dgst, SHA1_SIZE); + SHA1_Final(x509_ctx->fingerprint, &sha_fp_ctx); #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ /* use the appropriate signature algorithm (SHA1/MD5/MD2) */ @@ -254,7 +253,7 @@ void x509_free(X509_CTX *x509_ctx) if (x509_ctx->fingerprint) { - bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->fingerprint); + free(x509_ctx->fingerprint); } if (x509_ctx->subject_alt_dnsnames) From 10b41c811a486db7df19d6ee967dad33eaa220bb Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 17 Nov 2015 01:50:35 +0300 Subject: [PATCH 08/29] Increase plaintext buffer size after handshake is complete --- ssl/config.h | 2 +- ssl/tls1.c | 77 +++++++++++++++++++++++++++++++++++-------------- ssl/tls1.h | 7 +++-- ssl/tls1_clnt.c | 3 ++ 4 files changed, 65 insertions(+), 24 deletions(-) diff --git a/ssl/config.h b/ssl/config.h index 1bb1de6df..c1764e5ab 100644 --- a/ssl/config.h +++ b/ssl/config.h @@ -46,7 +46,7 @@ #undef CONFIG_SSL_USE_PKCS12 #define CONFIG_SSL_EXPIRY_TIME 24 #define CONFIG_X509_MAX_CA_CERTS 150 -#define CONFIG_SSL_MAX_CERTS 3 +#define CONFIG_SSL_MAX_CERTS 1 #undef CONFIG_SSL_CTX_MUTEXING #undef CONFIG_USE_DEV_URANDOM #undef CONFIG_WIN32_USE_CRYPTO_LIB diff --git a/ssl/tls1.c b/ssl/tls1.c index f0b527676..569d8ad0c 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -273,10 +273,8 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) free(ssl->encrypt_ctx); free(ssl->decrypt_ctx); disposable_free(ssl); -#ifdef CONFIG_SSL_CERT_VERIFICATION - x509_free(ssl->x509_ctx); -#endif - + free(ssl->bm_all_data); + free(ssl->fingerprint); free(ssl); } @@ -315,8 +313,8 @@ EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len) { nw = n; - if (nw > RT_MAX_PLAIN_LENGTH) /* fragment if necessary */ - nw = RT_MAX_PLAIN_LENGTH; + if (nw > ssl->max_plain_length) /* fragment if necessary */ + nw = ssl->max_plain_length; if ((i = send_packet(ssl, PT_APP_PROTOCOL_DATA, &out_data[tot], nw)) <= 0) @@ -564,15 +562,18 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) { SSL *ssl = (SSL *)calloc(1, sizeof(SSL)); ssl->ssl_ctx = ssl_ctx; + ssl->max_plain_length = 1460*4; + ssl->bm_all_data = (uint8_t*) calloc(1, ssl->max_plain_length + RT_EXTRA); ssl->need_bytes = SSL_RECORD_SIZE; /* need a record */ ssl->client_fd = client_fd; ssl->flag = SSL_NEED_RECORD; - ssl->bm_data = ssl->bm_all_data+BM_RECORD_OFFSET; /* space at the start */ + ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET; /* space at the start */ ssl->hs_status = SSL_NOT_OK; /* not connected */ #ifdef CONFIG_ENABLE_VERIFICATION ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx; #endif disposable_new(ssl); + ssl->fingerprint = 0; /* a bit hacky but saves a few bytes of memory */ ssl->flag |= ssl_ctx->options; @@ -646,20 +647,36 @@ static void increment_write_sequence(SSL *ssl) static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header, const uint8_t *buf, int buf_len, uint8_t *hmac_buf) { - int hmac_len = buf_len + 8 + SSL_RECORD_SIZE; - uint8_t *t_buf = (uint8_t *)malloc(hmac_len+10); + const prefix_size = 8 + SSL_RECORD_SIZE; + bool hmac_inplace = (uint32_t)buf - (uint32_t)ssl->bm_data >= prefix_size; + uint8_t tmp[prefix_size]; + int hmac_len = buf_len + prefix_size; + uint8_t *t_buf; + if (hmac_inplace) { + t_buf = buf - prefix_size; + memcpy(tmp, t_buf, prefix_size); + } else { + t_buf = (uint8_t *)malloc(hmac_len+10); + } - memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ? + memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ? ssl->write_sequence : ssl->read_sequence, 8); memcpy(&t_buf[8], hmac_header, SSL_RECORD_SIZE); - memcpy(&t_buf[8+SSL_RECORD_SIZE], buf, buf_len); + if (!hmac_inplace) { + memcpy(&t_buf[8+SSL_RECORD_SIZE], buf, buf_len); + } - ssl->cipher_info->hmac(t_buf, hmac_len, - (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ) ? - ssl->server_mac : ssl->client_mac, + ssl->cipher_info->hmac(t_buf, hmac_len, + (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ) ? + ssl->server_mac : ssl->client_mac, ssl->cipher_info->digest_size, hmac_buf); - free(t_buf); + if (hmac_inplace) { + memcpy(t_buf, tmp, prefix_size); + } + else { + free(t_buf); + } #if 0 print_blob("record", hmac_header, SSL_RECORD_SIZE); print_blob("buf", buf, buf_len); @@ -1272,9 +1289,10 @@ int basic_read(SSL *ssl, uint8_t **in_data) ssl->need_bytes = (buf[3] << 8) + buf[4]; /* do we violate the spec with the message size? */ - if (ssl->need_bytes > RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET) + if (ssl->need_bytes > ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET) { ret = SSL_ERROR_INVALID_PROT_MSG; + printf("ssl->need_bytes=%d > %d\r\n", ssl->need_bytes, ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET); goto error; } @@ -1389,6 +1407,19 @@ error: return ret; } +void increase_bm_data_size(SSL *ssl) +{ + uint8_t* pr = (uint8_t*) realloc(ssl->bm_all_data, RT_MAX_PLAIN_LENGTH + RT_EXTRA); + if (pr) { + ssl->max_plain_length = RT_MAX_PLAIN_LENGTH; + ssl->bm_all_data = pr; + ssl->bm_data = pr + BM_RECORD_OFFSET; + } + else { + printf("failed to grow plain buffer\r\n"); + } +} + /** * Do some basic checking of data and then perform the appropriate handshaking. */ @@ -1643,7 +1674,12 @@ void disposable_free(SSL *ssl) free(ssl->dc); ssl->dc = NULL; } - +#ifdef CONFIG_SSL_CERT_VERIFICATION + if (ssl->x509_ctx) { + x509_free(ssl->x509_ctx); + ssl->x509_ctx = 0; + } +#endif } #ifndef CONFIG_SSL_SKELETON_MODE /* no session resumption in this mode */ @@ -1889,10 +1925,9 @@ error: EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp) { - uint8_t cert_fp[SHA1_SIZE]; - X509_CTX* x509 = ssl->x509_ctx; - - return memcmp(x509->fingerprint, fp, SHA1_SIZE); + if (!ssl->fingerprint) + return 1; + return memcmp(ssl->fingerprint, fp, SHA1_SIZE); } #endif /* CONFIG_SSL_CERT_VERIFICATION */ diff --git a/ssl/tls1.h b/ssl/tls1.h index 4dcb9b503..673c7fa00 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -75,7 +75,7 @@ extern "C" { #define IS_SET_SSL_FLAG(A) (ssl->flag & A) #define MAX_KEY_BYTE_SIZE 512 /* for a 4096 bit key */ -#define RT_MAX_PLAIN_LENGTH 4096 +#define RT_MAX_PLAIN_LENGTH 16384 #define RT_EXTRA 1024 #define BM_RECORD_OFFSET 5 @@ -175,10 +175,11 @@ struct _SSL const cipher_info_t *cipher_info; void *encrypt_ctx; void *decrypt_ctx; - uint8_t bm_all_data[RT_MAX_PLAIN_LENGTH+RT_EXTRA]; + uint8_t *bm_all_data; uint8_t *bm_data; uint16_t bm_index; uint16_t bm_read_index; + size_t max_plain_length; struct _SSL *next; /* doubly linked list */ struct _SSL *prev; struct _SSL_CTX *ssl_ctx; /* back reference to a clnt/svr ctx */ @@ -189,6 +190,7 @@ struct _SSL #ifdef CONFIG_SSL_CERT_VERIFICATION X509_CTX *x509_ctx; #endif + uint8_t* fingerprint; uint8_t session_id[SSL_SESSION_ID_SIZE]; uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */ @@ -260,6 +262,7 @@ void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx); #ifdef CONFIG_SSL_ENABLE_CLIENT int do_client_connect(SSL *ssl); #endif +void increase_bm_data_size(SSL *ssl); #ifdef CONFIG_SSL_FULL_MODE void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok); diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index 196b40ed3..5f2598922 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -119,7 +119,10 @@ int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len) case HS_FINISHED: ret = process_finished(ssl, buf, hs_len); + ssl->fingerprint = ssl->x509_ctx->fingerprint; + ssl->x509_ctx->fingerprint = 0; disposable_free(ssl); /* free up some memory */ + increase_bm_data_size(ssl); /* note: client renegotiation is not allowed after this */ break; From 6830d98c7ff14d8bd667d28c871414d939c1d24d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 17 Nov 2015 02:32:59 +0300 Subject: [PATCH 09/29] Pre-allocate encrypt/decrypt ctx to reduce memory fragmentation --- ssl/tls1.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/ssl/tls1.c b/ssl/tls1.c index 569d8ad0c..19bf86d69 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -50,7 +50,7 @@ static const char * client_finished = "client finished"; static int do_handshake(SSL *ssl, uint8_t *buf, int read_len); static int set_key_block(SSL *ssl, int is_write); static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len); -static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt); +static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void* cached); static int send_raw_packet(SSL *ssl, uint8_t protocol); /** @@ -591,6 +591,9 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) ssl_ctx->tail = ssl; } + ssl->encrypt_ctx = malloc(sizeof(AES_CTX)); + ssl->decrypt_ctx = malloc(sizeof(AES_CTX)); + SSL_CTX_UNLOCK(ssl_ctx->mutex); return ssl; } @@ -917,14 +920,18 @@ void finished_digest(SSL *ssl, const char *label, uint8_t *digest) /** * Retrieve (and initialise) the context of a cipher. */ -static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt) +static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void* cached) { switch (ssl->cipher) { #ifndef CONFIG_SSL_SKELETON_MODE case SSL_AES128_SHA: { - AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX)); + AES_CTX *aes_ctx; + if (cached) + aes_ctx = (AES_CTX*) cached; + else + aes_ctx = (AES_CTX*) malloc(sizeof(AES_CTX)); AES_set_key(aes_ctx, key, iv, AES_MODE_128); if (is_decrypt) @@ -937,7 +944,12 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt) case SSL_AES256_SHA: { - AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX)); + AES_CTX *aes_ctx; + if (cached) + aes_ctx = (AES_CTX*) cached; + else + aes_ctx = (AES_CTX*) malloc(sizeof(AES_CTX)); + AES_set_key(aes_ctx, key, iv, AES_MODE_256); if (is_decrypt) @@ -952,7 +964,12 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt) #endif case SSL_RC4_128_SHA: { - RC4_CTX *rc4_ctx = (RC4_CTX *)malloc(sizeof(RC4_CTX)); + RC4_CTX* rc4_ctx; + if (cached) + rc4_ctx = (RC4_CTX*) cached; + else + rc4_ctx = (RC4_CTX*) malloc(sizeof(RC4_CTX)); + RC4_setup(rc4_ctx, key, 16); return (void *)rc4_ctx; } @@ -1184,7 +1201,7 @@ static int set_key_block(SSL *ssl, int is_write) } #endif - free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx); + // free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx); /* now initialise the ciphers */ if (is_client) @@ -1192,18 +1209,18 @@ static int set_key_block(SSL *ssl, int is_write) finished_digest(ssl, server_finished, ssl->dc->final_finish_mac); if (is_write) - ssl->encrypt_ctx = crypt_new(ssl, client_key, client_iv, 0); + ssl->encrypt_ctx = crypt_new(ssl, client_key, client_iv, 0, ssl->encrypt_ctx); else - ssl->decrypt_ctx = crypt_new(ssl, server_key, server_iv, 1); + ssl->decrypt_ctx = crypt_new(ssl, server_key, server_iv, 1, ssl->decrypt_ctx); } else { finished_digest(ssl, client_finished, ssl->dc->final_finish_mac); if (is_write) - ssl->encrypt_ctx = crypt_new(ssl, server_key, server_iv, 0); + ssl->encrypt_ctx = crypt_new(ssl, server_key, server_iv, 0, ssl->encrypt_ctx); else - ssl->decrypt_ctx = crypt_new(ssl, client_key, client_iv, 1); + ssl->decrypt_ctx = crypt_new(ssl, client_key, client_iv, 1, ssl->decrypt_ctx); } ssl->cipher_info = ciph_info; From 34ff4421d2c5f7386c70d17e2848091c1aa493f3 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 2 Dec 2015 23:49:49 +0300 Subject: [PATCH 10/29] Get random bytes from hardware RNG --- crypto/crypto_misc.c | 63 +++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/crypto/crypto_misc.c b/crypto/crypto_misc.c index 9a85ee82b..a2ea2e367 100644 --- a/crypto/crypto_misc.c +++ b/crypto/crypto_misc.c @@ -1,18 +1,18 @@ /* * Copyright (c) 2007, Cameron Rich - * + * * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without + * + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * * Redistributions of source code must retain the above copyright notice, + * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * * 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 + * * 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 @@ -44,6 +44,7 @@ #ifdef ESP8266 #define CONFIG_SSL_SKELETON_MODE 1 +uint32_t phy_get_rand(); #endif #if defined(CONFIG_USE_DEV_URANDOM) @@ -63,20 +64,20 @@ static uint8_t entropy_pool[ENTROPY_POOL_SIZE]; const char * const unsupported_str = "Error: Feature not supported\n"; #ifndef CONFIG_SSL_SKELETON_MODE -/** +/** * Retrieve a file and put it into memory * @return The size of the file, or -1 on failure. */ int get_file(const char *filename, uint8_t **buf) { int total_bytes = 0; - int bytes_read = 0; + int bytes_read = 0; int filesize; FILE *stream = fopen(filename, "rb"); if (stream == NULL) { -#ifdef CONFIG_SSL_FULL_MODE +#ifdef CONFIG_SSL_FULL_MODE printf("file '%s' does not exist\n", filename); TTY_FLUSH(); #endif return -1; @@ -93,7 +94,7 @@ int get_file(const char *filename, uint8_t **buf) bytes_read = fread(*buf+total_bytes, 1, filesize-total_bytes, stream); total_bytes += bytes_read; } while (total_bytes < filesize && bytes_read > 0); - + fclose(stream); return filesize; } @@ -110,25 +111,26 @@ EXP_FUNC void STDCALL RNG_initialize() #if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM) rng_fd = ax_open("/dev/urandom", O_RDONLY); #elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB) - if (!CryptAcquireContext(&gCryptProv, + if (!CryptAcquireContext(&gCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { if (GetLastError() == NTE_BAD_KEYSET && - !CryptAcquireContext(&gCryptProv, - NULL, - NULL, - PROV_RSA_FULL, + !CryptAcquireContext(&gCryptProv, + NULL, + NULL, + PROV_RSA_FULL, CRYPT_NEWKEYSET)) { printf("CryptoLib: %x\n", unsupported_str, GetLastError()); exit(1); } } +#elif defined(ESP8266) #else /* start of with a stack to copy across */ int i; memcpy(entropy_pool, &i, ENTROPY_POOL_SIZE); - srand((unsigned int)&i); + srand((unsigned int)&i); #endif } @@ -161,15 +163,22 @@ EXP_FUNC void STDCALL RNG_terminate(void) * Set a series of bytes with a random number. Individual bytes can be 0 */ EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data) -{ +{ #if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM) /* use the Linux default */ read(rng_fd, rand_data, num_rand_bytes); /* read from /dev/urandom */ #elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB) /* use Microsoft Crypto Libraries */ CryptGenRandom(gCryptProv, num_rand_bytes, rand_data); +#elif defined(ESP8266) + for (size_t cb = 0; cb < num_rand_bytes; cb += 4) { + uint32_t r = phy_get_rand(); + size_t left = num_rand_bytes - cb; + left = (left < 4) ? left : 4; + memcpy(rand_data + cb, &r, left); + } #else /* nothing else to use, so use a custom RNG */ - /* The method we use when we've got nothing better. Use RC4, time + /* The method we use when we've got nothing better. Use RC4, time and a couple of random seeds to generate a random sequence */ RC4_CTX rng_ctx; struct timeval tv; @@ -179,10 +188,10 @@ EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data) int i; /* A proper implementation would use counters etc for entropy */ - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); ep = (uint64_t *)entropy_pool; ep[0] ^= ENTROPY_COUNTER1; - ep[1] ^= ENTROPY_COUNTER2; + ep[1] ^= ENTROPY_COUNTER2; /* use a digested version of the entropy pool as a key */ MD5_Init(&rng_digest_ctx); @@ -214,8 +223,9 @@ void get_random_NZ(int num_rand_bytes, uint8_t *rand_data) for (i = 0; i < num_rand_bytes; i++) { - while (rand_data[i] == 0) /* can't be 0 */ - rand_data[i] = (uint8_t)(rand()); + while (rand_data[i] == 0) { + get_random(1, rand_data + i); + } } } @@ -267,7 +277,7 @@ static void print_hex(uint8_t hex) * @param data [in] The start of data to use * @param ... [in] Any additional arguments */ -EXP_FUNC void STDCALL print_blob(const char *format, +EXP_FUNC void STDCALL print_blob(const char *format, const uint8_t *data, int size, ...) { int i; @@ -348,7 +358,7 @@ EXP_FUNC int STDCALL base64_decode(const char *in, int len, } /* check that we don't go past the output buffer */ - if (z > *outlen) + if (z > *outlen) goto error; } @@ -368,4 +378,3 @@ error: } #endif - From 155107681689564acb141bff37cf1d4fe1b528e2 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 Dec 2015 17:04:49 +0300 Subject: [PATCH 11/29] Remove default private key and certificate (#3) --- ssl/cert.h | 43 ------------------------------------- ssl/loader.c | 10 ++++----- ssl/private_key.h | 54 ----------------------------------------------- ssl/tls1.c | 4 ++-- 4 files changed, 7 insertions(+), 104 deletions(-) delete mode 100644 ssl/cert.h delete mode 100644 ssl/private_key.h diff --git a/ssl/cert.h b/ssl/cert.h deleted file mode 100644 index 30c7b6588..000000000 --- a/ssl/cert.h +++ /dev/null @@ -1,43 +0,0 @@ -unsigned char default_certificate[] = { - 0x30, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0x40, 0x02, 0x09, 0x00, 0xab, - 0x08, 0x18, 0xa7, 0x03, 0x07, 0x27, 0xfd, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x34, - 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x29, 0x61, - 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x20, 0x44, 0x6f, 0x64, 0x67, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x31, 0x32, - 0x32, 0x36, 0x32, 0x32, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d, 0x32, - 0x34, 0x30, 0x39, 0x30, 0x33, 0x32, 0x32, 0x33, 0x33, 0x33, 0x39, 0x5a, - 0x30, 0x2c, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0d, 0x61, 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, - 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, - 0x81, 0x81, 0x00, 0xcd, 0xfd, 0x89, 0x48, 0xbe, 0x36, 0xb9, 0x95, 0x76, - 0xd4, 0x13, 0x30, 0x0e, 0xbf, 0xb2, 0xed, 0x67, 0x0a, 0xc0, 0x16, 0x3f, - 0x51, 0x09, 0x9d, 0x29, 0x2f, 0xb2, 0x6d, 0x3f, 0x3e, 0x6c, 0x2f, 0x90, - 0x80, 0xa1, 0x71, 0xdf, 0xbe, 0x38, 0xc5, 0xcb, 0xa9, 0x9a, 0x40, 0x14, - 0x90, 0x0a, 0xf9, 0xb7, 0x07, 0x0b, 0xe1, 0xda, 0xe7, 0x09, 0xbf, 0x0d, - 0x57, 0x41, 0x86, 0x60, 0xa1, 0xc1, 0x27, 0x91, 0x5b, 0x0a, 0x98, 0x46, - 0x1b, 0xf6, 0xa2, 0x84, 0xf8, 0x65, 0xc7, 0xce, 0x2d, 0x96, 0x17, 0xaa, - 0x91, 0xf8, 0x61, 0x04, 0x50, 0x70, 0xeb, 0xb4, 0x43, 0xb7, 0xdc, 0x9a, - 0xcc, 0x31, 0x01, 0x14, 0xd4, 0xcd, 0xcc, 0xc2, 0x37, 0x6d, 0x69, 0x82, - 0xd6, 0xc6, 0xc4, 0xbe, 0xf2, 0x34, 0xa5, 0xc9, 0xa6, 0x19, 0x53, 0x32, - 0x7a, 0x86, 0x0e, 0x91, 0x82, 0x0f, 0xa1, 0x42, 0x54, 0xaa, 0x01, 0x02, - 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x40, - 0xb4, 0x94, 0x9a, 0xa8, 0x89, 0x72, 0x1d, 0x07, 0xe5, 0xb3, 0x6b, 0x88, - 0x21, 0xc2, 0x38, 0x36, 0x9e, 0x7a, 0x8c, 0x49, 0x48, 0x68, 0x0c, 0x06, - 0xe8, 0xdb, 0x1f, 0x4e, 0x05, 0xe6, 0x31, 0xe3, 0xfd, 0xe6, 0x0d, 0x6b, - 0xd8, 0x13, 0x17, 0xe0, 0x2d, 0x0d, 0xb8, 0x7e, 0xcb, 0x20, 0x6c, 0xa8, - 0x73, 0xa7, 0xfd, 0xe3, 0xa7, 0xfa, 0xf3, 0x02, 0x60, 0x78, 0x1f, 0x13, - 0x40, 0x45, 0xee, 0x75, 0xf5, 0x10, 0xfd, 0x8f, 0x68, 0x74, 0xd4, 0xac, - 0xae, 0x04, 0x09, 0x55, 0x2c, 0xdb, 0xd8, 0x07, 0x07, 0x65, 0x69, 0x27, - 0x6e, 0xbf, 0x5e, 0x61, 0x40, 0x56, 0x8b, 0xd7, 0x33, 0x3b, 0xff, 0x6e, - 0x53, 0x7e, 0x9d, 0x3f, 0xc0, 0x40, 0x3a, 0xab, 0xa0, 0x50, 0x4e, 0x80, - 0x47, 0x46, 0x0d, 0x1e, 0xdb, 0x4c, 0xf1, 0x1b, 0x5d, 0x3c, 0x2a, 0x54, - 0xa7, 0x4d, 0xfa, 0x7b, 0x72, 0x66, 0xc5 -}; -unsigned int default_certificate_len = 475; diff --git a/ssl/loader.c b/ssl/loader.c index 333fb18e9..9d157f796 100644 --- a/ssl/loader.c +++ b/ssl/loader.c @@ -434,8 +434,8 @@ int load_key_certs(SSL_CTX *ssl_ctx) else if (!(options & SSL_NO_DEFAULT_KEY)) { #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE) - static const /* saves a few more bytes */ -#include "private_key.h" + extern const unsigned char* default_private_key; + extern const unsigned int default_private_key_len; ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key, default_private_key_len, NULL); @@ -462,9 +462,9 @@ int load_key_certs(SSL_CTX *ssl_ctx) else if (!(options & SSL_NO_DEFAULT_KEY)) { #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE) - static const /* saves a few bytes and RAM */ -#include "cert.h" - ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, + extern const unsigned char* default_certificate; + extern const unsigned int default_certificate_len; + ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, default_certificate, default_certificate_len, NULL); #endif } diff --git a/ssl/private_key.h b/ssl/private_key.h deleted file mode 100644 index ce7985c5a..000000000 --- a/ssl/private_key.h +++ /dev/null @@ -1,54 +0,0 @@ -unsigned char default_private_key[] = { - 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xcd, - 0xfd, 0x89, 0x48, 0xbe, 0x36, 0xb9, 0x95, 0x76, 0xd4, 0x13, 0x30, 0x0e, - 0xbf, 0xb2, 0xed, 0x67, 0x0a, 0xc0, 0x16, 0x3f, 0x51, 0x09, 0x9d, 0x29, - 0x2f, 0xb2, 0x6d, 0x3f, 0x3e, 0x6c, 0x2f, 0x90, 0x80, 0xa1, 0x71, 0xdf, - 0xbe, 0x38, 0xc5, 0xcb, 0xa9, 0x9a, 0x40, 0x14, 0x90, 0x0a, 0xf9, 0xb7, - 0x07, 0x0b, 0xe1, 0xda, 0xe7, 0x09, 0xbf, 0x0d, 0x57, 0x41, 0x86, 0x60, - 0xa1, 0xc1, 0x27, 0x91, 0x5b, 0x0a, 0x98, 0x46, 0x1b, 0xf6, 0xa2, 0x84, - 0xf8, 0x65, 0xc7, 0xce, 0x2d, 0x96, 0x17, 0xaa, 0x91, 0xf8, 0x61, 0x04, - 0x50, 0x70, 0xeb, 0xb4, 0x43, 0xb7, 0xdc, 0x9a, 0xcc, 0x31, 0x01, 0x14, - 0xd4, 0xcd, 0xcc, 0xc2, 0x37, 0x6d, 0x69, 0x82, 0xd6, 0xc6, 0xc4, 0xbe, - 0xf2, 0x34, 0xa5, 0xc9, 0xa6, 0x19, 0x53, 0x32, 0x7a, 0x86, 0x0e, 0x91, - 0x82, 0x0f, 0xa1, 0x42, 0x54, 0xaa, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, - 0x02, 0x81, 0x81, 0x00, 0x95, 0xaa, 0x6e, 0x11, 0xf5, 0x6a, 0x8b, 0xa2, - 0xc6, 0x48, 0xc6, 0x7c, 0x37, 0x6b, 0x1f, 0x55, 0x10, 0x76, 0x26, 0x24, - 0xc3, 0xf2, 0x5c, 0x5a, 0xdd, 0x2e, 0xf3, 0xa4, 0x1e, 0xbc, 0x7b, 0x1c, - 0x80, 0x10, 0x85, 0xbc, 0xd8, 0x45, 0x3c, 0xb8, 0xb2, 0x06, 0x53, 0xb5, - 0xd5, 0x7a, 0xe7, 0x0e, 0x92, 0xe6, 0x42, 0xc2, 0xe2, 0x2a, 0xd5, 0xd1, - 0x03, 0x9f, 0x6f, 0x53, 0x74, 0x68, 0x72, 0x8e, 0xbf, 0x03, 0xbb, 0xab, - 0xbd, 0xa1, 0xf9, 0x81, 0x7d, 0x12, 0xd4, 0x9d, 0xb6, 0xae, 0x4c, 0xad, - 0xca, 0xa8, 0xc9, 0x80, 0x8d, 0x0d, 0xd5, 0xd0, 0xa1, 0xbf, 0xec, 0x60, - 0x48, 0x49, 0xed, 0x97, 0x0f, 0x5e, 0xed, 0xfc, 0x39, 0x15, 0x96, 0x9e, - 0x5d, 0xe2, 0xb4, 0x5d, 0x2e, 0x04, 0xdc, 0x08, 0xa2, 0x65, 0x29, 0x2d, - 0x37, 0xfb, 0x62, 0x90, 0x1b, 0x7b, 0xe5, 0x3a, 0x58, 0x05, 0x55, 0xc1, - 0x02, 0x41, 0x00, 0xfc, 0x69, 0x28, 0xc9, 0xa8, 0xc4, 0x5c, 0xe3, 0xd0, - 0x5e, 0xaa, 0xda, 0xde, 0x87, 0x74, 0xdb, 0xcb, 0x40, 0x78, 0x8e, 0x1d, - 0x12, 0x96, 0x16, 0x61, 0x3f, 0xb3, 0x3e, 0xa3, 0x0d, 0xdc, 0x49, 0xa5, - 0x25, 0x87, 0xc5, 0x97, 0x85, 0x9d, 0xbb, 0xb4, 0xf0, 0x44, 0xfd, 0x6c, - 0xe8, 0xd2, 0x8c, 0xec, 0x33, 0x81, 0x46, 0x1e, 0x10, 0x12, 0x33, 0x16, - 0x95, 0x00, 0x4f, 0x75, 0xb4, 0xe5, 0x79, 0x02, 0x41, 0x00, 0xd0, 0xeb, - 0x65, 0x07, 0x10, 0x3b, 0xd9, 0x03, 0xeb, 0xdc, 0x6f, 0x4b, 0x8f, 0xc3, - 0x87, 0xce, 0x76, 0xd6, 0xc5, 0x14, 0x21, 0x4e, 0xe7, 0x4f, 0x1b, 0xe8, - 0x05, 0xf8, 0x84, 0x1a, 0xe0, 0xc5, 0xd6, 0xe3, 0x08, 0xb3, 0x54, 0x57, - 0x02, 0x1f, 0xd4, 0xd9, 0xfb, 0xff, 0x40, 0xb1, 0x56, 0x1c, 0x60, 0xf7, - 0xac, 0x91, 0xf3, 0xd3, 0xc6, 0x7f, 0x84, 0xfd, 0x84, 0x9d, 0xea, 0x26, - 0xee, 0xc9, 0x02, 0x41, 0x00, 0xa6, 0xcf, 0x1c, 0x6c, 0x81, 0x03, 0x1c, - 0x5c, 0x56, 0x05, 0x6a, 0x26, 0x70, 0xef, 0xd6, 0x13, 0xb7, 0x74, 0x28, - 0xf7, 0xca, 0x50, 0xd1, 0x2d, 0x83, 0x21, 0x64, 0xe4, 0xdd, 0x3f, 0x38, - 0xb8, 0xd6, 0xd2, 0x41, 0xb3, 0x1c, 0x9a, 0xea, 0x0d, 0xf5, 0xda, 0xdf, - 0xcd, 0x17, 0x9f, 0x9a, 0x1e, 0x15, 0xaf, 0x48, 0x1c, 0xbd, 0x9b, 0x63, - 0x5b, 0xad, 0xed, 0xd4, 0xa1, 0xae, 0xa9, 0x59, 0x09, 0x02, 0x40, 0x4e, - 0x08, 0xce, 0xa8, 0x8f, 0xc0, 0xba, 0xf3, 0x83, 0x02, 0xc8, 0x33, 0x62, - 0x14, 0x77, 0xc2, 0x7f, 0x93, 0x02, 0xf3, 0xdc, 0xe9, 0x1a, 0xee, 0xea, - 0x8e, 0x84, 0xc4, 0x69, 0x9b, 0x9c, 0x7f, 0x69, 0x1f, 0x4e, 0x1d, 0xa5, - 0x90, 0x06, 0x44, 0x1b, 0x7d, 0xfc, 0x69, 0x40, 0x21, 0xbc, 0xf7, 0x46, - 0xa4, 0xdc, 0x39, 0x7b, 0xe8, 0x8b, 0x49, 0x10, 0x44, 0x9d, 0x67, 0x5a, - 0x91, 0x86, 0x39, 0x02, 0x40, 0x41, 0x2c, 0x4e, 0xfe, 0xd9, 0x90, 0x89, - 0x00, 0x5c, 0x94, 0x0a, 0x4a, 0x7e, 0x1b, 0x1a, 0x80, 0x06, 0x01, 0x37, - 0xda, 0x50, 0x61, 0x9d, 0x9c, 0xfe, 0x25, 0x7f, 0xd8, 0xd4, 0xc4, 0x9e, - 0x81, 0xf2, 0x0c, 0x1e, 0x38, 0x21, 0x1e, 0x90, 0x3f, 0xd4, 0xba, 0x6c, - 0x53, 0xcb, 0xf0, 0x77, 0x79, 0x9b, 0xf1, 0xfa, 0x3f, 0x81, 0xdc, 0xf3, - 0x21, 0x02, 0x6d, 0xb7, 0x95, 0xc3, 0x2e, 0xce, 0xd5 -}; -unsigned int default_private_key_len = 609; diff --git a/ssl/tls1.c b/ssl/tls1.c index 19bf86d69..1f27265c5 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -650,13 +650,13 @@ static void increment_write_sequence(SSL *ssl) static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header, const uint8_t *buf, int buf_len, uint8_t *hmac_buf) { - const prefix_size = 8 + SSL_RECORD_SIZE; + const size_t prefix_size = 8 + SSL_RECORD_SIZE; bool hmac_inplace = (uint32_t)buf - (uint32_t)ssl->bm_data >= prefix_size; uint8_t tmp[prefix_size]; int hmac_len = buf_len + prefix_size; uint8_t *t_buf; if (hmac_inplace) { - t_buf = buf - prefix_size; + t_buf = ((uint8_t*)buf) - prefix_size; memcpy(tmp, t_buf, prefix_size); } else { t_buf = (uint8_t *)malloc(hmac_len+10); From f98cae7b2fb07658ed637cc469b43f1f0b98d5c2 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 Dec 2015 18:44:40 +0300 Subject: [PATCH 12/29] Don't try to load certificate and private key if it is null --- ssl/loader.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ssl/loader.c b/ssl/loader.c index 9d157f796..6c7a6308c 100644 --- a/ssl/loader.c +++ b/ssl/loader.c @@ -436,9 +436,9 @@ int load_key_certs(SSL_CTX *ssl_ctx) #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE) extern const unsigned char* default_private_key; extern const unsigned int default_private_key_len; - - ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key, - default_private_key_len, NULL); + if (default_private_key != NULL && default_private_key_len > 0) + ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key, + default_private_key_len, NULL); #endif } @@ -464,7 +464,8 @@ int load_key_certs(SSL_CTX *ssl_ctx) #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE) extern const unsigned char* default_certificate; extern const unsigned int default_certificate_len; - ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, + if (default_certificate != NULL && default_certificate_len > 0) + ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, default_certificate, default_certificate_len, NULL); #endif } From 514b6685c5a84232caeed72dc5720c652bbe9f73 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 9 Dec 2015 23:39:26 +0300 Subject: [PATCH 13/29] Disable RC4 --- ssl/tls1.c | 40 +++++++--------------------------------- ssl/tls1.h | 2 +- 2 files changed, 8 insertions(+), 34 deletions(-) diff --git a/ssl/tls1.c b/ssl/tls1.c index 1f27265c5..c4a676b10 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -58,18 +58,18 @@ static int send_raw_packet(SSL *ssl, uint8_t protocol); * ciphers are listed. This order is defined at compile time. */ #ifdef CONFIG_SSL_SKELETON_MODE -const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = +const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = { SSL_RC4_128_SHA }; #else static void session_free(SSL_SESSION *ssl_sessions[], int sess_index); -const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = +const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = #ifdef CONFIG_SSL_PROT_LOW /* low security, fast speed */ -{ SSL_RC4_128_SHA, SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_MD5 }; +{ SSL_AES128_SHA, SSL_AES256_SHA}; #elif CONFIG_SSL_PROT_MEDIUM /* medium security, medium speed */ -{ SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 }; +{ SSL_AES128_SHA, SSL_AES256_SHA}; #else /* CONFIG_SSL_PROT_HIGH */ /* high security, low speed */ -{ SSL_AES256_SHA, SSL_AES128_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 }; +{ SSL_AES256_SHA, SSL_AES128_SHA}; #endif #endif /* CONFIG_SSL_SKELETON_MODE */ @@ -108,40 +108,14 @@ static const cipher_info_t cipher_info[NUM_PROTOCOLS] = { /* AES256-SHA */ SSL_AES256_SHA, /* AES256-SHA */ 32, /* key size */ - 16, /* iv size */ + 16, /* iv size */ 2*(SHA1_SIZE+32+16), /* key block size */ 16, /* block padding size */ SHA1_SIZE, /* digest size */ hmac_sha1, /* hmac algorithm */ (crypt_func)AES_cbc_encrypt, /* encrypt */ (crypt_func)AES_cbc_decrypt /* decrypt */ - }, - { /* RC4-SHA */ - SSL_RC4_128_SHA, /* RC4-SHA */ - 16, /* key size */ - 0, /* iv size */ - 2*(SHA1_SIZE+16), /* key block size */ - 0, /* no padding */ - SHA1_SIZE, /* digest size */ - hmac_sha1, /* hmac algorithm */ - (crypt_func)RC4_crypt, /* encrypt */ - (crypt_func)RC4_crypt /* decrypt */ - }, - /* - * This protocol is from SSLv2 days and is unlikely to be used - but was - * useful for testing different possible digest algorithms. - */ - { /* RC4-MD5 */ - SSL_RC4_128_MD5, /* RC4-MD5 */ - 16, /* key size */ - 0, /* iv size */ - 2*(MD5_SIZE+16), /* key block size */ - 0, /* no padding */ - MD5_SIZE, /* digest size */ - hmac_md5, /* hmac algorithm */ - (crypt_func)RC4_crypt, /* encrypt */ - (crypt_func)RC4_crypt /* decrypt */ - }, + } }; #endif diff --git a/ssl/tls1.h b/ssl/tls1.h index 673c7fa00..b7cd7f36e 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -82,7 +82,7 @@ extern "C" { #ifdef CONFIG_SSL_SKELETON_MODE #define NUM_PROTOCOLS 1 #else -#define NUM_PROTOCOLS 4 +#define NUM_PROTOCOLS 2 #endif #define PARANOIA_CHECK(A, B) if (A < B) { \ From d78e7a07998f456d452a760d478d1518b009fd4a Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Mon, 1 Feb 2016 12:05:09 +0100 Subject: [PATCH 14/29] Initial version of axTLS integration with lwip raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP). --- tools/make_certs.sh | 186 ++++++++++++++++++++++++++++++++++ util/README.md | 149 +++++++++++++++++++++++++++ util/lwipr_compat.c | 241 ++++++++++++++++++++++++++++++++++++++++++++ util/lwipr_compat.h | 82 +++++++++++++++ 4 files changed, 658 insertions(+) create mode 100755 tools/make_certs.sh create mode 100644 util/README.md create mode 100644 util/lwipr_compat.c create mode 100644 util/lwipr_compat.h diff --git a/tools/make_certs.sh b/tools/make_certs.sh new file mode 100755 index 000000000..d521e9218 --- /dev/null +++ b/tools/make_certs.sh @@ -0,0 +1,186 @@ +#!/bin/sh +# +# Copyright (c) 2007, Cameron Rich +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * 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. +# + +AXDIR=`pwd`/`dirname $0` +CWD=`mktemp -d` && cd $dir +cd $CWD + +# +# Generate the certificates and keys for testing. +# + +PROJECT_NAME="axTLS 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 = 127.0.0.1 +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 axTLS.ca_key.pem 1024 +openssl genrsa -out axTLS.key_512.pem 512 +openssl genrsa -out axTLS.key_1024.pem 1024 +openssl genrsa -out axTLS.key_1042.pem 1042 +openssl genrsa -out axTLS.key_2048.pem 2048 +openssl genrsa -out axTLS.key_4096.pem 4096 +openssl genrsa -out axTLS.device_key.pem 1024 +openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512 +openssl genrsa -aes256 -passout pass:abcd -out axTLS.key_aes256.pem 512 + + +# convert private keys into DER format +openssl rsa -in axTLS.key_512.pem -out axTLS.key_512 -outform DER +openssl rsa -in axTLS.key_1024.pem -out axTLS.key_1024 -outform DER +openssl rsa -in axTLS.key_1042.pem -out axTLS.key_1042 -outform DER +openssl rsa -in axTLS.key_2048.pem -out axTLS.key_2048 -outform DER +openssl rsa -in axTLS.key_4096.pem -out axTLS.key_4096 -outform DER +openssl rsa -in axTLS.device_key.pem -out axTLS.device_key -outform DER + +# cert requests +openssl req -out axTLS.ca_x509.req -key axTLS.ca_key.pem -new \ + -config ./ca_cert.conf +openssl req -out axTLS.x509_512.req -key axTLS.key_512.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_1024.req -key axTLS.key_1024.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_1042.req -key axTLS.key_1042.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_2048.req -key axTLS.key_2048.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_4096.req -key axTLS.key_4096.pem -new \ + -config ./certs.conf +openssl req -out axTLS.x509_device.req -key axTLS.device_key.pem -new \ + -config ./device_cert.conf +openssl req -out axTLS.x509_aes128.req -key axTLS.key_aes128.pem \ + -new -config ./certs.conf -passin pass:abcd +openssl req -out axTLS.x509_aes256.req -key axTLS.key_aes256.pem \ + -new -config ./certs.conf -passin pass:abcd + +# generate the actual certs. +openssl x509 -req -in axTLS.ca_x509.req -out axTLS.ca_x509.pem \ + -sha1 -days 5000 -signkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_512.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_1024.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_1042.req -out axTLS.x509_1042.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_2048.req -out axTLS.x509_2048.pem \ + -md5 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_4096.req -out axTLS.x509_4096.pem \ + -md5 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_device.req -out axTLS.x509_device.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.x509_512.pem -CAkey axTLS.key_512.pem +openssl x509 -req -in axTLS.x509_aes128.req \ + -out axTLS.x509_aes128.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +openssl x509 -req -in axTLS.x509_aes256.req \ + -out axTLS.x509_aes256.pem \ + -sha1 -CAcreateserial -days 5000 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem + +# note: must be root to do this +DATE_NOW=`date` +if date -s "Jan 1 2025"; then +openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_before.pem \ + -sha1 -CAcreateserial -days 365 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem +date -s "$DATE_NOW" +touch axTLS.x509_bad_before.pem +fi +openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_after.pem \ + -sha1 -CAcreateserial -days -365 \ + -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem + +# some cleanup +rm axTLS*.req +rm axTLS.srl +rm *.conf + +# need this for the client tests +openssl x509 -in axTLS.ca_x509.pem -outform DER -out axTLS.ca_x509.cer +openssl x509 -in axTLS.x509_512.pem -outform DER -out axTLS.x509_512.cer +openssl x509 -in axTLS.x509_1024.pem -outform DER -out axTLS.x509_1024.cer +openssl x509 -in axTLS.x509_1042.pem -outform DER -out axTLS.x509_1042.cer +openssl x509 -in axTLS.x509_2048.pem -outform DER -out axTLS.x509_2048.cer +openssl x509 -in axTLS.x509_4096.pem -outform DER -out axTLS.x509_4096.cer +openssl x509 -in axTLS.x509_device.pem -outform DER -out axTLS.x509_device.cer + +# generate pkcs8 files (use RC4-128 for encryption) +openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8 +openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8 +openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -out axTLS.unencrypted_pem.p8 +openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -outform DER -out axTLS.unencrypted.p8 + +# generate pkcs12 files (use RC4-128 for encryption) +openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -certfile axTLS.ca_x509.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -name "p12_with_CA" -out axTLS.withCA.p12 -password pass:abcd +openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -name "p12_without_CA" -out axTLS.withoutCA.p12 -password pass:abcd +openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -out axTLS.noname.p12 -password pass:abcd + +# PEM certificate chain +cat axTLS.ca_x509.pem >> axTLS.x509_device.pem + +# set default key/cert for use in the server +xxd -i axTLS.x509_1024.cer | sed -e \ + "s/axTLS_x509_1024_cer/default_certificate/" > $AXDIR/../ssl/cert.h +xxd -i axTLS.key_1024 | sed -e \ + "s/axTLS_key_1024/default_private_key/" > $AXDIR/../ssl/private_key.h diff --git a/util/README.md b/util/README.md new file mode 100644 index 000000000..6c3b10ba3 --- /dev/null +++ b/util/README.md @@ -0,0 +1,149 @@ +If you are using [LWIP raw tcp mode](http://lwip.wikia.com/wiki/Raw/TCP) and want to add SSL support below are the steps that can help you to achieve this with the help of [axTLS]( http://axtls.sourceforge.net/ ). + +First you have to include the `lwipr_compat.h` header. + +```C +#include "util/lwipr_compat.h" +``` + +Then in the code block where you initialize the tcp raw connection you should call `axl_init`. +Take a look at the example below: + +```C +lwip_init(); + +/* + * The line below should be added AFTER the lwip_init code + * AND BEFORE the call to tcp_new() + * The parameter value 10 specifies how many SSL connections are expected + */ +axl_init(10); + +// .. some more code +tcp = tcp_new(); +tcp_sent(tcp, staticOnSent); +tcp_recv(tcp, staticOnReceive); +tcp_err(tcp, staticOnError); +tcp_poll(tcp, staticOnPoll, 4); +// ... and even more code +res = tcp_connect(tcp, &addr, port, staticOnConnected); + + +``` + +Now we should add in our `staticOnConnected` funciton code to create new ssl context and ssl object. +In the example below the `sslObj` and `sslContext` are defined as global + +```C +// global definitions +SSL *sslObj = NULL; +SSLCTX* sslContext = NULL; + +// and some more code... + +err_t staticOnConnected(void *arg, struct tcp_pcb *tcp, err_t err) +{ + int clientfd = -1; + uint32_t options = 0; + + if (tcp == NULL) { + /* @TODO: Take care to handle error conditions */ + return -1; + } + + clientfd = axl_append(tcp); + if(clientfd == -1) { + printf("Unable to add LWIP tcp -> clientfd mapping\n"); + return ERR_OK; + } + + printf("Connected: ClientId: %d\n", clientfd); +#ifdef SSL_DEBUG + options |= SSL_DISPLAY_STATES | SSL_DISPLAY_BYTES; +#endif + + // if you want to verify the server certificate later you can also add the following option + options |= SSL_SERVER_VERIFY_LATER + + sslContext = ssl_ctx_new(SSL_CONNECT_IN_PARTS | options, 1); // !!! SSL_CONNECT_IN_PARTS must be in the flags !!! + sslObj = ssl_client_new(sslContext, clientfd, NULL, 0); + + return ERR_OK; +} +``` + + +Once we are connected we can send and receive information. For the receiving part we can do the following + +```C +err_t staticOnReceive(void *arg, struct tcp_pcb *tcp, struct pbuf *p, err_t err) +{ + uint8_t *read_buf = NULL; + int read_bytes = 0; + + printf("Err: %d\n", err); + + if(tcp == NULL || p == NULL) { + /* @TODO: Take care to handle error conditions */ + return -1; + } + + read_bytes = axl_ssl_read(sslObj, &read_buf, tcp, p); + if(read_bytes > 0) { + printf("Got data: %s", read_buf); + // @TODO: Do something useful with the read_buf + } + + return ERR_OK; +} +``` + +In the receiving part you can also add debug code to display more information about the SSL handshake, once it was successul. + + +```C +err_t staticOnReceive(void *arg, struct tcp_pcb *tcp, struct pbuf *p, err_t err) +{ + static int show_info = 0; + const char *common_name = NULL; + + // .. + read_bytes = axl_ssl_read(sslObj, &read_buf, tcp, p); + if(read_bytes > 0) { + printf("Got data: %s", read_buf); + // @TODO: Do something useful with the read_buf + } + + if(!show_info && ssl_handshake_status(sslObj) == SSL_OK) { + common_name = ssl_get_cert_dn(sslObj, SSL_X509_CERT_COMMON_NAME); + if (common_name) { + printf("Common Name:\t\t\t%s\n", common_name); + } + + // These two funcitons below can be found in the axtls examples + display_session_id(sslObj); + display_cipher(sslObj); + show_info = 1; + } + + return ERR_OK; +} + +``` + + +And for the sending part we can use the following code sample as a start + +```C +void someSendingfunction() { + uint8_t *out_buf; + int out_bytes = 0; + + // ... take care to store something in the out_buf + + axl_ssl_write(sslObj, out_buf, out_bytes); +} + +``` + +Good luck and send your success stories at slaff@attachix.com. diff --git a/util/lwipr_compat.c b/util/lwipr_compat.c new file mode 100644 index 000000000..6cd75188f --- /dev/null +++ b/util/lwipr_compat.c @@ -0,0 +1,241 @@ +/* + * Compatibility for AxTLS with LWIP raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP) + * + * Created on: Jan 15, 2016 + * Author: Slavey Karadzhov + */ +#include "lwipr_compat.h" + +#include + +/* High Level "public" functions */ + +/** + * Function that should be called once we are ready to use the axTLS - LWIP raw compatibility + */ +void axl_init(int capacity) { + ax_fd_init(&axlFdArray, capacity); +} + +/** + * Appends a tcp to the internal array. Returns client file descriptor + */ +int axl_append(struct tcp_pcb *tcp) { + return ax_fd_append(&axlFdArray, tcp); +} + +/** + * Reads data from the SSL over TCP stream. Returns decrypted data. + * @param SSL *sslObj + * @param uint8_t **in_data - pointer to the decrypted incoming data, or NULL if nothing was read + * @param void *arg - possible arguments passed to the tcp raw layer during initialization + * @param tcp_pcb *tcp - pointer to the raw tcp object + * @param pbuf *p - pointer to the buffer with the TCP packet data + * + * @return int + * 0 - when everything is fine but there are no symbols to process yet + * < 0 - when there is an error + * > 0 - the length of the clear text characters that were read + */ +int axl_ssl_read(SSL *ssl, uint8_t **in_data, struct tcp_pcb *tcp, struct pbuf *p) { + int read_bytes = 0; + int total_bytes = 0; + int clientfd = -1; + + AxlTcpData* data = NULL; + + if (ssl == NULL) { + return ERR_AXL_INVALID_SSL; + } + + clientfd = ax_fd_getfd(&axlFdArray, tcp); + if(clientfd == -1) { + return ERR_AXL_INVALID_CLIENTFD; + } + + data = ax_fd_get(&axlFdArray, clientfd); + if(data == NULL) { + return ERR_AXL_INVALID_CLIENTFD_DATA; + } + + if (p != NULL) { + data->tcp_pbuf = p; + data->pbuf_offset = 0; + } + + tcp_recved(tcp, p->tot_len); + do { + read_bytes = ssl_read(ssl, in_data); + if(read_bytes < SSL_OK) { + /* An error has occurred. Give it back for further processing */ + total_bytes = read_bytes; + break; + } + total_bytes+= read_bytes; + } while (p->tot_len - data->pbuf_offset > 0); + + pbuf_free(p); + + return total_bytes; +} + +/* + * Lower Level LWIP RAW functions + */ + +/* + * The LWIP tcp raw version of the SOCKET_WRITE(A, B, C) + */ +int ax_port_write(int clientfd, uint8_t *buf, uint16_t bytes_needed) { + AxlTcpData *data = NULL; + int tcp_len = 0; + err_t err = ERR_OK; + + data = ax_fd_get(&axlFdArray, clientfd); + if(data == NULL) { + return ERR_AXL_INVALID_CLIENTFD; + } + + if (data == NULL || data->tcp == NULL || buf == NULL || bytes_needed == 0) { + return 0; + } + + if (tcp_sndbuf(data->tcp) < bytes_needed) { + tcp_len = tcp_sndbuf(data->tcp); + if(tcp_len == 0) { + AXL_DEBUG("The send buffer is full! We have problem.\n"); + return 0; + } + + } else { + tcp_len = bytes_needed; + } + + if (tcp_len > 2 * data->tcp->mss) { + tcp_len = 2 * data->tcp->mss; + } + + do { + err = tcp_write(data->tcp, buf, tcp_len, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); + if(err < SSL_OK) { + AXL_DEBUG("Got error: %d\n", err); + } + + if (err == ERR_MEM) { + tcp_len /= 2; + } + } while (err == ERR_MEM && tcp_len > 1); + AXL_DEBUG("send_raw_packet length %d\n", tcp_len); + if (err == ERR_OK) { + err = tcp_output(data->tcp); + if(err != ERR_OK) { + AXL_DEBUG("tcp_output got err: %d\n", err); + } + } + + return tcp_len; +} + +/* + * The LWIP tcp raw version of the SOCKET_READ(A, B, C) + */ +int ax_port_read(int clientfd, uint8_t *buf, int bytes_needed) { + AxlTcpData *data = NULL; + uint8_t *read_buf = NULL; + uint8_t *pread_buf = NULL; + u16_t recv_len = 0; + + data = ax_fd_get(&axlFdArray, clientfd); + if (data == NULL) { + return ERR_AXL_INVALID_CLIENTFD_DATA; + } + + if(data->tcp_pbuf == NULL || data->tcp_pbuf->tot_len == 0) { + AXL_DEBUG("Nothing to read?! May be the connection needs resetting?\n"); + return 0; + } + + read_buf =(uint8_t*)calloc(data->tcp_pbuf->len + 1, sizeof(uint8_t)); + pread_buf = read_buf; + if (pread_buf != NULL){ + recv_len = pbuf_copy_partial(data->tcp_pbuf, read_buf, bytes_needed, data->pbuf_offset); + data->pbuf_offset += recv_len; + } + + if (recv_len != 0) { + memcpy(buf, read_buf, recv_len); + } + + if(bytes_needed < recv_len) { + AXL_DEBUG("Bytes needed: %d, Bytes read: %d\n", bytes_needed, recv_len); + } + + free(pread_buf); + pread_buf = NULL; + + return recv_len; +} + +/* + * Utility functions + */ +void ax_fd_init(AxlTcpDataArray *vector, int capacity) { + vector->size = 0; + vector->capacity = capacity; + vector->data = (AxlTcpData*) malloc(sizeof(AxlTcpData) * vector->capacity); +} + +int ax_fd_append(AxlTcpDataArray *vector, struct tcp_pcb *tcp) { + int index; + + ax_fd_double_capacity_if_full(vector); + index = vector->size++; + vector->data[index].tcp = tcp; + vector->data[index].tcp_pbuf = NULL; + vector->data[index].pbuf_offset = 0; + + return index; +} + +AxlTcpData* ax_fd_get(AxlTcpDataArray *vector, int index) { + if (index >= vector->size || index < 0) { + AXL_DEBUG("Index %d out of bounds for vector of size %d\n", index, + vector->size); + return NULL; + } + return &(vector->data[index]); +} + +int ax_fd_getfd(AxlTcpDataArray *vector, struct tcp_pcb *tcp) { + int i; + for (i = 0; i < vector->size; i++) { + if (vector->data[i].tcp == tcp) { + return i; + } + } + + return -1; +} + +void ax_fd_set(AxlTcpDataArray *vector, int index, struct tcp_pcb *tcp) { + AxlTcpData value; + while (index >= vector->size) { + ax_fd_append(vector, 0); + } + + value.tcp = tcp; + value.tcp_pbuf = NULL; + value.pbuf_offset = 0; + vector->data[index] = value; +} + +void ax_fd_double_capacity_if_full(AxlTcpDataArray *vector) { + if (vector->size >= vector->capacity) { + vector->capacity *= 2; + vector->data = (AxlTcpData*)realloc(vector->data, sizeof(AxlTcpData) * vector->capacity); + } +} + +void ax_fd_free(AxlTcpDataArray *vector) { + free(vector->data); +} diff --git a/util/lwipr_compat.h b/util/lwipr_compat.h new file mode 100644 index 000000000..1e5d73fa2 --- /dev/null +++ b/util/lwipr_compat.h @@ -0,0 +1,82 @@ +/* + * Compatibility for AxTLS with LWIP raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP) + * + * Created on: Jan 15, 2016 + * Author: Slavey Karadzhov + */ + +#ifndef LWIPR_COMPAT_H +#define LWIPR_COMPAT_H + +#include + +/* + * All those functions will run only if LWIP tcp raw mode is used + */ +#if LWIP_RAW==1 + +#include "lwip/tcp.h" +#include "ssl/ssl.h" +#include "ssl/tls1.h" + +#define ERR_AXL_INVALID_SSL -101 +#define ERR_AXL_INVALID_TCP -102 +#define ERR_AXL_INVALID_CLIENTFD -103 +#define ERR_AXL_INVALID_CLIENTFD_DATA -104 + +#define SOCKET_READ(A, B, C) ax_port_read(A, B, C) +#define SOCKET_WRITE(A, B, C) ax_port_write(A, B, C) + +/* + * Define the AXL_DEBUG function to add debug functionality + */ +#ifndef AXL_DEBUG +#define AXL_DEBUG printf +#endif + +typedef struct { + struct tcp_pcb *tcp; + struct pbuf *tcp_pbuf; + int pbuf_offset; +} AxlTcpData; + + +typedef struct { + int size; /* slots used so far */ + int capacity; /* total available slots */ + AxlTcpData *data; /* array of TcpData objects */ +} AxlTcpDataArray; + +AxlTcpDataArray axlFdArray; + +/* + * High Level Functions - these are the ones that should be used directly + */ + +void axl_init(int capacity); +int axl_append(struct tcp_pcb *tcp); + +#define axl_ssl_write(A, B, C) ssl_write(A, B, C) +int axl_ssl_read(SSL *sslObj, uint8_t **in_data, struct tcp_pcb *tcp, struct pbuf *p); + +/* + * Lower Level Socket Functions - used internally from axTLS + */ + +int ax_port_write(int clientfd, uint8_t *buf, uint16_t bytes_needed); +int ax_port_read(int clientfd, uint8_t *buf, int bytes_needed); + +/* + * Lower Level Utility functions + */ +void ax_fd_init(AxlTcpDataArray *vector, int capacity); +int ax_fd_append(AxlTcpDataArray *vector, struct tcp_pcb *tcp); +AxlTcpData* ax_fd_get(AxlTcpDataArray *vector, int index); +int ax_fd_getfd(AxlTcpDataArray *vector, struct tcp_pcb *tcp); +void ax_fd_set(AxlTcpDataArray *vector, int index, struct tcp_pcb *tcp); +void ax_fd_double_capacity_if_full(AxlTcpDataArray *vector); +void ax_fd_free(AxlTcpDataArray *vector); + +#endif + +#endif /* LWIPR_COMPAT_H */ From 7c38865f66cfdd0884183619b0d1e89b8717cb01 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Fri, 19 Feb 2016 11:53:05 +0100 Subject: [PATCH 15/29] Restructured the lwip raw comat code. Added replacements for the time functions on ESP8266. --- {util => compat}/README.md | 2 +- {util => compat}/lwipr_compat.c | 45 +++++++++- {util => compat}/lwipr_compat.h | 25 ++++-- compat/lwipr_platform.h | 27 ++++++ replacements/time.c | 147 ++++++++++++++++++++++++++++++++ 5 files changed, 237 insertions(+), 9 deletions(-) rename {util => compat}/README.md (99%) rename {util => compat}/lwipr_compat.c (83%) rename {util => compat}/lwipr_compat.h (86%) create mode 100644 compat/lwipr_platform.h create mode 100644 replacements/time.c diff --git a/util/README.md b/compat/README.md similarity index 99% rename from util/README.md rename to compat/README.md index 6c3b10ba3..fff33837d 100644 --- a/util/README.md +++ b/compat/README.md @@ -3,7 +3,7 @@ If you are using [LWIP raw tcp mode](http://lwip.wikia.com/wiki/Raw/TCP) and wan First you have to include the `lwipr_compat.h` header. ```C -#include "util/lwipr_compat.h" +#include "compat/lwipr_compat.h" ``` Then in the code block where you initialize the tcp raw connection you should call `axl_init`. diff --git a/util/lwipr_compat.c b/compat/lwipr_compat.c similarity index 83% rename from util/lwipr_compat.c rename to compat/lwipr_compat.c index 6cd75188f..834b3f071 100644 --- a/util/lwipr_compat.c +++ b/compat/lwipr_compat.c @@ -6,6 +6,8 @@ */ #include "lwipr_compat.h" +AxlTcpDataArray axlFdArray; + #include /* High Level "public" functions */ @@ -24,6 +26,34 @@ int axl_append(struct tcp_pcb *tcp) { return ax_fd_append(&axlFdArray, tcp); } +/** + * Frees the internal mapping from this tcp. Returns the number of occurrences of the tcp + */ +int axl_free(struct tcp_pcb *tcp) { + int i; + int occurances = 0; + + if(tcp == NULL) { + return 0; + } + + AxlTcpDataArray *vector = &axlFdArray; + AXL_DEBUG("AXL: Freeing %d tcp item", vector->size); + for (i = 0; i < vector->size; i++) { + if (vector->data[i].tcp == tcp) { + if(vector->data[i].tcp_pbuf != NULL) { + pbuf_free(vector->data[i].tcp_pbuf); + vector->data[i].tcp_pbuf = NULL; + } + vector->data[i].tcp = NULL; + vector->data[i].pbuf_offset = 0; + occurances++; + } + } + + return occurances; +} + /** * Reads data from the SSL over TCP stream. Returns decrypted data. * @param SSL *sslObj @@ -63,9 +93,13 @@ int axl_ssl_read(SSL *ssl, uint8_t **in_data, struct tcp_pcb *tcp, struct pbuf * data->pbuf_offset = 0; } + AXL_DEBUG("READY TO READ SOME DATA\n"); + tcp_recved(tcp, p->tot_len); do { + WATCHDOG_FEED(); read_bytes = ssl_read(ssl, in_data); + AXL_DEBUG("axl_ssl_read: Read bytes: %d\n", read_bytes); if(read_bytes < SSL_OK) { /* An error has occurred. Give it back for further processing */ total_bytes = read_bytes; @@ -97,6 +131,7 @@ int ax_port_write(int clientfd, uint8_t *buf, uint16_t bytes_needed) { } if (data == NULL || data->tcp == NULL || buf == NULL || bytes_needed == 0) { + AXL_DEBUG("Return Zero.\n"); return 0; } @@ -116,16 +151,17 @@ int ax_port_write(int clientfd, uint8_t *buf, uint16_t bytes_needed) { } do { - err = tcp_write(data->tcp, buf, tcp_len, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); + err = tcp_write(data->tcp, buf, tcp_len, TCP_WRITE_FLAG_COPY); if(err < SSL_OK) { AXL_DEBUG("Got error: %d\n", err); } if (err == ERR_MEM) { + AXL_DEBUG("Not enough memory to write data with length: %d (%d)\n", tcp_len, bytes_needed); tcp_len /= 2; } } while (err == ERR_MEM && tcp_len > 1); - AXL_DEBUG("send_raw_packet length %d\n", tcp_len); + AXL_DEBUG("send_raw_packet length %d(%d)\n", tcp_len, bytes_needed); if (err == ERR_OK) { err = tcp_output(data->tcp); if(err != ERR_OK) { @@ -176,6 +212,11 @@ int ax_port_read(int clientfd, uint8_t *buf, int bytes_needed) { return recv_len; } +int ax_get_file(const char *filename, uint8_t **buf) { + *buf = 0; + return 0; +} + /* * Utility functions */ diff --git a/util/lwipr_compat.h b/compat/lwipr_compat.h similarity index 86% rename from util/lwipr_compat.h rename to compat/lwipr_compat.h index 1e5d73fa2..1a8846f94 100644 --- a/util/lwipr_compat.h +++ b/compat/lwipr_compat.h @@ -8,14 +8,16 @@ #ifndef LWIPR_COMPAT_H #define LWIPR_COMPAT_H -#include - /* * All those functions will run only if LWIP tcp raw mode is used */ #if LWIP_RAW==1 -#include "lwip/tcp.h" +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwipr_platform.h" #include "ssl/ssl.h" #include "ssl/tls1.h" @@ -31,7 +33,14 @@ * Define the AXL_DEBUG function to add debug functionality */ #ifndef AXL_DEBUG -#define AXL_DEBUG printf + #define AXL_DEBUG(...) +#endif + +/** + * Define watchdog function to be called during CPU intensive operations. + */ +#ifndef WATCHDOG_FEED + #define WATCHDOG_FEED() #endif typedef struct { @@ -47,14 +56,13 @@ typedef struct { AxlTcpData *data; /* array of TcpData objects */ } AxlTcpDataArray; -AxlTcpDataArray axlFdArray; - /* * High Level Functions - these are the ones that should be used directly */ void axl_init(int capacity); int axl_append(struct tcp_pcb *tcp); +int axl_free(struct tcp_pcb *tcp); #define axl_ssl_write(A, B, C) ssl_write(A, B, C) int axl_ssl_read(SSL *sslObj, uint8_t **in_data, struct tcp_pcb *tcp, struct pbuf *p); @@ -77,6 +85,11 @@ void ax_fd_set(AxlTcpDataArray *vector, int index, struct tcp_pcb *tcp); void ax_fd_double_capacity_if_full(AxlTcpDataArray *vector); void ax_fd_free(AxlTcpDataArray *vector); + +#ifdef __cplusplus +} #endif +#endif /* LWIP_RAW==1 */ + #endif /* LWIPR_COMPAT_H */ diff --git a/compat/lwipr_platform.h b/compat/lwipr_platform.h new file mode 100644 index 000000000..518e8bf4e --- /dev/null +++ b/compat/lwipr_platform.h @@ -0,0 +1,27 @@ +/* + * lwipr_platform.h + * + * Created on: Feb 8, 2016 + * Author: slavey + * + */ + +#ifndef AXTLS_8266_COMPAT_LWIPR_PLATFORM_H_ +#define AXTLS_8266_COMPAT_LWIPR_PLATFORM_H_ + +/* Add here all platform specific things */ + + +// Some calls require the watchdog to be reset +#ifndef WATCHDOG_FEED + #define WATCHDOG_FEED() +#endif + + +/* SSL_DEBUG is for more information */ +#ifndef SSL_DEBUG + #define AXL_DEBUG(...) +#endif + + +#endif /* AXTLS_8266_COMPAT_LWIPR_PLATFORM_H_ */ diff --git a/replacements/time.c b/replacements/time.c new file mode 100644 index 000000000..4972119bb --- /dev/null +++ b/replacements/time.c @@ -0,0 +1,147 @@ +/* + * time.c - ESP8266-specific functions for SNTP + * Copyright (c) 2015 Peter Dobler. All rights reserved. + * This file is part of the esp8266 core for Arduino environment. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include + +extern uint32_t system_get_time(void); +extern uint64_t system_mktime(uint32_t year, uint32_t mon, uint32_t day, uint32_t hour, uint32_t min, uint32_t sec); + +static int errno_var = 0; + +int* __errno(void) { + // DEBUGV("__errno is called last error: %d (not current)\n", errno_var); + return &errno_var; +} + +unsigned long millis(void) +{ + return system_get_time() / 1000UL; +} + +unsigned long micros(void) +{ + return system_get_time(); +} + +#ifndef _TIMEVAL_DEFINED +#define _TIMEVAL_DEFINED +struct timeval { + time_t tv_sec; + suseconds_t tv_usec; +}; +#endif + +extern char* sntp_asctime(const struct tm *t); +extern struct tm* sntp_localtime(const time_t *clock); + +// time gap in seconds from 01.01.1900 (NTP time) to 01.01.1970 (UNIX time) +#define DIFF1900TO1970 2208988800UL + +static int s_daylightOffset_sec = 0; +static long s_timezone_sec = 0; +static time_t s_bootTime = 0; + +// calculate offset used in gettimeofday +static void ensureBootTimeIsSet() +{ + if (!s_bootTime) + { + time_t now = sntp_get_current_timestamp(); + if (now) + { + s_bootTime = now - millis() / 1000; + } + } +} + +static void setServer(int id, const char* name_or_ip) +{ + if (name_or_ip) + { + //TODO: check whether server is given by name or IP + sntp_setservername(id, (char*) name_or_ip); + } +} + +void configTime(int timezone, int daylightOffset_sec, const char* server1, const char* server2, const char* server3) +{ + sntp_stop(); + + setServer(0, server1); + setServer(1, server2); + setServer(2, server3); + + s_timezone_sec = timezone; + s_daylightOffset_sec = daylightOffset_sec; + sntp_set_timezone(timezone/3600); + sntp_init(); +} + +int clock_gettime(clockid_t unused, struct timespec *tp) +{ + tp->tv_sec = millis() / 1000; + tp->tv_nsec = micros() * 1000; + return 0; +} + +// seconds since 1970 +time_t mktime(struct tm *t) +{ + // system_mktime expects month in range 1..12 + #define START_MONTH 1 + return DIFF1900TO1970 + system_mktime(t->tm_year, t->tm_mon + START_MONTH, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); +} + +time_t time(time_t * t) +{ + time_t seconds = sntp_get_current_timestamp(); + if (t) + { + *t = seconds; + } + return seconds; +} + +char* asctime(const struct tm *t) +{ + return sntp_asctime(t); +} + +struct tm* localtime(const time_t *clock) +{ + return sntp_localtime(clock); +} + +char* ctime(const time_t *t) +{ + struct tm* p_tm = localtime(t); + char* result = asctime(p_tm); + return result; +} + +int gettimeofday(struct timeval *tp, void *tzp) +{ + if (tp) + { + ensureBootTimeIsSet(); + tp->tv_sec = (s_bootTime + millis()) / 1000; + tp->tv_usec = micros() * 1000; + } + return 0; +} From 63da8991c2878f2a7cd526667f9e23adc9dca1c9 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Fri, 19 Feb 2016 11:41:45 +0100 Subject: [PATCH 16/29] Added SNI ( https://en.wikipedia.org/wiki/Server_Name_Indication ) support. --- ssl/ssl.h | 10 ++++++++++ ssl/tls1.c | 13 +++++++++++++ ssl/tls1.h | 1 + ssl/tls1_clnt.c | 20 ++++++++++++++++++++ 4 files changed, 44 insertions(+) diff --git a/ssl/ssl.h b/ssl/ssl.h index 97e87d495..c39f921f5 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -352,6 +352,16 @@ EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl); */ EXP_FUNC int STDCALL ssl_get_config(int offset); +/** + * @brief Sets the hostname to be used for SNI + * @see https://en.wikipedia.org/wiki/Server_Name_Indication + * @param char* hostname + * @return success from the operation + * - 1 on success + * - 0 on failure + */ +EXP_FUNC int STDCALL ssl_set_hostname(const SSL *ssl, const char* host_name); + /** * @brief Display why the handshake failed. * diff --git a/ssl/tls1.c b/ssl/tls1.c index c4a676b10..a1783bf46 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -1849,6 +1849,19 @@ EXP_FUNC int STDCALL ssl_get_config(int offset) } } +/** + * Sets the SNI hostname + */ +EXP_FUNC int STDCALL ssl_set_hostname(const SSL *ssl, const char* host_name) { + if(host_name == NULL || strlen(host_name) == 0 || strlen(host_name) > 255 ) { + return 0; + } + + strncpy((char*)&ssl->host_name, host_name, strlen(host_name)); + + return 1; +} + #ifdef CONFIG_SSL_CERT_VERIFICATION /** * Authenticate a received certificate. diff --git a/ssl/tls1.h b/ssl/tls1.h index b7cd7f36e..d5440aa6c 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -198,6 +198,7 @@ struct _SSL uint8_t read_sequence[8]; /* 64 bit sequence number */ uint8_t write_sequence[8]; /* 64 bit sequence number */ uint8_t hmac_header[SSL_RECORD_SIZE]; /* rx hmac */ + const char host_name[255]; /* Needed for the SNI support */ }; typedef struct _SSL SSL; diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index 5f2598922..5eee5713a 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -220,6 +220,26 @@ static int send_client_hello(SSL *ssl) buf[offset++] = 1; /* no compression */ buf[offset++] = 0; + + if (ssl->host_name[0] != 0) { + unsigned int host_len = strnlen((char*) ssl->host_name, 255); + + buf[offset++] = 0; + buf[offset++] = host_len+9; /* extensions length */ + + buf[offset++] = 0; + buf[offset++] = 0; /* server_name(0) (65535) */ + buf[offset++] = 0; + buf[offset++] = host_len+5; /* server_name length */ + buf[offset++] = 0; + buf[offset++] = host_len+3; /* server_list length */ + buf[offset++] = 0; /* host_name(0) (255) */ + buf[offset++] = 0; + buf[offset++] = host_len; /* host_name length */ + strncpy((char*) &buf[offset], ssl->host_name, host_len); + offset += host_len; + } + buf[3] = offset - 4; /* handshake size */ return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset); From 1154d0a985cc442f39f5e6b3678a7d4ffca5db31 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Mon, 22 Feb 2016 10:02:40 +0100 Subject: [PATCH 17/29] Changed the code to reserve bytes for hostname only if needed. --- ssl/ssl.h | 2 +- ssl/tls1.c | 24 ++++++++++++++++++------ ssl/tls1.h | 2 +- ssl/tls1_clnt.c | 30 +++++++++++++++--------------- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/ssl/ssl.h b/ssl/ssl.h index c39f921f5..b287d5aa8 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -360,7 +360,7 @@ EXP_FUNC int STDCALL ssl_get_config(int offset); * - 1 on success * - 0 on failure */ -EXP_FUNC int STDCALL ssl_set_hostname(const SSL *ssl, const char* host_name); +EXP_FUNC int STDCALL ssl_set_hostname(SSL *ssl, const char* host_name); /** * @brief Display why the handshake failed. diff --git a/ssl/tls1.c b/ssl/tls1.c index a1783bf46..195cb0196 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -568,6 +568,8 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) ssl->encrypt_ctx = malloc(sizeof(AES_CTX)); ssl->decrypt_ctx = malloc(sizeof(AES_CTX)); + ssl->host_name = NULL; + SSL_CTX_UNLOCK(ssl_ctx->mutex); return ssl; } @@ -1852,14 +1854,24 @@ EXP_FUNC int STDCALL ssl_get_config(int offset) /** * Sets the SNI hostname */ -EXP_FUNC int STDCALL ssl_set_hostname(const SSL *ssl, const char* host_name) { - if(host_name == NULL || strlen(host_name) == 0 || strlen(host_name) > 255 ) { - return 0; - } +EXP_FUNC int STDCALL ssl_set_hostname(SSL *ssl, const char* host_name) { + if(host_name == NULL || strlen(host_name) == 0 || strlen(host_name) > 255 ) { + return 0; + } - strncpy((char*)&ssl->host_name, host_name, strlen(host_name)); + if(ssl->host_name != NULL) { + free(ssl->host_name); + } - return 1; + ssl->host_name = (char *)malloc(strlen(host_name)+1); + if(ssl->host_name == NULL) { + // most probably there was no memory available + return 0; + } + + strcpy(ssl->host_name, host_name); + + return 1; } #ifdef CONFIG_SSL_CERT_VERIFICATION diff --git a/ssl/tls1.h b/ssl/tls1.h index d5440aa6c..c53ce6da0 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -198,7 +198,7 @@ struct _SSL uint8_t read_sequence[8]; /* 64 bit sequence number */ uint8_t write_sequence[8]; /* 64 bit sequence number */ uint8_t hmac_header[SSL_RECORD_SIZE]; /* rx hmac */ - const char host_name[255]; /* Needed for the SNI support */ + char *host_name; /* Needed for the SNI support */ }; typedef struct _SSL SSL; diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index 5eee5713a..b84877da7 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -221,23 +221,23 @@ static int send_client_hello(SSL *ssl) buf[offset++] = 1; /* no compression */ buf[offset++] = 0; - if (ssl->host_name[0] != 0) { - unsigned int host_len = strnlen((char*) ssl->host_name, 255); + if (ssl->host_name != NULL) { + unsigned int host_len = strlen(ssl->host_name); - buf[offset++] = 0; - buf[offset++] = host_len+9; /* extensions length */ + buf[offset++] = 0; + buf[offset++] = host_len+9; /* extensions length */ - buf[offset++] = 0; - buf[offset++] = 0; /* server_name(0) (65535) */ - buf[offset++] = 0; - buf[offset++] = host_len+5; /* server_name length */ - buf[offset++] = 0; - buf[offset++] = host_len+3; /* server_list length */ - buf[offset++] = 0; /* host_name(0) (255) */ - buf[offset++] = 0; - buf[offset++] = host_len; /* host_name length */ - strncpy((char*) &buf[offset], ssl->host_name, host_len); - offset += host_len; + buf[offset++] = 0; + buf[offset++] = 0; /* server_name(0) (65535) */ + buf[offset++] = 0; + buf[offset++] = host_len+5; /* server_name length */ + buf[offset++] = 0; + buf[offset++] = host_len+3; /* server_list length */ + buf[offset++] = 0; /* host_name(0) (255) */ + buf[offset++] = 0; + buf[offset++] = host_len; /* host_name length */ + strncpy((char*) &buf[offset], ssl->host_name, host_len); + offset += host_len; } buf[3] = offset - 4; /* handshake size */ From 28869ea94b3b1cabfbe8679d962adc12ba0b28db Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 26 Feb 2016 16:09:47 +0300 Subject: [PATCH 18/29] Use free followed by malloc instead of realloc when increasing raw buffer At this point we don't need to preserve the data inside the buffer. Using free followed by malloc reduces fragmentation for some heap implementations. --- ssl/tls1.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ssl/tls1.c b/ssl/tls1.c index 195cb0196..bac9d96f6 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -1402,15 +1402,19 @@ error: void increase_bm_data_size(SSL *ssl) { - uint8_t* pr = (uint8_t*) realloc(ssl->bm_all_data, RT_MAX_PLAIN_LENGTH + RT_EXTRA); - if (pr) { - ssl->max_plain_length = RT_MAX_PLAIN_LENGTH; - ssl->bm_all_data = pr; - ssl->bm_data = pr + BM_RECORD_OFFSET; + if (ssl->max_plain_length == RT_MAX_PLAIN_LENGTH) { + return; } - else { + + free(ssl->bm_all_data); + ssl->bm_data = 0; + ssl->bm_all_data = malloc(RT_MAX_PLAIN_LENGTH + RT_EXTRA); + if (!ssl->bm_all_data) { printf("failed to grow plain buffer\r\n"); + return; } + ssl->max_plain_length = RT_MAX_PLAIN_LENGTH; + ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET; } /** From 9eaeca3a030692bdf949b89d80705061b516f70b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 26 Feb 2016 16:21:09 +0300 Subject: [PATCH 19/29] Postpone freeing of X509 context to the first data exchange after handshake X509 context contains certificate fingerprint and various names which may be used to verify the certificate. Previously we would free it right after the handshake completion, which prevented the client from actually using any information from X509 context. Postponing this to the first ssl_read/ssl_write call after the handshake, we give the client a chance to verify the certificate. Also added logging to ssl_match_fingerprint function in case fingerprint doesn't match expected value. --- ssl/tls1.c | 32 +++++++++++++++++++++++++++----- ssl/tls1.h | 2 -- ssl/tls1_clnt.c | 5 +---- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/ssl/tls1.c b/ssl/tls1.c index bac9d96f6..51b64b1f8 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -52,6 +52,7 @@ static int set_key_block(SSL *ssl, int is_write); static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len); static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void* cached); static int send_raw_packet(SSL *ssl, uint8_t protocol); +static void certificate_free(SSL* ssl); /** * The server will pick the cipher based on the order that the order that the @@ -247,8 +248,8 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) free(ssl->encrypt_ctx); free(ssl->decrypt_ctx); disposable_free(ssl); + certificate_free(ssl); free(ssl->bm_all_data); - free(ssl->fingerprint); free(ssl); } @@ -257,6 +258,9 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) */ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data) { + if (ssl->hs_status == SSL_OK) { + certificate_free(ssl); + } int ret = basic_read(ssl, in_data); /* check for return code so we can send an alert */ @@ -281,7 +285,9 @@ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data) EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len) { int n = out_len, nw, i, tot = 0; - + if (ssl->hs_status == SSL_OK) { + certificate_free(ssl); + } /* maximum size of a TLS packet is around 16kB, so fragment */ do { @@ -547,7 +553,6 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx; #endif disposable_new(ssl); - ssl->fingerprint = 0; /* a bit hacky but saves a few bytes of memory */ ssl->flag |= ssl_ctx->options; @@ -1671,12 +1676,17 @@ void disposable_free(SSL *ssl) free(ssl->dc); ssl->dc = NULL; } +} + +static void certificate_free(SSL* ssl) +{ #ifdef CONFIG_SSL_CERT_VERIFICATION if (ssl->x509_ctx) { x509_free(ssl->x509_ctx); ssl->x509_ctx = 0; } #endif + increase_bm_data_size(ssl); } #ifndef CONFIG_SSL_SKELETON_MODE /* no session resumption in this mode */ @@ -1945,9 +1955,21 @@ error: EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp) { - if (!ssl->fingerprint) + if (ssl->x509_ctx == NULL || ssl->x509_ctx->fingerprint == NULL) return 1; - return memcmp(ssl->fingerprint, fp, SHA1_SIZE); + int res = memcmp(ssl->x509_ctx->fingerprint, fp, SHA1_SIZE); + if (res != 0) { + printf("cert FP: "); + for (int i = 0; i < SHA1_SIZE; ++i) { + printf("%02X ", ssl->x509_ctx->fingerprint[i]); + } + printf("\r\ntest FP: "); + for (int i = 0; i < SHA1_SIZE; ++i) { + printf("%02X ", fp[i]); + } + printf("\r\n"); + } + return res; } #endif /* CONFIG_SSL_CERT_VERIFICATION */ diff --git a/ssl/tls1.h b/ssl/tls1.h index c53ce6da0..2b002baea 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -190,8 +190,6 @@ struct _SSL #ifdef CONFIG_SSL_CERT_VERIFICATION X509_CTX *x509_ctx; #endif - uint8_t* fingerprint; - uint8_t session_id[SSL_SESSION_ID_SIZE]; uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */ uint8_t server_mac[SHA1_SIZE]; /* for HMAC verification */ diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index b84877da7..cdb94468e 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -119,10 +119,7 @@ int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len) case HS_FINISHED: ret = process_finished(ssl, buf, hs_len); - ssl->fingerprint = ssl->x509_ctx->fingerprint; - ssl->x509_ctx->fingerprint = 0; - disposable_free(ssl); /* free up some memory */ - increase_bm_data_size(ssl); + disposable_free(ssl); /* note: client renegotiation is not allowed after this */ break; From c18bb56e6100177cfa0bef3c90708efb9d7a071d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 26 Feb 2016 16:40:05 +0300 Subject: [PATCH 20/29] Add travis CI --- .travis.yml | 43 +++++++++++++++++++++++++++++++++++++++++ Makefile | 2 -- Makefile.local.template | 3 --- 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 .travis.yml delete mode 100644 Makefile.local.template diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e948be250 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,43 @@ +sudo: false +language: bash +os: + - linux + +script: + # Download Arduino IDE + - wget -O arduino.tar.xz https://www.arduino.cc/download.php?f=/arduino-nightly-linux64.tar.xz + - tar xf arduino.tar.xz + - mv arduino-nightly $HOME/arduino_ide + # Download ESP8266 Arduino core + - cd $HOME/arduino_ide/hardware + - mkdir esp8266com + - cd esp8266com + - git clone https://github.com/esp8266/Arduino.git esp8266 + - cd esp8266 + - export ESP8266_ARDUINO_DIR="$PWD" + # Download toolchain and esptool + - cd tools + - python get.py + - export PATH="$PATH:$PWD/xtensa-lx106-elf/bin" + # Build axTLS + - cd $TRAVIS_BUILD_DIR + - make + # Copy the library into Arduino core + - cp bin/libaxtls.a $ESP8266_ARDUINO_DIR/tools/sdk/lib/libaxtls.a + # Try building examples in ESP8266WiFi library from the ESP8266 Arduino core + - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 + - sleep 3 + - export DISPLAY=:1.0 + - export PATH="$HOME/arduino_ide:$PATH" + - which arduino + - cd $ESP8266_ARDUINO_DIR + - source tests/common.sh + - arduino --board esp8266com:esp8266:generic --save-prefs + - arduino --get-pref sketchbook.path + - build_sketches arduino $ESP8266_ARDUINO_DIR/libraries/ESP8266WiFi/examples/HTTPSRequest + # Feel free to add more test cases (for other environments) here + +notifications: + email: + on_success: change + on_failure: change diff --git a/Makefile b/Makefile index 2f9d349bf..5b3a9b2d0 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,3 @@ -include Makefile.local - TOOLCHAIN_PREFIX := xtensa-lx106-elf- CC := $(TOOLCHAIN_PREFIX)gcc AR := $(TOOLCHAIN_PREFIX)ar diff --git a/Makefile.local.template b/Makefile.local.template deleted file mode 100644 index 937027f99..000000000 --- a/Makefile.local.template +++ /dev/null @@ -1,3 +0,0 @@ -# Set this to SDK path and save as Makefile.local -SDK_BASE := $(HOME)/esp8266/sdk - From 96fbb39f21d3af7ca3e4dee78f8c45c4e2e652b5 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 26 Feb 2016 17:10:31 +0300 Subject: [PATCH 21/29] Update README.md --- README.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 04779e8de..e0e454a4b 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,28 @@ Replacement for Espressif's libssl, kept as close as possible to [axTLS](http://axtls.sourceforge.net/) source. Currently based on axTLS 1.4.9, will be upgraded to 1.5.3. +[![Build status](https://travis-ci.org/igrr/axtls-8266.svg)](https://travis-ci.org/igrr/axtls-8266) + This is not a self-sufficient library. Application has to provide the following symbols (list not complete yet): ``` -malloc -calloc -free -abort +ax_port_malloc +ax_port_calloc +ax_port_realloc +ax_port_free +ax_port_read +ax_port_write +ax_port_open +ax_port_close +ax_get_file +phy_get_rand (provided by the IoT SDK) +ets_printf (in ESP8266 ROM) +ets_putc (in ESP8266 ROM) gettimeofday time ctime -printf -vprintf ``` -Additionally, functions for non-blocking TCP socket reads and writes have to be provided (details TBD). +For use with LwIP raw TCP API, see [compat/README.md](compat/README.md) To build, add xtensa toolchain to your path, and run `make`. From 324c2fdade3f39b4c7fb7fbe707f4a313023ecd3 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 26 Feb 2016 17:53:19 +0300 Subject: [PATCH 22/29] Terminate connection if increase_bm_data_size fails As suggested in https://github.com/igrr/axtls-8266/issues/2#issuecomment-188544798 --- ssl/tls1.c | 29 ++++++++++++++++++----------- ssl/tls1.h | 2 +- ssl/tls1_clnt.c | 1 + 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/ssl/tls1.c b/ssl/tls1.c index 51b64b1f8..7652e086f 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -53,6 +53,7 @@ static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len); static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void* cached); static int send_raw_packet(SSL *ssl, uint8_t protocol); static void certificate_free(SSL* ssl); +static int increase_bm_data_size(SSL *ssl); /** * The server will pick the cipher based on the order that the order that the @@ -258,10 +259,11 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) */ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data) { - if (ssl->hs_status == SSL_OK) { - certificate_free(ssl); + int ret = increase_bm_data_size(ssl); + if (ret != SSL_OK) { + return ret; } - int ret = basic_read(ssl, in_data); + ret = basic_read(ssl, in_data); /* check for return code so we can send an alert */ if (ret < SSL_OK && ret != SSL_CLOSE_NOTIFY) @@ -285,8 +287,9 @@ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data) EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len) { int n = out_len, nw, i, tot = 0; - if (ssl->hs_status == SSL_OK) { - certificate_free(ssl); + int ret = increase_bm_data_size(ssl); + if (ret != SSL_OK) { + return ret; } /* maximum size of a TLS packet is around 16kB, so fragment */ do @@ -549,6 +552,7 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) ssl->flag = SSL_NEED_RECORD; ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET; /* space at the start */ ssl->hs_status = SSL_NOT_OK; /* not connected */ + ssl->can_increase_data_size = false; #ifdef CONFIG_ENABLE_VERIFICATION ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx; #endif @@ -1405,21 +1409,25 @@ error: return ret; } -void increase_bm_data_size(SSL *ssl) +int increase_bm_data_size(SSL *ssl) { - if (ssl->max_plain_length == RT_MAX_PLAIN_LENGTH) { - return; + if (!ssl->can_increase_data_size || + ssl->max_plain_length == RT_MAX_PLAIN_LENGTH) { + return SSL_OK; } - + ssl->can_increase_data_size = false; + certificate_free(ssl); free(ssl->bm_all_data); ssl->bm_data = 0; ssl->bm_all_data = malloc(RT_MAX_PLAIN_LENGTH + RT_EXTRA); if (!ssl->bm_all_data) { printf("failed to grow plain buffer\r\n"); - return; + ssl->hs_status == SSL_ERROR_DEAD; + return SSL_ERROR_CONN_LOST; } ssl->max_plain_length = RT_MAX_PLAIN_LENGTH; ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET; + return SSL_OK; } /** @@ -1686,7 +1694,6 @@ static void certificate_free(SSL* ssl) ssl->x509_ctx = 0; } #endif - increase_bm_data_size(ssl); } #ifndef CONFIG_SSL_SKELETON_MODE /* no session resumption in this mode */ diff --git a/ssl/tls1.h b/ssl/tls1.h index 2b002baea..7dfb918a9 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -189,6 +189,7 @@ struct _SSL #endif #ifdef CONFIG_SSL_CERT_VERIFICATION X509_CTX *x509_ctx; + bool can_increase_data_size; #endif uint8_t session_id[SSL_SESSION_ID_SIZE]; uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */ @@ -261,7 +262,6 @@ void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx); #ifdef CONFIG_SSL_ENABLE_CLIENT int do_client_connect(SSL *ssl); #endif -void increase_bm_data_size(SSL *ssl); #ifdef CONFIG_SSL_FULL_MODE void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok); diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index cdb94468e..2de777f07 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -119,6 +119,7 @@ int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len) case HS_FINISHED: ret = process_finished(ssl, buf, hs_len); + ssl->can_increase_data_size = true; disposable_free(ssl); /* note: client renegotiation is not allowed after this */ break; From b33ef68e6a3e2be1171e5a9f5b6156af424489ec Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 2 Mar 2016 15:17:47 +0300 Subject: [PATCH 23/29] Fix handshake status not being set if increase_bm_data_size fails Also set warning level to -Wall https://github.com/esp8266/Arduino/issues/1708 --- Makefile | 2 +- ssl/tls1.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 5b3a9b2d0..15c5e7223 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ LDFLAGS += -L$(XTENSA_LIBS)/lib \ CFLAGS+=-std=c99 -DESP8266 -CFLAGS += -Os -g -O2 -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mno-text-section-literals -D__ets__ -DICACHE_FLASH +CFLAGS += -Wall -Os -g -O2 -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mno-text-section-literals -D__ets__ -DICACHE_FLASH BIN_DIR := bin AXTLS_AR := $(BIN_DIR)/libaxtls.a diff --git a/ssl/tls1.c b/ssl/tls1.c index 7652e086f..8b53ee36a 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -1415,16 +1415,16 @@ int increase_bm_data_size(SSL *ssl) ssl->max_plain_length == RT_MAX_PLAIN_LENGTH) { return SSL_OK; } - ssl->can_increase_data_size = false; certificate_free(ssl); free(ssl->bm_all_data); ssl->bm_data = 0; ssl->bm_all_data = malloc(RT_MAX_PLAIN_LENGTH + RT_EXTRA); if (!ssl->bm_all_data) { printf("failed to grow plain buffer\r\n"); - ssl->hs_status == SSL_ERROR_DEAD; + ssl->hs_status = SSL_ERROR_DEAD; return SSL_ERROR_CONN_LOST; } + ssl->can_increase_data_size = false; ssl->max_plain_length = RT_MAX_PLAIN_LENGTH; ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET; return SSL_OK; From 5b4be7d2738de5874f2e302157a0b726fe7bd4a6 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 2 Mar 2016 15:34:15 +0300 Subject: [PATCH 24/29] Reserve 16k fragment buffer only when it is actually required. This change reduces memory pressure when server response size fits into 6k buffer allocated by default. --- ssl/tls1.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/ssl/tls1.c b/ssl/tls1.c index 8b53ee36a..e7b8319d0 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -259,11 +259,7 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) */ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data) { - int ret = increase_bm_data_size(ssl); - if (ret != SSL_OK) { - return ret; - } - ret = basic_read(ssl, in_data); + int ret = basic_read(ssl, in_data); /* check for return code so we can send an alert */ if (ret < SSL_OK && ret != SSL_CLOSE_NOTIFY) @@ -287,10 +283,6 @@ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data) EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len) { int n = out_len, nw, i, tot = 0; - int ret = increase_bm_data_size(ssl); - if (ret != SSL_OK) { - return ret; - } /* maximum size of a TLS packet is around 16kB, so fragment */ do { @@ -1293,9 +1285,21 @@ int basic_read(SSL *ssl, uint8_t **in_data) /* do we violate the spec with the message size? */ if (ssl->need_bytes > ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET) { - ret = SSL_ERROR_INVALID_PROT_MSG; printf("ssl->need_bytes=%d > %d\r\n", ssl->need_bytes, ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET); - goto error; + if (ssl->can_increase_data_size) + { + ret = increase_bm_data_size(ssl); + if (ret != SSL_OK) + { + ret = SSL_ERROR_INVALID_PROT_MSG; + goto error; + } + } + else + { + ret = SSL_ERROR_INVALID_PROT_MSG; + goto error; + } } CLR_SSL_FLAG(SSL_NEED_RECORD); From fe4518da8de87a751ff74111884c775152287ae5 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 19 Apr 2016 07:56:22 +0300 Subject: [PATCH 25/29] Make SNI host name an ssl_client_new argument ssl_set_hostname was mostly useless, because it allowed setting host name of an existing SSL object. However SNI was sent as part of client_hello, which was done in ssl_client_new. So it wasn't possible to actually set host name before connection would start. --- ssl/ssl.h | 13 ++----------- ssl/tls1.c | 24 +----------------------- ssl/tls1_clnt.c | 6 +++++- 3 files changed, 8 insertions(+), 35 deletions(-) diff --git a/ssl/ssl.h b/ssl/ssl.h index b287d5aa8..9d9a61463 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -241,10 +241,11 @@ EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd); * can be null if no session resumption is being used or required. This option * is not used in skeleton mode. * @param sess_id_size The size of the session id (max 32) + * @param host_name If non-zero, host name to be sent to server for SNI support * @return An SSL object reference. Use ssl_handshake_status() to check * if a handshake succeeded. */ -EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size); +EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size, const char* host_name); /** * @brief Free any used resources on this connection. @@ -352,16 +353,6 @@ EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl); */ EXP_FUNC int STDCALL ssl_get_config(int offset); -/** - * @brief Sets the hostname to be used for SNI - * @see https://en.wikipedia.org/wiki/Server_Name_Indication - * @param char* hostname - * @return success from the operation - * - 1 on success - * - 0 on failure - */ -EXP_FUNC int STDCALL ssl_set_hostname(SSL *ssl, const char* host_name); - /** * @brief Display why the handshake failed. * diff --git a/ssl/tls1.c b/ssl/tls1.c index e7b8319d0..e581ae0ea 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -251,6 +251,7 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) disposable_free(ssl); certificate_free(ssl); free(ssl->bm_all_data); + free(ssl->host_name); free(ssl); } @@ -1876,29 +1877,6 @@ EXP_FUNC int STDCALL ssl_get_config(int offset) } } -/** - * Sets the SNI hostname - */ -EXP_FUNC int STDCALL ssl_set_hostname(SSL *ssl, const char* host_name) { - if(host_name == NULL || strlen(host_name) == 0 || strlen(host_name) > 255 ) { - return 0; - } - - if(ssl->host_name != NULL) { - free(ssl->host_name); - } - - ssl->host_name = (char *)malloc(strlen(host_name)+1); - if(ssl->host_name == NULL) { - // most probably there was no memory available - return 0; - } - - strcpy(ssl->host_name, host_name); - - return 1; -} - #ifdef CONFIG_SSL_CERT_VERIFICATION /** * Authenticate a received certificate. diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index 2de777f07..c72a2072e 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -48,7 +48,7 @@ static int send_cert_verify(SSL *ssl); * Establish a new SSL connection to an SSL server. */ EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const - uint8_t *session_id, uint8_t sess_id_size) + uint8_t *session_id, uint8_t sess_id_size, const char* host_name) { SSL *ssl = ssl_new(ssl_ctx, client_fd); ssl->version = SSL_PROTOCOL_VERSION_MAX; /* try top version first */ @@ -66,6 +66,10 @@ EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const SET_SSL_FLAG(SSL_SESSION_RESUME); /* just flag for later */ } + if(host_name != NULL && strlen(host_name) > 0 || strlen(host_name) < 255 ) { + ssl->host_name = (char *)strdup(host_name); + } + SET_SSL_FLAG(SSL_IS_CLIENT); do_client_connect(ssl); return ssl; From 3fdea2885d0f8287c81069b5b90cce7a170f0b48 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 19 Apr 2016 08:41:06 +0300 Subject: [PATCH 26/29] Fix Travis build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e948be250..5258cf589 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ script: - source tests/common.sh - arduino --board esp8266com:esp8266:generic --save-prefs - arduino --get-pref sketchbook.path - - build_sketches arduino $ESP8266_ARDUINO_DIR/libraries/ESP8266WiFi/examples/HTTPSRequest + - build_sketches $HOME/arduino_ide $ESP8266_ARDUINO_DIR/libraries/ESP8266WiFi/examples/HTTPSRequest # Feel free to add more test cases (for other environments) here notifications: From 69c757f2a366c79e0ff7385aa7b0bcbec958b2a2 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 19 Apr 2016 09:30:50 +0300 Subject: [PATCH 27/29] Allow plain buffer size increase during handshake --- ssl/tls1.c | 45 +++++++++++++++++++++++---------------------- ssl/tls1.h | 2 +- ssl/tls1_clnt.c | 3 +-- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/ssl/tls1.c b/ssl/tls1.c index e581ae0ea..68c188e10 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -53,7 +53,7 @@ static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len); static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void* cached); static int send_raw_packet(SSL *ssl, uint8_t protocol); static void certificate_free(SSL* ssl); -static int increase_bm_data_size(SSL *ssl); +static int increase_bm_data_size(SSL *ssl, size_t size); /** * The server will pick the cipher based on the order that the order that the @@ -285,6 +285,11 @@ EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len) { int n = out_len, nw, i, tot = 0; /* maximum size of a TLS packet is around 16kB, so fragment */ + + if (ssl->can_free_certificates) { + certificate_free(ssl); + } + do { nw = n; @@ -545,9 +550,9 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) ssl->flag = SSL_NEED_RECORD; ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET; /* space at the start */ ssl->hs_status = SSL_NOT_OK; /* not connected */ - ssl->can_increase_data_size = false; #ifdef CONFIG_ENABLE_VERIFICATION ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx; + ssl->can_free_certificates = false; #endif disposable_new(ssl); @@ -1214,6 +1219,10 @@ int basic_read(SSL *ssl, uint8_t **in_data) int read_len, is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT); uint8_t *buf = ssl->bm_data; + if (ssl->can_free_certificates) { + certificate_free(ssl); + } + read_len = SOCKET_READ(ssl->client_fd, &buf[ssl->bm_read_index], ssl->need_bytes-ssl->got_bytes); @@ -1287,16 +1296,8 @@ int basic_read(SSL *ssl, uint8_t **in_data) if (ssl->need_bytes > ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET) { printf("ssl->need_bytes=%d > %d\r\n", ssl->need_bytes, ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET); - if (ssl->can_increase_data_size) - { - ret = increase_bm_data_size(ssl); - if (ret != SSL_OK) - { - ret = SSL_ERROR_INVALID_PROT_MSG; - goto error; - } - } - else + ret = increase_bm_data_size(ssl, ssl->need_bytes + BM_RECORD_OFFSET - RT_EXTRA); + if (ret != SSL_OK) { ret = SSL_ERROR_INVALID_PROT_MSG; goto error; @@ -1414,24 +1415,22 @@ error: return ret; } -int increase_bm_data_size(SSL *ssl) +int increase_bm_data_size(SSL *ssl, size_t size) { - if (!ssl->can_increase_data_size || - ssl->max_plain_length == RT_MAX_PLAIN_LENGTH) { + if (ssl->max_plain_length == RT_MAX_PLAIN_LENGTH) { return SSL_OK; } - certificate_free(ssl); - free(ssl->bm_all_data); - ssl->bm_data = 0; - ssl->bm_all_data = malloc(RT_MAX_PLAIN_LENGTH + RT_EXTRA); - if (!ssl->bm_all_data) { + size_t required = (size + 1023) & ~(1023); // round up to 1k + required = (required < RT_MAX_PLAIN_LENGTH) ? required : RT_MAX_PLAIN_LENGTH; + uint8_t* new_bm_all_data = (uint8_t*) realloc(ssl->bm_all_data, required + RT_EXTRA); + if (!new_bm_all_data) { printf("failed to grow plain buffer\r\n"); ssl->hs_status = SSL_ERROR_DEAD; return SSL_ERROR_CONN_LOST; } - ssl->can_increase_data_size = false; - ssl->max_plain_length = RT_MAX_PLAIN_LENGTH; + ssl->bm_all_data = new_bm_all_data; ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET; + ssl->max_plain_length = required; return SSL_OK; } @@ -1689,6 +1688,7 @@ void disposable_free(SSL *ssl) free(ssl->dc); ssl->dc = NULL; } + ssl->can_free_certificates = true; } static void certificate_free(SSL* ssl) @@ -1698,6 +1698,7 @@ static void certificate_free(SSL* ssl) x509_free(ssl->x509_ctx); ssl->x509_ctx = 0; } + ssl->can_free_certificates = false; #endif } diff --git a/ssl/tls1.h b/ssl/tls1.h index 7dfb918a9..e03eef9be 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -189,7 +189,7 @@ struct _SSL #endif #ifdef CONFIG_SSL_CERT_VERIFICATION X509_CTX *x509_ctx; - bool can_increase_data_size; + bool can_free_certificates; #endif uint8_t session_id[SSL_SESSION_ID_SIZE]; uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */ diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index c72a2072e..46f9df24b 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -66,7 +66,7 @@ EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const SET_SSL_FLAG(SSL_SESSION_RESUME); /* just flag for later */ } - if(host_name != NULL && strlen(host_name) > 0 || strlen(host_name) < 255 ) { + if(host_name != NULL && strlen(host_name) > 0) { ssl->host_name = (char *)strdup(host_name); } @@ -123,7 +123,6 @@ int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len) case HS_FINISHED: ret = process_finished(ssl, buf, hs_len); - ssl->can_increase_data_size = true; disposable_free(ssl); /* note: client renegotiation is not allowed after this */ break; From cd6c04a809e93da2f2fe861368fea610159612b5 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 10 May 2016 23:00:33 +0800 Subject: [PATCH 28/29] Add hooks to feed watchdog during lengthy bigint operations --- compat/lwipr_compat.c | 3 +++ crypto/bigint.c | 2 ++ ssl/os_port.h | 2 ++ 3 files changed, 7 insertions(+) diff --git a/compat/lwipr_compat.c b/compat/lwipr_compat.c index 834b3f071..a334454fb 100644 --- a/compat/lwipr_compat.c +++ b/compat/lwipr_compat.c @@ -217,6 +217,9 @@ int ax_get_file(const char *filename, uint8_t **buf) { return 0; } +void ax_wdt_feed() { +} + /* * Utility functions */ diff --git a/crypto/bigint.c b/crypto/bigint.c index e9ca04cb9..3d44def09 100644 --- a/crypto/bigint.c +++ b/crypto/bigint.c @@ -1218,6 +1218,7 @@ bigint *bi_mont(BI_CTX *ctx, bigint *bixy) check(bixy); + ax_wdt_feed(); if (ctx->use_classical) /* just use classical instead */ { return bi_mod(ctx, bixy); @@ -1274,6 +1275,7 @@ bigint *bi_barrett(BI_CTX *ctx, bigint *bi) check(bi); check(bim); + ax_wdt_feed(); /* use Classical method instead - Barrett cannot help here */ if (bi->size > k*2) { diff --git a/ssl/os_port.h b/ssl/os_port.h index 73a0e917b..c11ec3bd3 100644 --- a/ssl/os_port.h +++ b/ssl/os_port.h @@ -81,6 +81,8 @@ extern "C" { #define hmac_sha1 ax_hmac_sha1 #define hmac_md5 ax_hmac_md5 +void ax_wdt_feed(); + #elif defined(WIN32) /* Windows CE stuff */ From 139914f31250d8341b6ecdae7e3c8ab3422135a6 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 10 May 2016 23:17:44 +0800 Subject: [PATCH 29/29] Add option for blocking reads --- ssl/ssl.h | 1 + ssl/tls1.c | 37 +++++++++++++++++++++++++------------ ssl/tls1_clnt.c | 3 +++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ssl/ssl.h b/ssl/ssl.h index 9d9a61463..11debcb94 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -83,6 +83,7 @@ extern "C" { #define SSL_DISPLAY_CERTS 0x00200000 #define SSL_DISPLAY_RSA 0x00400000 #define SSL_CONNECT_IN_PARTS 0x00800000 +#define SSL_READ_BLOCKING 0x01000000 /* errors that can be generated */ #define SSL_OK 0 diff --git a/ssl/tls1.c b/ssl/tls1.c index 68c188e10..f8ec6b0a7 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -260,21 +260,23 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) */ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data) { - int ret = basic_read(ssl, in_data); + int ret = SSL_OK; + do { + ret= basic_read(ssl, in_data); - /* check for return code so we can send an alert */ - if (ret < SSL_OK && ret != SSL_CLOSE_NOTIFY) - { - if (ret != SSL_ERROR_CONN_LOST) + /* check for return code so we can send an alert */ + if (ret < SSL_OK && ret != SSL_CLOSE_NOTIFY) { - send_alert(ssl, ret); -#ifndef CONFIG_SSL_SKELETON_MODE - /* something nasty happened, so get rid of this session */ - kill_ssl_session(ssl->ssl_ctx->ssl_sessions, ssl); -#endif + if (ret != SSL_ERROR_CONN_LOST) + { + send_alert(ssl, ret); + #ifndef CONFIG_SSL_SKELETON_MODE + /* something nasty happened, so get rid of this session */ + kill_ssl_session(ssl->ssl_ctx->ssl_sessions, ssl); + #endif + } } - } - + } while (IS_SET_SSL_FLAG(SSL_READ_BLOCKING) && (ssl->got_bytes < ssl->need_bytes) && ret == 0 && !IS_SET_SSL_FLAG(SSL_NEED_RECORD)); return ret; } @@ -558,6 +560,9 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) /* a bit hacky but saves a few bytes of memory */ ssl->flag |= ssl_ctx->options; + if (IS_SET_SSL_FLAG(SSL_CONNECT_IN_PARTS) && IS_SET_SSL_FLAG(SSL_READ_BLOCKING)) { + CLR_SSL_FLAG(SSL_READ_BLOCKING); + } SSL_CTX_LOCK(ssl_ctx->mutex); if (ssl_ctx->head == NULL) @@ -1293,6 +1298,14 @@ int basic_read(SSL *ssl, uint8_t **in_data) ssl->need_bytes = (buf[3] << 8) + buf[4]; /* do we violate the spec with the message size? */ + if (ssl->need_bytes > RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET) + { + printf("ssl->need_bytes=%d violates spec\r\n", ssl->need_bytes, RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET); + ret = SSL_ERROR_INVALID_PROT_MSG; + goto error; + } + + /* is the allocated buffer large enough to handle all the data? if not, increase its size*/ if (ssl->need_bytes > ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET) { printf("ssl->need_bytes=%d > %d\r\n", ssl->need_bytes, ssl->max_plain_length+RT_EXTRA-BM_RECORD_OFFSET); diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index 46f9df24b..c02d903eb 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -124,6 +124,9 @@ int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len) case HS_FINISHED: ret = process_finished(ssl, buf, hs_len); disposable_free(ssl); + if (ssl->ssl_ctx->options & SSL_READ_BLOCKING) { + ssl->flag |= SSL_READ_BLOCKING; + } /* note: client renegotiation is not allowed after this */ break;