diff --git a/CHANGES.md b/CHANGES.md index 8ea8d80..f578f5e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,11 +1,12 @@ MatrixSSL Release Notes -======== +======================= + +Changes in 3.8.6 +---------------- -#Changes in 3.8.6 --------- > **Version 3.8.6** > October 2016 -> *© INSIDE Secure - 2016 - All Rights Reserved* +> (C) Copyright 2016 INSIDE Secure - All Rights Reserved 1. BUG FIXES - Critical parsing bug for X.509 certificates @@ -90,17 +91,19 @@ Added additional field parsing support for X.509, including multiple OU support. ##Removed OpenSSL API Emulation - `opensslApi.c` and `opensslSocket.c` files removed temporarily in anticipation of moving to a more fully supported OpenSSL layer. -#Changes in 3.8.5 --------- +Changes in 3.8.5 +---------------- + > **Version 3.8.5** > September 2016 > *Note: 3.8.5 was a limited customer release only.* -#Changes in 3.8.4 --------- +Changes in 3.8.4 +---------------- + > **Version 3.8.4** > July 2016 -> *© INSIDE Secure - 2016 - All Rights Reserved* +> (C) Copyright 2016 INSIDE Secure - All Rights Reserved 1. FEATURES AND IMPROVEMENTS - Coverity coverage @@ -157,11 +160,12 @@ SSLv3 mode is not recommended for deployment, but had become broken in a recent ## Assembly compatibility with more compilers Fixed "invalid register constraints" error on some versions of GCC and LLVM for ARM, MIPS and x86_64. -#Changes in 3.8.3 --------- +Changes in 3.8.3 +---------------- + > **Version 3.8.3** > April 2016 -> *© INSIDE Secure - 2016 - All Rights Reserved* +> (C) Copyright 2016 INSIDE Secure - All Rights Reserved 1. FEATURES AND IMPROVEMENTS - Simplified Configuration Options @@ -301,11 +305,12 @@ TLS cipher suites with CBC mode in TLS 1.1 and 1.2 could have an access violatio - *Microsoft Windows* targets do not support certificate date validation currently. Users requiring this feature can use Windows APIs to get and parse the current date, using the POSIX implementation as a reference. - *Arm* platforms linking with some versions of *OpenSSL* `libcrypto` library may have errors in AES-CBC cipher suites due to the library's inability to handle in-situ encryption within the same block. -#Changes in 3.8.2 --------- +Changes in 3.8.2 +---------------- + > **Version 3.8.2** > December 2015 -> *© INSIDE Secure - 2015 - All Rights Reserved* +> (C) Copyright 2015 INSIDE Secure - All Rights Reserved 1. FILE/API REORGANIZATION - File Locations diff --git a/Makefile b/Makefile index a2f9245..14317eb 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # # Copyright (c) 2016 INSIDE Secure Corporation. All Rights Reserved. # -# +# @version $Format:%h%d$ # A list of the most important build targets provided by this Makefile: # Make command Description @@ -193,10 +193,20 @@ tests: if make --directory=crypto parse-config | grep -q '#define USE_CMS'; then $(MAKE) --directory=crypto/cms/test;fi # Note apps is also a direct subdirectory -apps: +#ifdef MATRIXSSL_COMMERCIAL + +APPS_ADDITIONAL = apps_crypto + +.PHONY: apps_crypto + +apps_crypto: + if [ -e apps/crypto ];then $(MAKE) --directory=apps/crypto;fi + +#endif /* MATRIXSSL_COMMERCIAL */ + +apps: $(APPS_ADDITIONAL) $(MAKE) --directory=apps/ssl $(MAKE) --directory=apps/dtls - if [ -e apps/crypto ];then $(MAKE) --directory=apps/crypto;fi clean: $(MAKE) clean --directory=core diff --git a/apps/dtls/Makefile b/apps/dtls/Makefile old mode 100755 new mode 100644 diff --git a/apps/ssl/Makefile b/apps/ssl/Makefile old mode 100755 new mode 100644 diff --git a/apps/ssl/XGetopt.c b/apps/ssl/XGetopt.c old mode 100755 new mode 100644 diff --git a/apps/ssl/XGetopt.h b/apps/ssl/XGetopt.h old mode 100755 new mode 100644 diff --git a/apps/ssl/client.c b/apps/ssl/client.c index 680633c..016fa34 100644 --- a/apps/ssl/client.c +++ b/apps/ssl/client.c @@ -1661,7 +1661,7 @@ int32 fetchCRL(psPool_t *pool, char *url, uint32_t urlLen, int hostAddrLen, getReqLen, pageLen; int32 transferred, sawOK, sawContentLength, grown; int32 err, httpUriLen, port, offset; - unsigned char crlChunk[HTTP_REPLY_CHUNK_SIZE]; + unsigned char crlChunk[HTTP_REPLY_CHUNK_SIZE + 1]; unsigned char *crlBin; /* allocated */ uint32_t crlBinLen; @@ -1761,12 +1761,12 @@ int32 fetchCRL(psPool_t *pool, char *url, uint32_t urlLen, and \r\n\r\n for beginning of CRL data. If a recv happens to fall right on the boundary of any of these patterns, the behavior is undefined. There are some asserts sprinked around to notify if this happens. - It SHOULD be sufficient to keep a decent size HTTP_REPLLY_CHUNK_SIZE + It SHOULD be sufficient to keep a decent size HTTP_REPLY_CHUNK_SIZE that you can be pretty sure will hold the entire HTTP header but the "recv" call itself is also a factor in how many bytes will be recevied in the first call */ while ((transferred = recv(fd, crlChunk, HTTP_REPLY_CHUNK_SIZE, 0)) > 0) { - + crlChunk[transferred] = 0; /* Ensure zero termination for strstr(). */ if (crlBin == NULL) { /* Still getting the details of the HTTP response */ /* Did we get an OK response? */ diff --git a/apps/ssl/server.c b/apps/ssl/server.c index cced65b..13c5e09 100644 --- a/apps/ssl/server.c +++ b/apps/ssl/server.c @@ -86,12 +86,13 @@ static int g_disabledCiphers; static uint16_t g_disabledCipher[SSL_MAX_DISABLED_CIPHERS]; #define MAX_KEYFILE_PATH 256 +#define MAX_PASSWORD_LEN MAX_KEYFILE_PATH static char g_keyfilePath[MAX_KEYFILE_PATH]; static char g_privkeyFile[MAX_KEYFILE_PATH]; static char g_identityCert[MAX_KEYFILE_PATH]; static char g_dhParamFile[MAX_KEYFILE_PATH]; static char g_caFile[MAX_KEYFILE_PATH]; -static char g_password[32]; +static char g_password[MAX_PASSWORD_LEN]; static unsigned char g_httpResponseHdr[] = "HTTP/1.0 200 OK\r\n" "Server: MatrixSSL/" MATRIXSSL_VERSION "\r\n" @@ -705,13 +706,13 @@ static int32 process_cmd_options(int32 argc, char **argv) int optionChar, str_len, version, numCiphers; char *cipherListString; - + /* Start with all options zeroized. */ memset(g_keyfilePath, 0, MAX_KEYFILE_PATH); - memset(g_privkeyFile, 0, sizeof(MAX_KEYFILE_PATH)); - memset(g_identityCert, 0, sizeof(MAX_KEYFILE_PATH)); - memset(g_dhParamFile, 0, sizeof(MAX_KEYFILE_PATH)); - memset(g_caFile, 0, sizeof(MAX_KEYFILE_PATH)); - memset(g_password, 0, 32); + memset(g_privkeyFile, 0, MAX_KEYFILE_PATH); + memset(g_identityCert, 0, MAX_KEYFILE_PATH); + memset(g_dhParamFile, 0, MAX_KEYFILE_PATH); + memset(g_caFile, 0, MAX_KEYFILE_PATH); + memset(g_password, 0, MAX_PASSWORD_LEN); g_port = HTTPS_PORT; g_version = 3; diff --git a/common.mk b/common.mk old mode 100755 new mode 100644 index 51cfa04..098607c --- a/common.mk +++ b/common.mk @@ -1,6 +1,6 @@ ## # Common Makefile definitions. -# +# @version $Format:%h%d$ # Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. # #------------------------------------------------------------------------------- diff --git a/core/Makefile b/core/Makefile old mode 100755 new mode 100644 diff --git a/core/coreApi.h b/core/coreApi.h index b9eb38c..a1fa246 100644 --- a/core/coreApi.h +++ b/core/coreApi.h @@ -39,7 +39,11 @@ extern "C" { #endif +#ifdef MATRIX_CONFIGURATION_INCDIR_FIRST +#include /* Must be first included */ +#else #include "coreConfig.h" /* Must be first included */ +#endif #include "osdep.h" #include "list.h" #include "psmalloc.h" diff --git a/core/coreConfig.h b/core/coreConfig.h new file mode 100644 index 0000000..1dc1ecf --- /dev/null +++ b/core/coreConfig.h @@ -0,0 +1,83 @@ +/** + * @file coreConfig.h + * @version $Format:%h%d$ + * + * Configuration settings for Matrix core module. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_CORECONFIG +#define _h_PS_CORECONFIG + + +/******************************************************************************/ +/* Configurable features */ +/******************************************************************************/ +/** + Enable various levels of trace. + When these option is turned off, messages are silently + discarded and their text does not take space in the binary image. +*/ +//#define USE_CORE_TRACE +#ifndef NO_CORE_ERROR + #define USE_CORE_ERROR +#endif +#ifndef NO_CORE_ASSERT + #define USE_CORE_ASSERT +#endif + +/** + If enabled, calls to the psError set of APIs will perform a platform + abort on the exeutable to aid in debugging. +*/ +#ifdef DEBUG +//#define HALT_ON_PS_ERROR /* NOT RECOMMENDED FOR PRODUCTION BUILDS */ +#endif + +/** + Include the psCoreOsdepMutex family of APIs + + @note If intending to compile crypto-cl, then this flag should + always be set. +*/ +#ifndef NO_MULTITHREADING +#define USE_MULTITHREADING +#endif /* NO_MULTITHREADING */ + +/** + Include the psNetwork family of APIs + + These APIs allow simple high-level socket api. + */ +#define USE_PS_NETWORKING + +#endif /* _h_PS_CORECONFIG */ + +/******************************************************************************/ + diff --git a/core/corelib.c b/core/corelib.c index 57c5675..642fcad 100644 --- a/core/corelib.c +++ b/core/corelib.c @@ -309,4 +309,21 @@ void psBurnStack(uint32 len) } /******************************************************************************/ +/* + Free pointed memory and clear the pointer to avoid accidental + double free. +*/ +void psFreeAndClear(void *ptrptr, psPool_t *pool) +{ + void *ptr; + + if (ptrptr != NULL) { + ptr = *(void **)ptrptr; + psFree(ptr, pool); + *(void **)ptrptr = NULL; + PS_PARAMETER_UNUSED(pool); /* Parameter can be unused. */ + } +} + +/******************************************************************************/ diff --git a/crypto/Makefile b/crypto/Makefile old mode 100755 new mode 100644 diff --git a/crypto/cryptoApi.h b/crypto/cryptoApi.h index 30a9bee..9d348c1 100644 --- a/crypto/cryptoApi.h +++ b/crypto/cryptoApi.h @@ -40,7 +40,11 @@ extern "C" { #endif #include "../core/coreApi.h" /* Must be included first */ +#ifdef MATRIX_CONFIGURATION_INCDIR_FIRST +#include /* Must be included second */ +#else #include "cryptoConfig.h" /* Must be included second */ +#endif #include "cryptolib.h" /******************************************************************************/ diff --git a/crypto/cryptoConfig.h b/crypto/cryptoConfig.h new file mode 100644 index 0000000..3a07dc4 --- /dev/null +++ b/crypto/cryptoConfig.h @@ -0,0 +1,217 @@ +/** + * @file cryptoConfig.h + * @version $Format:%h%d$ + * + * Configuration file for crypto features. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_CRYPTOCONFIG +#define _h_PS_CRYPTOCONFIG + +/******************************************************************************/ +/* Configurable features */ +/******************************************************************************/ +/** + Define to enable psTrace*Crypto APIs for debugging the crypto module. +*/ +//#define USE_CRYPTO_TRACE + +#ifdef DEBUG +//#define CRYPTO_ASSERT /**< Extra sanity asserts */ +#endif + +/******************************************************************************/ +/* + Use built-in cryptographic library delivered with MatrixSSL +*/ +#define USE_NATIVE_RSA /* Default built-in software support */ + +/******************************************************************************/ +/** + Security related settings. + + @security MIN_*_BITS is the minimum supported key sizes in bits, weaker + keys will be rejected. +*/ +#define MIN_ECC_BITS 192/**< @security Affects ECC curves below */ + +#define MIN_RSA_BITS 1024 + +#define MIN_DH_BITS 1024 + +#define USE_BURN_STACK/**< @security Zero sensitive data from the stack. */ + +/******************************************************************************/ +/** + Public-Key Algorithm Support. +*/ +#define USE_RSA +#define USE_ECC +#define USE_DH +/**< @note Enable verification of DSA signatures in certificate validation. + Works only when using the CL/SL library. */ +//#define USE_DSA_VERIFY + +/******************************************************************************/ +/** + Build the PKCS and ASN1 extra CL sublibraries. + These are needed by the CL_PKCS API. +*/ + +/******************************************************************************/ + +/** + Define to enable the individual NIST Prime curves. + @see http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf +*/ +#ifdef USE_ECC + #define USE_SECP192R1/**< @security FIPS allowed for sig ver only. */ + #define USE_SECP224R1 + #define USE_SECP256R1/**< @security NIST_SHALL */ + #define USE_SECP384R1/**< @security NIST_SHALL */ + #define USE_SECP521R1 +#endif + +/** + Define to enable the individual Brainpool curves. + @see https://tools.ietf.org/html/rfc5639 + @security WARNING: Public points on Brainpool curves are not validated +*/ +#ifdef USE_ECC +//#define USE_BRAIN224R1 +//#define USE_BRAIN256R1 +//#define USE_BRAIN384R1 +//#define USE_BRAIN512R1 +#endif + +/******************************************************************************/ +/** + Symmetric and AEAD ciphers. + @security Deprecated ciphers must be enabled in cryptolib.h +*/ +//#define USE_AES /* Enable/Disable AES */ +#define USE_AES_CBC +#define USE_AES_GCM + +#ifdef USE_LIBSODIUM +//#define USE_CHACHA20_POLY1305 +#endif + +/** @security 3DES is still relatively secure, however is deprecated for TLS */ +#define USE_3DES + +/******************************************************************************/ +/** + Digest algorithms. + + @note SHA256 and above are used with TLS 1.2, and also used for + certificate signatures on some certificates regardless of TLS version. + + @security MD5 is deprecated, but still required in combination with SHA-1 + for TLS handshakes before TLS 1.2, meaning that the strength is at least + that of SHA-1 in this usage. The only other usage of MD5 by TLS is for + certificate signatures and MD5 based cipher suites. Both of which are + disabled at compile time by default. + + @security SHA1 will be deprecated in the future, but is still required in + combination with MD5 for versions prior to TLS 1.2. In addition, SHA1 + certificates are still commonly used, so SHA1 support may be needed + to validate older certificates. It is possible to completely disable + SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting + only with newer certificates. +*/ +//#define USE_SHA224 /**< @note Used only for cert signature */ +#define USE_SHA256/**< @note Required for TLS 1.2 and above */ +#define USE_HMAC_SHA256 +#define USE_SHA384/**< @pre USE_SHA512 */ +#define USE_HMAC_SHA384 +#define USE_SHA512 + +/** + @security SHA-1 based hashes are deprecated but enabled by default + @note ENABLE_SHA1_SIGNED_CERTS can additionally be configured below. +*/ +#define USE_SHA1 +#define USE_HMAC_SHA1 + +/** + @security MD5 is considered insecure, but required by TLS < 1.2 + @note ENABLE_MD5_SIGNED_CERTS can additionally be configured below. +*/ +#define USE_MD5 +#define USE_MD5SHA1/* Required for < TLS 1.2 Handshake */ +#define USE_HMAC_MD5/* TODO currently needed for prf */ + +/** + @security MD2 is considered insecure, but is sometimes used for + verification of legacy root certificate signatures. + @note MD2 signature verification also requires + ENABLE_MD5_SIGNED_CERTS and USE_MD5. +*/ +//#define USE_MD2 + +/* Please enable, unless using no HMAC algorithms. */ +#define USE_HMAC + +/******************************************************************************/ +/** + X.509 Certificates/PKI +*/ +#define USE_BASE64_DECODE +#define USE_X509 +#define USE_CERT_PARSE/**< Usually required. @pre USE_X509 */ +#define USE_FULL_CERT_PARSE/**< @pre USE_CERT_PARSE */ + /**< Support extra distinguished name attributes that SHOULD be supported according to RFC 5280. */ +//#define USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + /**< Support extra distinguished name attributes not mentioned in RFC 5280. */ +//#define USE_EXTRA_DN_ATTRIBUTES +//#define ENABLE_CA_CERT_HASH /**< Used only for TLS trusted CA ind ext. */ +//#define ENABLE_MD5_SIGNED_CERTS /** @security Accept MD5 signed certs? */ +#define ENABLE_SHA1_SIGNED_CERTS/** @security Accept SHA1 signed certs? */ + /**< @security Allow parsing of locally trusted v1 root certs? */ +//#define ALLOW_VERSION_1_ROOT_CERT_PARSE +#define USE_CRL/***< @pre USE_FULL_CERT_PARSE */ +#define USE_OCSP/**< @pre USE_SHA1 */ + +/******************************************************************************/ +/** + Various PKCS standards support +*/ +#define USE_PRIVATE_KEY_PARSING +//#define USE_PKCS5 /**< v2.0 PBKDF encrypted priv keys. @pre USE_3DES */ +#define USE_PKCS8/* Alternative private key storage format */ +#define USE_PKCS12/**< @pre USE_PKCS8 */ +#define USE_PKCS1_OAEP/* OAEP padding algorithm */ +#define USE_PKCS1_PSS/* PSS padding algorithm */ + +#endif /* _h_PS_CRYPTOCONFIG */ + +/******************************************************************************/ + diff --git a/crypto/digest/digest_libsodium.c b/crypto/digest/digest_libsodium.c old mode 100755 new mode 100644 diff --git a/crypto/digest/digest_libsodium.h b/crypto/digest/digest_libsodium.h old mode 100755 new mode 100644 diff --git a/crypto/keyformat/asn1.h b/crypto/keyformat/asn1.h index 2c44518..19ece9c 100644 --- a/crypto/keyformat/asn1.h +++ b/crypto/keyformat/asn1.h @@ -33,9 +33,13 @@ /******************************************************************************/ +/* Allow inclusion of asn1.h as standalone. */ +#ifndef _h_PS_CRYPTOAPI +#include "../cryptoApi.h" +#endif /* _h_PS_CRYPTOAPI */ + #ifndef _h_PS_ASN1 #define _h_PS_ASN1 -#include "../cryptoConfig.h" /******************************************************************************/ /* diff --git a/crypto/keyformat/pkcs.c b/crypto/keyformat/pkcs.c index 19f6de8..358c5c3 100644 --- a/crypto/keyformat/pkcs.c +++ b/crypto/keyformat/pkcs.c @@ -187,6 +187,11 @@ int32 pkcs8ParsePrivBin(psPool_t *pool, unsigned char *buf, int32 size, int32 icount; #endif /* USE_PKCS5 */ + /* Check for too large (invalid) inputs, unparseable with uint16_t */ + if (size > 65535) { + return PS_FAILURE; + } + p = buf; end = p + size; @@ -299,9 +304,11 @@ int32 pkcs8ParsePrivBin(psPool_t *pool, unsigned char *buf, int32 size, /* PrivateKeyInfo per PKCS#8 Section 6. */ if (getAsnSequence(&p, (int32)(end - p), &seqlen) < 0) { psTraceCrypto("Initial PrivateKeyInfo parse failure\n"); +#ifdef USE_PKCS5 if (pass) { psTraceCrypto("Is it possible the password is incorrect?\n"); } +#endif /* USE_PKCS5 */ return PS_FAILURE; } /* Version */ @@ -404,8 +411,6 @@ int32 pkcs8ParsePrivBin(psPool_t *pool, unsigned char *buf, int32 size, goto PKCS8_FAIL; } } - } else if (plen < 0) { - goto PKCS8_FAIL; } return PS_SUCCESS; @@ -641,7 +646,8 @@ static int32 pkcs12import(psPool_t *pool, const unsigned char **buf, int32 rc, oi, asnint; uint32_t keyLen, ivLen; uint16_t tmplen, tmpint; - short armor, cipher; + short cipher; + const short armor = PBE12; *plaintext = NULL; *ptLen = 0; @@ -659,7 +665,6 @@ static int32 pkcs12import(psPool_t *pool, const unsigned char **buf, if (oi == OID_PKCS_PBESHA40RC2) { #ifdef USE_RC2 - armor = PBE12; cipher = AUTH_SAFE_RC2; keyLen = 8; #else @@ -667,7 +672,6 @@ static int32 pkcs12import(psPool_t *pool, const unsigned char **buf, return PS_UNSUPPORTED_FAIL; #endif } else if (oi == OID_PKCS_PBESHA3DES3) { - armor = PBE12; cipher = AUTH_SAFE_3DES; keyLen = DES3_KEYLEN; } else { @@ -716,11 +720,6 @@ static int32 pkcs12import(psPool_t *pool, const unsigned char **buf, } return PS_UNSUPPORTED_FAIL; } - - } else { - /* PBES2 */ - psTraceCrypto("Error PBES2 unsupported\n"); - return PS_UNSUPPORTED_FAIL; } /* Got the keys but we still need to find the start of the encrypted data. @@ -960,7 +959,7 @@ static int32 parseSafeContents(psPool_t *pool, unsigned char *password, } if ((rc = psX509ParseCert(pool, p, tmplen, &currCert, CERT_STORE_UNPARSED_BUFFER)) < 0) { - psX509FreeCert(*cert); + psX509FreeCert(currCert); *cert = NULL; psTraceCrypto("Couldn't parse certificate from CertBag\n"); return rc; @@ -1772,6 +1771,7 @@ int32_t pkcs3ParseDhParamFile(psPool_t *pool, const char *fileName, psDhParams_t p = pemOut = psMalloc(pool, baseLen); if (p == NULL) { psError("Memory allocation error in pkcs3ParseDhParamFile\n"); + psFree(dhFileBuf, pool); return PS_MEM_FAIL; } diff --git a/crypto/keyformat/x509.c b/crypto/keyformat/x509.c index b01736c..f64e2fb 100644 --- a/crypto/keyformat/x509.c +++ b/crypto/keyformat/x509.c @@ -4653,6 +4653,33 @@ static int32_t parse_nonce_ext(const unsigned char *p, size_t sz, return PS_SUCCESS; /* No parsing errors detected. */ } +static void parseSingleResponseRevocationTimeAndReason( + const unsigned char *p, + uint16_t glen, + mOCSPSingleResponse_t *res) +{ + /* Note: res has to have been cleared before this function. + The function does not fill-in the relevant fields if they are + not found. */ + + /* get revocation time ASN.1 (GeneralizedTime / 0x18) */ + if (glen >= sizeof(res->revocationTime) + 2 && + p[0] == 0x18 && p[1] == sizeof(res->revocationTime)) { + memcpy(res->revocationTime, p + 2, + sizeof(res->revocationTime)); + /* revocationReason [0] EXPLICIT CRLReason OPTIONAL + CRLReason ::= ENUMERATED [RFC 5280] */ + if (glen >= sizeof(res->revocationTime) + 0x5 && + p[17] == 0xa0 && /* [0] */ + p[18] == 0x03 && /* length */ + p[19] == 0x0a && /* ENUMERATED */ + p[20] == 0x01 && /* length */ + p[21] <= 10 && /* CRL reason code 0-10, excluding 7. */ + p[21] != 7) { + res->revocationReason = p[21]; + } + } +} static int32_t parseSingleResponse(uint32_t len, const unsigned char **cp, const unsigned char *end, mOCSPSingleResponse_t *res) @@ -4749,19 +4776,8 @@ static int32_t parseSingleResponse(uint32_t len, const unsigned char **cp, psTraceCrypto("Initial parseSingleResponse parse failure\n"); return PS_PARSE_FAIL; } - /* get revocation time. */ - if (p[0] == 0x18 && p[1] == sizeof(res->revocationTime) && - glen >= sizeof(res->revocationTime) + 2) { - memcpy(res->revocationTime, p + 2, - sizeof(res->revocationTime)); - if (glen >= sizeof(res->revocationTime) + 0x5 && - p[17] == 0xa0 && p[18] == 0x03 && - p[19] == 0x0a && p[20] == 0x01 && p[21] >= 0 && - p[21] <= 10 && p[21] != 7) { - res->revocationReason = p[21]; - } - } - /* skip the rest of revocation info */ + /* subfunction for parsing RevokedInfo. */ + parseSingleResponseRevocationTimeAndReason(p, glen, res); p += glen; } else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) { res->certStatus = 2; @@ -5255,11 +5271,12 @@ int32_t checkOCSPResponseDates(mOCSPResponse_t *response, ok = 0; if (subjectResponse->nextUpdate != NULL) { + /* Next update provided, OCSP is valid until that time. */ ok &= parsedate_ocsp(subjectResponse->nextUpdate, ASN_GENERALIZEDTIME, subjectResponse->nextUpdateLen, nextUpdate); - } else { + } else if (ok) { /* If there is no next update, the server supports continous updates and nextUpdate time is considered identical to the this update time. */ diff --git a/crypto/pubkey/dh.c b/crypto/pubkey/dh.c index a8944df..59af8d6 100644 --- a/crypto/pubkey/dh.c +++ b/crypto/pubkey/dh.c @@ -197,7 +197,7 @@ int32_t psDhImportPubKey(psPool_t *pool, { int32_t rc; - memset(&key->priv, 0x0, sizeof(psDhKey_t)); + memset(&key->priv, 0, sizeof(key->priv)); if ((rc = pstm_init_for_read_unsigned_bin(pool, &key->pub, inlen)) < 0) { return rc; } diff --git a/crypto/symmetric/symmetric_libsodium.c b/crypto/symmetric/symmetric_libsodium.c old mode 100755 new mode 100644 diff --git a/crypto/symmetric/symmetric_libsodium.h b/crypto/symmetric/symmetric_libsodium.h old mode 100755 new mode 100644 diff --git a/crypto/test/Makefile b/crypto/test/Makefile old mode 100755 new mode 100644 diff --git a/crypto/test/algorithmTest.c b/crypto/test/algorithmTest.c index 3dff677..8153e2a 100644 --- a/crypto/test/algorithmTest.c +++ b/crypto/test/algorithmTest.c @@ -2201,6 +2201,7 @@ int32 psSha256Test2(void) psSha256Init(&md3); psSha256Update(&md3, array, 32768); psSha256Update(&md3, array, 32768); + psSha256PreInit(&md4); psSha256Init(&md4); psSha256Update(&md4, array, 32768); psSha256Update(&md4, array, 32768); diff --git a/crypto/test/dhperf/Makefile b/crypto/test/dhperf/Makefile old mode 100755 new mode 100644 diff --git a/crypto/test/eccperf/Makefile b/crypto/test/eccperf/Makefile old mode 100755 new mode 100644 diff --git a/crypto/test/rsaperf/Makefile b/crypto/test/rsaperf/Makefile old mode 100755 new mode 100644 diff --git a/doc/MatrixSSL_API.pdf b/doc/MatrixSSL_API.pdf index ffdf352..5c5911b 100644 Binary files a/doc/MatrixSSL_API.pdf and b/doc/MatrixSSL_API.pdf differ diff --git a/doc/MatrixSSL_EllipticCurveCiphers.pdf b/doc/MatrixSSL_EllipticCurveCiphers.pdf index 9a4096c..15ecce3 100644 Binary files a/doc/MatrixSSL_EllipticCurveCiphers.pdf and b/doc/MatrixSSL_EllipticCurveCiphers.pdf differ diff --git a/doc/matrixssl_dev_guide.md b/doc/matrixssl_dev_guide.md index c4bfdc9..6011833 100644 --- a/doc/matrixssl_dev_guide.md +++ b/doc/matrixssl_dev_guide.md @@ -1,25 +1,21 @@ ---- -layout: doc -title: MatrixSSL Developer's Guide -wrap_title: ---- +#MatrixSSL Developer's Guide -# MatrixSSL Developer's Guide +![INSIDE Secure](http://www.insidesecure.com/extension/isinside/design/front/images/logo.png) **Version 3.8** *© INSIDE Secure - 2016 - All Rights Reserved* -# 1 OVERVIEW +[TOC] -This developer’s guide is a general SSL/TLS overview and a MatrixSSL specific integration reference for adding SSL security into an application. +#1 OVERVIEW +This developer's guide is a general SSL/TLS overview and a MatrixSSL specific integration reference for adding SSL security into an application. This document is primarily intended for the software developer performing MatrixSSL integration into their custom application but is also a useful reference for anybody wishing to learn more about MatrixSSL or the SSL/TLS protocol in general. For additional information on the APIs discussed here please see the _MatrixSSL API_ document included in this package. -## 1.1 Nomenclature +##1.1 Nomenclature +MatrixSSL supports both the TLS and SSL protocols. Despite the difference in acronym, TLS 1.0 is simply version 3.1 of SSL. There are no practical security differences between the protocols, and only minor differences in how they are implemented. It was felt that ‘Transport Layer Security’ was a more appropriate name than ‘Secure Sockets Layer’ going forward beyond SSL 3.0. In this documentation, the term SSL is used generically to mean SSL/TLS, and TLS is used to indicate specifically the TLS protocol. SSL 2.0 is deprecated and not supported. MatrixSSL supports SSL 3.0, TLS 1.0, TLS 1.1 and TLS 1.2 protocols. In addition, the DTLS protocol is based closely on TLS 1.1 and beyond. -MatrixSSL supports both the TLS and SSL protocols. Despite the difference in acronym, TLS 1.0 is simply version 3.1 of SSL. There are no practical security differences between the protocols, and only minor differences in how they are implemented. It was felt that ‘Transport Layer Security’ was a more appropriate name than ‘Secure Sockets Layer’ going forward beyond SSL 3.0. In this documentation, the term SSL is used generically to mean SSL/TLS, and TLS is used to indicate specifically the TLS protocol. SSL 2.0 is deprecated and not supported. MatrixSSL supports SSL 3.0, TLS 1.0, TLS 1.1 and TLS 1.2 protocols. In addition, the DTLS protocol is based closely on TLS 1.1 and beyond. - -## 1.2 Supported RFCs +##1.2 Supported RFCs The following TLS RFCs are implemented by MatrixSSL. @@ -80,8 +76,7 @@ Supported Point Formats: [RFC 5469](https://tools.ietf.org/html/rfc5469) DES and IDEA Cipher Suites for Transport Layer Security (TLS) : These ciphers are removed per spec: - -> ...the single-DES cipher suites SHOULD NOT be implemented by TLS libraries ...the IDEA cipher suite SHOULD NOT be implemented by TLS libraries and SHOULD be removed from existing implementations. +> ...the single-DES cipher suites SHOULD NOT be implemented by TLS libraries ...the IDEA cipher suite SHOULD NOT be implemented by TLS libraries and SHOULD be removed from existing implementations. [RFC 5487](https://tools.ietf.org/html/rfc5487) Pre-Shared Key Cipher Suites for TLS with SHA-256/384 and AES Galois Counter Mode : Supported: @@ -141,8 +136,7 @@ Supported Point Formats: [draft-ietf-tls-falsestart](https://datatracker.ietf.org/doc/draft-ietf-tls-falsestart/) Transport Layer Security (TLS) False Start : Supported. Disabled by default due to security concerns. [See False Start below](#21-ssltls-version-security). -## 1.3 Currently Unsupported RFCs - +##1.3 Currently Unsupported RFCs The following "Proposed Standard RFCs" for TLS are not currently supported. Numerous "Experimental" and "Informational" RFCs are not listed here. [RFC 2712](https://tools.ietf.org/html/rfc2712) Addition of Kerberos Cipher Suites to Transport Layer Security (TLS) [RFC 4785](https://tools.ietf.org/html/rfc4785) Pre-Shared Key (PSK) Ciphersuites with NULL Encryption for Transport Layer Security (TLS) @@ -157,10 +151,8 @@ The following "Proposed Standard RFCs" for TLS are not currently supported. Nume [RFC 7633](https://tools.ietf.org/html/rfc7685) X.509v3 Transport Layer Security (TLS) Feature Extension [RFC 7685](https://tools.ietf.org/html/rfc7685) A Transport Layer Security (TLS) ClientHello Padding Extension -## 1.4 Supported Cipher Suites - +##1.4 Supported Cipher Suites Supported suites in priority order (not all suites are enabled by default): - ``` TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 @@ -208,9 +200,7 @@ TLS_PSK_WITH_AES_128_CBC_SHA256 TLS_PSK_WITH_AES_256_CBC_SHA TLS_PSK_WITH_AES_128_CBC_SHA ``` - Deprecated, disabled by default: - ``` SSL_RSA_WITH_RC4_128_SHA TLS_RSA_WITH_SEED_CBC_SHA @@ -223,18 +213,15 @@ TLS_DH_anon_WITH_AES_128_CBC_SHA SSL_DH_anon_WITH_3DES_EDE_CBC_SHA SSL_DH_anon_WITH_RC4_128_MD5 ``` - -# 2 SECURITY CONSIDERATIONS - +#2 SECURITY CONSIDERATIONS Prior to working directly with the MatrixSSL library there are some critical SSL security concepts that application integrators should be familiar with. -## 2.1 SSL/TLS Version Security - +##2.1 SSL/TLS Version Security Although TLS 1.0 and above can be considered secure if configured correctly, several weaknesses have been discovered in some versions and cipher combinations. For an overview, see: [RFC7457 Summarizing Known Attacks on Transport Layer Security (TLS) and Datagram TLS (DTLS)](https://tools.ietf.org/html/rfc7457) -> Timing and Power Attacks +>Timing and Power Attacks >: While attempts are made for constant-time operation, the MatrixSSL crypto library is not explicitly designed to be resilient to every type of timing, cache and power attack. If these are a concern, MatrixSSL TLS protocol library has support for hardware crypto, DPA resistant tokens, and hardened software crypto implementations. All of the issues discovered below are mitigated by default in MatrixSSL. Additionally, SSL 3.0 and weak ciphers and key strengths are disabled by default in MatrixSSL to reduce version downgrade attacks and the padding oracle attack (POODLE). TLS 1.0 is also disabled by default at compile time in an effort to move protocol support forward. @@ -299,17 +286,16 @@ MD5 Certificate Weakness SHA1 Certificate Weakness : `ENABLE_SHA1_SIGNED_CERTS` can be disabled. Many certificates still use SHA1, so enabling may introduce compatibility issues with certain hosts. -## 2.2 Selecting Cipher Suites +##2.2 Selecting Cipher Suites +The strength of the secure communications is primarily determined by the choice of cipher suites that will be supported. A cipher suite determines how two peers progress through an SSL handshake as well as how the final application data will be encrypted over the secure connection. The four components of any given cipher suite are key exchange, authentication, encryption and digest hash. -The strength of the secure communications is primarily determined by the choice of cipher suites that will be supported. A cipher suite determines how two peers progress through an SSL handshake as well as how the final application data will be encrypted over the secure connection. The four components of any given cipher suite are key exchange, authentication, encryption and digest hash. +Key exchange mechanisms refer to how the peers agree upon a common symmetric key that will be used to encrypt data after handshaking is complete. The two common key exchange algorithms are RSA and Diffie-Hellman (DH or ECDH). Currently, when Diffie-Hellman is chosen it is used almost exclusively in ephemeral mode (DHE or ECDHE) in which new private key pairs are generated for each connection to allow perfect forward secrecy. The trade-off for DHE is a much slower SSL handshake as key generation is a relatively processor-intensive operation. Some older protocols also specify DH, as it was the first widely publicized key exchange algorithm. The elliptic curve variations on the Diffie-Hellman algorithms are denoted ECDH or ECDHE in the cipher suite name. -Key exchange mechanisms refer to how the peers agree upon a common symmetric key that will be used to encrypt data after handshaking is complete. The two common key exchange algorithms are RSA and Diffie-Hellman (DH or ECDH). Currently, when Diffie-Hellman is chosen it is used almost exclusively in ephemeral mode (DHE or ECDHE) in which new private key pairs are generated for each connection to allow perfect forward secrecy. The trade-off for DHE is a much slower SSL handshake as key generation is a relatively processor-intensive operation. Some older protocols also specify DH, as it was the first widely publicized key exchange algorithm. The elliptic curve variations on the Diffie-Hellman algorithms are denoted ECDH or ECDHE in the cipher suite name. +Authentication algorithms specify how the peers will prove their identities to each other. Authentication options within cipher suites are RSA, DSA, Elliptic Curve DSA (ECDSA), Pre-shared Key (PSK), or anonymous if no authentication is required. RSA has the unique property that it can be used for both key exchange and authentication. For this reason, RSA has become the most widely implemented cipher suite mechanism for SSL communications. RSA key strengths of between 1024 and 2048 bits are the most common. -Authentication algorithms specify how the peers will prove their identities to each other. Authentication options within cipher suites are RSA, DSA, Elliptic Curve DSA (ECDSA), Pre-shared Key (PSK), or anonymous if no authentication is required. RSA has the unique property that it can be used for both key exchange and authentication. For this reason, RSA has become the most widely implemented cipher suite mechanism for SSL communications. RSA key strengths of between 1024 and 2048 bits are the most common. +The encryption component of the cipher suite identifies which symmetric cipher is to be used when exchanging data at the completion of the handshake. The AES block cipher is recommended for new implementations, and is the most likely to have hardware acceleration support. -The encryption component of the cipher suite identifies which symmetric cipher is to be used when exchanging data at the completion of the handshake. The AES block cipher is recommended for new implementations, and is the most likely to have hardware acceleration support. - -Finally, the digest hash is the choice of checksum algorithm used to confirm the integrity of exchanged data, with SHA-1 being the most common and SHA256 recommended for new implementations. Here is a selection of cipher suites that illustrate how to identify the four components. +Finally, the digest hash is the choice of checksum algorithm used to confirm the integrity of exchanged data, with SHA-1 being the most common and SHA256 recommended for new implementations. Here is a selection of cipher suites that illustrate how to identify the four components. Cipher Suite|Key Exchange|Auth Type|Encryption|MAC ---|---|---|---|--- @@ -374,40 +360,37 @@ Suite Type|Auth|Exchange|Ok?|Typical Risks `RSA`|RSA|RSA|Yes|The most commonly used authentication method. Supported by X.509 PKI infrastructure. Additional security can be had by directly comparing `RSA` key IDs to trusted Key Ids (similar to Certificate Pinning). Usually faster than ECC based authentication. `DHE_RSA`|RSA|Diffie-Hellman Ephemeral|Yes|RSA for authentication, Ephemeral DH for key exchange. Provides [perfect forward secrecy](http://en.wikipedia.org/wiki/Forward_secrecy). `DHE_PSK`|PSK|Diffie-Hellman Ephemeral|Yes|PSK for authentication, Ephemeral DH for key exchange. Does not rely on X.509. -`ECDH_ECDSA`|ECC DSA|ECC Diffie-Hellman|Yes|ECC DSA for authentication, ECC for key exchange. Most commonly used in embedded devices supporting hardware based ECC support. -`ECDH_RSA`|RSA|ECC Diffie-Hellman|Yes|ECC key exchange, with RSA authentication. Uses widely deployed X.509 RSA certificate infrastructure, but ECC for key exchange. Not often deployed due to the implementation having to support ECC and RSA. +`ECDH_ECDSA`|ECC DSA|ECC Diffie-Hellman|Yes|ECC DSA for authentication, ECC for key exchange. Most commonly used in embedded devices supporting hardware based ECC support. +`ECDH_RSA`|RSA|ECC Diffie-Hellman|Yes|ECC key exchange, with RSA authentication. Uses widely deployed X.509 RSA certificate infrastructure, but ECC for key exchange. Not often deployed due to the implementation having to support ECC and RSA. `ECDHE_ECDSA`|ECC DSA|ECC Diffie-Hellman Ephemeral|Yes|ECC key exchange with ephemeral keys, ECC DSA authentication. Most commonly used in embedded devices supporting hardware based ECC support. `ECDHE_RSA`|RSA|ECC Diffie-Hellman Ephemeral|Yes|Ephemeral counterpart to ECDH_RSA. -## 2.3 Authentication Mode +##2.3 Authentication Mode +By default in SSL, it is the server that is authenticated by a client. It is easiest to remember this when thinking about purchasing a product online with a credit card over an HTTPS (SSL) connection. The client Web browser must authenticate the server in order to be confident the credit card information is being sent to a trusted source. This is referred to as one-way authentication or server authentication and is performed as part of all standard SSL connections (unless, of course, a cipher suite with an authentication type of anonymous has been agreed upon). -By default in SSL, it is the server that is authenticated by a client. It is easiest to remember this when thinking about purchasing a product online with a credit card over an HTTPS (SSL) connection. The client Web browser must authenticate the server in order to be confident the credit card information is being sent to a trusted source. This is referred to as one-way authentication or server authentication and is performed as part of all standard SSL connections (unless, of course, a cipher suite with an authentication type of anonymous has been agreed upon). - -However, in some use-case scenarios the user may require that both peers authenticate each other. This is referred to as mutual authentication or client authentication. If the project requires client authentication there is an additional set of key material that must be used to support it as described in the next section. +However, in some use-case scenarios the user may require that both peers authenticate each other. This is referred to as mutual authentication or client authentication. If the project requires client authentication there is an additional set of key material that must be used to support it as described in the next section. Client authentication is also done inherently in Pre-shared Key cipher suites, as both sides of a connection must have a common shared secret. -## 2.4 Authentication and Key Exchange +##2.4 Authentication and Key Exchange -### 2.4.1 Server and Client Authentication +###2.4.1 Server and Client Authentication +With a cipher suite and authentication mode chosen, the user will need to obtain or generate the necessary key material for supporting the authentication and key exchange mechanisms. X.509 is the standard for how key material is stored in certificate files. -With a cipher suite and authentication mode chosen, the user will need to obtain or generate the necessary key material for supporting the authentication and key exchange mechanisms. X.509 is the standard for how key material is stored in certificate files. +The peer that is being authenticated must have a private key and a public certificate. The peer performing the authentication must have the Certificate Authority (CA) certificate that was used to issue the public certificate. In the standard one-way authentication scenario this means the server will load a private key and certificate while the client will load the CA file. -The peer that is being authenticated must have a private key and a public certificate. The peer performing the authentication must have the Certificate Authority (CA) certificate that was used to issue the public certificate. In the standard one-way authentication scenario this means the server will load a private key and certificate while the client will load the CA file. - -If client authentication is needed the mirror image of CA, certificate, and private key files must also be used. This chart shows which files clients and server must load when using a standard RSA based cipher suite such as `TLS_RSA_WITH_AES_256_GCM_SHA384`. +If client authentication is needed the mirror image of CA, certificate, and private key files must also be used. This chart shows which files clients and server must load when using a standard RSA based cipher suite such as `TLS_RSA_WITH_AES_256_GCM_SHA384`. Authentication Mode|Server Key Files|Client Key Files ---|---|--- One-way server authentication|RSA server certificate file and corresponding RSA private key file.|Certificate Authority certificate file that issued the server certificate Additions for client authentication|Certificate Authority certificate file that issued the client certificate|RSA client certificate file and corresopnding RSA private key file. -### 2.4.2 Certificate Validation and Authentication - +###2.4.2 Certificate Validation and Authentication Authentication in SSL is most often based on X.509 Certificate chain validation. -Example [Equifax GeoTrust](https://www.geotrust.com/resources/root-certificates/) trusted root certificate loaded by a MatrixSSL client with `matrixSslLoadRsaKeys`. +Example [Equifax GeoTrust](https://www.geotrust.com/resources/root-certificates/) trusted root certificate loaded by a MatrixSSL client with `matrixSslLoadRsaKeys`. -> `Subject: C=US, O=Equifax, OU=Equifax Secure Certificate Authority` +>**Subject: C=US, O=Equifax, OU=Equifax Secure Certificate Authority** *Authority KeyId*:48:E6:68:F9:2B:D2:B2:95... [Valid, self-signed OK for root] *Subject KeyId*: 48:E6:68:F9:2B:D2:B2:95... *Basic Constraints*: critical CA:TRUE [Valid, this certificate can sign others] @@ -416,24 +399,22 @@ Example [Equifax GeoTrust](https://www.geotrust.com/resources/root-certificates/ Certificate chain sent to a MatrixSSL client during SSL handshake Certificate message by remote server https://www.google.com. -> `C=US, O=GeoTrust Inc., CN=GeoTrust Global CA` +>**C=US, O=GeoTrust Inc., CN=GeoTrust Global CA** *Issuer*: C=US, O=Equifax, OU=Equifax Secure Certificate Authority [Valid, matches a loaded trusted root subject] *Authority KeyId*: 48:E6:68:F9:2B:D2:B2:95... [Valid, matches the Issuer Subject KeyId] *Subject KeyId*: C0:7A:98:68:8D:89:FB:AB... *Basic Constraints*: critical CA:TRUE [Valid, this certificate can sign others] *Key Usage*: critical Certificate Sign, CRL Sign [Valid, able to sign certificates] *Validity*: (May 21 04:00:00 2002 GMT to Aug 21 04:00:00 2018 GMT) [Valid] - ->> `C=US, O=Google Inc, CN=Google Internet Authority G2` +>>**C=US, O=Google Inc, CN=Google Internet Authority G2** *Issuer*: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA [Valid, matches parent subject] *Authority KeyId*: C0:7A:98:68:8D:89:FB:AB... [Valid, matches the Issuer Subject KeyId] *Subject KeyId*: 4A:DD:06:16:1B:BC:F6:68... -*Validity*: (Apr 5 15:15:55 2013 GMT to Apr 4 15:15:55 2015 GMT) [Valid] +*Validity*: (Apr 5 15:15:55 2013 GMT to Apr 4 15:15:55 2015 GMT) [Valid] *Basic Constraints*: critical CA:TRUE, pathlen:0 [Valid, this certificate can sign others and the signed certificate is not also a CA] *Key Usage*: critical Certificate Sign, CRL Sign [Valid, able to sign certificates] *Version*: 3 [Valid] - ->>> `C=US, ST=California, L=Mountain View, O=Google Inc, CN=*.google.com` +>>>**C=US, ST=California, L=Mountain View, O=Google Inc, CN=*.google.com** *Issuer*: C=US, O=Google Inc, CN=Google Internet Authority G2 [Valid, matches parent subject] *X509v3 Basic Constraints*: critical CA:FALSE [Valid, this is a leaf cert] *Extended Key Usage*: TLS Web Server Authentication, TLS Web Client Authentication [Valid] @@ -451,7 +432,7 @@ Issuer|In a chain, issuer must match the subject of the immediate (following) pa Validity|Current date must be within notBefore and notAfter range on all certs in the chain. Time is not currently validated. On platforms without a date function, the range check is always flagged as failed and must be handled by the *Certificate Validation Callback*. For platforms without a date API, validation must be done within the user *Certificate Validation Callback*. Subject|Common name must contain only printable characters. Common name will be validated via full match to expectedName, if provided in `matrixSslNewClientSession`. Partial match not allowed. Wildcard match is allowed for the first segment of a DNS name. More complex validation must be done within the user *Certificate Validation Callback*. Subject Public Key Info|RSA and ECC keys supported. RSA public key modulus must be at least `MIN_RSA_SIZE` bits. ECC public key must be at least `MIN_ECC_SIZE` bits. -Signature|The hash of the certificate contents must match the hash that is signed by the `Issuer Public Key`. +Signature|The hash of the certificate contents must match the hash that is signed by the `Issuer Public Key`. Basic Constraints|For Root or intermediate certs, must be marked `Critical` with `CA:TRUE`. Path Length constraints are validated. Key Usage|For Root or intermediate certs, must be marked for use as `CertificateSign`. For CRL checks, `CrlSign` flag must be set. Extended Key Usage|If marked Critical, must have `TLS Web Server Authentication` or `TLS Web Client Authentication` set in the leaf certificate. @@ -462,44 +443,39 @@ CRL Distribution Points|If USE_CRL is defined, `matrixSslGetCRL` will download t CRL Validation|CRL file must be signed by certificate with `CrlSign` Basic constraints. MD5 signatures not supported by default. Unknown Extensions|Unknown extensions are ignored, unless flagged as `Critical`. Validation will fail for any Critical extension unrecognized by MatrixSSL. -For information on how to create Certificate Authority root and child certificates please see the _Matrix Key and Cert Generation_ Utilities document. +In _MatrixSSL Commercial Edition_, Certificate Authority root and child certificates can be created using the provided command-line tools and API. For more information, please consult the _Matrix Key and Cert Generation Utilities_ and _MatrixSSL Certificates and Certificate Revocation Lists_ documents. -# 3 APPLICATION INTEGRATION FLOW - -MatrixSSL is a C code library that provides a security layer for client and server applications allowing them to securely communicate with other SSL enabled peers. MatrixSSL is transport agnostic and can just as easily integrate with an HTTP server as it could with a device communicating through a serial port. For simplicity, this developer’s guide will assume a socket-based implementation for all its examples unless otherwise noted. +#3 APPLICATION INTEGRATION FLOW +MatrixSSL is a C code library that provides a security layer for client and server applications allowing them to securely communicate with other SSL enabled peers. MatrixSSL is transport agnostic and can just as easily integrate with an HTTP server as it could with a device communicating through a serial port. For simplicity, this developer's guide will assume a socket-based implementation for all its examples unless otherwise noted. The term application in this document refers to the peer (client or server) application the MatrixSSL library is being integrated into. -This section will detail the specific points in the application life cycle where MatrixSSL should be integrated. In general, MatrixSSL APIs are used for initialization/cleanup, when new secure connections are being established (handshaking), and when encrypting/decrypting messages exchanged with peers. +This section will detail the specific points in the application life cycle where MatrixSSL should be integrated. In general, MatrixSSL APIs are used for initialization/cleanup, when new secure connections are being established (handshaking), and when encrypting/decrypting messages exchanged with peers. -Refer to the MatrixSSL API document to get familiar with the interface to the library and with the example code to see how they are used at implementation. Follow the guidelines below when using these APIs to integrate MatrixSSL into an application. +Refer to the MatrixSSL API document to get familiar with the interface to the library and with the example code to see how they are used at implementation. Follow the guidelines below when using these APIs to integrate MatrixSSL into an application. -## 3.1 `ssl_t` Structure +##3.1 `ssl_t` Structure +The `ssl_t` structure holds the state and keys for each client or server connection as well as buffers for encoding and decoding SSL data. The buffers are dynamically managed internally to make the integration with existing non-secure software easier. SSL is a record based protocol, and the internal buffer management makes a better 'impedance match' with classic stream based protocols. For example, data may be read from a socket, but if a full SSL record has not been received, no data is available for the caller to process. This partial record is held within the `ssl_t` buffer. The MatrixSSL API is also designed so there are no buffer copies, and the caller is able to read and write network data directly into the SSL buffers, providing a very low memory overhead per session. -The `ssl_t` structure holds the state and keys for each client or server connection as well as buffers for encoding and decoding SSL data. The buffers are dynamically managed internally to make the integration with existing non-secure software easier. SSL is a record based protocol, and the internal buffer management makes a better “impedance match” with classic stream based protocols. For example, data may be read from a socket, but if a full SSL record has not been received, no data is available for the caller to process. This partial record is held within the `ssl_t` buffer. The MatrixSSL API is also designed so there are no buffer copies, and the caller is able to read and write network data directly into the SSL buffers, providing a very low memory overhead per session. +##3.2 Initialization +MatrixSSL must be initialized as part of the application initialization with a call to `matrixSslOpen`. This function sets up the internal structures needed by the library. -## 3.2 Initialization - -MatrixSSL must be initialized as part of the application initialization with a call to `matrixSslOpen`. This function sets up the internal structures needed by the library. - -In most cases, the application will subsequently load the key material from the file system. RSA or EC certificates, Diffie-Hellman parameters, and Pre-Shared Keys for the specific peer application must be parsed before creating a new SSL session. The `matrixSslNewKeys` function is used to allocate the key storage and `matrixSslLoadRsaKeys`, `matrixSslLoadEcKeys`, `matrixSslLoadDhParams`, and `matrixSslLoadPsk` are used to parse the key material into the `sslKeys_t` structure during initialization. The populated key structure will be used as an input parameter to `matrixSslNewClientSession` or `matrixSslNewServerSession`. -The allocation and loading of the `sslKeys_t` structure is most commonly done a single time at start and the application uses those keys for each connection. Alternatively, a new `sslKeys_t` structure can be allocated once for each secure connection and freed immediately after the connection is closed. This should be done if the application has multiple certificate files depending on the identity of the connecting entity or if there is a security concern with keeping the RSA keys in memory for extended periods of time. +In most cases, the application will subsequently load the key material from the file system. RSA or EC certificates, Diffie-Hellman parameters, and Pre-Shared Keys for the specific peer application must be parsed before creating a new SSL session. The `matrixSslNewKeys` function is used to allocate the key storage and `matrixSslLoadRsaKeys`, `matrixSslLoadEcKeys`, `matrixSslLoadDhParams`, and `matrixSslLoadPsk` are used to parse the key material into the `sslKeys_t` structure during initialization. The populated key structure will be used as an input parameter to `matrixSslNewClientSession` or `matrixSslNewServerSession`. +The allocation and loading of the `sslKeys_t` structure is most commonly done a single time at start and the application uses those keys for each connection. Alternatively, a new `sslKeys_t` structure can be allocated once for each secure connection and freed immediately after the connection is closed. This should be done if the application has multiple certificate files depending on the identity of the connecting entity or if there is a security concern with keeping the RSA keys in memory for extended periods of time. Once the application is done with the keys, the associated memory is freed with a call to `matrixSslDeleteKeys`. -## 3.3 Creating a Session +##3.3 Creating a Session +The next MatrixSSL integration point in the application is when a new session is starting. In the case of a client, this is whenever it chooses to begin one because SSL is a client-initiated protocol (like HTTP). In the case of a server, a new session should be started when the server accepts an incoming connection from a client on a secure port. In a socket based application, this would typically happen when the accept socket call returns with a valid incoming socket. The application sets up a new session with the API `matrixSslNewClientSession` or `matrixSslNewServerSession`. The returned `ssl_t` context will become the input parameter for all public APIs that act at a per-session level. -The next MatrixSSL integration point in the application is when a new session is starting. In the case of a client, this is whenever it chooses to begin one because SSL is a client-initiated protocol (like HTTP). In the case of a server, a new session should be started when the server accepts an incoming connection from a client on a secure port. In a socket based application, this would typically happen when the accept socket call returns with a valid incoming socket. The application sets up a new session with the API `matrixSslNewClientSession` or `matrixSslNewServerSession`. The returned `ssl_t` context will become the input parameter for all public APIs that act at a per-session level. +The required input parameters to the session creation APIs differ based on whether the application is assuming a server or client role. Both require a populated keys structure (discussed in the previous section) but a client can also nominate a specific cipher suite or session ID when starting a session. The ciphers that the server will accept are determined at compile time. +The client should also always nominate a certificate callback function during `matrixSslNewClientSession`. This callback function will be invoked mid-handshake to allow the user to inspect the key material, date and other certificate information sent from the server. For detailed information on this callback function, see the API documentation for the _Certificate Validation Callback Function_ section. -The required input parameters to the session creation APIs differ based on whether the application is assuming a server or client role. Both require a populated keys structure (discussed in the previous section) but a client can also nominate a specific cipher suite or session ID when starting a session. The ciphers that the server will accept are determined at compile time. -The client should also always nominate a certificate callback function during `matrixSslNewClientSession`. This callback function will be invoked mid-handshake to allow the user to inspect the key material, date and other certificate information sent from the server. For detailed information on this callback function, see the API documentation for the _Certificate Validation Callback Function_ section. +The server may also choose to nominate a certificate callback function if client authentication is desired. The MatrixSSL library must have been compiled with `USE_CLIENT_AUTH` defined in order to use this parameter in the `matrixSslNewServerSession` function. -The server may also choose to nominate a certificate callback function if client authentication is desired. The MatrixSSL library must have been compiled with `USE_CLIENT_AUTH` defined in order to use this parameter in the `matrixSslNewServerSession` function. +For clients wishing to quickly (and securely) reconnect to a server that it has recently connected to, there is an optional sessonId parameter that may be used to initiate a faster resumed handshake (the cpu intensive public key exchange is omitted). To use the session parameter, a client should allocate a `sslSessionId_t` structure with `matrixSslNewSessionId` and pass it to `matrixSslNewClientSession` during the initial connection with the server. Over the course of the session negotiation, the MatrixSSL library will populate that structure behind-the-scenes so that during the next connection the same sessionId parameter address can be used to initiate the resumed session. -For clients wishing to quickly (and securely) reconnect to a server that it has recently connected to, there is an optional sessonId parameter that may be used to initiate a faster resumed handshake (the cpu intensive public key exchange is omitted). To use the session parameter, a client should allocate a `sslSessionId_t` structure with `matrixSslNewSessionId` and pass it to `matrixSslNewClientSession` during the initial connection with the server. Over the course of the session negotiation, the MatrixSSL library will populate that structure behind-the-scenes so that during the next connection the same sessionId parameter address can be used to initiate the resumed session. - -## 3.4 Handshaking - -During client session initialization with `matrixSslNewClientSession` the SSL handshake message `CLIENT_HELLO` is encoded to the internal outgoing buffer. The client now needs to send this message to the server over a communication channel. +##3.4 Handshaking +During client session initialization with `matrixSslNewClientSession` the SSL handshake message `CLIENT_HELLO` is encoded to the internal outgoing buffer. The client now needs to send this message to the server over a communication channel. The sequence of events that should always be used to transmit pending handshake data is as follows: 1. The user calls `matrixSslGetOutdata` to retrieve the encoded data and number of bytes to be sent @@ -515,39 +491,38 @@ The sequence of events that should always be used when expecting handshake data 3. The application calls `matrixSslReceivedData` to process the data 4. The application examines the return code from `matrixSslReceivedData` to determine the next step -All incoming messages should be copied into the provided buffer and passed to `matrixSslReceivedData`, which processes the message and drives the handshake through the built-in SSLv3 or TLS state machine. The parameters include the SSL context and the number of bytes that have been received. The return code from `matrixSslReceivedData` tells the application what the message was and how it is to be handled: +All incoming messages should be copied into the provided buffer and passed to `matrixSslReceivedData`, which processes the message and drives the handshake through the built-in SSLv3 or TLS state machine. The parameters include the SSL context and the number of bytes that have been received. The return code from `matrixSslReceivedData` tells the application what the message was and how it is to be handled: `MATRIXSSL_REQUEST_SEND` -: Success. The processing of the received data resulted in an SSL response message that needs to be sent to the peer. If this return code is hit the user should call `matrixSslGetOutdata` to retrieve the encoded outgoing data. +: Success. The processing of the received data resulted in an SSL response message that needs to be sent to the peer. If this return code is hit the user should call `matrixSslGetOutdata` to retrieve the encoded outgoing data. `MATRIXSSL_REQUEST_RECV` -: Success. More data must be received and this function must be called again. User must first call `matrixSslGetReadbuf` again to receive the updated buffer pointer and length to where the remaining data should be read into. +: Success. More data must be received and this function must be called again. User must first call `matrixSslGetReadbuf` again to receive the updated buffer pointer and length to where the remaining data should be read into. `MATRIXSSL_HANDSHAKE_COMPLETE` -: Success. The SSL handshake is complete. This return code is returned to client side implementation during a full handshake after parsing the `FINISHED` message from the server. It is possible for a server to receive this value if a resumed handshake is being performed where the client sends the final `FINISHED` message. +: Success. The SSL handshake is complete. This return code is returned to client side implementation during a full handshake after parsing the `FINISHED` message from the server. It is possible for a server to receive this value if a resumed handshake is being performed where the client sends the final `FINISHED` message. `MATRIXSSL_RECEIVED_ALERT` -: Success. The data that was processed was an SSL alert message. In this case, the ptbuf pointer will be two bytes (ptLen will be 2) in which the first byte will be the alert level and the second byte will be the alert description. After examining the alert, the user must call `matrixSslProcessedData` to indicate the alert was processed and the data may be internally discarded. +: Success. The data that was processed was an SSL alert message. In this case, the ptbuf pointer will be two bytes (ptLen will be 2) in which the first byte will be the alert level and the second byte will be the alert description. After examining the alert, the user must call `matrixSslProcessedData` to indicate the alert was processed and the data may be internally discarded. `MATRIXSSL_APP_DATA` -: Success. The data that was processed was application data that the user should process. In this return code case the ptbuf and ptLen output parameters will be valid. The user may process the data directly from ptbuf or copy it aside for later processing. After handling the data the user must call `matrixSslProcessedData` to indicate the plain text data may be internally discarded +: Success. The data that was processed was application data that the user should process. In this return code case the ptbuf and ptLen output parameters will be valid. The user may process the data directly from ptbuf or copy it aside for later processing. After handling the data the user must call `matrixSslProcessedData` to indicate the plain text data may be internally discarded `PS_SUCCESS` -: Success. This return code will be returned if the bytes parameter is 0 and there is no remaining internal data to process. This could be useful as a polling mechanism to confirm the internal buffer is empty. One real life use-case for this method of invocation is when dealing with a *Google Chrome* browser that uses *False Start*. +: Success. This return code will be returned if the bytes parameter is 0 and there is no remaining internal data to process. This could be useful as a polling mechanism to confirm the internal buffer is empty. One real life use-case for this method of invocation is when dealing with a *Google Chrome* browser that uses *False Start*. `< 0` -: Failure. See API documentation +: Failure. See API documentation -## 3.5 Communicating Securely With Peers - -### 3.5.1 Encrypting Data +##3.5 Communicating Securely With Peers +###3.5.1 Encrypting Data Once the handshake is complete, the application wishing to encrypt data that will be sent to the peer has the choice between two encoding options. **In-Situ Encryption** -An in-situ encryption occurs when the outputted cipher text overwrites the plain text during the encoding process. In this case, the user will retrieve an allocated buffer from the MatrixSSL library, populate the buffer with the desired plaintext, and then notify the library that the plaintext is ready to be encoded. The API steps for the in-situ method are as follows: +An in-situ encryption occurs when the outputted cipher text overwrites the plain text during the encoding process. In this case, the user will retrieve an allocated buffer from the MatrixSSL library, populate the buffer with the desired plaintext, and then notify the library that the plaintext is ready to be encoded. The API steps for the in-situ method are as follows: -1. The application first determines the length of the plaintext that needs to be sent +1. The application first determines the length of the plaintext that needs to be sent 2. The application calls `matrixSslGetWritebuf` with that length to retrieve a pointer to an internally allocated buffer. 3. The application writes the plaintext into the buffer and then calls `matrixSslEncodeWritebuf` to encrypt the plaintext 4. The application calls `matrixSslGetOutdata` to retrieve the encoded data and length to be sent (SSL always adds some overhead to the message size) @@ -555,43 +530,40 @@ An in-situ encryption occurs when the outputted cipher text overwrites the plain 6. The application calls `matrixSslSentData` with the number of bytes that were actually sent **User provided plaintext data location** -The alternative to in-situ encryption is to allow the user to provide the location and length of the plaintext data that needs to be encoded. In this case, the encrypted data is still written to the internal MatrixSSL out data buffer but the user provided plaintext data is left untouched. The API steps for this method are as follows: +The alternative to in-situ encryption is to allow the user to provide the location and length of the plaintext data that needs to be encoded. In this case, the encrypted data is still written to the internal MatrixSSL out data buffer but the user provided plaintext data is left untouched. The API steps for this method are as follows: 1. The user passes the plaintext and length to `matrixSslEncodeToOutdata` 2. The application calls `matrixSslGetOutdata` to retrieve the encoded data and length to be sent (SSL always adds some overhead to the message size) 3. The application sends the out data buffer contents to the peer. 4. The application calls `matrixSslSentData` with the # of bytes that were actually sent -### 3.5.2 Decrypting Data - +###3.5.2 Decrypting Data The sequence of events that should always be used when expecting application data from a peer is as follows: 1. The application calls `matrixSslGetReadbuf` to retrieve an allocated buffer 2. The application copies the incoming data into that buffer 3. The application calls `matrixSslReceivedData` to process the data -4. The application confirms the return code from `matrixSslReceivedData` is `MATRIXSSL_APP_DATA` and parses `ptLen` bytes of the returned plain text +4. The application confirms the return code from `matrixSslReceivedData` is `MATRIXSSL_APP_DATA` and parses `ptLen` bytes of the returned plain text 5. If the return code does not indicate application data, handle the return code as described in the handshaking section above. 6. The application calls `matrixSslProcessedData` to inform the library it is finished with the plaintext and checks to see if there are additional records in the buffer to process. -## 3.6 Ending a Session +##3.6 Ending a Session +When the application receives notice that the session is complete or has determined itself that the session is complete, it should notify the other side, close the socket and delete the session. Calling `matrixSslEncodeClosureAlert` and `matrixSslDeleteSession` will perform this step. -When the application receives notice that the session is complete or has determined itself that the session is complete, it should notify the other side, close the socket and delete the session. Calling `matrixSslEncodeClosureAlert` and `matrixSslDeleteSession` will perform this step. +A call to `matrixSslEncodeClosureAlert` is an optional step that will encode an alert message to pass along to the other side to inform them to close the session cleanly. The closure alert buffer is retrieved and sent using the same `matrixSslGetOutdata` then `matrixSslSentData` mechanism that all outgoing data uses. Since the connection is being closed, the application shouldn’t block indefinitely on sending the closure alert. -A call to `matrixSslEncodeClosureAlert` is an optional step that will encode an alert message to pass along to the other side to inform them to close the session cleanly. The closure alert buffer is retrieved and sent using the same `matrixSslGetOutdata` then `matrixSslSentData` mechanism that all outgoing data uses. Since the connection is being closed, the application shouldn’t block indefinitely on sending the closure alert. +##3.7 Closing the Library +At application exit the MatrixSSL library should be un-initialized with a call to `matrixSslClose`. If the application has called `matrixSsNewKeys` as part of the initialization process and kept its keys in memory it should call `matrixSslDeleteKeys` before calling `matrixSslClose`. Also, any existing SSL sessions should be freed by calling `matrixSslDeleteSession` before calling `matrixSslClose`. -## 3.7 Closing the Library +Example implementations of MatrixSSL client and server applications integration can be found in the apps subdirectory of the distribution package. -At application exit the MatrixSSL library should be un-initialized with a call to `matrixSslClose`. If the application has called `matrixSsNewKeys` as part of the initialization process and kept its keys in memory it should call `matrixSslDeleteKeys` before calling `matrixSslClose`. Also, any existing SSL sessions should be freed by calling `matrixSslDeleteSession` before calling `matrixSslClose`. - -Example implementations of MatrixSSL client and server applications integration can be found in the apps subdirectory of the distribution package. - -# 4 CONFIGURABLE FEATURES - -MatrixSSL contains a set of optional features that are configurable at compile time. This allows the user to remove unneeded functionality to reduce code size footprint and disable potentially insecure features. Each of these options are pre-processor defines that can be disabled by simply commenting out the #define in the header files or by using the -D compile flag during build. APIs with dependencies on optional features are highlighted in the Define Dependencies sub-section in the API documentation for that function. +#4 CONFIGURABLE FEATURES +MatrixSSL contains a set of optional features that are configurable at compile time. This allows the user to remove unneeded functionality to reduce code size footprint and disable potentially insecure features. Each of these options are pre-processor defines that can be disabled by simply commenting out the #define in the header files or by using the -D compile flag during build. APIs with dependencies on optional features are highlighted in the Define Dependencies sub-section in the API documentation for that function. *Not all configurable options are listed below. See comments directly in configuration header files for more fine-tuning.* -## 4.1 Protocol and Performance +##4.1 Protocol and Performance + `USE_CLIENT_SIDE_SSL` : matrixsslConfig.h - Enables client side SSL support @@ -608,10 +580,10 @@ MatrixSSL contains a set of optional features that are configurable at compile t : Support DTLS connections (TLS over UDP) in addition to TLS. DTLS version support is based on the underlying level of TLS support. `SSL_SESSION_TABLE_SIZE` -: matrixsslConfig.h – Applicable to servers only. The size of the session resumption table for caching session identifiers. Old entries will be overwritten when size is reached +: matrixsslConfig.h – Applicable to servers only. The size of the session resumption table for caching session identifiers. Old entries will be overwritten when size is reached `SSL_SESSION_ENTRY_LIFE` -: matrixsslConfig.h – Applicable to servers only. The time in seconds that a session identifier will be valid in the session table. A value of 0 will disable SSL resumption. Also applies to the lifetime of Stateless Session Tickets, below. +: matrixsslConfig.h – Applicable to servers only. The time in seconds that a session identifier will be valid in the session table. A value of 0 will disable SSL resumption. Also applies to the lifetime of Stateless Session Tickets, below. `USE_STATELESS_SESSION_TICKETS` : matrixsslConfig.h – Enable stateless session tickets as defined in RFC 5077 @@ -622,13 +594,13 @@ MatrixSSL contains a set of optional features that are configurable at compile t : Disabled by default. `REQUESTED_MAX_PLAINTEXT_RECORD_LEN` -: matrixsslConfig.h – Enable the “max_fragment_length” TLS extension defined in RFC 4366. Value of #define determines fragment length (server may reject) +: matrixsslConfig.h – Enable the “max_fragment_length” TLS extension defined in RFC 4366. Value of #define determines fragment length (server may reject) `USE_CLIENT_AUTH` -: matrixsslConfig.h - Enables two-way(mutual) authentication +: matrixsslConfig.h - Enables two-way(mutual) authentication `SERVER_CAN_SEND_EMPTY_CERT_REQUEST` -: matrixsslConfig.h – A client authentication feature. Allows the server to send an empty CertificateRequest message if no CA files have been loaded +: matrixsslConfig.h – A client authentication feature. Allows the server to send an empty CertificateRequest message if no CA files have been loaded `SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG` : matrixsslConfig.h – A client authentication feature. Allows the server to ‘downgrade’ a client authentication handshake to a standard handshake if client does not provide a certificate @@ -637,16 +609,23 @@ MatrixSSL contains a set of optional features that are configurable at compile t : matrixsslConfig.h - Enable Application Level Protocol Negotiation. Also must be enabled via runtime option for new client sessions. `USE_TRUSTED_CA_INDICATION` -: matrixsslConfig.h - Enable this RFC. +: matrixsslConfig.h - Enable the Trusted CA Indication extension defined in RFC 6066. `USE_OCSP` `USE_OCSP_MUST_STAPLE` : cryptoConfig.h and matrixsslConfig.h respectively. Enable OCSP and require OCSP stapling. -`MIN_RSA_SIZE` -`MIN_DH_SIZE` -`MIN_ECC_SIZE` -: cryptoConfig.h – The minimum size in bits that MatrixSSL will accept for key exchange for each algorithm. Prevents weak keys from being used or downgraded to. +`USE_X509` +: cryptoConfig.h - Enables basic support for X.509 certificates. + +`USE_CERT_PARSE` +: cryptoConfig.h - Enables X.509 certificate parsing. + +`USE_FULL_CERT_PARSE` +: cryptoConfig.h - Enables the parsing of some additional certificate extensions, such as nameConstraints and authorityInfoAccess. + +`USE_CERT_GEN` +: cryptoConfig.h - _(MatrixSSL Commercial Edition only:)_ Enables X.509 certificate generation. `ENABLE_MD5_SIGNED_CERTS` `ENABLE_SHA1_SIGNED_CERTS` @@ -655,6 +634,26 @@ MatrixSSL contains a set of optional features that are configurable at compile t `USE_CRL` : cryptoConfig.h - Enable Certificate Revocation List APIs. +`USE_FIPS_CRYPTO` +`USE_CL_CRYPTO` +: cryptoConfig.h - _(MatrixSSL FIPS Edition only:)_ Enable using the FIPS 140-2 validated SafeZone CL/FIPSLib 1.1 as the cryptographic library in MatrixSSL. For more information on FIPS 140-2 specific configuration options, please consult the _MatrixSSL with CL Library_ document, included with the _MatrixSSL FIPS Edition_. + +`USE_CMS` +: cryptoConfig.h - _(MatrixSSL Commercial Edition only:)_ Enable support for Cryptographic Messaging Syntax (CMS). + +`USE_RSA` +`USE_ECC` +`USE_DH` +: cryptoConfig.h - Enable RSA, ECC and DH support, respectively. + +`USE_DSA_VERIFY` +: cryptoConfig.h - _(MatrixSSL FIPS Edition only:)_ Enable verification of DSA signatures in certificate validation. + +`MIN_RSA_SIZE` +`MIN_DH_SIZE` +`MIN_ECC_SIZE` +: cryptoConfig.h – The minimum size in bits that MatrixSSL will accept for key exchange for each algorithm. Prevents weak keys from being used or downgraded to. + `USE_PRIVATE_KEY_PARSING` : cryptoConfig.h - Enables X.509 private key parsing @@ -670,11 +669,21 @@ MatrixSSL contains a set of optional features that are configurable at compile t `USE_BEAST_WORKAROUND` : matrixssllib.h – Enabled by default. See code comments in file. +`ENABLE_FALSE_START` +: matrixsslConfig.h - Disabled by default. See code comments in file. + +`NO_ECC_EPHEMERAL_CACHE` +: matrixsslConfig.h - By default, MatrixSSL caches the ECDHE keys it generates and re-uses the cached keys for connections within a certain time frame and a certain usage count. This improves performance of ECDHE suites, and is in line with the configuration current web browsers. Enabling NO_ECC_EPHEMERAL_CACHE disables the key caching and forces new ECDHE keys to be created for every TLS connection. Note that caching ECDHE keys is against some standards such as NIST SP 800-56A, and disallowed in the FIPS 140-2 mode of operation. NO_ECC_EPHEMERAL_CACHE is disabled by default. + +`ECC_EPHEMERAL_CACHE_SECONDS` +`ECC_EPHEMERAL_CACHE_USAGE` +: matrixssllib.h - The maximum time period and usage count of a cached ECDHE key. After these limits have been exceeded, the key will be removed from the cache. + `USE_1024_KEY_SPEED_OPTIMIZATIONS` `USE_2048_KEY_SPEED_OPTIMIZATIONS` `PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM` `PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED` -: crypto/layer/layer.h - RSA and Diffie-Hellman speed vs. runtime memory tradeoff. By default these will be enabled if the compiler is invoked with optimization that is not for size (eg. `-O1 to -O3`). They will be disabled for `-O0` and `-Os`. +: crypto/layer/layer.h - RSA and Diffie-Hellman speed vs. runtime memory tradeoff. By default these will be enabled if the compiler is invoked with optimization that is not for size (eg. `-O1 to -O3`). They will be disabled for `-O0` and `-Os`. `PS_AES_IMPROVE_PERF_INCREASE_CODESIZE` `PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE` @@ -688,9 +697,8 @@ MatrixSSL contains a set of optional features that are configurable at compile t `USE_MULTITHREADING` : coreConfig.h: Enable if using MatrixSSL with a multithreading client or server, where session cache may be shared between threads simultaneously. -## 4.2 Public Key Math Assembly Optimizations - -Optimizing assembly code for low level math operations is available for many common processor architectures. The files _pstm_montgomery_reduce.c_, _pstm_mul_comba.c_, and _pstm_sqr_comba.c_ in the _crypto/math_ directory implement the available assembly optimizations. These following defines are set in the _osdep.h_ header file by detecting the platform. These should be set accordingly when porting to an unsupported platform. +##4.2 Public Key Math Assembly Optimizations +Optimizing assembly code for low level math operations is available for many common processor architectures. The files _pstm_montgomery_reduce.c_, _pstm_mul_comba.c_, and _pstm_sqr_comba.c_ in the _crypto/math_ directory implement the available assembly optimizations. These following defines are set in the _osdep.h_ header file by detecting the platform. These should be set accordingly when porting to an unsupported platform. `PSTM_X86` : 32-bit x86 processor @@ -710,12 +718,11 @@ Optimizing assembly code for low level math operations is available for many com *None of the above* : Standard C code implementation -## 4.3 Debug Configuration - -MatrixSSL contains a set of optional debug features that are configurable at compile time. Each of these options are pre-processor defines that can be disabled by simply commenting out the `#define` in the specified header files. +##4.3 Debug Configuration +MatrixSSL contains a set of optional debug features that are configurable at compile time. Each of these options are pre-processor defines that can be disabled by simply commenting out the `#define` in the specified header files. `HALT_ON_PS_ERROR` -: coreConfig.h - Enables the osdepBreak platform function whenever a psError trace function is called. Helpful in debug environments. +: coreConfig.h - Enables the osdepBreak platform function whenever a psError trace function is called. Helpful in debug environments. `USE_CORE_ERROR` `USE_CORE_ASSERT` @@ -731,8 +738,13 @@ MatrixSSL contains a set of optional debug features that are configurable at com `USE_SSL_INFORMATIONAL_TRACE` : matrixsslConfig.h - Enables SSL function level debug trace for troubleshooting connection problems. -## 4.4 Minimum Firmware Configuration +`USE_DTLS_DEBUG_TRACE` +: matrixsslConfig.h - Enables DTLS-specific trace messages for troubleshooting connection problems. +`DTLS_SEND_RECORDS_INDIVIDUALLY` +: matrixsslConfig.h - If enabled, each DTLS handshake message will be returned individually when matrixDtlsGetOutdata is called. When left disabled, the default behaviour of matrixDtlsGetOutdata is to return as much data as possible that fits within the maximum PMTU. + +##4.4 Minimum Firmware Configuration MatrixSSL can be built to a minimum size using TLS 1.2, PSK cipher with AES128 and SHA256. If interoperability with *OpenSSL* is desired, this standard cipher suite is not implemented (as of 1.0.1j). In this case, `USE_SHA` must also be defined and the cipher suite changed to `USE_TLS_PSK_WITH_AES_256_CBC_SHA` or `USE_TLS_PSK_WITH_AES_128_CBC_SHA`. @@ -761,23 +773,31 @@ Optional: For *OpenSSL* compatibility, enable: `USE_TLS_PSK_WITH_AES_256_CBC_SHA` or `USE_TLS_PSK_WITH_AES_128_CBC_SHA` -**Code + Data Size ARM Thumb 2 Results:** +**Code + Data Size ARM Thumb 2 Results:** `PSK_AES128_SHA256` | `PSK_AES128_SHA1` :---:|:---: 24,108 B | 25,771 B -# 5 SSL HANDSHAKING +##4.5 Example configurations -The core of SSL security is the handshake protocol that allows two peers to authenticate and negotiate symmetric encryption keys. A handshake is defined by the specific sequence of SSL messages that are exchanged between the client and server. A collection of messages being sent from one peer to another is called a flight. +MatrixSSL ships with a few example configurations, which are described here. _MatrixSSL FIPS edition_ contains additional example configurations; these are described in the _MatrixCrypto CL_ document included in that distribution. -## 5.1 Standard Handshake +Configuration|Comment +---|--- +default|The default configuration +nonfips|Same as default +noecc|Disables ECC support +rsaonly|Disables ECC and DH support +tls|The recommended configuration for TLS -The standard handshake is the most common and allows a client to authenticate a server. There are four flights in the standard handshake. +These configurations can be applied with the commands _make all-nonfips_, _make all-noecc_, _make all-rsaonly_ and _make all-tls_, respectively. Applying a new configuration will override the existing _./core/coreConfig.h_, _./crypto/cryptoConfig.h_, and _./matrixssl/matrixsslConfig.h_ files. After applying the configuration, these files can be further adapted per specific needs and the MatrixSSL can be compiled as usual, via the make commands described in the _MatrixSSL Getting Started_ document. -![Standard Handshake](/assets/svg/handshake.svg) +#5 SSL HANDSHAKING +The core of SSL security is the handshake protocol that allows two peers to authenticate and negotiate symmetric encryption keys. A handshake is defined by the specific sequence of SSL messages that are exchanged between the client and server. A collection of messages being sent from one peer to another is called a flight. - - **Client Notes** -The client is the first to send and the last to receive. Therefore, a MatrixSSL implementation of a client must be testing for the `MATRIXSSL_HANDSHAKE_COMPLETE` return code from `matrixSslReceivedData` to determine when application data is ready to be encrypted and sent to the server. When a client wishes to begin a standard handshake, `matrixSslNewClientSession` will be called with an empty sessionId. +The client is the first to send and the last to receive. Therefore, a MatrixSSL implementation of a client must be testing for the `MATRIXSSL_HANDSHAKE_COMPLETE` return code from `matrixSslReceivedData` to determine when application data is ready to be encrypted and sent to the server. When a client wishes to begin a standard handshake, `matrixSslNewClientSession` will be called with an empty sessionId. -## 5.2 Client Authentication Handshake - -The client authentication handshake allows a two-way authentication. There are four flights in the client authentication handshake. - -![Client Auth Handshake](/assets/svg/handshake_clientauth.svg) - - - **Client Notes** -The client is the first to send and the last to receive. Therefore, a MatrixSSL implementation of a client must be testing for the `MATRIXSSL_HANDSHAKE_COMPLETE` return code from `matrixSslReceivedData` to determine when application data is ready to be encrypted and sent to the server. +The client is the first to send and the last to receive. Therefore, a MatrixSSL implementation of a client must be testing for the `MATRIXSSL_HANDSHAKE_COMPLETE` return code from `matrixSslReceivedData` to determine when application data is ready to be encrypted and sent to the server. In order to participate in a client authentication handshake, the client must have loaded a Certificate Authority file during the call to `matrixSslLoadRsaKeys`. **Server Notes** -To prepare for a client authentication handshake the server must nominate a certificate and private key during the call to `matrixSslLoadRsaKeys`. The actual determination of whether or not to perform a client authentication handshake is made when nominating a certificate callback parameter when invoking `matrixSslNewServerSession`. If the callback is provided, a client authentication handshake will be requested. - -## 5.3 Session Resumption Handshake - -Session resumption enables a previously connected client to quickly resume a session with a server. Session resumption is much faster than other handshake types because public key authentication is not performed (authentication is implicit since both sides will be using secret information from the previous connection). This handshake types has three flights. - -![Resumed Handshake](/assets/svg/handshake_resumed.svg) - - - **Client Notes** -The client is the first and the last to send data. Therefore, a MatrixSSL implementation of a client must be testing for the `MATRIXSSL_HANDSHAKE_COMPLETE` return code from `matrixSslSentData` to determine when application data is ready to be encrypted and sent to the server. +The client is the first and the last to send data. Therefore, a MatrixSSL implementation of a client must be testing for the `MATRIXSSL_HANDSHAKE_COMPLETE` return code from `matrixSslSentData` to determine when application data is ready to be encrypted and sent to the server. The client initiates a session resumption handshake by reusing the same `sessionId_t` structure from a previously connected session when calling `matrixSslNewClientSession`. **Server Notes** -The MatrixSSL server will cache a `SSL_SESSION_TABLE_SIZE` number of session IDs for resumption. The length of time a session ID will remain in the case is determined by `SSL_SESSION_ENTRY_LIFE`. Also, the server sends the `FINISHED` message first in this case, which is different from the standard handshake. - -## 5.4 Other Handshakes +The MatrixSSL server will cache a `SSL_SESSION_TABLE_SIZE` number of session IDs for resumption. The length of time a session ID will remain in the case is determined by `SSL_SESSION_ENTRY_LIFE`. Also, the server sends the `FINISHED` message first in this case, which is different from the standard handshake. +##5.4 Other Handshakes Other cipher suites can require variations on the handshake flights. PSK cipher suites do not use any key exchange. DSA cipher suites do not use certificates, and DH/DHE/ECDH/ECDHE cipher suites may or may not use certificates for authentication. -## 5.5 Re-Handshakes +##5.5 Re-Handshakes +A re-handshake is a handshake over a currently connected SSL session. A re-handshake may take the form of a standard handshake, a client authentication handshake, or a resumed handshake. Either the client or server may initiate a re-handshake. -A re-handshake is a handshake over a currently connected SSL session. A re-handshake may take the form of a standard handshake, a client authentication handshake, or a resumed handshake. Either the client or server may initiate a re-handshake. +>Re-handshaking is not often used and can be the source of cross protocol attacks and implementation bugs. MatrixSSL by default disables the `USE_REHANDSHAKING` option at compile time to reduce code size and complexity. -> Re-handshaking is not often used and can be the source of cross protocol attacks and implementation bugs. MatrixSSL by default disables the `USE_REHANDSHAKING` option at compile time to reduce code size and complexity. +The `matrixSslEncodeRehandshake` API is used to initiate a re-handshake. The three most common reasons for initiating re-handshakes are: -The `matrixSslEncodeRehandshake` API is used to initiate a re-handshake. The three most common reasons for initiating re-handshakes are: +1. *Re-key the symmetric cryptographic material* +Re-keying the symmetric keys adds an extra level of security for applications that require the connection be open for long periods of time or transferring large amounts of data. Periodic changes to the keys can discourage hackers who are mounting timing attacks on a connection. +2. *Perform a client authentication handshake* +A scenario may arise in which the server requires that the data being exchanged is only allowed for a client whose certificate has been authenticated, but the original negotiation took place without client authentication. In order to do a client authenticated re-handshake the server must call matrixSslEncodeRehandshake with a certificate callback parameter. +3. *Change cipher spec* +The cipher suite may be changed on a connected session using a re-handshake if needed. The client must call matrixSslEncodeRehandshake with the new cipherSpec. -1. *Re-key the symmetric cryptographic material* -Re-keying the symmetric keys adds an extra level of security for applications that require the connection be open for long periods of time or transferring large amounts of data. Periodic changes to the keys can discourage hackers who are mounting timing attacks on a connection. -2. *Perform a client authentication handshake* -A scenario may arise in which the server requires that the data being exchanged is only allowed for a client whose certificate has been authenticated, but the original negotiation took place without client authentication. In order to do a client authenticated re-handshake the server must call matrixSslEncodeRehandshake with a certificate callback parameter. -3. *Change cipher spec* -The cipher suite may be changed on a connected session using a re-handshake if needed. The client must call matrixSslEncodeRehandshake with the new cipherSpec. +###5.5.1 Disable Re-Handshaking At Runtime +Global disabling of re-handshakes can be controlled at compile time using the `USE_REHANDSHAKING` define but sometimes a per-session control of the feature is required. In these cases, the `matrixSslDisableRehandshakes` and `matrixSslReEnableRehandshakes` APIs are used. -### 5.5.1 Disable Re-Handshaking At Runtime +###5.5.2 The Re-Handshake Credit Mechanism +The re-handshake feature has been used at the entry point in a couple TLS attacks. In an effort to combat these attacks, MatrixSSL has incorporated a mechanism that prevents a peer from continually re-handshaking. This “re-handshake credit” mechanism is simply a count of how often the MatrixSSL-enabled application will allow a peer to request a re-handshake before sending the `NO_RENEGOTIATION` alert. The default number of credits is set using the `DEFAULT_RH_CREDITS` define in _matrixssllib.h_. The shipped default is 1. -Global disabling of re-handshakes can be controlled at compile time using the `USE_REHANDSHAKING` define but sometimes a per-session control of the feature is required. In these cases, the `matrixSslDisableRehandshakes` and `matrixSslReEnableRehandshakes` APIs are used. +In order to allow real-life conditions of re-handshakes, a single credit will be added after transmitting a given number of application data bytes. The default count of bytes that have to be sent before gaining a credit is set using the `BYTES_BEFORE_RH_CREDIT` define in _matrixssllib.h_. The shipped default is 20MB. -### 5.5.2 The Re-Handshake Credit Mechanism +#6 OPTIONAL FEATURES +This section describes some of the optional SSL handshake features. Additional details can be found in the API documentation for the specific functions that are referenced here. -The re-handshake feature has been used at the entry point in a couple TLS attacks. In an effort to combat these attacks, MatrixSSL has incorporated a mechanism that prevents a peer from continually re-handshaking. This “re-handshake credit” mechanism is simply a count of how often the MatrixSSL-enabled application will allow a peer to request a re-handshake before sending the `NO_RENEGOTIATION` alert. The default number of credits is set using the `DEFAULT_RH_CREDITS` define in _matrixssllib.h_. The shipped default is 1. - -In order to allow real-life conditions of re-handshakes, a single credit will be added after transmitting a given number of application data bytes. The default count of bytes that have to be sent before gaining a credit is set using the `BYTES_BEFORE_RH_CREDIT` define in _matrixssllib.h_. The shipped default is 20MB. - -# 6 OPTIONAL FEATURES - -This section describes some of the optional SSL handshake features. Additional details can be found in the API documentation for the specific functions that are referenced here. - -## 6.1 Stateless Session Ticket Resumption - -[RFC 5077](https://tools.ietf.org/html/rfc5077) defines an alternative method to the standard server-cached session ID mechanism. The stateless ticket mechanism allows the server to send an encrypted session ticket to the client that the client can use in a later connection to speed up the handshake process. The server does not have to store a large number of session ID entries when this stateless mechanism is used. +##6.1 Stateless Session Ticket Resumption +[RFC 5077](https://tools.ietf.org/html/rfc5077) defines an alternative method to the standard server-cached session ID mechanism. The stateless ticket mechanism allows the server to send an encrypted session ticket to the client that the client can use in a later connection to speed up the handshake process. The server does not have to store a large number of session ID entries when this stateless mechanism is used. **Servers and Clients** -The feature is made available with the USE_STATELESS_SESSION_TICKETS define in _matrixsslConfig.h_. +The feature is made available with the USE_STATELESS_SESSION_TICKETS define in _matrixsslConfig.h_. **Clients** Clients that wish to use the stateless session resumption mechanism must set the ticketResumption member of the `sslSessOpts_t` structure to 1 when calling `matrixSslNewClientSession`. -With that session option set, the client only has to use the standard session resumption API, `matrixSslNewSessionId`, to complete the use of the feature. If a server does not support stateless session tickets, the standard resumption mechanism will still work. +With that session option set, the client only has to use the standard session resumption API, `matrixSslNewSessionId`, to complete the use of the feature. If a server does not support stateless session tickets, the standard resumption mechanism will still work. **Servers** -The server must load at least one session ticket key using `matrixSslLoadSessionTicketKeys` to enable the feature. A user callback can optionally be registered that will be called each time a session ticket is received from a client. The callback will indicate to the user whether or not the server already has the correct ticket key cached. The callback can be used to locate a ticket key or to void the ticket and revert to a full handshake. The `matrixSslSetSessionTicketCallback` API is used to register this function. -The MatrixSSL implementation for resumption does not renew the session ticket as described in section [3.1 of the RFC](https://tools.ietf.org/html/rfc5077#section-3.1) (Figure 2). If the ticket is valid, the server progresses with the standard resumed handshake without a `NewSessionTicket` handshake message. If the server is unable to decrypt the session ticket, a full handshake will take place and a new session ticket will be issued. The MatrixSSL library also handles the expiration of a session ticket based on the value of the `SSL_SESSION_ENTRY_LIFE` in _matrixsslConfig.h_. +The server must load at least one session ticket key using `matrixSslLoadSessionTicketKeys` to enable the feature. A user callback can optionally be registered that will be called each time a session ticket is received from a client. The callback will indicate to the user whether or not the server already has the correct ticket key cached. The callback can be used to locate a ticket key or to void the ticket and revert to a full handshake. The `matrixSslSetSessionTicketCallback` API is used to register this function. +The MatrixSSL implementation for resumption does not renew the session ticket as described in section [3.1 of the RFC](https://tools.ietf.org/html/rfc5077#section-3.1) (Figure 2). If the ticket is valid, the server progresses with the standard resumed handshake without a `NewSessionTicket` handshake message. If the server is unable to decrypt the session ticket, a full handshake will take place and a new session ticket will be issued. The MatrixSSL library also handles the expiration of a session ticket based on the value of the `SSL_SESSION_ENTRY_LIFE` in _matrixsslConfig.h_. -## 6.2 Server Name Indication Extension - -[RFC 6066](https://tools.ietf.org/html/rfc6066) defines a TLS hello extension to allow the client to send the name of the server it is trying to securely connect to. This allows “virtual” servers to locate the correct server with the expected key material to complete the connection. +##6.2 Server Name Indication Extension +[RFC 6066](https://tools.ietf.org/html/rfc6066) defines a TLS hello extension to allow the client to send the name of the server it is trying to securely connect to. This allows “virtual” servers to locate the correct server with the expected key material to complete the connection. **Servers** -Server applications should register the SNI callback using `matrixSslRegisterSNICallback`. This function must be called immediately after `matrixSslNewServerSession` before the first incoming flight from the client is processed. The callback will be invoked during the processing of the `CLIENT_HELLO` message if the client has included the SNI extension. The callback will use the incoming hostname to locate the correct key material and return them in the `sslKeys_t` structure format. +Server applications should register the SNI callback using `matrixSslRegisterSNICallback`. This function must be called immediately after `matrixSslNewServerSession` before the first incoming flight from the client is processed. The callback will be invoked during the processing of the `CLIENT_HELLO` message if the client has included the SNI extension. The callback will use the incoming hostname to locate the correct key material and return them in the `sslKeys_t` structure format. **Clients** -Clients must include the SNI extension in the `CLIENT_HELLO` message. The utility function `matrixSslCreateSNIext` is provided to help format the extension given a hostname and hostname length. Once the extension format has been created it will be loaded into the `tlsExtension_t` structure with the `matrixSslLoadHelloExtension` API (`matrixSslNewHelloExtension` must first be called). The `tlsExtension_t` type is then passed to `matrixSslNewClientSession` to complete the client side SNI integration. +Clients must include the SNI extension in the `CLIENT_HELLO` message. The utility function `matrixSslCreateSNIext` is provided to help format the extension given a hostname and hostname length. Once the extension format has been created it will be loaded into the `tlsExtension_t` structure with the `matrixSslLoadHelloExtension` API (`matrixSslNewHelloExtension` must first be called). The `tlsExtension_t` type is then passed to `matrixSslNewClientSession` to complete the client side SNI integration. -## 6.3 Extended Master Secret +##6.3 Extended Master Secret +The “extended master secret” as specified in [RFC 7627](https://tools.ietf.org/html/rfc7627) is an important security feature for TLS implementations that use session resumption. The extended master secret feature associates the internal TLS master secret directly to the connection context to prevent man-in-the-middle attacks during session resumption. One such attack is a synchronizing triple handshake as described in [Triple Handshakes and Cookie Cutters: Breaking and Fixing Authentication over TLS](https://mitls.org/pages/attacks/3SHAKE). -The “extended master secret” as specified in [RFC 7627](https://tools.ietf.org/html/rfc7627) is an important security feature for TLS implementations that use session resumption. The extended master secret feature associates the internal TLS master secret directly to the connection context to prevent man-in-the-middle attacks during session resumption. One such attack is a synchronizing triple handshake as described in [Triple Handshakes and Cookie Cutters: Breaking and Fixing Authentication over TLS](https://mitls.org/pages/attacks/3SHAKE). - -This feature is always enabled by default in both MatrixSSL clients and servers. The peer agreement mechanism is the `CLIENT_HELLO` and `SERVER_HELLO` `extended_master_secret` extension. +This feature is always enabled by default in both MatrixSSL clients and servers. The peer agreement mechanism is the `CLIENT_HELLO` and `SERVER_HELLO` `extended_master_secret` extension. **Clients** -A client will always include the `extended_master_secret` extension when creating the `CLIENT_HELLO` message. If the server replies with an `extended_master_secret`, the upgraded master secret generation will be used. If the server does not reply with an `extended_master_secret`, the standard master secret generation will be used for the connection. +A client will always include the `extended_master_secret` extension when creating the `CLIENT_HELLO` message. If the server replies with an `extended_master_secret`, the upgraded master secret generation will be used. If the server does not reply with an `extended_master_secret`, the standard master secret generation will be used for the connection. -A client may REQUIRE that a server support the `extended_master_secret` feature by setting the `extendedMasterSecret` member of `sslSessOpts_t` to 1. The `sslSessOpts_t` structure is passed to `matrixSslNewClientSession` when starting a TLS session. If `extendedMasterSecret` is set, the client will send a fatal `handshake_failure` alert to the server if the `extended_master_secret` extension is not included in the `SERVER_HELLO`. +A client may REQUIRE that a server support the `extended_master_secret` feature by setting the `extendedMasterSecret` member of `sslSessOpts_t` to 1. The `sslSessOpts_t` structure is passed to `matrixSslNewClientSession` when starting a TLS session. If `extendedMasterSecret` is set, the client will send a fatal `handshake_failure` alert to the server if the `extended_master_secret` extension is not included in the `SERVER_HELLO`. **Servers** A server will always reply with the `extended_master_secret` extension if the client includes it in the `CLIENT_HELLO` message. -A server may **require** that a client support the `extended_master_secret` feature by setting the `extendedMasterSecret` member of `sslSessOpts_t` to 1. The `sslSessOpts_t` structure is passed to `matrixSslNewServerSession` when starting a TLS session. If `extendedMasterSecret` is set, the server will send a fatal `handshake_failure` alert to the client if the `extended_master_secret` extension is not included in the `CLIENT_HELLO`. +A server may **require** that a client support the `extended_master_secret` feature by setting the `extendedMasterSecret` member of `sslSessOpts_t` to 1. The `sslSessOpts_t` structure is passed to `matrixSslNewServerSession` when starting a TLS session. If `extendedMasterSecret` is set, the server will send a fatal `handshake_failure` alert to the client if the `extended_master_secret` extension is not included in the `CLIENT_HELLO`. -When creating the session resumption information (either the standard session table or the stateless session ticket) the server will flag whether the extended master secret was used for the initial connection. When a client attempts session resumption, the `CLIENT_HELLO` must include the `extended_master_secret` extension if it was used in the initial connection. Likewise, if the initial connection did not use the `extended_master_secret` the session resumption `CLIENT_HELLO` must also exclude that extension. If there is a mismatch, the server will not allow the session resumption and a full handshake will occur instead. +When creating the session resumption information (either the standard session table or the stateless session ticket) the server will flag whether the extended master secret was used for the initial connection. When a client attempts session resumption, the `CLIENT_HELLO` must include the `extended_master_secret` extension if it was used in the initial connection. Likewise, if the initial connection did not use the `extended_master_secret` the session resumption `CLIENT_HELLO` must also exclude that extension. If there is a mismatch, the server will not allow the session resumption and a full handshake will occur instead. -## 6.4 Maximum Fragment Length - -[RFC 6066](https://tools.ietf.org/html/rfc6066) defines a TLS extension for negotiating a smaller maximum message size. The default maximum is 16KB (and can't be set larger). The only allowed sizes that may be negotiated are 512, 1024, 2048, or 4096 bytes. The client requests the feature in a `CLIENT_HELLO` extension and if the server agrees to the new maximum fragment length it will acknowledge that in the `SERVER_HELLO` reply. +##6.4 Maximum Fragment Length +[RFC 6066](https://tools.ietf.org/html/rfc6066) defines a TLS extension for negotiating a smaller maximum message size. The default maximum is 16KB (and can't be set larger). The only allowed sizes that may be negotiated are 512, 1024, 2048, or 4096 bytes. The client requests the feature in a `CLIENT_HELLO` extension and if the server agrees to the new maximum fragment length it will acknowledge that in the `SERVER_HELLO` reply. **Clients** -To request a smaller maximum fragment length the user sets the maxFragLen member of the `sslSessOpts_t * ` options parameter to 512, 1024, 2048, or 4096 when calling `matrixSslNewClientSession`. The server is free to deny the request. +To request a smaller maximum fragment length the user sets the maxFragLen member of the `sslSessOpts_t * ` options parameter to 512, 1024, 2048, or 4096 when calling `matrixSslNewClientSession`. The server is free to deny the request. **Servers** -Servers will agree to the maximum fragment length request by default. To disable the feature for a session, the user may set the `maxFragLen` member of the `sslSessOpts_t * ` options parameter to -1 when calling `matrixSslNewServerSession`. +Servers will agree to the maximum fragment length request by default. To disable the feature for a session, the user may set the `maxFragLen` member of the `sslSessOpts_t * ` options parameter to -1 when calling `matrixSslNewServerSession`. -## 6.5 Truncated HMAC - -[RFC 6066](https://tools.ietf.org/html/rfc6066) defines a TLS extension for negotiating an HMAC length of 10 bytes. The client requests the feature in a `CLIENT_HELLO` extension and if the server agrees to the truncation it will acknowledge that in the `SERVER_HELLO` reply. +##6.5 Truncated HMAC +[RFC 6066](https://tools.ietf.org/html/rfc6066) defines a TLS extension for negotiating an HMAC length of 10 bytes. The client requests the feature in a `CLIENT_HELLO` extension and if the server agrees to the truncation it will acknowledge that in the `SERVER_HELLO` reply. **Clients** -To request a truncated HMAC session the user sets the `truncHmac` member of the `sslSessOpts_t * `options parameter to PS_TRUE when calling `matrixSslNewClientSession`. The server is free to deny the request. +To request a truncated HMAC session the user sets the `truncHmac` member of the `sslSessOpts_t * `options parameter to PS_TRUE when calling `matrixSslNewClientSession`. The server is free to deny the request. **Servers** -Servers will agree to HMAC truncation by default. To disable the feature for a session, the user may set the `truncHmac` member of the `sslSessOpts_t * ` options parameter to -1 when calling `matrixSslNewServerSession`. +Servers will agree to HMAC truncation by default. To disable the feature for a session, the user may set the `truncHmac` member of the `sslSessOpts_t * ` options parameter to -1 when calling `matrixSslNewServerSession`. -## 6.6 Application Layer Protocol Negotiation Extension - -[RFC 7301](https://tools.ietf.org/html/rfc7301) defines a TLS hello extension that enables servers and client to agree on the protocol that will be used after the TLS handshake is complete. The idea is to embed the negotiation in the TLS handshake to save any round trips that might be needed to negotiate the protocol after the handshake. The extension works the same as any extension by the client sending a list of protocols it wishes to use in the `CLIENT_HELLO` and the server replying with an extension in the `SERVER_HELLO`. The trade-off for negotiating the protocol during the handshake is that both MatrixSSL servers and clients must be prepared to intervene in the middle of the handshake process via registered callback functions. +##6.6 Application Layer Protocol Negotiation Extension +[RFC 7301](https://tools.ietf.org/html/rfc7301) defines a TLS hello extension that enables servers and client to agree on the protocol that will be used after the TLS handshake is complete. The idea is to embed the negotiation in the TLS handshake to save any round trips that might be needed to negotiate the protocol after the handshake. The extension works the same as any extension by the client sending a list of protocols it wishes to use in the `CLIENT_HELLO` and the server replying with an extension in the `SERVER_HELLO`. The trade-off for negotiating the protocol during the handshake is that both MatrixSSL servers and clients must be prepared to intervene in the middle of the handshake process via registered callback functions. **Servers and Clients** -The ALPN extension APIs will be available only if the `USE_ALPN` define in _matrixsslConfig.h_ is enabled at compile-time. The define `MAX_PROTO_EXT` is the maximum number of protocols that can be expected in the list of protocols. The default is 8 and can be found in _matrixssllib.h_. +The ALPN extension APIs will be available only if the `USE_ALPN` define in _matrixsslConfig.h_ is enabled at compile-time. The define `MAX_PROTO_EXT` is the maximum number of protocols that can be expected in the list of protocols. The default is 8 and can be found in _matrixssllib.h_. **Servers** -Servers that wish to process ALPN extensions sent from a client must call the `matrixSslRegisterALPNCallback` function immediately after the session is created with `matrixSslNewServerSession`. The timing of the registration is important so that the callback can be associated with the proper session context before the first handshake message from the client is passed to `matrixSslReceivedData`. +Servers that wish to process ALPN extensions sent from a client must call the `matrixSslRegisterALPNCallback` function immediately after the session is created with `matrixSslNewServerSession`. The timing of the registration is important so that the callback can be associated with the proper session context before the first handshake message from the client is passed to `matrixSslReceivedData`. The server ALPN callback that is registered with `matrixSslRegisterALPNCallback` must have a prototype of: - ```C void ALPN_callback(void *ssl, short protoCount, char *proto[MAX_PROTO_EXT], int32_t protoLen[MAX_PROTO_EXT], int32_t *index) ``` - `ssl` : parameter is the session context and may be typecast to an `ssl_t * ` type if access is required. `protoCount` -: is the number of protocols that the client has sent in the `CLIENT_HELLO` extension. It is the count of the number of array entries in the `proto` and `protoLen` parameters to follow. +: is the number of protocols that the client has sent in the `CLIENT_HELLO` extension. It is the count of the number of array entries in the `proto` and `protoLen` parameters to follow. `proto` -: parameter is the priority-ordered list of string protocol names the client wants to communicate with following the TLS handshake. The `protoLen` parameter holds the string lengths of the `proto` counterpart parameter for each protocol. +: parameter is the priority-ordered list of string protocol names the client wants to communicate with following the TLS handshake. The `protoLen` parameter holds the string lengths of the `proto` counterpart parameter for each protocol. `index` : parameter is an output that the callback logic will assign based on the desired action: -- The index of the proto array member the server has agreed to use. The index is the zero-based index to the array so a return value of 0 will indicate the first protocol in the list. This selection will result in the server including its own ALPN extension in the `SERVER_HELLO` message with the chosen protocol. -- A negative value assigned to index indicates the server is not willing to communicate using any of the protocols. A fatal “`no_application_protocol`” alert will be sent to the client and the handshake will terminate. -- If the callback does not assign any value to the outgoing parameter, the server will not take any action. That is, neither a reply ALPN extension nor an alert will be sent to the client and the handshake will continue normally. +- The index of the proto array member the server has agreed to use. The index is the zero-based index to the array so a return value of 0 will indicate the first protocol in the list. This selection will result in the server including its own ALPN extension in the `SERVER_HELLO` message with the chosen protocol. +- A negative value assigned to index indicates the server is not willing to communicate using any of the protocols. A fatal “`no_application_protocol`” alert will be sent to the client and the handshake will terminate. +- If the callback does not assign any value to the outgoing parameter, the server will not take any action. That is, neither a reply ALPN extension nor an alert will be sent to the client and the handshake will continue normally. **Clients** -To support this feature, clients must be able to generate the ALPN extension and also receive the server reply. +To support this feature, clients must be able to generate the ALPN extension and also receive the server reply. To generate the ALPN extension, the API `matrixSslCreateALPNext` is used in conjunction with the `matrixSslNewHelloExtension` or `matrixSslLoadHelloExtension` framework. -The `matrixSslCreateALPNext` API accepts an array of `unsigned char * ` string values (array length of `MAX_PROTO_EXT`) along with a companion array that hold the string lengths for the protocol list. The function will format the protocols into the specified ALPN extension format and return that to the caller in the output parameters. Once the extension has been created the client must load the extension using the `matrixSslLoadHelloExtension` API (`matrixSslNewHelloExtension` must have been called as well). Finally, the extension must be passed to `matrixSslNewClientSession` in the extensions parameter. Here is what the ALPN extension creation and session start might look like: - -```c -tlsExtension_t *extension; +The `matrixSslCreateALPNext` API accepts an array of `unsigned char * ` string values (array length of `MAX_PROTO_EXT`) along with a companion array that hold the string lengths for the protocol list. The function will format the protocols into the specified ALPN extension format and return that to the caller in the output parameters. Once the extension has been created the client must load the extension using the `matrixSslLoadHelloExtension` API (`matrixSslNewHelloExtension` must have been called as well). Finally, the extension must be passed to `matrixSslNewClientSession` in the extensions parameter. Here is what the ALPN extension creation and session start might look like: +```C +tlsExtension_t * extension; unsigned char *alpn[MAX_PROTO_EXT]; int32_t alpnLen[MAX_PROTO_EXT]; @@ -1036,17 +1026,11 @@ matrixSslNewClientSession(&ssl, keys, sid, g_cipher, g_ciphers, certCb, g_ip, ex matrixSslDeleteHelloExtension(extension); ``` - -To receive the server reply to the ALPN extension the client must register an extension callback routine using the `extCb` parameter when calling `matrixSslNewClientSession`. The callback will be invoked with the ALPN extension ID of `EXT_ALPN` (16) with a format of a single byte length followed by the protocol string value the server has agreed to. +To receive the server reply to the ALPN extension the client must register an extension callback routine using the `extCb` parameter when calling `matrixSslNewClientSession`. The callback will be invoked with the ALPN extension ID of `EXT_ALPN` (16) with a format of a single byte length followed by the protocol string value the server has agreed to. See the example in _apps/ssl/client.c_ for full implementation details. -## 6.7 TLS Fallback SCSV - +##6.7 TLS Fallback SCSV [RFC 7507](https://tools.ietf.org/html/rfc7507) defines a method to prevent protocol downgrade attacks. Such an attack is illustrated below: - -![SCSV Attack](/assets/svg/scsv_attack.svg) - - - MatrixSSL does not automatically do such version fallback, but client software using MatrixSSL may choose to do this for compatibility with unknown servers. In this case, the `TLS_FALLBACK_SCSV` option flag MUST be set for each connection attempt at a lower protocol version. This will mitigate the attack as follows: - -![SCSV Extension](/assets/svg/scsv_prevent.svg) - - - The client indicates that the lower version being requested is due to a previous response from the server that it was not supported. If the server sees this flag, but supports a higher version, it will recognize that something is amiss and return an alert, rather than a valid `SERVER_HELLO`. - > Note that if the attacker attempted to remove the `TLS_FALLBACK_SCSV` indication from the message, the tampering would be detected by the server and client later, as part of the `FINISHED` message handshake hash validation. The indication is specified by the RFC as a special ciphersuite value, rather than a TLS extension for maximum compatibility. **Clients** @@ -1101,18 +1076,13 @@ If the client connection is being made at a lower protocol level because the ser **Servers** Servers will evaluate the FALLBACK_SCSV indication automatically as per RFC: - > If TLS_FALLBACK_SCSV appears in ClientHello.cipher_suites and the highest protocol version supported by the server is higher than the version indicated in ClientHello.client_version, the server MUST respond with a fatal inappropriate_fallback alert -## 6.8 OCSP - +##6.8 OCSP The Online Certificate Status Protocol (OCSP) is an alternative to the Certificate Revocation List (CRL) mechanism for performing certificate revocation tests on server keys. TLS integrates with OCSP in a mechanism known as _OCSP stapling_. This feature allows the client to request that the server provide a time-stamped OCSP response when presenting the X.509 certificate during the TLS handshake. The primary goal for this method is to allow resource constrained clients to perform certificate revocation tests without having to communicate with an OCSP Responder themselves. The general process is illustrated below. OCSP stapling is specified in Section 8 (Certificate Status Request) of the TLS Extensions [RFC 6066](https://tools.ietf.org/html/rfc6066#section-8). The `USE_OCSP` define in cryptoConfig.h must be enabled for these features to be available. -![OCSP](/assets/svg/ocsp.svg) - - **Clients** A client application can request OCSP stapling by setting the OCSPstapling member of the `sslSessOpts_t` structure when invoking `matrixSslNewClientSession`. This flag will trigger the creation of the Certificate Status Request extension in the `CLIENT_HELLO` message. The resulting `status_request` extension will not specify any responder identification hints or request extensions. This indicates that the server is free to provide whatever OCSP response is relevant to its identity certificate. @@ -1145,9 +1114,8 @@ A server application wishing to support OCSP stapling must communicate out of ba When a client sends the `status_request` extension the server will look to see if an OCSP response is available in the `sslKeys_t` structure and reply with a `status_request` extension and the `CERTIFICATE_STATUS` message that holds the OCSP response for the client to validate. -## 6.9 MatrixSSL Statistics Framework - -Implementations that wish to capture counts of SSL events can tap into the `MATRIXSSL_STATS` framework by enabling `USE_MATRIXSSL_STATS` during the compile. The mechanism is a very simple callback that can be registered to record whatever specific SSL event the user wants. The default set of events capture the following: +##6.9 MatrixSSL Statistics Framework +Implementations that wish to capture counts of SSL events can tap into the `MATRIXSSL_STATS` framework by enabling `USE_MATRIXSSL_STATS` during the compile. The mechanism is a very simple callback that can be registered to record whatever specific SSL event the user wants. The default set of events capture the following: - `CLIENT_HELLO` count (sent for clients and received for servers) - `SERVER_HELLO` count (sent for servers and received for clients) @@ -1162,19 +1130,15 @@ To add an event to the framework the user must: 1. Add a unique ID to the list of existing stats in matrixsslApi.h 2. Add the call to `matrixsslUpdateStat` in the appropriate place in the MatrixSSL library -# 7 Deprecated Features - +#7 Deprecated Features The features in this section are minimally supported and should only be used in cases where they are explicitly required for compatibility. Please be aware of any security implications of these features before enabling them. - -## 7.1 EAP_FAST Mode - +##7.1 EAP_FAST Mode [EAP-FAST](https://tools.ietf.org/html/rfc4851) is an aging, proprietary EAP method that uses TLS to bootstrap a higher level EAP authentication method. It is supported by MatrixSSL for the client (EAP Supplicant) side only. Unlike EAP-TLS or EAP-TTLS, EAP-FAST requires modifications to the TLS protocol and therefore must be explicitly enabled with both a compile time define `USE_EAP_FAST` and a client side API `matrixSslSetSessionIdEapFast` in _matrixssllib.h_. -EAP-FAST requires a _Protected Access Credential (PAC)_ to be provisioned between the peers out-of-band (see [RFC5422](https://tools.ietf.org/html/rfc5422) _Dynamic Provisioning Using Flexible Authentication via Secure Tunneling Extensible Authentication Protocol (EAP-FAST)_. Like the `TLS_PSK` cipher suites, this _PAC_ consists of a secret key (pac-key) and a unique id associated with the key, both shared between the peers. However, the `TLS_PSK` ciphers are not used for this mechanism directly. +EAP-FAST requires a _Protected Access Credential (PAC)_ to be provisioned between the peers out-of-band (see [RFC5422](https://tools.ietf.org/html/rfc5422) _Dynamic Provisioning Using Flexible Authentication via Secure Tunneling Extensible Authentication Protocol (EAP-FAST)_. Like the `TLS_PSK` cipher suites, this _PAC_ consists of a secret key (pac-key) and a unique id associated with the key, both shared between the peers. However, the `TLS_PSK` ciphers are not used for this mechanism directly. -The _PAC_ is exchanged between the peers by the client sending the [Stateless Session Ticket Resumption](#61-stateless-session-ticket-resumption) specification: the `CLIENT_HELLO SessionTicket Extension`. However, a _PAC_ explicitly cannot be received by a client in the corresponding `NewSessionTicket` handshake message from the server, and must be provisioned out-of-band. Unfortunately this requires alteration of the standard TLS state machine logic. - -```c +The _PAC_ is exchanged between the peers by the client sending the [Stateless Session Ticket Resumption](#61-stateless-session-ticket-resumption) specification: the `CLIENT_HELLO SessionTicket Extension`. However, a _PAC_ explicitly cannot be received by a client in the corresponding `NewSessionTicket` handshake message from the server, and must be provisioned out-of-band. Unfortunately this requires alteration of the standard TLS state machine logic. +```C sslSessionId_t *sid; ssl_t *ssl; ... @@ -1189,17 +1153,16 @@ matrixSslDeleteSession(ssl); matrixSslDeleteSessionId(sid); ``` -## 7.2 ZLIB Compression +##7.2 ZLIB Compression +The TLS specification specifies a mechanism for peers to agree on an algorithm to compress data before being encrypted. Although the feature is not widely adopted and is deprecated due to the ‘CRIME’ attack, there is limited support in MatrixSSL for zlib compression for implementations that are sensitive to throughput. -The TLS specification specifies a mechanism for peers to agree on an algorithm to compress data before being encrypted. Although the feature is not widely adopted and is deprecated due to the ‘CRIME’ attack, there is limited support in MatrixSSL for zlib compression for implementations that are sensitive to throughput. +To enable the feature, enable `USE_ZLIB_COMPRESSION` in _matrixssllib.h_. It will also be necessary to edit the development environment to link with a zlib library. For a standard *GCC* *POSIX* environment this should simply mean including `–lz` in the linker flags. -To enable the feature, enable `USE_ZLIB_COMPRESSION` in _matrixssllib.h_. It will also be necessary to edit the development environment to link with a zlib library. For a standard *GCC* *POSIX* environment this should simply mean including `–lz` in the linker flags. - -The built-in support for this feature is limited. The feature only supports the internal compression and decompression of the `FINISHED` handshake message for initial handshakes. This means re-handshaking is not supported and that the application MUST compress and decompress application data manually. +The built-in support for this feature is limited. The feature only supports the internal compression and decompression of the `FINISHED` handshake message for initial handshakes. This means re-handshaking is not supported and that the application MUST compress and decompress application data manually. **On the application data sending side:** -After a successful handshake with `USE_ZLIB_COMPRESSION` enabled, the user should call `matrixSslIsSessionCompressionOn` to test whether that mode has been successfully negotiated. If `PS_TRUE`, the user must manually zlib deflate any application data before calling the Matrix encryption functions. Do not compress more plaintext data in a single record than the maximum allowed record size to remain compatible with 3rd party SSL implementations. +After a successful handshake with `USE_ZLIB_COMPRESSION` enabled, the user should call `matrixSslIsSessionCompressionOn` to test whether that mode has been successfully negotiated. If `PS_TRUE`, the user must manually zlib deflate any application data before calling the Matrix encryption functions. Do not compress more plaintext data in a single record than the maximum allowed record size to remain compatible with 3rd party SSL implementations. **On the application data receiving side:** -Applications must test for `MATRIXSSL_APP_DATA_COMPRESSED` as the return code from `matrixSslReceivedData`. If found, the data must be zlib inflated to obtain the plaintext data +Applications must test for `MATRIXSSL_APP_DATA_COMPRESSED` as the return code from `matrixSslReceivedData`. If found, the data must be zlib inflated to obtain the plaintext data diff --git a/matrixssl/Makefile b/matrixssl/Makefile old mode 100755 new mode 100644 diff --git a/matrixssl/cipherSuite.c b/matrixssl/cipherSuite.c index fd3ec6e..5d20641 100644 --- a/matrixssl/cipherSuite.c +++ b/matrixssl/cipherSuite.c @@ -126,6 +126,7 @@ int32 csDes3Decrypt(void *ssl, unsigned char *ct, /******************************************************************************/ #ifdef USE_AES_CIPHER_SUITE +#ifdef USE_NATIVE_AES #ifdef USE_TLS_1_2 #ifdef USE_AES_GCM int32 csAesGcmInit(sslSec_t *sec, int32 type, uint32 keysize) @@ -311,6 +312,7 @@ int32 csAesDecrypt(void *ssl, unsigned char *ct, return len; } #endif /*USE_AES_CBC */ +#endif /* USE_NATIVE_AES */ #endif /* USE_AES_CIPHER_SUITE */ /******************************************************************************/ diff --git a/matrixssl/dtls.c b/matrixssl/dtls.c index 6d15782..edb0bfc 100644 --- a/matrixssl/dtls.c +++ b/matrixssl/dtls.c @@ -774,9 +774,11 @@ static int32 dtlsRevertWriteCipher(ssl_t *ssl) ssl->enIvSize = ssl->oenIvSize; ssl->enBlockSize = ssl->oenBlockSize; memcpy(ssl->sec.writeIV, ssl->owriteIV, ssl->oenIvSize); +#ifdef USE_NATIVE_TLS_ALGS memcpy(ssl->sec.writeMAC, ssl->owriteMAC, ssl->oenMacSize); memcpy(&ssl->sec.encryptCtx, &ssl->oencryptCtx, sizeof(psCipherContext_t)); +#endif #ifdef ENABLE_SECURE_REHANDSHAKES memcpy(ssl->myVerifyData, ssl->omyVerifyData, ssl->omyVerifyDataLen); ssl->myVerifyDataLen = ssl->omyVerifyDataLen; diff --git a/matrixssl/hsDecode.c b/matrixssl/hsDecode.c index e58e1c4..cf9869b 100644 --- a/matrixssl/hsDecode.c +++ b/matrixssl/hsDecode.c @@ -874,11 +874,10 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp, ssl->sec.premaster[0] = (ssl->sec.premasterSize & 0xFF00) >> 8; ssl->sec.premaster[1] = (ssl->sec.premasterSize & 0xFF); /* - Next, uint16 length of PSK and key itself + Next, uint8_t length of PSK and key itself */ - ssl->sec.premaster[ssl->sec.premasterSize + 2] = - (pskLen & 0xFF00) >> 8; - ssl->sec.premaster[ssl->sec.premasterSize + 3] =(pskLen & 0xFF); + ssl->sec.premaster[ssl->sec.premasterSize + 2] = 0; + ssl->sec.premaster[ssl->sec.premasterSize + 3] = (pskLen & 0xFF); memcpy(&ssl->sec.premaster[ssl->sec.premasterSize + 4], pskKey, pskLen); /* @@ -927,10 +926,10 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp, return SSL_MEM_ERROR; } memset(ssl->sec.premaster, 0, ssl->sec.premasterSize); - ssl->sec.premaster[0] = (pskLen & 0xFF00) >> 8; + ssl->sec.premaster[0] = 0; ssl->sec.premaster[1] = (pskLen & 0xFF); /* memset to 0 handled middle portion */ - ssl->sec.premaster[2 + pskLen] = (pskLen & 0xFF00) >> 8; + ssl->sec.premaster[2 + pskLen] = 0; ssl->sec.premaster[3 + pskLen] = (pskLen & 0xFF); memcpy(&ssl->sec.premaster[4 + pskLen], pskKey, pskLen); } else { @@ -1498,6 +1497,20 @@ PROTOCOL_DETERMINED: matrixsslUpdateStat(ssl, FAILED_RESUMPTIONS_STAT, 1); #endif } +#ifdef USE_EAP_FAST //TODO Could also do this for any TICKET + if (ssl->sid->sessionTicketState == SESS_TICKET_STATE_SENT_TICKET) { + if (ssl->flags & SSL_FLAGS_RESUMED) { + /* The server has accepted our session ticket, and indicated that + by echoing the random session id we sent. */ + ssl->extFlags.eap_fast_master_secret = 1; + //TODO could derive eap keys here + } else { + /* The server isn't going to use our ticket. But may still + send a ticket extension and (possibly blank) ticket message */ + ssl->extFlags.eap_fast_master_secret = 0; + } + } +#endif } else { ssl->sessionIdLen = (unsigned char)sessionIdLen; memcpy(ssl->sessionId, c, sessionIdLen); @@ -1992,6 +2005,7 @@ int32 parseServerKeyExchange(ssl_t *ssl, /* TLS 1.2 uses single hashes everywhere */ if (ssl->flags & SSL_FLAGS_TLS_1_2) { if (hashSize == SHA256_HASH_SIZE) { + psSha256PreInit(&digestCtx.sha256); psSha256Init(&digestCtx.sha256); psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -2002,6 +2016,7 @@ int32 parseServerKeyExchange(ssl_t *ssl, psSha256Final(&digestCtx.sha256, hsMsgHash); #ifdef USE_SHA384 } else if (hashSize == SHA384_HASH_SIZE) { + psSha384PreInit(&digestCtx.sha384); psSha384Init(&digestCtx.sha384); psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -2013,6 +2028,7 @@ int32 parseServerKeyExchange(ssl_t *ssl, #endif /* USE_SHA384 */ #ifdef USE_SHA512 } else if (hashSize == SHA512_HASH_SIZE) { + psSha512PreInit(&digestCtx.sha512); psSha512Init(&digestCtx.sha512); psSha512Update(&digestCtx.sha512, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -2024,6 +2040,7 @@ int32 parseServerKeyExchange(ssl_t *ssl, #endif /* USE_SHA512 */ #ifdef USE_SHA1 } else if (hashSize == SHA1_HASH_SIZE) { + psSha1PreInit(&digestCtx.sha1); psSha1Init(&digestCtx.sha1); psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -2038,50 +2055,40 @@ int32 parseServerKeyExchange(ssl_t *ssl, } } else { -#ifdef USE_MD5 - psMd5Init(&digestCtx.md5); - psMd5Update(&digestCtx.md5, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); - psMd5Update(&digestCtx.md5, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psMd5Update(&digestCtx.md5, sigStart, - (uint32)(sigStop - sigStart)); - psMd5Final(&digestCtx.md5, hsMsgHash); - - psSha1Init(&digestCtx.sha1); - psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, sigStart, - (uint32)(sigStop - sigStart)); - psSha1Final(&digestCtx.sha1, hsMsgHash + MD5_HASH_SIZE); -#else +#ifdef USE_MD5SHA1 + psMd5Sha1PreInit(&digestCtx.md5sha1); + psMd5Sha1Init(&digestCtx.md5sha1); + psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psMd5Sha1Update(&digestCtx.md5sha1, sigStart, + (uint32)(sigStop - sigStart)); + psMd5Sha1Final(&digestCtx.md5sha1, hsMsgHash); +#else /* USE_MD5SHA1 */ + psTraceInfo("USE_MD5SHA1 required\n"); return MATRIXSSL_ERROR; -#endif +#endif /* USE_MD5SHA1 */ } #else /* USE_TLS_1_2 */ /* The signature portion is an MD5 and SHA1 concat of the randoms and the contents of this server key exchange message. */ - psMd5Init(&digestCtx.md5); - psMd5Update(&digestCtx.md5, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); - psMd5Update(&digestCtx.md5, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psMd5Update(&digestCtx.md5, sigStart, - (uint32)(sigStop - sigStart)); - psMd5Final(&digestCtx.md5, hsMsgHash); - - psSha1Init(&digestCtx.sha1); - psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, sigStart, - (uint32)(sigStop - sigStart)); - psSha1Final(&digestCtx.sha1, hsMsgHash + MD5_HASH_SIZE); +#ifdef USE_MD5SHA1 + psMd5Sha1PreInit(&digestCtx.md5sha1); + psMd5Sha1Init(&digestCtx.md5sha1); + psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psMd5Sha1Update(&digestCtx.md5sha1, sigStart, + (uint32)(c - sigStart)); + psMd5Sha1Final(&digestCtx.md5sha1, hsMsgHash); +#else + psTraceInfo("USE_MD5SHA1 required\n"); + return MATRIXSSL_ERROR; +#endif /* USE_MD5SHA1 */ #endif /* USE_TLS_1_2 */ @@ -2140,6 +2147,7 @@ int32 parseServerKeyExchange(ssl_t *ssl, #ifdef USE_TLS_1_2 if (ssl->flags & SSL_FLAGS_TLS_1_2 && (hashSize == SHA256_HASH_SIZE)) { + psSha256PreInit(&digestCtx.sha256); psSha256Init(&digestCtx.sha256); psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -2151,6 +2159,7 @@ int32 parseServerKeyExchange(ssl_t *ssl, #ifdef USE_SHA384 } else if (ssl->flags & SSL_FLAGS_TLS_1_2 && (hashSize == SHA384_HASH_SIZE)) { + psSha384PreInit(&digestCtx.sha384); psSha384Init(&digestCtx.sha384); psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -2162,6 +2171,7 @@ int32 parseServerKeyExchange(ssl_t *ssl, #endif #ifdef USE_SHA512 } else if (hashSize == SHA512_HASH_SIZE) { + psSha512PreInit(&digestCtx.sha512); psSha512Init(&digestCtx.sha512); psSha512Update(&digestCtx.sha512, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -2179,6 +2189,7 @@ int32 parseServerKeyExchange(ssl_t *ssl, ((ssl->flags & SSL_FLAGS_TLS_1_2) && (hashSize == SHA1_HASH_SIZE))) { hashSize = SHA1_HASH_SIZE; + psSha1PreInit(&digestCtx.sha1); psSha1Init(&digestCtx.sha1); psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); diff --git a/matrixssl/hsHash.c b/matrixssl/hsHash.c index df62db2..207feb0 100644 --- a/matrixssl/hsHash.c +++ b/matrixssl/hsHash.c @@ -33,6 +33,8 @@ #include "matrixsslApi.h" +#ifdef USE_NATIVE_TLS_HS_HASH + #define FINISHED_LABEL_SIZE 15 #define LABEL_CLIENT "client finished" #define LABEL_SERVER "server finished" @@ -465,5 +467,7 @@ int32_t sslSnapshotHSHash(ssl_t *ssl, unsigned char *out, int32 senderFlag) return len; } +#endif /* USE_NATIVE_TLS_HS_HASH */ + /******************************************************************************/ diff --git a/matrixssl/matrixssl.c b/matrixssl/matrixssl.c index 37bc51a..6d045c8 100644 --- a/matrixssl/matrixssl.c +++ b/matrixssl/matrixssl.c @@ -2442,6 +2442,10 @@ static int32 getTicketKeys(ssl_t *ssl, unsigned char *c, } return PS_SUCCESS; } + } else { + /* Unlock, because if the function fails, the + locking status need to be unlocked. */ + psUnlockMutex(&g_sessTicketLock); } return PS_FAILURE; /* not in list and no callback registered */ } diff --git a/matrixssl/matrixsslApi.c b/matrixssl/matrixsslApi.c index 3a7910a..9e103dc 100644 --- a/matrixssl/matrixsslApi.c +++ b/matrixssl/matrixsslApi.c @@ -98,6 +98,16 @@ int32_t matrixSslNewClientSession(ssl_t **ssl, const sslKeys_t *keys, *ssl = NULL; lssl = NULL; +#ifdef USE_EAP_FAST + if (sid && sid->sessionTicketState == SESS_TICKET_STATE_EAP_FAST) { + /* EAP-FAST mode places some restrictions on session resumption */ + if (sid->cipherId != 0 || sid->sessionTicket == NULL || + sid->sessionTicketLen == 0 || + sid->sessionTicketLifetimeHint != 0) { + return PS_ARG_FAIL; + } + } +#endif /* Give priority to cipher suite if session id is provided and doesn't match */ if (cipherSpec != NULL && cipherSpec[0] != 0 && sid != NULL && sid->cipherId != 0) { @@ -137,6 +147,15 @@ int32_t matrixSslNewClientSession(ssl_t **ssl, const sslKeys_t *keys, if (extCb) { lssl->extCb = extCb; } +#ifdef USE_EAP_FAST + if (sid && sid->sessionTicketState == SESS_TICKET_STATE_EAP_FAST) { + /* Flag for EncodeClientHello that we want to resume with a ticket */ + sid->sessionTicketState = SESS_TICKET_STATE_INIT; + options->ticketResumption = 1; + /* Indicate we're tunnelled below EAP_FAST */ + lssl->flags |= SSL_FLAGS_EAP_FAST; + } +#endif RETRY_HELLO: tmp.size = lssl->outsize; tmp.buf = tmp.start = tmp.end = lssl->outbuf; @@ -205,6 +224,54 @@ void matrixSslDeleteSessionId(sslSessionId_t *sess) psFree(sess, NULL); } +#ifdef USE_EAP_FAST +/** + Set the TLS connection to connect using an externally provisioned EAP-FAST + Protected Access Credential (PAC). + @see https://tools.ietf.org/html/rfc4851 + @param[in,out] sess SessionID structure to fill in with PAC. + @param[in] pac_key 32 byte secret key shared between the EAP-FAST peers. + This is used by EAP-FAST peers to do session key derivation and is + never sent over the wire (encrypted or unencrypted) by TLS. + @param[in] pac_opaque Opaque value to be sent as plaintext to the server + within the SessionTicket ClientHello Extension so the server can + choose the correct pac_key. + @param[in] pac_opaque_len Length in bytes of 'pac_opaque' +*/ +void matrixSslSetSessionIdEapFast(sslSessionId_t *sess, + const unsigned char pac_key[EAP_FAST_PAC_KEY_LEN], + const unsigned char *pac_opaque, uint16_t pac_opaque_len) +{ + psAssert(sess && pac_key && pac_opaque && (pac_opaque_len > 0)); + + /* Indicate we're overriding the default Ticket fields and behavior */ + sess->sessionTicketState = SESS_TICKET_STATE_EAP_FAST; +#if EAP_TLS_PAC_KEY_LEN > SSL_HS_MASTER_SIZE +#error EAP_TLS_PAC_KEY_LEN too large +#endif + /** @note, sess->master_secret must go through tprf() before being used */ + memcpy(sess->masterSecret, pac_key, EAP_FAST_PAC_KEY_LEN); + sess->sessionTicket = psMalloc(sess->pool, pac_opaque_len); + memcpy(sess->sessionTicket, pac_opaque, pac_opaque_len); + sess->sessionTicketLen = pac_opaque_len; +} + +int32_t matrixSslGetEapFastSKS(const ssl_t *ssl, + unsigned char session_key_seed[EAP_FAST_SESSION_KEY_SEED_LEN]) +{ + if (!ssl || !session_key_seed) { + psAssert(ssl && session_key_seed); + return PS_FAIL; + } + if (!ssl->sec.eap_fast_session_key_seed || + matrixSslHandshakeIsComplete(ssl) != PS_TRUE) { + return PS_EAGAIN; + } + memcpy(session_key_seed, ssl->sec.eap_fast_session_key_seed, + EAP_FAST_SESSION_KEY_SEED_LEN); + return PS_SUCCESS; +} +#endif /* USE_EAP_FAST */ #endif /* USE_CLIENT_SIDE_SSL */ #ifdef USE_SERVER_SIDE_SSL diff --git a/matrixssl/matrixsslApi.h b/matrixssl/matrixsslApi.h index ca856a9..776e79b 100644 --- a/matrixssl/matrixsslApi.h +++ b/matrixssl/matrixsslApi.h @@ -41,10 +41,14 @@ extern "C" { #endif -#include "../core/coreApi.h" -#include "../crypto/cryptoApi.h" +#include "../core/coreApi.h" /* cryptoApi.h and matrixsslApi.h depend on this */ +#include "../crypto/cryptoApi.h" /* matrixsslApi.h depend on cryptoApi.h. */ -#include "matrixsslConfig.h" +#ifdef MATRIX_CONFIGURATION_INCDIR_FIRST +#include /* Get matrixssl configuration from -I dir. */ +#else +#include "matrixsslConfig.h" /* Get local matrixssl configuration file. */ +#endif #include "matrixssllib.h" #include "version.h" diff --git a/matrixssl/matrixsslCheck.h b/matrixssl/matrixsslCheck.h index 70edfe4..b8eb8dd 100644 --- a/matrixssl/matrixsslCheck.h +++ b/matrixssl/matrixsslCheck.h @@ -75,6 +75,24 @@ extern "C" { #endif #endif +#ifdef USE_EAP_FAST +/******************************************************************************/ +#ifndef USE_SHA1 +# error "Must enable USE_SHA1 in cryptoConfig.h for EAP_FAST" +#endif +#if !defined(USE_TLS_RSA_WITH_RC4_128_SHA) || \ + !defined(USE_TLS_RSA_WITH_AES_128_CBC_SHA) || \ + !defined(USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA) +#pragma message("WARNING: Not all EAP_FAST required ciphersuites enabled") +#endif +#ifndef USE_CLIENT_SIDE_SSL +# error "EAP_FAST requires CLIENT_SIDE_SSL" +#endif +#ifndef USE_STATELESS_SESSION_TICKETS +# error "EAP_FAST requires STATELESS_SESSION_TICKETS" +#endif +#endif /* USE_EAP_FAST */ + /******************************************************************************/ /* SHA1 and MD5 are essential elements for SSL key derivation during protocol diff --git a/matrixssl/matrixsslConfig.h b/matrixssl/matrixsslConfig.h new file mode 100644 index 0000000..e923a91 --- /dev/null +++ b/matrixssl/matrixsslConfig.h @@ -0,0 +1,336 @@ +/** + * @file matrixsslConfig.h + * @version $Format:%h%d$ + * + * Configuration settings for building the MatrixSSL library. + * This configuration is intended to be used in FIPS Mode of operation. + * The configuration aims to be compatible with NIST SP 800-52 Rev 1 and + * to enable the most commonly used cipher suites. + */ +/* + * Copyright (c) 2013-2016 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_MATRIXSSLCONFIG +#define _h_MATRIXSSLCONFIG + +#ifdef __cplusplus +extern "C" { +#endif + +/** + NIST SP 800-52 Rev 1 Conformance. + Guidelines for the Selection, Configuration, and Use of Transport Layer + Security (TLS) Implementations + The key words "shall", "shall not", "should", "should not" and "may" + are used as references to the NIST SP 800-52 Rev 1. Algorithms marked as + "shall" must not be disabled unless NIST SP 800-52 Rev 1 compatibility + is not relevant. + @see http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r1.pdf +*/ + +/******************************************************************************/ +/** + Show which SSL messages are created and parsed +*/ +//#define USE_SSL_HANDSHAKE_MSG_TRACE + +/** + Informational trace that could help pinpoint problems with SSL connections +*/ +//#define USE_SSL_INFORMATIONAL_TRACE +//#define USE_DTLS_DEBUG_TRACE + +/******************************************************************************/ +/** + Recommended cipher suites. + Define the following to enable various cipher suites + At least one of these must be defined. If multiple are defined, + the handshake negotiation will determine which is best for the connection. + @note Ephemeral ciphersuites offer perfect forward security (PFS) + at the cost of a slower TLS handshake. +*/ + +/** Ephemeral ECC DH keys, ECC DSA certificates */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA/**< @security NIST_MAY */ +/* TLS 1.2 ciphers */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256/**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384/**< @security NIST_MAY */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256/**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384/**< @security NIST_SHOULD */ +//#define USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + +/** Ephemeral ECC DH keys, RSA certificates */ +#define USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +/* TLS 1.2 ciphers */ +#define USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256/**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384/**< @security NIST_MAY */ +#define USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256/**< @security NIST_SHOULD */ +#define USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384/**< @security NIST_SHOULD */ +//#define USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + +/** Ephemeral Diffie-Hellman ciphersuites, with RSA certificates */ +//#define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA +//#define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA +/* TLS 1.2 ciphers */ +//#define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +//#define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + +/** Non-Ephemeral RSA keys/certificates */ +#define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */ +#define USE_TLS_RSA_WITH_AES_256_CBC_SHA/**< @security NIST_SHOULD */ +/* TLS 1.2 ciphers */ +#define USE_TLS_RSA_WITH_AES_128_CBC_SHA256/**< @security NIST_MAY */ +#define USE_TLS_RSA_WITH_AES_256_CBC_SHA256/**< @security NIST_MAY */ +#define USE_TLS_RSA_WITH_AES_128_GCM_SHA256/**< @security NIST_SHALL */ +#define USE_TLS_RSA_WITH_AES_256_GCM_SHA384/**< @security NIST_SHOULD */ + +/******************************************************************************/ +/** + These cipher suites are secure, but not widely deployed. +*/ + +/** Ephemeral Diffie-Hellman ciphersuites, with RSA certificates */ +//#define USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA + +/** Ephemeral Diffie-Hellman ciphersuites, with PSK authentication */ +//#define USE_TLS_DHE_PSK_WITH_AES_128_CBC_SHA /**< @security NIST_SHOULD_NOT */ +//#define USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA /**< @security NIST_SHOULD_NOT */ + +/** Ephemeral ECC DH keys, RSA certificates */ +//#define USE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA /**< @security NIST_SHOULD */ + +/** Pre-Shared Key Ciphers. + NIST SP 800-52 Rev 1 recommends against using PSK unless neccessary + See NIST SP 800-52 Rev 1 Appendix C */ +#define USE_TLS_PSK_WITH_AES_128_CBC_SHA/**< @security NIST_SHOULD_NOT */ +#define USE_TLS_PSK_WITH_AES_256_CBC_SHA/**< @security NIST_SHOULD_NOT */ +/* TLS 1.2 ciphers */ +#define USE_TLS_PSK_WITH_AES_128_CBC_SHA256/**< @security NIST_SHOULD_NOT */ +#define USE_TLS_PSK_WITH_AES_256_CBC_SHA384/**< @security NIST_SHOULD_NOT */ + +/** Non-Ephemeral ECC DH keys, ECC DSA certificates */ +#define USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA/**< @security NIST_MAY */ +#define USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA/**< @security NIST_MAY */ +/* TLS 1.2 ciphers */ +#define USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256/**< @security NIST_MAY */ +#define USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384/**< @security NIST_MAY */ +#define USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256/**< @security NIST_MAY */ +#define USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384/**< @security NIST_MAY */ + +/** Non-Ephemeral ECC DH keys, RSA certificates */ +#define USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +#define USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +/* TLS 1.2 ciphers */ +#define USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +#define USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +#define USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +#define USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + +/** Non-Ephemeral RSA keys/certificates */ +//#define USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA /**< @security NIST_SHALL */ + +/** @note Some of (non-mandatory) cipher suites mentioned in NIST SP 800-52 + Rev 1 are not supported by the MatrixSSL / MatrixDTLS. + ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (NIST SP 800-52 Rev 1 "should") + is rarely used cipher suite and is not supported. + Also (NIST SP 800-52 Rev 1 "may") TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_DSS_WITH_* and TLS_RSA_WITH_AES_*_CCM cipher suites cannot be + enabled as they are not supported. */ + +/******************************************************************************/ +/** + Ephemeral key cache support. + If not using cache, new key exchange keys are created for each TLS session. + If using cache, keys are generated initially, and re-used in each + subsequent TLS connection within a given time frame and usage count. + @see ECC_EPHEMERAL_CACHE_SECONDS and ECC_EPHEMERAL_CACHE_USAGE + + @security Do not cache Ephemeral ECC keys as it is against some standards, + including NIST SP 800-56A, when in FIPS 140-2 mode of operation. +*/ +//#define NO_ECC_EPHEMERAL_CACHE /**< @security NIST_SHALL */ + +/******************************************************************************/ +/** + Configure Support for TLS protocol versions. + Define one of: + USE_TLS_1_2_AND_ABOVE + USE_TLS_1_1_AND_ABOVE + USE_TLS_1_0_AND_ABOVE + @note There is no option for enabling SSL3.0 at this level +*/ +#define USE_TLS_1_1_AND_ABOVE/**< @security default 1_1_AND_ABOVE */ +//#define USE_TLS_1_2_AND_ABOVE /**< @security better than 1_1_AND_ABOVE if no backwards compatiblity concerns */ +//#define USE_TLS_1_0_AND_ABOVE /**< @security no longer recommended. */ + +/******************************************************************************/ +/** + Datagram TLS support. + Enables DTLS in addition to TLS. + @pre TLS_1_1 +*/ +#define USE_DTLS + +/******************************************************************************/ +/** + Compile time support for server or client side SSL +*/ +#define USE_CLIENT_SIDE_SSL +#define USE_SERVER_SIDE_SSL + +/******************************************************************************/ +/** + Client certificate authentication +*/ +#define USE_CLIENT_AUTH + +/** + Enable if the server should send an empty CertificateRequest message if + no CA files have been loaded +*/ +//#define SERVER_CAN_SEND_EMPTY_CERT_REQUEST + +/** + Enabling this define will allow the server to "downgrade" a client auth + handshake to a standard handshake if the client replies to a + CERTIFICATE_REQUEST with an empty CERTIFICATE message. The user callback + will be called with a NULL cert in this case and the user can determine if + the handshake should continue in a non-client auth state. +*/ +//#define SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG + +/******************************************************************************/ +/** + Enable the Application Layer Protocol Negotiation extension. + Servers and Clients will still have to use the required public API to + set protocols and register application callbacks to negotiate the + protocol that will be tunneled over TLS. + @see ALPN section in the developer's guide for information. + */ +//#define USE_ALPN + +/******************************************************************************/ +/** + Enable the Trusted CA Indication CLIENT_HELLO extension. Will send the + sha1 hash of each CA file to the server for help in server selection. + This extra level of define is to help isolate the SHA1 requirement +*/ +//#define USE_TRUSTED_CA_INDICATION /**< @security NIST_SHOULD */ + +/******************************************************************************/ +/** + A client side configuration that requires a server to provide an OCSP + response if the client uses the certitificate status request extension. + The "must staple" terminology is typically associated with certificates + at the X.509 layer but it is a good description of what is being required + of the server at the TLS level. + @pre USE_OCSP must be enbled at the crypto level and the client application + must use the OCSPstapling session option at run time for this setting to + have any effect +*/ +#ifdef USE_OCSP +#define USE_OCSP_MUST_STAPLE /**< @security NIST_SHALL */ +#endif + +/******************************************************************************/ +/** + Rehandshaking support. + + Enabling USE_REHANDSHAKING will allow secure-rehandshakes using the + protocol defined in RFC 5748 which fixed a critical exploit in + the standard TLS specification. + + @security Looking towards TLS 1.3, which removes re-handshaking, this + feature is disabled by default. +*/ +//#define USE_REHANDSHAKING + +/******************************************************************************/ +/** + If SERVER you may define the number of sessions to cache and how + long a session will remain valid in the cache from first access. + Session caching enables very fast "session resumption handshakes". + + SSL_SESSION_TABLE_SIZE minimum value is 1 + SSL_SESSION_ENTRY_LIFE is in milliseconds, minimum 0 + + @note Session caching can be disabled by setting SSL_SESSION_ENTRY_LIFE to 0 + however, this will also immediately expire SESSION_TICKETS below. +*/ +#ifdef USE_SERVER_SIDE_SSL +#define SSL_SESSION_TABLE_SIZE 32 +#define SSL_SESSION_ENTRY_LIFE (86400*1000)/* one day, in milliseconds */ +#endif + +/******************************************************************************/ +/** + Use RFC 5077 session resumption mechanism. The SSL_SESSION_ENTRY_LIFE + define applies to this method as well as the standard method. The + SSL_SESSION_TICKET_LIST_LEN is the max size of the server key list. +*/ +#define USE_STATELESS_SESSION_TICKETS +#define SSL_SESSION_TICKET_LIST_LEN 32 + +/******************************************************************************/ +/** + The initial buffer sizes for send and receive buffers in each ssl_t session. + Buffers are internally grown if more incoming or outgoing data storage is + needed, up to a maximum of SSL_MAX_BUF_SIZE. Once the memory used by the + buffer again drops below SSL_DEFAULT_X_BUF_SIZE, the buffer will be reduced + to this size. Most standard SSL handshakes require on the order of 1024 B. + + SSL_DEFAULT_x_BUF_SIZE value in bytes, maximum SSL_MAX_BUF_SIZE + */ +#ifndef USE_DTLS +#can_define SSL_DEFAULT_IN_BUF_SIZE 1500 /* Base recv buf size, bytes */ +#can_define SSL_DEFAULT_OUT_BUF_SIZE 1500 /* Base send buf size, bytes */ +#else +/******************************************************************************/ +/** + The Path Maximum Transmission Unit is the largest datagram that can be + sent or recieved. It is beyond the scope of DTLS to negotiate this value + so make sure both sides have agreed on this value. This is an enforced + limitation in MatrixDTLS so connections will not succeed if a peer has a + PTMU set larger than this value. +*/ +#define DTLS_PMTU 1500/* 1500 Default/Maximum datagram len */ +#define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU/* See PMTU comments above */ +#define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU/* See PMTU comments above */ + +//#define DTLS_SEND_RECORDS_INDIVIDUALLY /* Max one record per datagram */ +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _h_MATRIXCONFIG */ +/******************************************************************************/ + diff --git a/matrixssl/matrixssllib.h b/matrixssl/matrixssllib.h index 0e0dd55..db3f0c8 100644 --- a/matrixssl/matrixssllib.h +++ b/matrixssl/matrixssllib.h @@ -681,6 +681,14 @@ static __inline uint16_t HASH_SIG_MASK(uint8_t hash, uint8_t sig) #define SSL_MAX_KEY_BLOCK_SIZE ((2 * 48) + (2 * 32) + (2 * 16) + \ SHA1_HASH_SIZE) #endif +#ifdef USE_EAP_FAST +#define EAP_FAST_SESSION_KEY_SEED_LEN 40 +#define EAP_FAST_PAC_KEY_LEN 32 +#undef SSL_MAX_KEY_BLOCK_SIZE +#define SSL_MAX_KEY_BLOCK_SIZE ((2 * 48) + (2 * 32) + (2 * 16) + \ + SHA256_HASH_SIZE + \ + EAP_FAST_SESSION_KEY_SEED_LEN) +#endif /* Master secret is 48 bytes, sessionId is 32 bytes max @@ -904,6 +912,7 @@ typedef struct { uint16_t premasterSize; unsigned char keyBlock[SSL_MAX_KEY_BLOCK_SIZE]; /* Storage for 'ptr' */ +#ifdef USE_NATIVE_TLS_ALGS unsigned char *wMACptr; unsigned char *rMACptr; unsigned char *wKeyptr; @@ -914,10 +923,14 @@ typedef struct { unsigned char readMAC[SSL_MAX_MAC_SIZE]; unsigned char writeKey[SSL_MAX_SYM_KEY_SIZE]; unsigned char readKey[SSL_MAX_SYM_KEY_SIZE]; +#endif unsigned char *wIVptr; unsigned char *rIVptr; unsigned char writeIV[SSL_MAX_IV_SIZE]; unsigned char readIV[SSL_MAX_IV_SIZE]; +#ifdef USE_EAP_FAST + unsigned char *eap_fast_session_key_seed; +#endif unsigned char seq[8]; unsigned char remSeq[8]; @@ -936,14 +949,19 @@ typedef struct { int32 certMatch; #endif /* USE_CLIENT_SIDE_SSL */ +#ifdef USE_NATIVE_SYMMETRIC psCipherContext_t encryptCtx; psCipherContext_t decryptCtx; +#endif +#ifdef USE_NATIVE_TLS_HS_HASH #ifndef USE_ONLY_TLS_1_2 psMd5Sha1_t msgHashMd5Sha1; #endif +#endif #ifdef USE_TLS_1_2 +#ifdef USE_NATIVE_TLS_HS_HASH psSha256_t msgHashSha256; #ifdef USE_SHA1 @@ -955,6 +973,7 @@ typedef struct { #ifdef USE_SHA512 psSha512_t msgHashSha512; #endif +#endif #endif /* USE_TLS_1_2 */ #if defined(USE_SERVER_SIDE_SSL) && defined(USE_CLIENT_AUTH) @@ -1013,6 +1032,9 @@ typedef struct { #ifdef USE_STATELESS_SESSION_TICKETS enum sessionTicketState_e { SESS_TICKET_STATE_INIT = 0, +#ifdef USE_EAP_FAST + SESS_TICKET_STATE_EAP_FAST, /* Initialized with pre-provisioned key */ +#endif SESS_TICKET_STATE_SENT_EMPTY, SESS_TICKET_STATE_SENT_TICKET, SESS_TICKET_STATE_RECVD_EXT, @@ -1259,8 +1281,10 @@ struct ssl { unsigned char oenIvSize; unsigned char oenBlockSize; unsigned char owriteIV[16]; /* GCM uses this in the nonce */ +#ifdef USE_NATIVE_TLS_ALGS unsigned char owriteMAC[SSL_MAX_MAC_SIZE]; psCipherContext_t oencryptCtx; +#endif #ifdef ENABLE_SECURE_REHANDSHAKES unsigned char omyVerifyData[SHA384_HASH_SIZE]; uint32 omyVerifyDataLen; @@ -1310,6 +1334,9 @@ struct ssl { uint32 status_request: 1; /* received EXT_STATUS_REQUEST */ uint32 status_request_v2: 1; /* received EXT_STATUS_REQUEST_V2 */ uint32 require_extended_master_secret: 1; /* peer may require */ +#ifdef USE_EAP_FAST + uint32 eap_fast_master_secret: 1; /* Using eap_fast key derivation */ +#endif } extFlags; /**< Extension flags */ #ifdef USE_MATRIX_OPENSSL_LAYER @@ -1590,6 +1617,7 @@ extern int32_t extMasterSecretSnapshotHSHash(ssl_t *ssl, unsigned char *out, /* prf.c */ +#if defined(USE_NATIVE_TLS_ALGS) || defined(USE_NATIVE_TLS_HS_HASH) extern int32_t prf(const unsigned char *sec, uint16_t secLen, const unsigned char *seed, uint16_t seedLen, unsigned char *out, uint16_t outLen); @@ -1598,6 +1626,7 @@ extern int32_t prf2(const unsigned char *sec, uint16_t secLen, const unsigned char *seed, uint16_t seedLen, unsigned char *out, uint16_t outLen, uint32_t flags); #endif /* USE_TLS_1_2 */ +#endif /* USE_NATIVE_TLS_ALGS || USE_NATIVE_TLS_HS_HASH */ #endif /* USE_TLS */ #ifdef USE_AES_CIPHER_SUITE @@ -1663,6 +1692,20 @@ extern int32_t eccSuitesSupported(const ssl_t *ssl, const uint16_t cipherSpecs[], uint8_t cipherSpecLen); #endif /* USE_ECC_CIPHER_SUITE */ +#ifdef USE_EAP_FAST +/******************************************************************************/ +extern void matrixSslSetSessionIdEapFast(sslSessionId_t *sess, + const unsigned char *pac_key, uint16_t pac_key_len, + const unsigned char *pac_opaque, uint16_t pac_opaque_len); + +extern int32_t matrixSslGetEapFastSKS(const ssl_t *ssl, + unsigned char session_key_seed[EAP_FAST_SESSION_KEY_SEED_LEN]); + +extern int32_t tprf(const unsigned char *key, uint16_t keyLen, + const unsigned char seed, uint16_t seedLen, + unsigned char out[SSL_HS_MASTER_SIZE]); +#endif + /******************************************************************************/ /* Deprected defines for compatibility */ #define CH_RECV_STAT 1 diff --git a/matrixssl/prf.c b/matrixssl/prf.c index cbb0529..6d43dff 100644 --- a/matrixssl/prf.c +++ b/matrixssl/prf.c @@ -58,6 +58,7 @@ int32_t prf2(const unsigned char *sec, uint16_t secLen, #else +#if defined(USE_NATIVE_TLS_ALGS) || defined(USE_NATIVE_TLS_HS_HASH) #ifdef USE_TLS #ifndef USE_ONLY_TLS_1_2 /******************************************************************************/ @@ -351,7 +352,97 @@ int32_t prf2(const unsigned char *sec, uint16_t secLen, } #endif /* USE_TLS_1_2 */ +#ifdef USE_EAP_FAST +/******************************************************************************/ +/** + EAP-FAST T-PRF function. + This proprietary EAP protocol uses TLS to establish a session, but + defines a modified SessionTicket mechansism that alters the generation + of the TLS master secret. + @see https://tools.ietf.org/html/rfc4851#section-5.5 + + @param[in] key The PAC-Key, a shared secret provisioned out of band. + @param[in] keyLen The length in bytes of PAC-Key. + @param[in] seed The seed used for TLS master_secret generation. + @param[in] seedLen For TLS this is always 64 bytes (server_random[32] + + client_random[32]) + @param[out] out The derived master_secret. + @return < on error. SSL_HS_MASTER_SIZE on success. + +*/ +int32_t tprf(const unsigned char *key, uint16_t keyLen, + const unsigned char *seed, uint16_t seedLen, + unsigned char out[SSL_HS_MASTER_SIZE]) +{ + /** @note The 32 byte label includes the null terminator byte */ + static const unsigned char TPRF_LABEL[32] = + "PAC to master secret label hash"; + + psHmacSha1_t ctx; + int32_t rc = PS_FAIL; + unsigned char sha1out[SHA1_HASH_SIZE]; + unsigned char olen_iter[3]; /* outputlength[2] + iteration[1] */ + + psAssert(seedLen == (SSL_HS_RANDOM_SIZE * 2)); + + /** + The first 20 bytes are generated as follows. + T1 = HMAC-SHA1 (key, S + outputlength + 0x01) + S = label + 0x00 + seed + 'label' is 31 bytes of [PAC to master secret label hash] and a + null byte (32 bytes total) + 'seed' as provided is server_random[32] + client_random[32] + outputlength is a 2 byte big endian length of the output, + always 48 bytes in TLS case. + For our use, we simplify the above as: + T1 = HMAC-SHA1 (key, label_with_0x0 + seed + 0x00 + 0x30 + 0x01 + */ + olen_iter[0] = 0x0; // = ((outputlength >> 8) & 0xFF); + olen_iter[1] = SSL_HS_MASTER_SIZE; // = (outputlength & 0xFF); + olen_iter[2] = 0x01; + if ((rc = psHmacSha1Init(&ctx, key, keyLen)) < 0) { + goto L_RETURN; + } + psHmacSha1Update(&ctx, TPRF_LABEL, sizeof(TPRF_LABEL)); /* Includes 0x00 byte */ + psHmacSha1Update(&ctx, seed, seedLen); + psHmacSha1Update(&ctx, olen_iter, sizeof(olen_iter)); + psHmacSha1Final(&ctx, out); + + /* T2 = HMAC-SHA1 (key, T1 + S + outputlength + 0x02) */ + olen_iter[2] = 0x02; + if ((rc = psHmacSha1Init(&ctx, key, keyLen)) < 0) { + goto L_RETURN; + } + psHmacSha1Update(&ctx, out, SHA1_HASH_SIZE); + psHmacSha1Update(&ctx, TPRF_LABEL, sizeof(TPRF_LABEL)); + psHmacSha1Update(&ctx, seed, seedLen); + psHmacSha1Update(&ctx, olen_iter, sizeof(olen_iter)); + psHmacSha1Final(&ctx, out + SHA1_HASH_SIZE); + + /* T3 = HMAC-SHA1 (key, T2 + S + outputlength + 0x03) */ + olen_iter[2] = 0x03; + if ((rc = psHmacSha1Init(&ctx, key, keyLen)) < 0) { + goto L_RETURN; + } + psHmacSha1Update(&ctx, out + SHA1_HASH_SIZE, SHA1_HASH_SIZE); + psHmacSha1Update(&ctx, TPRF_LABEL, sizeof(TPRF_LABEL)); + psHmacSha1Update(&ctx, seed, seedLen); + psHmacSha1Update(&ctx, olen_iter, sizeof(olen_iter)); + psHmacSha1Final(&ctx, sha1out); + + /* Copy the first 8 bytes from T3 to out, making 48 bytes total */ + memcpy(out + (2 * SHA1_HASH_SIZE), sha1out, 8); + rc = SSL_HS_MASTER_SIZE; +L_RETURN: + memzero_s(sha1out, sizeof(sha1out)); + if (rc < 0) { + memzero_s(out, SSL_HS_MASTER_SIZE); /* zero any partial result on error */ + } + return rc; +} +#endif /* USE_EAP_FAST */ #endif /* USE_TLS */ +#endif /* USE_NATIVE_TLS_ALGS || USE_NATIVE_TLS_HS_HASH */ #endif /* USE_TLS_PRF || USE_TLS_PRF2 */ /******************************************************************************/ diff --git a/matrixssl/sslDecode.c b/matrixssl/sslDecode.c index 5a279a0..8234790 100644 --- a/matrixssl/sslDecode.c +++ b/matrixssl/sslDecode.c @@ -820,6 +820,7 @@ ADVANCE_TO_APP_DATA: switch (ssl->deMacSize) { #ifdef USE_SHA256 case SHA256_HASH_SIZE: + psSha256PreInit(&md.sha256); psSha256Init(&md.sha256); while (rc > 0) { psSha256Update(&md.sha256, tmp, 64); @@ -830,6 +831,7 @@ ADVANCE_TO_APP_DATA: #endif #ifdef USE_SHA384 case SHA384_HASH_SIZE: + psSha384PreInit(&md.sha384); psSha384Init(&md.sha384); while (rc > 0) { psSha384Update(&md.sha384, tmp, 128); @@ -840,6 +842,7 @@ ADVANCE_TO_APP_DATA: #endif #ifdef USE_SHA1 case SHA1_HASH_SIZE: + psSha1PreInit(&md.sha1); psSha1Init(&md.sha1); while (rc > 0) { psSha1Update(&md.sha1, tmp, 64); @@ -2255,6 +2258,13 @@ SKIP_HSHEADER_PARSE: case SSL_HS_NEW_SESSION_TICKET: psTraceHs(">>> Client parsing NEW_SESSION_TICKET message\n"); +#ifdef USE_EAP_FAST + if (ssl->flags & SSL_FLAGS_EAP_FAST) { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("NEW_SESSION_TICKET unsupported in EAP-FAST\n"); + return MATRIXSSL_ERROR; + } +#endif if (hsLen < 6) { ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; psTraceInfo("Invalid NewSessionTicket message\n"); diff --git a/matrixssl/sslEncode.c b/matrixssl/sslEncode.c index 8fb3db8..30e57ea 100644 --- a/matrixssl/sslEncode.c +++ b/matrixssl/sslEncode.c @@ -779,9 +779,8 @@ static int32 nowDoCkePka(ssl_t *ssl) ssl->sec.premasterSize); ssl->sec.premaster[0] = (ssl->sec.premasterSize & 0xFF00) >> 8; ssl->sec.premaster[1] = (ssl->sec.premasterSize & 0xFF); - /* Next, uint16 length of PSK and key itself */ - ssl->sec.premaster[ssl->sec.premasterSize + 2] = - (pskIdLen & 0xFF00) >> 8; + /* Next, uint8_t length of PSK and key itself */ + ssl->sec.premaster[ssl->sec.premasterSize + 2] = 0; ssl->sec.premaster[ssl->sec.premasterSize + 3] = (pskIdLen & 0xFF); memcpy(&ssl->sec.premaster[ssl->sec.premasterSize + 4], pskKey, @@ -3532,7 +3531,7 @@ static int32 writePskServerKeyExchange(ssl_t *ssl, sslBuf_t *out) return rc; } - *c = (hintLen & 0xFF00) >> 8; c++; + *c = 0; c++; *c = (hintLen & 0xFF); c++; memcpy(c, hint, hintLen); c += hintLen; @@ -3735,7 +3734,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, #if defined(USE_PSK_CIPHER_SUITE) && defined(USE_ANON_DH_CIPHER_SUITE) /* PSK suites have a leading PSK identity hint (may be zero length) */ if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { - *c = (hintLen & 0xFF00) >> 8; c++; + *c = 0; c++; *c = (hintLen & 0xFF); c++; if (hintLen != 0 && hint != NULL) { memcpy(c, hint, hintLen); @@ -3814,6 +3813,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, /* Using the algorithm from the certificate */ if (ssl->keys->cert->sigAlgorithm == OID_SHA256_RSA_SIG) { hashSize = SHA256_HASH_SIZE; + psSha256PreInit(&digestCtx.sha256); psSha256Init(&digestCtx.sha256); psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -3827,6 +3827,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, #ifdef USE_SHA384 } else if (ssl->keys->cert->sigAlgorithm == OID_SHA384_RSA_SIG) { hashSize = SHA384_HASH_SIZE; + psSha384PreInit(&digestCtx.sha384); psSha384Init(&digestCtx.sha384); psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -3844,6 +3845,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, } else if (ssl->keys->cert->sigAlgorithm == OID_SHA1_RSA_SIG || ssl->keys->cert->sigAlgorithm == OID_MD5_RSA_SIG) { hashSize = SHA1_HASH_SIZE; + psSha1PreInit(&digestCtx.sha1); psSha1Init(&digestCtx.sha1); psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -3861,43 +3863,40 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, return PS_UNSUPPORTED_FAIL; } } else { -#if defined(USE_SHA1) && defined(USE_MD5) - hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; - psMd5Init(&digestCtx.md5); - psMd5Update(&digestCtx.md5, ssl->sec.clientRandom, +#ifdef USE_MD5SHA1 + hashSize = MD5SHA1_HASHLEN; + psMd5Sha1PreInit(&digestCtx.md5sha1); + psMd5Sha1Init(&digestCtx.md5sha1); + psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); - psMd5Update(&digestCtx.md5, ssl->sec.serverRandom, + psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); - psMd5Update(&digestCtx.md5, sigStart, (uint32)(c - sigStart)); - psMd5Final(&digestCtx.md5, hsMsgHash); - - psSha1Init(&digestCtx.sha1); - psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, sigStart, (uint32)(c - sigStart)); - psSha1Final(&digestCtx.sha1, hsMsgHash + MD5_HASH_SIZE); + psMd5Sha1Update(&digestCtx.md5sha1, sigStart, (uint32)(c - sigStart)); + psMd5Sha1Final(&digestCtx.md5sha1, hsMsgHash); #else psTraceIntInfo("Unavailable sigAlgorithm for SKE write: %d\n", ssl->keys->cert->sigAlgorithm); psFree(hsMsgHash, ssl->hsPool); return PS_UNSUPPORTED_FAIL; -#endif +#endif /* USE_MD5SHA1 */ } #else /* USE_TLS_1_2 */ - hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; - psMd5Init(&digestCtx.md5); - psMd5Update(&digestCtx.md5, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); - psMd5Update(&digestCtx.md5, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); - psMd5Update(&digestCtx.md5, sigStart, (uint32)(c - sigStart)); - psMd5Final(&digestCtx.md5, hsMsgHash); - - psSha1Init(&digestCtx.sha1); - psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, sigStart, (uint32)(c - sigStart)); - psSha1Final(&digestCtx.sha1, hsMsgHash + MD5_HASH_SIZE); +#ifdef USE_MD5SHA1 + hashSize = MD5SHA1_HASHLEN; + psMd5Sha1PreInit(&digestCtx.md5sha1); + psMd5Sha1Init(&digestCtx.md5sha1); + psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psMd5Sha1Update(&digestCtx.md5sha1, sigStart, (uint32)(c - sigStart)); + psMd5Sha1Final(&digestCtx.md5sha1, hsMsgHash); +#else + psTraceIntInfo("Unavailable sigAlgorithm for SKE write: %d\n", + ssl->keys->cert->sigAlgorithm); + psFree(hsMsgHash, ssl->hsPool); + return PS_UNSUPPORTED_FAIL; +#endif /* USE_MD5SHA1 */ #endif /* USE_TLS_1_2 */ *c = (ssl->keys->privKey.keysize & 0xFF00) >> 8; c++; @@ -3949,6 +3948,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, if ((ssl->flags & SSL_FLAGS_TLS_1_2) && (ssl->keys->cert->sigAlgorithm == OID_SHA256_ECDSA_SIG)) { hashSize = SHA256_HASH_SIZE; + psSha256PreInit(&digestCtx.sha256); psSha256Init(&digestCtx.sha256); psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -3962,6 +3962,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, } else if ((ssl->flags & SSL_FLAGS_TLS_1_2) && (ssl->keys->cert->sigAlgorithm == OID_SHA384_ECDSA_SIG)) { hashSize = SHA384_HASH_SIZE; + psSha384PreInit(&digestCtx.sha384); psSha384Init(&digestCtx.sha384); psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -3981,6 +3982,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, ((ssl->flags & SSL_FLAGS_TLS_1_2) && (ssl->keys->cert->sigAlgorithm == OID_SHA1_ECDSA_SIG))) { hashSize = SHA1_HASH_SIZE; + psSha1PreInit(&digestCtx.sha1); psSha1Init(&digestCtx.sha1); psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -3999,6 +4001,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, } #else hashSize = SHA1_HASH_SIZE; + psSha1PreInit(&digestCtx.sha1); psSha1Init(&digestCtx.sha1); psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); @@ -5630,7 +5633,8 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out) if (explicitLen == 1) { #ifdef USE_PSK_CIPHER_SUITE if (ssl->flags & SSL_FLAGS_PSK_CIPHER) { - *c = (pskIdLen & 0xFF00) >> 8; c++; + /* pskIdLen is uint8_t. */ + *c = 0; c++; *c = (pskIdLen & 0xFF); c++; /* The cke message begins with the ID of the desired key @@ -5776,10 +5780,10 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out) return SSL_MEM_ERROR; } memset(ssl->sec.premaster, 0, ssl->sec.premasterSize); - ssl->sec.premaster[0] = (pskIdLen & 0xFF00) >> 8; + ssl->sec.premaster[0] = 0; ssl->sec.premaster[1] = (pskIdLen & 0xFF); /* memset to 0 handled middle portion */ - ssl->sec.premaster[2 + pskIdLen] = (pskIdLen & 0xFF00) >> 8; + ssl->sec.premaster[2 + pskIdLen] = 0; ssl->sec.premaster[3 + pskIdLen] = (pskIdLen & 0xFF); memcpy(&ssl->sec.premaster[4 + pskIdLen], pskKey, pskIdLen); /* Now that we've got the premaster secret, derive the various diff --git a/matrixssl/test/Makefile b/matrixssl/test/Makefile old mode 100755 new mode 100644 diff --git a/matrixssl/tls.c b/matrixssl/tls.c index 8571fb1..59ca555 100644 --- a/matrixssl/tls.c +++ b/matrixssl/tls.c @@ -37,6 +37,7 @@ #include "matrixsslApi.h" +#ifdef USE_NATIVE_TLS_ALGS /******************************************************************************/ #ifdef USE_TLS /******************************************************************************/ @@ -65,6 +66,28 @@ static int32_t genKeyBlock(ssl_t *ssl) reqKeyLen = 2 * ssl->cipher->macSize + 2 * ssl->cipher->keySize + 2 * ssl->cipher->ivSize; +#ifdef USE_EAP_FAST + /** + Generate master secret with tprf. + Make space for additional key material (session key seed). + @see https://tools.ietf.org/html/rfc4851#section-5.1 + */ + if (ssl->flags & SSL_FLAGS_EAP_FAST) { + if (ssl->sid == NULL) { + goto L_RETURN; + } + /* sid->masterSecret actually holds pac-key. Use tprf() here + to derive session masterSecret, now that we're about to use it. + masterSecret is also used after this for the finished message hash */ + rc = tprf(ssl->sid->masterSecret, EAP_FAST_PAC_KEY_LEN, + msSeed + LABEL_SIZE, 2 * SSL_HS_RANDOM_SIZE, + ssl->sec.masterSecret); + if (rc < 0) { + goto L_RETURN; + } + reqKeyLen += EAP_FAST_SESSION_KEY_SEED_LEN; + } +#endif /* Ensure there's enough room */ if (reqKeyLen > SSL_MAX_KEY_BLOCK_SIZE) { @@ -103,6 +126,11 @@ static int32_t genKeyBlock(ssl_t *ssl) ssl->sec.wKeyptr = ssl->sec.rKeyptr + ssl->cipher->keySize; ssl->sec.rIVptr = ssl->sec.wKeyptr + ssl->cipher->keySize; ssl->sec.wIVptr = ssl->sec.rIVptr + ssl->cipher->ivSize; +#ifdef USE_EAP_FAST + if (ssl->flags & SSL_FLAGS_EAP_FAST) { + ssl->sec.eap_fast_session_key_seed = ssl->sec.wIVptr + ssl->cipher->ivSize; + } +#endif } else { ssl->sec.wMACptr = ssl->sec.keyBlock; ssl->sec.rMACptr = ssl->sec.wMACptr + ssl->cipher->macSize; @@ -110,6 +138,11 @@ static int32_t genKeyBlock(ssl_t *ssl) ssl->sec.rKeyptr = ssl->sec.wKeyptr + ssl->cipher->keySize; ssl->sec.wIVptr = ssl->sec.rKeyptr + ssl->cipher->keySize; ssl->sec.rIVptr = ssl->sec.wIVptr + ssl->cipher->ivSize; +#ifdef USE_EAP_FAST + if (ssl->flags & SSL_FLAGS_EAP_FAST) { + ssl->sec.eap_fast_session_key_seed = ssl->sec.rIVptr + ssl->cipher->ivSize; + } +#endif } rc = SSL_HS_MASTER_SIZE; @@ -145,6 +178,12 @@ int32_t tlsDeriveKeys(ssl_t *ssl) if (ssl->flags & SSL_FLAGS_RESUMED) { return genKeyBlock(ssl); } +#ifdef USE_EAP_FAST + /* We should only do EAP_FAST key derivation on resumed connections */ + if (ssl->flags & SSL_FLAGS_EAP_FAST) { + return PS_FAIL; + } +#endif /* master_secret = PRF(pre_master_secret, "master secret", @@ -223,6 +262,12 @@ int32_t tlsExtendedDeriveKeys(ssl_t *ssl) psTraceInfo("Invalid invokation of extended key derivation.\n"); return PS_FAIL; } +#ifdef USE_EAP_FAST + /* We should only do EAP_FAST key derivation on resumed connections */ + if (ssl->flags & SSL_FLAGS_EAP_FAST) { + return PS_FAIL; + } +#endif extMasterSecretSnapshotHSHash(ssl, hash, &outLen); /* @@ -702,6 +747,7 @@ int32 sslActivateWriteCipher(ssl_t *ssl) } /******************************************************************************/ +#endif /* USE_NATIVE_TLS_ALGS */ #ifdef USE_CLIENT_SIDE_SSL diff --git a/testkeys/DH/3072_DH_PARAMS.h b/testkeys/DH/3072_DH_PARAMS.h index 4d004fa..0e0665f 100644 --- a/testkeys/DH/3072_DH_PARAMS.h +++ b/testkeys/DH/3072_DH_PARAMS.h @@ -1,6 +1,6 @@ /** * @file dh3072.h - * @version $Format:%h%d$ + * @version $Format:%h%d$ * * Summary. */ diff --git a/testkeys/DH/dh3072.h b/testkeys/DH/dh3072.h index 6d098c7..d0de69b 100644 --- a/testkeys/DH/dh3072.h +++ b/testkeys/DH/dh3072.h @@ -1,6 +1,6 @@ /** * @file dh3072.h - * @version $Format:%h%d$ + * @version $Format:%h%d$ * * Summary. */