diff --git a/Makefile b/Makefile index e7f4167..a2f9245 100644 --- a/Makefile +++ b/Makefile @@ -1,38 +1,217 @@ # -# Recursively build the directories below -# @version $Format:%h%d$ +# Top-level Makefile for building various versions of MatrixSSL. # +# Copyright (c) 2016 INSIDE Secure Corporation. All Rights Reserved. +# +# + +# A list of the most important build targets provided by this Makefile: +# Make command Description +# make all Default target: Build all software using current +# MatrixSSL configuration +# make libs Build MatrixSSL libraries using current +# MatrixSSL configuration +# make tests Build MatrixSSL test programs using current +# MatrixSSL configuration +# make apps Build MatrixSSL example programs using current +# MatrixSSL configuration +# make check-config Apply default configuration if not present. +# make *-config (Specify *) select one of prepackaged configurations +# from configs directory. +# +# Additional targets for MatrixSSL Open Source and Commercial Editions +# +# make all-tls Build MatrixSSL using options suitable for most +# TLS use cases and the MatrixSSL stock crypto. +# make all-noecc Build MatrixSSL using options that disable ECC, +# using the MatrixSSL stock crypto. +# make all-rsaonly Build MatrixSSL using options that disable ECC and DH, +# using the MatrixSSL stock crypto. +# +# Additional targets for MatrixSSL FIPS Edition +# +# make all-fips Compile MatrixSSL FIPS Edition with default +# configuration. +# make all-cl-nonfips Compile MatrixSSL FIPS Edition using CL library in +# non-FIPS Mode of operation. +# make all-combined Compile MatrixSSL FIPS Edition allowing run-time +# selection of FIPS or non-FIPS mode. +# make all-combined-default-nonfips The same than make all combined, but +# non-FIPS mode is the default. +# +# + +default: all +util: all-utils + +CONFIG_EXTRA_DEPENDENCIES= + +# Use default config if no config is being used. +check-config: $(CONFIG_EXTRA_DEPENDENCIES) + @if [ ! -e core/coreConfig.h ];then \ + cp configs/default/coreConfig.h core/coreConfig.h;\ + echo NOTE: Using default configuration from configs/default/coreConfig.h.;\ + fi + @if [ ! -e crypto/cryptoConfig.h ];then \ + cp configs/default/cryptoConfig.h crypto/cryptoConfig.h;\ + echo NOTE: Using default configuration from configs/default/cryptoConfig.h.;\ + fi + @if [ ! -e matrixssl/matrixsslConfig.h ];then \ + cp configs/default/matrixsslConfig.h matrixssl/matrixsslConfig.h;\ + echo NOTE: Using default configuration from configs/default/matrixsslConfig.h.;\ + fi + +clean-config: + rm -f core/coreConfig.h crypto/cryptoConfig.h matrixssl/matrixsslConfig.h + +# Apply any of pre-existing configurations from configs directory +%-config: configs/% $(CONFIG_EXTRA_DEPENDENCIES) + @echo Using $next) { - if (psX509AuthenticateCRL(ic, crl, NULL) > 0) { + if (psX509AuthenticateCRL(ic, crl, NULL) >= 0) { _psTrace("NOTE: Able to authenticate CRL\n"); break; /* Stop looking */ } @@ -1595,7 +1595,7 @@ static int32_t fetchParseAndAuthCRLfromCert(psPool_t *pool, psX509Cert_t *cert, from the cert authentication. Here, we run through the list of potential issuers the caller thinks could work */ for (ic = potentialIssuers; ic != NULL; ic = ic->next) { - if (psX509AuthenticateCRL(ic, crl, NULL) > 0) { + if (psX509AuthenticateCRL(ic, crl, NULL) >= 0) { _psTrace("NOTE: Able to authenticate CRL\n"); break; /* Stop looking */ } @@ -1612,7 +1612,7 @@ static int32_t fetchParseAndAuthCRLfromCert(psPool_t *pool, psX509Cert_t *cert, certificate of the server chain will need to be authenticated */ for (ic = cert; ic != NULL; ic = ic->next) { - if (psX509AuthenticateCRL(ic, crl, NULL) > 0) { + if (psX509AuthenticateCRL(ic, crl, NULL) >= 0) { _psTrace("NOTE: Able to authenticate CRL\n"); break; /* Stop looking */ } @@ -1751,6 +1751,7 @@ int32 fetchCRL(psPool_t *pool, char *url, uint32_t urlLen, /* Get a chunk at a time so we can peek at the size on the first chunk and allocate the correct CRL size */ crlBin = NULL; + crlBinLen = 0; *crlBuf = NULL; *crlBufLen = 0; sawOK = sawContentLength = 0; diff --git a/apps/ssl/server.c b/apps/ssl/server.c index 1c0108d..cced65b 100644 --- a/apps/ssl/server.c +++ b/apps/ssl/server.c @@ -37,6 +37,7 @@ #include "matrixssl/matrixsslApi.h" #ifdef USE_SERVER_SIDE_SSL +#ifdef MATRIX_USE_FILE_SYSTEM #include /* Defines SIGTERM, etc. */ @@ -85,11 +86,11 @@ static int g_disabledCiphers; static uint16_t g_disabledCipher[SSL_MAX_DISABLED_CIPHERS]; #define MAX_KEYFILE_PATH 256 -#define MAX_KEYFILE_NAME 32 static char g_keyfilePath[MAX_KEYFILE_PATH]; -static char g_privkeyFile[MAX_KEYFILE_NAME]; -static char g_identityCert[MAX_KEYFILE_NAME]; -static char g_dhParamFile[MAX_KEYFILE_NAME]; +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 unsigned char g_httpResponseHdr[] = "HTTP/1.0 200 OK\r\n" @@ -103,22 +104,11 @@ static unsigned char g_httpResponseHdr[] = "HTTP/1.0 200 OK\r\n" #ifdef USE_STATELESS_SESSION_TICKETS static int32 sessTicketCb(void *keys, unsigned char name[16], short found); - -/* SAMPLE KEYS: DO NOT USE IN PRODUCTION */ -static unsigned char sessTicketSymKey[32] = { - 0x2A, 0x34, 0xC2, 0x11, 0x45, 0x8F, 0x3D, 0x08, - 0x2A, 0x34, 0xC2, 0x11, 0x45, 0x8F, 0x3D, 0x08, - 0x2A, 0x34, 0xC2, 0x11, 0x45, 0x8F, 0x3D, 0x08, - 0x2A, 0x34, 0xC2, 0x11, 0x45, 0x8F, 0x3D, 0x08}; - -static unsigned char sessTicketMacKey[32] = { - 0x2A, 0x34, 0xC2, 0x11, 0x45, 0x8F, 0x3D, 0x08, - 0x2A, 0x34, 0xC2, 0x11, 0x45, 0x8F, 0x3D, 0x08, - 0x2A, 0x34, 0xC2, 0x11, 0x45, 0x8F, 0x3D, 0x08, - 0x2A, 0x34, 0xC2, 0x11, 0x45, 0x8F, 0x3D, 0x08}; +static unsigned char sessTicketSymKey[32] = { 0 }; +static unsigned char sessTicketMacKey[32] = { 0 }; #endif -/***************************** Static Prototypes ******************************/ +/****************************** Local Functions *******************************/ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd); static int32 httpWriteResponse(httpConn_t *conn); @@ -155,9 +145,11 @@ int32 sessTicketCb(void *keys, unsigned char name[16], short found) /* Was already cached */ return PS_SUCCESS; } - /* Example. If name was located, the keys would be loaded this way */ + /* Example. If name was located, different keys would be loaded this way. Of course here + we are loading the same keys already loaded. */ return matrixSslLoadSessionTicketKeys((sslKeys_t*)keys, name, - sessTicketSymKey, 32, sessTicketMacKey, 32); + sessTicketSymKey, sizeof(sessTicketSymKey), + sessTicketMacKey, sizeof(sessTicketMacKey)); } #endif @@ -166,7 +158,6 @@ void SNIcallback(void *ssl, char *hostname, int32 hostnameLen, { ssl_t *lssl = ssl; *newKeys = lssl->keys; - } /******************************************************************************/ @@ -650,6 +641,7 @@ static void usage(void) "\n" "-c - Server certificate file\n" "-k - Server private key file of certificate\n" + "-a - CA certificate file\n" "-p - Private key password\n" "-d - Diffie-Hellman parameters file\n" "-D - Directory path to certificate, private key, \n" @@ -715,9 +707,10 @@ static int32 process_cmd_options(int32 argc, char **argv) memset(g_keyfilePath, 0, MAX_KEYFILE_PATH); - memset(g_privkeyFile, 0, sizeof(MAX_KEYFILE_NAME)); - memset(g_identityCert, 0, sizeof(MAX_KEYFILE_NAME)); - memset(g_dhParamFile, 0, sizeof(MAX_KEYFILE_NAME)); + 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); g_port = HTTPS_PORT; @@ -725,7 +718,7 @@ static int32 process_cmd_options(int32 argc, char **argv) g_disabledCiphers = 0; opterr = 0; - while ((optionChar = getopt(argc, argv, "c:d:D:hk:p:P:v:x:")) != -1) + while ((optionChar = getopt(argc, argv, "c:d:a:D:hk:p:P:v:x:")) != -1) { switch (optionChar) { @@ -756,16 +749,25 @@ static int32 process_cmd_options(int32 argc, char **argv) case 'c': // Certfile str_len = strlen(optarg); - if (str_len > MAX_KEYFILE_NAME - 1) { + if (str_len > MAX_KEYFILE_PATH - 1) { return -1; } strncpy(g_identityCert, optarg, str_len); break; + case 'a': + // Cert authority file + str_len = strlen(optarg); + if (str_len > MAX_KEYFILE_PATH - 1) { + return -1; + } + strncpy(g_caFile, optarg, str_len); + break; + case 'd': // Diffie-Hellman parameters str_len = strlen(optarg); - if (str_len > MAX_KEYFILE_NAME - 1) { + if (str_len > MAX_KEYFILE_PATH - 1) { return -1; } strncpy(g_dhParamFile, optarg, str_len); @@ -775,7 +777,7 @@ static int32 process_cmd_options(int32 argc, char **argv) case 'k': // Keyfile str_len = strlen(optarg); - if (str_len > MAX_KEYFILE_NAME - 1) { + if (str_len > MAX_KEYFILE_PATH - 1) { return -1; } strncpy(g_privkeyFile, optarg, str_len); @@ -784,7 +786,7 @@ static int32 process_cmd_options(int32 argc, char **argv) case 'p': // password str_len = strlen(optarg); - if (str_len > MAX_KEYFILE_NAME - 1) { + if (str_len > MAX_KEYFILE_PATH - 1) { return -1; } strncpy(g_password, optarg, str_len); @@ -822,13 +824,13 @@ int32 main(int32 argc, char **argv) WSADATA wsaData; #endif #ifdef USE_STATELESS_SESSION_TICKETS - unsigned char randKey[16]; + unsigned char sessTicketName[16]; #endif char certpath[FILENAME_MAX]; char keypath[FILENAME_MAX]; char capath[FILENAME_MAX]; sslKeys_t *keys = NULL; - + #ifdef WIN32 WSAStartup(MAKEWORD(1, 1), &wsaData); #endif @@ -847,29 +849,31 @@ int32 main(int32 argc, char **argv) _psTrace("MatrixSSL library init failure. Exiting\n"); return rc; } - + if (matrixSslNewKeys(&keys, NULL) < 0) { return -1; } - + if (0 != process_cmd_options(argc, argv)) { usage(); return 0; } - -#ifdef USE_OCSP - OCSPRequestAndResponseTest(); -#endif - + #ifdef USE_STATELESS_SESSION_TICKETS - _psTrace("Session Ticket resumption enabled\n"); - _psTrace("WARNING: Do not use sample session ticket keys in production\n"); - matrixSslSetSessionTicketCallback(keys, sessTicketCb); - psGetEntropy(randKey, 16, NULL); - if (matrixSslLoadSessionTicketKeys(keys, randKey, - sessTicketSymKey, 32, sessTicketMacKey, 32) < 0) { - _psTrace("Error loading session ticket encryption key\n"); + if (matrixCryptoGetPrngData(sessTicketSymKey, sizeof(sessTicketSymKey), NULL) < 0 + || matrixCryptoGetPrngData(sessTicketMacKey, sizeof(sessTicketMacKey), NULL) < 0 + || matrixCryptoGetPrngData(sessTicketName, sizeof(sessTicketName), NULL) < 0) { + _psTrace("Error generating session ticket encryption key\n"); + return EXIT_FAILURE; } + if (matrixSslLoadSessionTicketKeys(keys, sessTicketName, + sessTicketSymKey, sizeof(sessTicketSymKey), + sessTicketMacKey, sizeof(sessTicketMacKey)) < 0) { + _psTrace("Error loading session ticket encryption key\n"); + return EXIT_FAILURE; + } + matrixSslSetSessionTicketCallback(keys, sessTicketCb); + _psTrace("Session Ticket resumption enabled\n"); #endif @@ -888,7 +892,7 @@ int32 main(int32 argc, char **argv) snprintf(certpath, FILENAME_MAX - 1, "%s/%s", KEY_DIR, g_defaultCertFile); } - + if (g_privkeyFile[0] != 0) { // User provided a key if (g_keyfilePath[0] != 0) { @@ -903,9 +907,21 @@ int32 main(int32 argc, char **argv) snprintf(keypath, FILENAME_MAX - 1, "%s/%s", KEY_DIR, g_defaultPrivkeyFile); } - - snprintf(capath, FILENAME_MAX - 1, "%s/%s", KEY_DIR, g_defaultCAFile); - + + if (g_caFile[0] != 0) { + // User provided a CA file + if (g_keyfilePath[0] != 0) { + snprintf(capath, FILENAME_MAX - 1, "%s/%s", + g_keyfilePath, g_caFile); + } else { + snprintf(capath, FILENAME_MAX - 1, "%s", g_caFile); + } + } else { + // Default key + snprintf(capath, FILENAME_MAX - 1, "%s/%s", + KEY_DIR, g_defaultCAFile); + } + /* Still don't have a generic key loading function. Try RSA first and then ECC if that doesn't load */ if ((rc = matrixSslLoadRsaKeys(keys, certpath, keypath, g_password, capath)) < 0) { @@ -1150,3 +1166,13 @@ int32 main(int32 argc, char **argv) /******************************************************************************/ +#else +#include + +int main(int argc, char **argv) +{ + printf("You need to #define MATRIX_USE_FILE_SYSTEM for this test\n"); + return 1; +} + +#endif /* MATRIX_USE_FILE_SYSTEM */ diff --git a/common.mk b/common.mk index ab02f08..51cfa04 100755 --- a/common.mk +++ b/common.mk @@ -1,10 +1,11 @@ ## # Common Makefile definitions. -# @version $Format:%h%d$ +# # Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. # #------------------------------------------------------------------------------- + #------------------------------------------------------------------------------- ## Makefile variables that must be defined in this file # @param[out] $(BUILD) Set here for release or debug @@ -29,7 +30,7 @@ BUILD:=release ##< Release build strips binary and optimizes #------------------------------------------------------------------------------- ## Makefile variables that are created by this file # @param[out] $(OSDEP) Set to platform code directory (./core/$OSDEP/osdep.c), based on $(CC) -# @param[out] $(CCARCH) Set to compiler's target architecture, based on $(CC) +# @param[out] $(CCARCH) Set to compilers target architecture, based on $(CC) # @param[out] $(STRIP) Set to the executable to use to strip debug symbols from executables # @param[out] $(STROPS) Human readable description of relevant MatrixSSL compile options. # @param[out] $(O) Set to the target platform specific object file extension @@ -41,6 +42,9 @@ BUILD:=release ##< Release build strips binary and optimizes ## Auto-detect cross compiler for some platforms based on environment variables +# Execute commands in environment with default locale. +CLEAN_ENV=LC_ALL=POSIX + ## Based on the value of CC, determine the target, eg. # x86_64-redhat-linux # i686-linux-gnu @@ -51,7 +55,19 @@ BUILD:=release ##< Release build strips binary and optimizes # mips-linux-gnu # mipsisa64-octeon-elf-gcc # powerpc-linux-gnu -CCARCH:=$(shell $(CC) -v 2>&1 | sed -n '/Target: / s/// p') +# i386-redhat-linux +# x86_64-redhat-linux +ifeq '$(CCARCH)' '' +CCARCH:=$(shell $(CLEAN_ENV) $(CC) -v 2>&1 | sed -n '/Target: / s/// p') +ifeq '$(CCARCH)' '' +# Could not obtain target triplet: Try still -dumpmachine (supported by +# some versions of GCC) +CCARCH:=$(shell $(CLEAN_ENV) $(CC) -dumpmachine) +ifeq '$(CCARCH)' '' +$(error Unable to determine compiler architecture. $(CC) -v or $(CC) -dumpmachine does not work. Please, provide CCARCH manually via an environment variable.) +endif +endif +endif CCVER:=$(shell $(CC) --version 2>&1) STROPTS:="Built for $(CCARCH)" @@ -78,6 +94,21 @@ ifneq (,$(findstring -apple,$(CCARCH))) endif endif +# Select options affecting C language and API standards to enable. +C_STD:= +ifneq (,$(findstring (GCC),$(CCVER))) + ifneq (,$(findstring 3.4,$(CCVER))) + # Enable linux platform extensions for APIs and provide the length of + # types. + # Also remove spurious warnings on some opaque types + ifneq (,$(findstring x86_64,$(CCARCH))) + C_STD := -D_GNU_SOURCE -D__SIZEOF_LONG_LONG__=8 -DSIZEOF_LONG=8 + else + C_STD := -D_GNU_SOURCE -D__SIZEOF_LONG_LONG__=8 -DSIZEOF_LONG=4 + endif + endif +endif + #Manually enable debug here #MATRIX_DEBUG:=1 @@ -93,15 +124,7 @@ ifndef MATRIX_DEBUG endif STRIP:=strip endif -CFLAGS+=$(OPT) - -# Detect multicore and do parallel build. Uncomment if desired: -#> ifneq (,$(findstring -linux,$(CCARCH))) -#> JOBS:=-j$(shell grep -ic processor /proc/cpuinfo) -#> endif -#> ifneq (,$(findstring apple,$(CCARCH))) -#> JOBS:=-j$(shell sysctl -n machdep.cpu.thread_count) -#> endif +CFLAGS+=$(OPT) $(C_STD) default: $(BUILD) @@ -111,6 +134,10 @@ debug: release: @$(MAKE) $(JOBS) compile +ifeq ($(SSH_PACKAGE),1) + CFLAGS+=-DSSH_PACKAGE +endif + # 64 Bit Intel Target ifneq (,$(findstring x86_64-,$(CCARCH))) CFLAGS+=-m64 @@ -150,13 +177,16 @@ ifneq (,$(findstring i686-,$(CCARCH))) CFLAGS+=-m32 STROPTS+=", 32-bit Intel RSA/ECC ASM" endif +ifneq (,$(findstring i386-,$(CCARCH))) + STROPTS+=", 32-bit Intel RSA/ECC ASM" +endif # MIPS Target ifneq (,$(findstring mips-,$(CCARCH))) STROPTS+=", 32-bit MIPS RSA/ECC ASM" endif -# MIPS64 Target +# MIPS64 Target ifneq (,$(filter mips%64-,$(CCARCH))) endif @@ -205,7 +235,7 @@ CFLAGS_OMIT_FRAMEPOINTER=-fomit-frame-pointer CFLAGS+=-ffunction-sections -fdata-sections $(CFLAGS_OMIT_FRAMEPOINTER) endif -# If we're using clang (it may be invoked via 'cc' or 'gcc'), +# If we are using clang (it may be invoked via 'cc' or 'gcc'), # handle minor differences in compiler behavior vs. gcc ifneq (,$(findstring clang,$(CCVER))) CFLAGS+=-Wno-error=unused-variable -Wno-error=\#warnings -Wno-error=\#pragma-messages @@ -213,13 +243,19 @@ endif # Handle differences between the OS X ld and GNU ld ifneq (,$(findstring -apple,$(CCARCH))) - LDFLAGS+=-Wl,-dead_strip + LDFLAGS_GARBAGE_COLLECTION=-Wl,-dead_strip else - LDFLAGS+=-Wl,--gc-sections + LDFLAGS_GARBAGE_COLLECTION+=-Wl,--gc-sections +endif + +# Optionally turn on garbage collection. +ifeq '$(NO_LINKER_GARBAGE_COLLECTION)' '' +LDFLAGS += $(LDFLAGS_GARBAGE_COLLECTION) endif CFLAGS+=-I$(MATRIXSSL_ROOT) +#ifdef USE_OPENSSL_CRYPTO #USE_OPENSSL_CRYPTO:=1 ifdef USE_OPENSSL_CRYPTO OPENSSL_ROOT:=/opt/openssl-1.0.2d @@ -229,8 +265,8 @@ ifdef USE_OPENSSL_CRYPTO LDFLAGS+=$(OPENSSL_ROOT)/libcrypto.a -ldl endif ifneq (,$(findstring -apple,$(CCARCH))) - # Dynamically link against the sytem default openssl tree - # Apple has deprecated the built in openssl, so supress warnings here + # Dynamically link against the system default openssl tree + # Apple has deprecated the built in openssl, so suppress warnings here CFLAGS+=-Wno-error=deprecated-declarations -Wno-deprecated-declarations LDFLAGS+=-lcrypto OPENSSL_ROOT=included_in_the_OS @@ -246,7 +282,9 @@ ifdef USE_OPENSSL_CRYPTO CFLAGS+=-DUSE_OPENSSL_CRYPTO STROPTS+=", USE_OPENSSL_CRYPTO" endif +#endif +#ifdef USE_LIBSODIUM_CRYPTO #USE_LIBSODIUM_CRYPTO:=1 ifdef USE_LIBSODIUM_CRYPTO LIBSODIUM_ROOT:=/opt/libsodium-1.0.8/src/libsodium @@ -261,12 +299,15 @@ ifdef USE_LIBSODIUM_CRYPTO CFLAGS+=-DUSE_LIBSODIUM_CRYPTO STROPTS+=", USE_LIBSODIUM_CRYPTO" endif +#endif # Linux Target ifneq (,$(findstring -linux,$(CCARCH))) OSDEP:=POSIX #For USE_HIGHRES_TIME LDFLAGS+=-lrt + #For multithreading + LDFLAGS+=-lpthread endif # OS X Target diff --git a/core/coreConfig.h b/configs/default/coreConfig.h similarity index 88% rename from core/coreConfig.h rename to configs/default/coreConfig.h index c48aca9..1dc1ecf 100644 --- a/core/coreConfig.h +++ b/configs/default/coreConfig.h @@ -35,6 +35,7 @@ #ifndef _h_PS_CORECONFIG #define _h_PS_CORECONFIG + /******************************************************************************/ /* Configurable features */ /******************************************************************************/ @@ -61,8 +62,20 @@ /** Include the psCoreOsdepMutex family of APIs + + @note If intending to compile crypto-cl, then this flag should + always be set. */ -//#define USE_MULTITHREADING +#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/configs/default/cryptoConfig.h b/configs/default/cryptoConfig.h new file mode 100644 index 0000000..3a07dc4 --- /dev/null +++ b/configs/default/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/configs/default/matrixsslConfig.h b/configs/default/matrixsslConfig.h new file mode 100644 index 0000000..e923a91 --- /dev/null +++ b/configs/default/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/configs/noecc/coreConfig.h b/configs/noecc/coreConfig.h new file mode 100644 index 0000000..1dc1ecf --- /dev/null +++ b/configs/noecc/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/configs/noecc/cryptoConfig.h b/configs/noecc/cryptoConfig.h new file mode 100644 index 0000000..960f95b --- /dev/null +++ b/configs/noecc/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/configs/noecc/matrixsslConfig.h b/configs/noecc/matrixsslConfig.h new file mode 100644 index 0000000..fa9fb52 --- /dev/null +++ b/configs/noecc/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/configs/nonfips/coreConfig.h b/configs/nonfips/coreConfig.h new file mode 100644 index 0000000..1dc1ecf --- /dev/null +++ b/configs/nonfips/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/configs/nonfips/cryptoConfig.h b/configs/nonfips/cryptoConfig.h new file mode 100644 index 0000000..3a07dc4 --- /dev/null +++ b/configs/nonfips/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/configs/nonfips/matrixsslConfig.h b/configs/nonfips/matrixsslConfig.h new file mode 100644 index 0000000..0cf7b0f --- /dev/null +++ b/configs/nonfips/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/configs/rsaonly/coreConfig.h b/configs/rsaonly/coreConfig.h new file mode 100644 index 0000000..1dc1ecf --- /dev/null +++ b/configs/rsaonly/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/configs/rsaonly/cryptoConfig.h b/configs/rsaonly/cryptoConfig.h new file mode 100644 index 0000000..6f75395 --- /dev/null +++ b/configs/rsaonly/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/matrixssl/matrixsslConfig.h b/configs/rsaonly/matrixsslConfig.h similarity index 80% rename from matrixssl/matrixsslConfig.h rename to configs/rsaonly/matrixsslConfig.h index fd1df00..d614833 100644 --- a/matrixssl/matrixsslConfig.h +++ b/configs/rsaonly/matrixsslConfig.h @@ -3,6 +3,9 @@ * @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 @@ -73,23 +76,23 @@ extern "C" { */ /** 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 */ +//#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_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 +//#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_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 */ @@ -100,13 +103,13 @@ extern "C" { //#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 */ +#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 */ +#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 */ /******************************************************************************/ /** @@ -126,11 +129,11 @@ extern "C" { /** 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 */ +#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 */ +#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 */ @@ -170,11 +173,9 @@ extern "C" { @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. + including NIST SP 800-56A, when in FIPS 140-2 mode of operation. */ -#ifdef USE_NIST_GUIDELINES -#define NO_ECC_EPHEMERAL_CACHE /**< @security NIST_SHALL */ -#endif +//#define NO_ECC_EPHEMERAL_CACHE /**< @security NIST_SHALL */ /******************************************************************************/ /** @@ -185,7 +186,9 @@ extern "C" { 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_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. */ /******************************************************************************/ /** @@ -193,7 +196,7 @@ extern "C" { Enables DTLS in addition to TLS. @pre TLS_1_1 */ -//#define USE_DTLS +#define USE_DTLS /******************************************************************************/ /** @@ -204,7 +207,7 @@ extern "C" { /******************************************************************************/ /** - Client certifiate authentication + Client certificate authentication */ #define USE_CLIENT_AUTH @@ -282,8 +285,8 @@ extern "C" { 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 */ +#define SSL_SESSION_TABLE_SIZE 32 +#define SSL_SESSION_ENTRY_LIFE (86400*1000)/* one day, in milliseconds */ #endif /******************************************************************************/ @@ -293,6 +296,7 @@ extern "C" { 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 /******************************************************************************/ /** @@ -305,8 +309,8 @@ extern "C" { SSL_DEFAULT_x_BUF_SIZE value in bytes, maximum SSL_MAX_BUF_SIZE */ #ifndef USE_DTLS -#define SSL_DEFAULT_IN_BUF_SIZE 1500 /* Base recv buf size, bytes */ -#define SSL_DEFAULT_OUT_BUF_SIZE 1500 /* Base send buf size, bytes */ +#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 /******************************************************************************/ /** @@ -316,9 +320,9 @@ extern "C" { 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_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 diff --git a/configs/tls/coreConfig.h b/configs/tls/coreConfig.h new file mode 100644 index 0000000..1dc1ecf --- /dev/null +++ b/configs/tls/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/crypto/cryptoConfig.h b/configs/tls/cryptoConfig.h similarity index 67% rename from crypto/cryptoConfig.h rename to configs/tls/cryptoConfig.h index 05dbc2e..78e41eb 100644 --- a/crypto/cryptoConfig.h +++ b/configs/tls/cryptoConfig.h @@ -44,9 +44,15 @@ //#define USE_CRYPTO_TRACE #ifdef DEBUG -// #define CRYPTO_ASSERT /**< Extra sanity asserts */ +//#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. @@ -54,13 +60,13 @@ @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_ECC_BITS 192/**< @security Affects ECC curves below */ #define MIN_RSA_BITS 1024 -#define MIN_DH_BITS 1024 +#define MIN_DH_BITS 1024 -#define USE_BURN_STACK /**< @security Zero sensitive data from the stack. */ +#define USE_BURN_STACK/**< @security Zero sensitive data from the stack. */ /******************************************************************************/ /** @@ -69,6 +75,15 @@ #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. +*/ /******************************************************************************/ @@ -77,10 +92,10 @@ @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_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_SECP256R1/**< @security NIST_SHALL */ + #define USE_SECP384R1/**< @security NIST_SHALL */ #define USE_SECP521R1 #endif @@ -101,22 +116,22 @@ 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 -//#define USE_AES_GCM_GIV -#ifdef USE_LIBSODIUM_CRYPTO - #define USE_CHACHA20_POLY1305 +#ifdef USE_LIBSODIUM +//#define USE_CHACHA20_POLY1305 #endif /** @security 3DES is still relatively secure, however is deprecated for TLS */ -//#define USE_3DES +#define USE_3DES /******************************************************************************/ /** Digest algorithms. - @note SHA256 and above are used with TLS 1.2, and also used for + @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 @@ -127,15 +142,15 @@ @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 + 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_SHA256/**< @note Required for TLS 1.2 and above */ #define USE_HMAC_SHA256 -#define USE_SHA384 /**< @pre USE_SHA512 */ +#define USE_SHA384/**< @pre USE_SHA512 */ #define USE_HMAC_SHA384 #define USE_SHA512 @@ -151,8 +166,19 @@ @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 */ +#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 /******************************************************************************/ /** @@ -160,14 +186,19 @@ */ #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 */ +#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? */ - -//#define USE_CRL /***< @pre USE_FULL_CERT_PARSE */ -//#define USE_OCSP /**< @pre USE_SHA1 */ +#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 */ /******************************************************************************/ /** @@ -175,10 +206,10 @@ */ #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 */ +#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/configs/tls/matrixsslConfig.h b/configs/tls/matrixsslConfig.h new file mode 100644 index 0000000..e923a91 --- /dev/null +++ b/configs/tls/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/core/Makefile b/core/Makefile index 0688979..76e57fc 100755 --- a/core/Makefile +++ b/core/Makefile @@ -10,6 +10,7 @@ include $(MATRIXSSL_ROOT)/common.mk SRC:=\ memset_s.c \ corelib.c \ + psbuf.c \ $(OSDEP)/osdep.c ASM:=memset_s.s @@ -33,10 +34,13 @@ $(ASM): memset_s.c $(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile *.h # Build the static library -# Redirect stderr to null so we don't see the 'empty file' warnings + $(STATIC): $(OBJS) - $(AR) -rcuv $@ $^ 2>/dev/null + $(AR) -rcu $@ $^ clean: rm -f $(STATIC) $(OBJS) $(ASM) +# Allows to check configuration options. +parse-config: + echo '#include "coreConfig.h"' | $(CC) $(CFLAGS) -dM -E -x c - diff --git a/core/POSIX/osdep.c b/core/POSIX/osdep.c index d018326..d5eb2da 100644 --- a/core/POSIX/osdep.c +++ b/core/POSIX/osdep.c @@ -273,22 +273,20 @@ int32_t psCreateMutex(psMutex_t *mutex, uint32_t flags) return PS_SUCCESS; } -int32_t psLockMutex(psMutex_t *mutex) +void psLockMutex(psMutex_t *mutex) { if (pthread_mutex_lock(mutex) != 0) { psTraceCore("pthread_mutex_lock failed\n"); - return PS_PLATFORM_FAIL; + abort(); /* Catastrophic error: mutex does not work correctly. */ } - return PS_SUCCESS; } -int32_t psUnlockMutex(psMutex_t *mutex) +void psUnlockMutex(psMutex_t *mutex) { if (pthread_mutex_unlock(mutex) != 0) { psTraceCore("pthread_mutex_unlock failed\n"); - return PS_PLATFORM_FAIL; + abort(); /* Catastrophic error: mutex does not work correctly. */ } - return PS_SUCCESS; } void psDestroyMutex(psMutex_t *mutex) diff --git a/core/WIN32/osdep.c b/core/WIN32/osdep.c index 15db6bf..5b202b6 100644 --- a/core/WIN32/osdep.c +++ b/core/WIN32/osdep.c @@ -118,16 +118,14 @@ int32_t psCreateMutex(psMutex_t *mutex, uint32_t flags) return PS_SUCCESS; } -int32_t psLockMutex(psMutex_t *mutex) +void psLockMutex(psMutex_t *mutex) { EnterCriticalSection(mutex); - return PS_SUCCESS; } -int32_t psUnlockMutex(psMutex_t *mutex) +void psUnlockMutex(psMutex_t *mutex) { LeaveCriticalSection(mutex); - return PS_SUCCESS; } void psDestroyMutex(psMutex_t *mutex) diff --git a/core/coreApi.h b/core/coreApi.h index 15b4454..b9eb38c 100644 --- a/core/coreApi.h +++ b/core/coreApi.h @@ -44,6 +44,29 @@ extern "C" { #include "list.h" #include "psmalloc.h" +/******************************************************************************/ +/* + psCore helper macros: for communicating with compiler + These macros allow to remove spurious warnings. +*/ + +/* Tell compiler a variable is intended that it can be set, but not used. + (The variable is for debugging, future extension or used in some + conditionally disabled/unifdeffed branches of execution). */ +#define PS_VARIABLE_SET_BUT_UNUSED(x) do { (void)(x); } while(0) + +/* Tell compiler a variable is intended that it can be unused. + This is for compilers which detect variables that are not set. + (The variable is for debugging, future extension or used in some + conditionally disabled/unifdeffed branches of execution). */ +#define PS_VARIABLE_UNUSED(x) do { (void)(x); } while(0) + +/* Tell compiler a function parameter is intended that it can be unused. + This is for compilers which detect parameters that are not used. + (The parameter is for debugging, future extension or used in some + conditionally disabled/unifdeffed branches of execution). */ +#define PS_PARAMETER_UNUSED(x) do { (void)(x); } while(0) + /******************************************************************************/ /* psCore return codes @@ -71,7 +94,10 @@ extern "C" { #define PS_INTERRUPT_FAIL -14 /* An interrupt occurred and MAY be an error */ #define PS_PENDING -15 /* In process. Not necessarily an error */ #define PS_EAGAIN -16 /* Try again later. Not necessarily an error */ - +#define PS_OUTPUT_LENGTH -17 /* Output length negotiation: + output buffer is too small. */ +#define PS_HOSTNAME_RESOLUTION -18 /* Cannot resolve host name. */ +#define PS_CONNECT -19 /* Cannot connect to remote host. */ #define PS_TRUE 1 #define PS_FALSE 0 @@ -112,6 +138,36 @@ typedef struct { int32 size; /* Size of buffer in bytes */ } psBuf_t; +/* Dynamically allocated automatically resizing psBuf_t. */ +struct psDynBuf; +typedef struct psDynBuf psDynBuf_t; +struct psDynBuf { + psBuf_t buf; + psPool_t *pool; + int err; + psDynBuf_t *master; +}; +#define PS_DYNBUF_GROW 256 /* Usual grow amount. */ + +/* Buffer for parsing input. */ +struct psParseBuf; +typedef struct psParseBuf psParseBuf_t; +/* The contents of parsebuf are exactly the same than psDynBuf_t. + this allows them to share some of implementation. */ +struct psParseBuf { + psBuf_t buf; + psPool_t *pool; + int err; + psParseBuf_t *master; +}; + +/* psDynBuf or psParseBuf allocated from this pool + is never freed automatically. */ +extern psPool_t * const psStaticAllocationsPool; + +/* Function definitions for Static and Dynamic Buffer API. */ +#include "psbuf.h" + /******************************************************************************/ #ifdef MATRIX_USE_FILE_SYSTEM @@ -165,15 +221,15 @@ PSPUBLIC int32 psGetFileBuf(psPool_t *pool, const char *fileName, #ifdef USE_MULTITHREADING #define PS_SHARED 0x1 PSPUBLIC int32_t psCreateMutex(psMutex_t *mutex, uint32_t flags); -PSPUBLIC int32_t psLockMutex(psMutex_t *mutex); -PSPUBLIC int32_t psUnlockMutex(psMutex_t *mutex); +PSPUBLIC void psLockMutex(psMutex_t *mutex); +PSPUBLIC void psUnlockMutex(psMutex_t *mutex); PSPUBLIC void psDestroyMutex(psMutex_t *mutex); #else /** @note These are defines rather than inline functions because it allows the caller to not allocate a mutex that will never be used. */ #define psCreateMutex(A, B) (PS_SUCCESS) -#define psLockMutex(A) (PS_SUCCESS) -#define psUnlockMutex(A) (PS_SUCCESS) +#define psLockMutex(A) do { } while(0) +#define psUnlockMutex(A) do { } while(0) #define psDestroyMutex(A) #endif /* USE_MULTITHREADING */ diff --git a/core/osdep.h b/core/osdep.h index 8e89bb5..9de9ad1 100644 --- a/core/osdep.h +++ b/core/osdep.h @@ -83,6 +83,8 @@ #else #define PSTM_MIPS /* MIPS assembly supported on 32 bit only */ #endif +#elif defined(__aarch64__) + #define PSTM_64BIT /* Supported by architecture */ #endif #endif /* GNUC/CLANG */ @@ -235,13 +237,15 @@ extern void osdepEntropyClose(void); typedef signed long long int64_t; #endif #elif defined(METAL) - typedef signed long int32; - typedef unsigned long uint32; - typedef signed short int16; - typedef unsigned short uint16; + #include + typedef int32_t int32; + typedef uint32_t uint32; + typedef int16_t int16; + typedef uint16_t uint16; + typedef uint8_t uint8; #ifdef HAVE_NATIVE_INT64 - typedef unsigned long long uint64; - typedef signed long long int64; + typedef int64_t int64; + typedef uint64_t uint64; #endif #elif defined (NUCLEUS) #include diff --git a/core/psbuf.c b/core/psbuf.c new file mode 100644 index 0000000..a5454a3 --- /dev/null +++ b/core/psbuf.c @@ -0,0 +1,742 @@ +/** + * @file psbuf.c + * @version $Format:%h%d$ + * + * Implementation of API for handling buffers containing binary data. + */ +/* + * Copyright (c) 2016 INSIDE Secure Corporation + * 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 + */ +/******************************************************************************/ + +#include +#include +#include +#include +#include +#include "coreApi.h" + +/* Omit debug printouts. */ +#define debugf(...) do { } while(0) + +/* This address is indicator for static allocations pool, and does not + need to point to any valid pool. The pool cannot be NULL, because + NULL is reserved for "default memory pool". */ +psPool_t * const psStaticAllocationsPool = + (psPool_t *)&psStaticAllocationsPool; + +void *psBufInit(psPool_t *pool, psBuf_t *buf, size_t capacity) +{ + buf->buf = psMalloc(pool, capacity); + buf->start = buf->buf; + buf->end = buf->start; + buf->size = buf->buf ? capacity : 0; + return buf->buf; +} + +void psBufUninit(psPool_t *pool, psBuf_t *buf) { + if (pool != psStaticAllocationsPool) + psFree(buf->buf, pool); + buf->buf = NULL; + buf->start = NULL; + buf->end = NULL; + buf->size = 0; +} + +void *psBufDetach(psPool_t *pool, psBuf_t *buf, size_t *len_p) { + void * new; + size_t len = buf->end - buf->start; + new = psMalloc(pool, len ? len : 1); + if (new) { + memcpy(new, buf->start, len); + *len_p = len; + } + psBufUninit(pool, buf); + return new; +} + +int32_t psBufFromData(psPool_t *pool, psBuf_t *buf, const void *data, size_t len) +{ + void *new = NULL; + buf->buf = buf->start = buf->end = NULL; + buf->size = 0; + + if (data != NULL) { + new = psMalloc(pool, len ? len : 1); + if (new != NULL) { + buf->buf = buf->start = buf->end = new; + buf->size = len; + buf->end += len; + memcpy(new, data, len); + } + } + return new ? PS_SUCCESS : PS_MEM_FAIL; +} + +static int32_t psBufFromStaticData(psBuf_t *buf, const void *data, size_t len) +{ + if (!data) + len = 0; + buf->buf = buf->start = buf->end = (void *) data; + buf->size = len; + buf->end += len; + return data ? PS_SUCCESS : PS_ARG_FAIL; +} + +char *psBufAsHex(psPool_t *pool, const psBuf_t *buf) +{ + char * hexstr; + size_t len = buf->end - buf->start; + hexstr = psMalloc(pool, len * 2 + 1); + if (hexstr) { + size_t i; + hexstr[0] = 0; + for(i = 0; i < len; i++) + sprintf(hexstr + i * 2, "%02x", buf->start[i]); + } + return hexstr; +} + +void *psBufAppendSize(psBuf_t *buf, size_t sz) +{ + unsigned char *loc = buf->end; + unsigned char *bufend = buf->buf + buf->size; + if (loc + sz <= bufend) { + buf->end += sz; + } else { + loc = NULL; + } + return loc; +} + +void psBufReservePrepend(psBuf_t *buf, size_t sz) +{ + unsigned char *bufend = buf->buf + buf->size; + unsigned char *loc = buf->end; + + assert(buf->start == buf->end); /* Must be done at the beginning. */ + + if (loc + sz <= bufend) { + buf->start += sz; + buf->end += sz; + } +} + +void *psBufPrependSize(psBuf_t *buf, size_t sz) +{ + if (buf->buf <= buf->start && buf->buf + sz <= buf->start) { + buf->start -= sz; + return buf->start; + } + + return NULL; +} + +void *psDynBufInit(psPool_t *pool, psDynBuf_t *db, size_t capacity) +{ + void *mem = psBufInit(pool, &db->buf, capacity); + db->pool = pool; + db->err = (mem == NULL); + db->master = NULL; + return mem; +} + +void psDynBufUninit(psDynBuf_t *db) +{ + psBufUninit(db->pool, &db->buf); + db->err = 0; + db->pool = NULL; + db->master = NULL; +} + +void *psDynBufDetach(psDynBuf_t *db, size_t *len_p) +{ + void *new; + + if (db->err) { + psDynBufUninit(db); + return NULL; + } + + new = psBufDetach(db->pool, &db->buf, len_p); + db->pool = NULL; + return new; +} + +void assert_subbuf(psDynBuf_t *sub) +{ + const psDynBuf_t *db; + /* Has master. */ + assert(sub->master != NULL); + + db = sub->master; + + /* Does not have pool */ + assert(sub->pool == NULL); + + /* The buf begin and is within master allocated data area. */ + assert(sub->buf.buf >= db->buf.start && sub->buf.buf <= db->buf.end); + assert(sub->buf.buf + sub->buf.size >= db->buf.start && + sub->buf.buf + sub->buf.size <= db->buf.end); + + /* For debugging: Mark head and tail visually. */ + memset(sub->buf.buf, '(', sub->buf.start - sub->buf.buf); + memset(sub->buf.end, ')', sub->buf.buf + sub->buf.size - sub->buf.end); +} + +static void *psDynBufGrow(psDynBuf_t *db, size_t head_sz, size_t tail_sz) +{ + void *alloc; + void *loc; + psBuf_t new; + size_t headroom = db->buf.start - db->buf.buf; + size_t tailroom = (db->buf.buf + db->buf.size) - db->buf.end; + size_t filled = db->buf.end - db->buf.start; + size_t offset; + size_t offset_tail; + + if (db->err) + return NULL; + + if (head_sz != 0 && head_sz < PS_DYNBUF_GROW) + head_sz = PS_DYNBUF_GROW; + if (tail_sz < PS_DYNBUF_GROW) + tail_sz = PS_DYNBUF_GROW; + + if (db->master) { + offset = db->buf.buf - db->master->buf.start; + offset_tail = db->master->buf.end - (db->buf.buf + db->buf.size); + debugf("Sub Grow: %zu+%zu+%zu => %zu+%zu+%zu; sub @ pos=%zd...-%zd\n", + headroom, filled, tailroom, headroom + head_sz, filled, tailroom + tail_sz, offset, offset_tail); + assert_subbuf(db); + + /* For debugging: */ + memset(db->buf.buf, '{', headroom); + memset(db->buf.end, '}', tailroom); + + loc = psDynBufGrow(db->master, 0, head_sz + tail_sz); + if (loc) { + db->master->buf.end += head_sz + tail_sz; + if (offset_tail) + memmove(db->master->buf.end - offset_tail, + db->master->buf.end - offset_tail - head_sz - tail_sz, + offset_tail); + + db->buf.buf = db->master->buf.start + offset; + db->buf.start = db->buf.buf + headroom + head_sz; + if (head_sz > 0) + memmove(db->buf.start, + db->buf.start - head_sz, + filled); + db->buf.end = db->buf.start + filled; + db->buf.size = head_sz + headroom + filled + + tailroom + tail_sz; + + debugf("Sub Grown: sub @ pos=%d, %zd bytes (%zd+%zd+%zd)\n", + (int) (db->buf.buf - db->master->buf.start), + db->buf.size, db->buf.start - db->buf.buf, + db->buf.end - db->buf.start, db->buf.buf + db->buf.size - db->buf.end); + + /* For debugging: */ + memset(db->buf.buf, '<', head_sz + headroom); + memset(db->buf.end, '>', tail_sz + tailroom); + } else { + db->err++; + } + assert_subbuf(db); + + return loc; + } + + head_sz += headroom; + tail_sz += tailroom; + + debugf("Grow: %zu+%zu+%zu => %zu+%zu+%zu\n", + headroom, filled, tailroom, head_sz, filled, tail_sz); + + alloc = psBufInit(db->pool, &new, head_sz + filled + tail_sz); + if (alloc) { + psBufReservePrepend(&new, head_sz); + loc = psBufAppendSize(&new, filled); + /* Just allocated so there is space. */ + assert(loc != NULL); + memcpy(loc, db->buf.start, filled); + psBufUninit(db->pool, &db->buf); + db->buf.buf = new.buf; + db->buf.start = new.start; + db->buf.end = new.end; + db->buf.size = new.size; + } else { + db->err++; + loc = NULL; + } + + return loc; +} + +void *psDynBufAppendSize(psDynBuf_t *db, size_t sz) +{ + unsigned char *loc = psBufAppendSize(&db->buf, sz); + if (loc == NULL) + if (psDynBufGrow(db, 0, sz)) { + loc = psBufAppendSize(&db->buf, sz); + assert(loc != NULL); + } + return loc; +} + +void psDynBufReservePrepend(psDynBuf_t *db, size_t sz) +{ + /* This function only performs action if nothing has been pushed. + The logic for prepending will make sure prepend succeeds even + if there is no head room. */ + if (db->buf.start == db->buf.end) + psBufReservePrepend(&db->buf, sz); +} + +void *psDynBufPrependSize(psDynBuf_t *db, size_t sz) +{ + unsigned char *loc = psBufPrependSize(&db->buf, sz); + if (loc == NULL) + if (psDynBufGrow(db, sz, 0)) { + loc = psBufPrependSize(&db->buf, sz); + assert(loc != NULL); + } + return loc; +} + +void *psDynBufSubInit(psDynBuf_t *db, psDynBuf_t *sub, size_t capacity) +{ + void *mem = psDynBufAppendSize(db, capacity); + if (mem) { + sub->buf.buf = db->buf.end - capacity; + sub->buf.start = sub->buf.buf; + sub->buf.end = sub->buf.buf; + sub->buf.size = capacity; + sub->pool = NULL; + sub->master = db; + sub->err = 0; + memset(sub->buf.buf, '#', capacity); + assert_subbuf(sub); + } else { + sub->buf.buf = sub->buf.start = sub->buf.end = NULL; + sub->buf.size = 0; + sub->pool = NULL; + sub->err = 1; + db->err++; + sub->master = db; + } + + return mem; +} + +void *psDynBufSubInitAt(psDynBuf_t *db, psDynBuf_t *sub, size_t at, + size_t length) +{ + size_t len = db->buf.end - db->buf.start; + if (db->err == 0 && at + length <= len) { + sub->buf.buf = db->buf.start + at; + sub->buf.start = sub->buf.buf; + sub->buf.end = sub->buf.buf; + sub->buf.size = length; + sub->pool = NULL; + sub->master = db; + sub->err = 0; + memset(sub->buf.buf, '#', length); + assert_subbuf(sub); + } else { + sub->buf.buf = sub->buf.start = sub->buf.end = NULL; + sub->buf.size = 0; + sub->pool = NULL; + sub->err++; + db->err++; + sub->master = db; + } + + return sub->buf.buf; +} + +void *psDynBufSubFinish(psDynBuf_t *sub) +{ + void *loc = NULL; + psDynBuf_t *db = sub->master; + if (sub->err) { + db->err += sub->err; + } else { + size_t total = sub->buf.size; + size_t filled = sub->buf.end - sub->buf.start; + size_t offset_tail; + + offset_tail = db->buf.end - (sub->buf.buf + sub->buf.size); + + assert_subbuf(sub); + if (sub->buf.buf != sub->buf.start && filled > 0) { + memmove(sub->buf.buf, sub->buf.start, filled); + } + if (offset_tail > 0) { + memmove(db->buf.end - total + filled - offset_tail, + db->buf.end - offset_tail, offset_tail); + } + db->buf.end -= total; + db->buf.end += filled; + loc = sub->buf.buf; + } + sub->buf.buf = NULL; + psDynBufUninit(sub); + return loc; +} + +static size_t len_of_tag_and_len(size_t len) +{ + size_t lentaglen; + if (len < 128) + lentaglen = 2; + else if (len < 256) + lentaglen = 3; + else if (len < 65536) + lentaglen = 4; + else if (len < 16777216) + lentaglen = 5; + else + lentaglen = 6; /* Supports up-to 32-bit sizes. */ + return lentaglen; +} + +static void output_len(size_t len, unsigned char *target) +{ + if (len < 128) + target[1] = (unsigned char) len; + else if (len < 256) { + target[1] = 0x81; + target[2] = (unsigned char) len; + } else if (len < 65536) { + target[1] = 0x82; + target[2] = (unsigned char) (len >> 8); + target[3] = (unsigned char) len; + } else if (len < 16777216) { + target[1] = 0x83; + target[2] = (unsigned char) (len >> 16); + target[3] = (unsigned char) (len >> 8); + target[4] = (unsigned char) len; + } else { + target[1] = 0x84; + target[2] = (unsigned char) (len >> 24); + target[3] = (unsigned char) (len >> 16); + target[4] = (unsigned char) (len >> 8); + target[5] = (unsigned char) len; + } +} + +char *psDynBufAppendAsn1TagGen(psDynBuf_t *db, unsigned char tag, + const unsigned char *bytes, size_t len) +{ + size_t extralen = len_of_tag_and_len(len); + unsigned char *target = psDynBufAppendSize(db, len + extralen); + if (target) { + target[0] = tag; + output_len(len, target); + memcpy(target + extralen, bytes, len); + } + return (char *)target; +} + +char *psDynBufBeginConstructedTag(psDynBuf_t *db, psDynBuf_t *sub) +{ + char *target = psDynBufSubInit(db, sub, 20); + if (target) { + psDynBufReservePrepend(sub, 4); + } + return target; +} + +char *psDynBufEndConstructedTag(psDynBuf_t *sub, unsigned char tag) +{ + size_t len = sub->buf.end - sub->buf.start; + size_t extralen = len_of_tag_and_len(len); + unsigned char *target = psDynBufPrependSize(sub, extralen); + if (target) { + target[0] = tag; + output_len(len, target); + } + psDynBufSubFinish(sub); + return (char*)target; +} + +int32_t psParseBufFromStaticData(psParseBuf_t *pb, const void *data, size_t len) +{ + int32_t rc = psBufFromStaticData(&pb->buf, data, len); + pb->pool = psStaticAllocationsPool; + pb->err = rc != PS_SUCCESS; + pb->master = NULL; + return rc; +} + +/* The maximum supported PS_PARSE_MAXIMUM_TAG_CONTENT: */ +#define PS_PARSE_MAXIMUM_TAG_CONTENT 0x40000000U /* 1 gigabyte. */ +/* Note: If the value needs to be extended, the limit for function + psParseBufGetTagLen() on 32-bit hosts is 0xFFFFFFFFU - 5. */ +size_t psParseBufGetTagLen(const psParseBuf_t *pb, + unsigned char tag, + size_t *hdrLen_p) +{ + unsigned char lenlen; + size_t len_at = 1; + size_t len_hdr = 2; + size_t len_content; + size_t len_out; + const unsigned char *ptr = pb->buf.start; + size_t bytes = pb->buf.end - pb->buf.start; + + if (bytes < 2) + return 0; + if (tag != 0 && ptr[0] != tag) + return 0; + + /* Check size tag: long input lengths. */ + lenlen = ptr[1]; /* Use lenlen temporarily to parse length field. */ + if (lenlen >= 0x80) { + if (bytes < 0x83) + return 0; + + if (lenlen == 0x81 && ptr[2] < 0x80) + return 0; + + if (lenlen == 0x82 && ptr[2] == 0x00) + return 0; + + if (lenlen == 0x83 && ptr[2] == 0x00) + return 0; + + if (lenlen == 0x84 && ptr[2] == 0x00) + return 0; + + if (lenlen == 0x80 || lenlen > 0x84) + return 0; /* Too large or indefinite len. */ + len_at++; + lenlen -= 0x80; + len_hdr += lenlen; + } else { + lenlen = 1; + } + + /* len_at and lenlen now express length and of the len. */ + /* additionally, its known that all the length bytes are accessible. */ + len_content = 0; + while(lenlen) { + len_content <<= 8; + len_content += ptr[len_at]; + len_at++; + lenlen--; + } + + if (len_content > PS_PARSE_MAXIMUM_TAG_CONTENT) + return 0; + + len_out = len_content + len_hdr; + + if (len_out > bytes) + return 0; + + if (hdrLen_p) + *hdrLen_p = len_hdr; + + return len_out; +} + +int psParseBufCanGetTag(const psParseBuf_t *pb, unsigned char tag) +{ + return psParseBufGetTagLen(pb, tag, NULL) > 0; +} + +size_t psParseBufTrySkipBytes(psParseBuf_t *pb, + const unsigned char *bytes, + size_t numbytes) +{ + size_t skip_bytes = 0; + if (psParseCanRead(pb, numbytes) && + memcmp(bytes, pb->buf.start, numbytes) == 0) + skip_bytes = numbytes; + pb->buf.start += skip_bytes; + return skip_bytes; +} + +size_t psParseBufSkipBytes(psParseBuf_t *pb, const unsigned char *bytes, + size_t numbytes) +{ + size_t sz = psParseBufTrySkipBytes(pb, bytes, numbytes); + if (sz == 0) + pb->err ++; + return sz; +} + +size_t psParseBufTryReadTagSub(const psParseBuf_t *pb, + psParseBuf_t *content, unsigned char tag) +{ + size_t hdrlen; + size_t len = psParseBufGetTagLen(pb, tag, &hdrlen); + size_t len_content; + psParseBuf_t content_tmp; /* Allows calling the function with + content == NULL to skip the tag. */ + + if (!content) + content = & content_tmp; + if (!len) { + content->buf.buf = content->buf.start = content->buf.end = NULL; + content->buf.size = 0; + content->pool = NULL; + /* Mark state of content as error. */ + content->err = 1; + /* Do not raise error status of main pb. */ + content->master = (psParseBuf_t *)pb; + return 0; + } + + len_content = len - hdrlen; + content->buf.start = content->buf.buf = pb->buf.start + hdrlen; + content->buf.size = len_content; + content->buf.end = content->buf.start + len_content; + content->pool = NULL; + content->master = (psParseBuf_t *)pb; + content->err = 0; + + return len; +} + +size_t psParseBufReadTagSub(psParseBuf_t *pb, + psParseBuf_t *content, unsigned char tag) +{ + size_t len = psParseBufTryReadTagSub(pb, content, tag); + if (len == 0) { + /* Mark this also as an error in main parse buffer. */ + pb->err++; + + /* Initialize sub as the same memory than main parse buffer, + to allow parsing using it (typically unsuccessfully) + in following parsing operations. */ + memcpy(&(content->buf), &(pb->buf), sizeof content->buf); + } + return len; +} + +size_t psParseBufReadTagRef(psParseBuf_t *pb, + psBuf_t *ref, unsigned char tag) +{ + psParseBuf_t content; + size_t len = psParseBufReadTagSub(pb, &content, tag); + if (len) { + memcpy(ref, &content.buf, sizeof(psBuf_t)); + pb->buf.start += len; + } + return len; +} + +size_t psParseBufTrySkipTag(psParseBuf_t *pb, unsigned char tag) +{ + psParseBuf_t sub; + size_t sz = psParseBufTryReadTagSub(pb, &sub, tag); + if (sz) + (void) psParseBufFinish(&sub); + return sz; +} + +size_t psParseBufSkipTag(psParseBuf_t *pb, unsigned char tag) +{ + psParseBuf_t sub; + size_t sz = psParseBufReadTagSub(pb, &sub, tag); + if (sz) + (void) psParseBufFinish(&sub); + return sz; +} + +int32_t psParseBufCopyAll(const psParseBuf_t *pb, unsigned char *target, + size_t *targetlen) +{ + size_t len = pb->buf.end - pb->buf.start; + + if (pb->err != 0) + return PS_FAILURE; + + if (target == NULL) { + *targetlen = len; + return PS_OUTPUT_LENGTH; + } + + if (len > *targetlen) { + *targetlen = len; + return PS_OUTPUT_LENGTH; + } + + memcpy(target, pb->buf.start, len); + return PS_SUCCESS; +} + +int psParseBufEq(const psParseBuf_t *pb1, const psParseBuf_t *pb2) +{ + if (pb1->err || pb2->err) + return 0; + + return psBufEq(&pb1->buf, &pb2->buf); +} + +int32_t psParseBufCheckState(const psParseBuf_t *pb) +{ + return pb->err == 0 ? PS_SUCCESS : PS_FAILURE; +} + +int32_t psParseBufFinish(psParseBuf_t *pb) +{ + int32_t rc; + if (pb->master) { + if (pb->err) + /* Signal master on error. */ + pb->master->err++; + else + /* Advance master. */ + pb->master->buf.start = pb->buf.buf + pb->buf.size; + + pb->buf.buf = NULL; /* Do not free any data. */ + } + + /* Free state. */ + rc = psParseBufCheckState(pb); + psBufUninit(pb->pool, &pb->buf); + pb->master = NULL; + pb->err = 0; + pb->pool = NULL; + return rc; +} + +void psParseBufCancel(psParseBuf_t *pb) +{ + /* Free state. */ + if (pb->master) + pb->buf.buf = NULL; /* Do not free any data. */ + psBufUninit(pb->pool, &pb->buf); + pb->master = NULL; + pb->err = 0; + pb->pool = NULL; +} + +/* end of file psbuf.c */ diff --git a/core/psbuf.h b/core/psbuf.h new file mode 100644 index 0000000..80a0a54 --- /dev/null +++ b/core/psbuf.h @@ -0,0 +1,297 @@ +/** + * @file psbuf.h + * @version $Format:%h%d$ + * + * API for handling buffers containing binary data. + */ +/* + * Copyright (c) 2016 INSIDE Secure Corporation + * 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_BUF +#define _h_PS_BUF + +#include "coreApi.h" +#include + +/* API for psBuf initialization and basic usage.*/ +void *psBufInit(psPool_t *pool, psBuf_t *buf, size_t capacity); +void psBufUninit(psPool_t *pool, psBuf_t *buf); +void *psBufDetach(psPool_t *pool, psBuf_t *buf, size_t *len_p); +void *psBufAppendSize(psBuf_t *buf, size_t sz); +void psBufReservePrepend(psBuf_t *buf, size_t sz); +void *psBufPrependSize(psBuf_t *buf, size_t sz); +char *psBufAsHex(psPool_t *pool, const psBuf_t *buf); + +int32_t psBufFromData(psPool_t *pool, psBuf_t *buf, + const void *data, size_t len); + + +static __inline int psBufEq(const psBuf_t *buf1, const psBuf_t *buf2) +{ + return (buf1->end - buf1->start) == (buf2->end - buf2->start) && + buf1->start != NULL && + buf2->start != NULL && + memcmp(buf1->start, buf2->start, (buf1->end - buf1->start)) + == 0; +} + +static __inline void *psBufAppendChar(psBuf_t *buf, char ch) +{ + void *loc = psBufAppendSize(buf, 1); + if (loc) + *(char*)loc = ch; + return loc; +} + +static __inline void *psBufPrependChar(psBuf_t *buf, char ch) +{ + void *loc = psBufPrependSize(buf, 1); + if (loc) + *(char*)loc = ch; + return loc; +} + +/* API for Dynamic Buffers initialization and basic usage. */ +void *psDynBufInit(psPool_t *pool, psDynBuf_t *db, size_t capacity); +void psDynBufUninit(psDynBuf_t *db); +void *psDynBufDetach(psDynBuf_t *db, size_t *len_p); +void *psDynBufAppendSize(psDynBuf_t *db, size_t sz); +void psDynBufReservePrepend(psDynBuf_t *db, size_t sz); +void *psDynBufPrependSize(psDynBuf_t *db, size_t sz); + +static __inline void *psDynBufAppendChar(psDynBuf_t *db, char ch) +{ + void *loc = psDynBufAppendSize(db, 1); + if (loc) + *(char*)loc = ch; + return loc; +} + +static __inline void *psDynBufPrependChar(psDynBuf_t *db, char ch) +{ + void *loc = psDynBufPrependSize(db, 1); + if (loc) + *(char*)loc = ch; + return loc; +} + +static __inline void *psDynBufAppendStr(psDynBuf_t *db, const char *s) +{ + size_t len = s ? strlen(s) : 0; + void *loc = psDynBufAppendSize(db, len); + if (loc) + memcpy(loc, s, len); + return loc; +} + +static __inline void *psDynBufPrependStr(psDynBuf_t *db, const char *s) +{ + size_t len = s ? strlen(s) : 0; + void *loc = psDynBufPrependSize(db, len); + if (loc) + memcpy(loc, s, len); + return loc; +} + +static __inline void *psDynBufAppendOctets(psDynBuf_t *db, const void *data, + size_t len) +{ + void *loc = psDynBufAppendSize(db, len); + if (loc) + memcpy(loc, data, len); + return loc; +} + +static __inline void *psDynBufAppendBuf(psDynBuf_t *db, const psBuf_t *b) +{ + return psDynBufAppendOctets(db, b->start, b->end - b->start); +} + +static __inline void *psDynBufIncorporateDynBuf(psDynBuf_t *db, psDynBuf_t *db2) +{ + size_t len; + void *data = psDynBufDetach(db2, &len); + if (data) { + return psDynBufAppendOctets(db, data, len); + } else { + db->err++; + return NULL; + } +} + +/* Dynamic buffer subbuffers. */ +void *psDynBufSubInit(psDynBuf_t *db, psDynBuf_t *sub, size_t capacity); +void *psDynBufSubInitAt(psDynBuf_t *db, psDynBuf_t *sub, size_t at, + size_t length); +void *psDynBufSubFinish(psDynBuf_t *sub); + +/* Note: This variable argument function is currently implemented as a macro. */ +#define psDynBufAppendStrf(ps_dyn_buf_p, ...) \ + do { \ + char tmp; \ + size_t len = 1 + snprintf(&tmp, 1, __VA_ARGS__); \ + char *target = psDynBufAppendSize((ps_dyn_buf_p), len); \ + if (target) { \ + snprintf(target, len, __VA_ARGS__); \ + (ps_dyn_buf_p)->buf.end -= 1; \ + } \ + } while(0) + + +/* Subset of ASN.1 via psDynBuf. */ +char *psDynBufAppendAsn1TagGen(psDynBuf_t *db, unsigned char tag, + const unsigned char *bytes, size_t len); + +char *psDynBufBeginConstructedTag(psDynBuf_t *db, psDynBuf_t *sub); +char *psDynBufEndConstructedTag(psDynBuf_t *sub, unsigned char tag); + +static __inline char *psDynBufBeginSequence(psDynBuf_t *db, psDynBuf_t *sub) +{ + return psDynBufBeginConstructedTag(db, sub); +} + +static __inline char *psDynBufEndSequence(psDynBuf_t *sub) +{ + return psDynBufEndConstructedTag(sub, 0x30); +} + +static __inline int32_t psDynBufDetachBuf(psDynBuf_t *db, psBuf_t *target) +{ + size_t sz; + void *buf; + + target->start = target->buf = buf = psDynBufDetach(db, &sz); + if (!buf) { + /* Exception path: memory allocation failure. */ + target->size = 0; + target->end = buf; + return PS_MEM_FAIL; + } + + target->size = sz; + target->end = ((unsigned char *) buf) + sz; + return PS_SUCCESS; +} + +/* Start parsing static data using psParseBuf_t. */ +int32_t psParseBufFromStaticData(psParseBuf_t *pb, + const void *data, size_t len); + +/* Check if there is sufficient data to parse left. */ +static __inline int psParseCanRead(const psParseBuf_t *pb, size_t nbytes) +{ + size_t bytes_readable; + + if (pb->err) + return 0; + + bytes_readable = pb->buf.end - pb->buf.start; + return bytes_readable >= nbytes; +} + +/* Get length of following ASN.1 tag + (specify tag as unsigned char or 0 for ANY). + + This is for parsing content of parsebuf as ASN.1 DER data. + + If hdrLen_p is non-null, the function also returns the length of tag header. +*/ +size_t psParseBufGetTagLen(const psParseBuf_t *pb, unsigned char tag, + size_t *hdrLen_p); +/* Test if there is specific (tag > 0) or any (tag == 0) ASN.1 der + encoding at current parsing location. + return 0 no, 1 yes */ +int psParseBufCanGetTag(const psParseBuf_t *pb, unsigned char tag); +/* Try read ASN.1 DER specific (tag > 0) or any (tag == 0) at the + current parsing location. Reading will return sub parsebuf, + which allows reading constructed tags. + Returns length of tag read (including header) or 0 if no tag was read. + Parsing location will advance once finished with content. + */ +size_t psParseBufTryReadTagSub(const psParseBuf_t *pb, + psParseBuf_t *content, unsigned char tag); +/* Read specified (or any) ASN.1 tag at the current parsing location. + it is considered error if read fails. + Parsing location will advance once finished with content. */ +size_t psParseBufReadTagSub(psParseBuf_t *pb, + psParseBuf_t *content, unsigned char tag); +/* Copy all data from parse buffer. Supports length negotiations. + Fails if parsing errors have been seen. */ +int32_t psParseBufCopyAll(const psParseBuf_t *pb, unsigned char *target, + size_t *targetlen); +/* Return true only if buffers have encountered no parsing errors and + the contents are equal. */ +int psParseBufEq(const psParseBuf_t *pb1, const psParseBuf_t *pb2); +/* return PS_SUCCESS if pb has not encountered parsing errors. */ +int32_t psParseBufCheckState(const psParseBuf_t *pb); + +/* Alias (implemented as a macro) for psParseBufTryReadTagSub used on sequence. + */ +#define psParseBufTryReadSequenceSub(pb, content) \ + psParseBufTryReadTagSub(pb, content, 0x30) + +/* Alias (implemented as a macro) for psParseBufReadTagSub used on sequence. */ +#define psParseBufReadSequenceSub(pb, content) \ + psParseBufReadTagSub(pb, content, 0x30) + +/* Skip tag with specified tag id (or 0 for any) if possible. + If tag was skipped, return length in bytes that was skipped. */ +size_t psParseBufTrySkipTag(psParseBuf_t *pb, unsigned char tag); + +/* Skip tag with specified tag id (or 0 for any) if possible. + Tag not existing is considered error and error is set in pb. */ +size_t psParseBufSkipTag(psParseBuf_t *pb, unsigned char tag); + +/* Signal errors from sub to master buffer. + If invoked on allocated main parse buffer, the memory will be freed. + If invoked on subbuffer, the position on main buffer is advanced. + The return value will only be PS_SUCCESS is no errors have been observed. */ +int32_t psParseBufFinish(psParseBuf_t *buf); + +/* Cancel processing of subbuffer. + Errors are not propagated to the master buffer, and master buffer is not + advanced. + If invoked on allocated main parse buffer, any memory allocated will + still be freed. */ +void psParseBufCancel(psParseBuf_t *buf); + +/* Skip specified bytes (such as tag with specific contents or non-ASN.1 data)*/ +size_t psParseBufTrySkipBytes(psParseBuf_t *pb, + const unsigned char *bytes, + size_t numbytes); + +/* Skip specified bytes. Not finding the bytes is an error. */ +size_t psParseBufSkipBytes(psParseBuf_t *pb, const unsigned char *bytes, + size_t numbytes); + +/* Read given tag and fill-in reference with the content. + Parse buffer is moved to point to the next parsing location. */ +size_t psParseBufReadTagRef(psParseBuf_t *pb, + psBuf_t *ref, unsigned char tag); + +#endif /* _h_PS_BUF */ +/* end of file psbuf.h */ diff --git a/core/psmalloc.h b/core/psmalloc.h index 52552d2..6a4135b 100644 --- a/core/psmalloc.h +++ b/core/psmalloc.h @@ -49,6 +49,11 @@ #define MATRIX_NO_POOL (void *)0x0 +/* Introduce variables used for memory pooling, so that the compiler does not + give spurious warnings even when memory pools are not supported by the + target operating system. */ +#define PS_POOL_USED(poolVar) PS_VARIABLE_SET_BUT_UNUSED(poolVar) + /******************************************************************************/ /* Native memory routines @@ -68,14 +73,7 @@ #define psMemset memset #define psMemcpy memcpy -/* - Support for memory allocation in order to avoid applications that redefine - malloc/free (see Perl) -*/ -__inline static void *psMallocNative(size_t size) { return malloc(size); } -__inline static void psFreeNative(void *ptr) { free(ptr); } - -typedef int32_t psPool_t; +typedef int32 psPool_t; /******************************************************************************/ diff --git a/crypto/Makefile b/crypto/Makefile index 54f9788..e53469f 100755 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -43,17 +43,21 @@ SRC:=\ pubkey/ecc.c \ pubkey/pubkey.c \ pubkey/rsa.c +#ifdef USE_OPENSSL_CRYPTO ifdef USE_OPENSSL_CRYPTO SRC+=\ digest/digest_openssl.c \ symmetric/symmetric_openssl.c \ pubkey/rsa_openssl.c endif +#endif +#ifdef USE_LIBSODIUM_CRYPTO ifdef USE_LIBSODIUM_CRYPTO SRC+=\ symmetric/symmetric_libsodium.c \ digest/digest_libsodium.c endif +#endif # Generated files STATIC:=libcrypt_s.a @@ -64,12 +68,12 @@ compile: $(OBJS) $(STATIC) @echo $(STROPTS) # Additional Dependencies -$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile *.h */*.h +$(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile *.h */$(BLANK)*.h # Build the static library -# Direct stderr to null so we don't see the 'empty file' warnings + $(STATIC): $(OBJS) - $(AR) -rcuv $@ $^ 2>/dev/null + $(AR) -rcu $@ $^ clean: rm -f $(STATIC) $(OBJS) diff --git a/crypto/cryptoApi.h b/crypto/cryptoApi.h index 745ad11..30a9bee 100644 --- a/crypto/cryptoApi.h +++ b/crypto/cryptoApi.h @@ -270,14 +270,16 @@ PSPUBLIC void psMd5Final(psMd5_t *md, unsigned char hash[MD5_HASHLEN]); #ifdef USE_SHA1 /******************************************************************************/ +/* Pre-init should be called for uninitialized, e.g. function local + digest contexts, before calling the initialization function. */ +static __inline void psSha1PreInit(psSha1_t *sha1) +{ + /* Nothing to pre-initialize for native crypto. */ +} PSPUBLIC int32_t psSha1Init(psSha1_t *sha1); PSPUBLIC void psSha1Update(psSha1_t *sha1, const unsigned char *buf, uint32_t len); PSPUBLIC void psSha1Final(psSha1_t *sha1, unsigned char hash[SHA1_HASHLEN]); -#ifdef USE_CL_DIGESTS -PSPUBLIC void psSha1Sync(psSha1_t *ctx, int sync_all); -PSPUBLIC void psSha1Cpy(psSha1_t *ctx, const psSha1_t *ctx_in); -#else static __inline void psSha1Sync(psSha1_t *ctx, int sync_all) { } @@ -285,11 +287,16 @@ static __inline void psSha1Cpy(psSha1_t *d, const psSha1_t *s) { memcpy(d, s, sizeof(psSha1_t)); } -#endif /* USE_CL_DIGESTS */ #endif /* USE_SHA1 */ #ifdef USE_MD5SHA1 /******************************************************************************/ +/* Pre-init should be called for uninitialized, e.g. function local + digest contexts, before calling the initialization function. */ +static __inline void psMd5Sha1PreInit(psMd5Sha1_t *md) +{ + /* Nothing to pre-initialize for native crypto. */ +} PSPUBLIC int32_t psMd5Sha1Init(psMd5Sha1_t *md); PSPUBLIC void psMd5Sha1Update(psMd5Sha1_t *md, const unsigned char *buf, uint32_t len); @@ -306,16 +313,17 @@ static __inline void psMd5Sha1Cpy(psMd5Sha1_t *d, const psMd5Sha1_t *s) #ifdef USE_SHA256 /******************************************************************************/ - +/* Pre-init should be called for uninitialized, e.g. function local + digest contexts, before calling the initialization function. */ +static __inline void psSha256PreInit(psSha256_t *sha256) +{ + /* Nothing to pre-initialize for native crypto. */ +} PSPUBLIC int32_t psSha256Init(psSha256_t *sha256); PSPUBLIC void psSha256Update(psSha256_t *sha256, const unsigned char *buf, uint32_t len); PSPUBLIC void psSha256Final(psSha256_t *sha256, unsigned char hash[SHA256_HASHLEN]); -#ifdef USE_CL_DIGESTS -PSPUBLIC void psSha256Sync(psSha256_t * md, int sync_all); -PSPUBLIC void psSha256Cpy(psSha256_t * d, const psSha256_t * s); -#else static __inline void psSha256Sync(psSha256_t * md, int sync_all) { } @@ -323,20 +331,21 @@ static __inline void psSha256Cpy(psSha256_t * d, const psSha256_t * s) { memcpy(d, s, sizeof(psSha256_t)); } -#endif /* USE_CL_DIGESTS */ #endif /* USE_SHA256 */ /******************************************************************************/ #ifdef USE_SHA384 +/* Pre-init should be called for uninitialized, e.g. function local + digest contexts, before calling the initialization function. */ +static __inline void psSha384PreInit(psSha384_t *sha384) +{ + /* Nothing to pre-initialize for native crypto. */ +} PSPUBLIC int32_t psSha384Init(psSha384_t *sha384); PSPUBLIC void psSha384Update(psSha384_t *sha384, const unsigned char *buf, uint32_t len); PSPUBLIC void psSha384Final(psSha384_t *sha384, unsigned char hash[SHA384_HASHLEN]); -#ifdef USE_CL_DIGESTS -PSPUBLIC void psSha384Sync(psSha384_t * md, int sync_all); -PSPUBLIC void psSha384Cpy(psSha384_t * d, const psSha384_t * s); -#else static __inline void psSha384Sync(psSha384_t * md, int sync_all) { } @@ -344,20 +353,21 @@ static __inline void psSha384Cpy(psSha384_t * d, const psSha384_t * s) { memcpy(d, s, sizeof(psSha384_t)); } -#endif /* USE_CL_DIGESTS */ #endif /* USE_SHA384 */ #ifdef USE_SHA512 /******************************************************************************/ +/* Pre-init should be called for uninitialized, e.g. function local + digest contexts, before calling the initialization function. */ +static __inline void psSha512PreInit(psSha512_t *sha512) +{ + /* Nothing to pre-initialize for native crypto. */ +} PSPUBLIC int32_t psSha512Init(psSha512_t *md); PSPUBLIC void psSha512Update(psSha512_t *md, const unsigned char *buf, uint32_t len); PSPUBLIC void psSha512Final(psSha512_t *md, unsigned char hash[SHA512_HASHLEN]); -#ifdef USE_CL_DIGESTS -PSPUBLIC void psSha512Sync(psSha512_t * md, int sync_all); -PSPUBLIC void psSha512Cpy(psSha512_t * d, const psSha512_t * s); -#else static __inline void psSha512Sync(psSha512_t * md, int sync_all) { } @@ -365,7 +375,6 @@ static __inline void psSha512Cpy(psSha512_t * d, const psSha512_t * s) { memcpy(d, s, sizeof(psSha512_t)); } -#endif /* USE_CL_DIGESTS */ #endif /* USE_SHA512 */ /******************************************************************************/ @@ -664,6 +673,9 @@ PSPUBLIC int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 s psX509Cert_t **outcert, int32 flags); PSPUBLIC void psX509FreeCert(psX509Cert_t *cert); #ifdef USE_CERT_PARSE +PSPUBLIC int32 psX509GetCertPublicKeyDer(psX509Cert_t *cert, + unsigned char *der_out, + uint16_t *der_out_len); PSPUBLIC int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, psX509Cert_t *issuerCert, psX509Cert_t **foundIssuer, void *hwCtx, void *poolUserPtr); diff --git a/crypto/cryptolib.h b/crypto/cryptolib.h index a02cade..959707e 100644 --- a/crypto/cryptolib.h +++ b/crypto/cryptolib.h @@ -41,6 +41,7 @@ */ /** Symmetric. @security These are generally insecure and not enabled by default. */ +//#define USE_RC2 //#define USE_ARC4 //#define USE_SEED //#define USE_IDEA @@ -133,6 +134,7 @@ extern int32_t matrixCryptoGetPrngData(unsigned char *bytes, uint16_t size, #define OID_SHA256_RSA_SIG 655 /* 42.134.72.134.247.13.1.1.11 */ #define OID_SHA384_RSA_SIG 656 /* 42.134.72.134.247.13.1.1.12 */ #define OID_SHA512_RSA_SIG 657 /* 42.134.72.134.247.13.1.1.13 */ +#define OID_SHA1_DSA_SIG 517 /* 1.2.840.10040.4.3 */ #define OID_SHA1_ECDSA_SIG 520 /* 42.134.72.206.61.4.1 */ #define OID_SHA224_ECDSA_SIG 523 /* 42.134.72.206.61.4.3.1 */ #define OID_SHA256_ECDSA_SIG 524 /* 42.134.72.206.61.4.3.2 */ @@ -141,6 +143,7 @@ extern int32_t matrixCryptoGetPrngData(unsigned char *bytes, uint16_t size, /* Public key algorithms */ #define OID_RSA_KEY_ALG 645 +#define OID_DSA_KEY_ALG 515 /* 1.2.840.10040.4.1 */ #define OID_ECDSA_KEY_ALG 518 /* 1.2.840.10045.2.1 */ /* Encryption algorithms */ @@ -155,10 +158,8 @@ extern int32_t matrixCryptoGetPrngData(unsigned char *bytes, uint16_t size, #define OID_AES_256_WRAP 457 /* 2.16.840.1.101.3.4.1.45 */ #define OID_AES_256_GCM 458 /* 2.16.840.1.101.3.4.1.46 */ - /* TODO: Made this up. Couldn't find */ #define OID_AES_CMAC 612 /* 2.16.840.1.101.3.4.1.200 */ -/* TODO: These are not officially defined yet */ #define OID_AES_CBC_CMAC_128 143 #define OID_AES_CBC_CMAC_192 144 #define OID_AES_CBC_CMAC_256 145 diff --git a/crypto/digest/digest_libsodium.h b/crypto/digest/digest_libsodium.h index 6ed196c..deb23b9 100755 --- a/crypto/digest/digest_libsodium.h +++ b/crypto/digest/digest_libsodium.h @@ -1,5 +1,5 @@ /** - * @file digest_openssl.h + * @file digest_sodium.h * @version $Format:%h%d$ * * Header for libsodium crypto Layer. diff --git a/crypto/keyformat/asn1.h b/crypto/keyformat/asn1.h index 3440bb2..2c44518 100644 --- a/crypto/keyformat/asn1.h +++ b/crypto/keyformat/asn1.h @@ -68,7 +68,8 @@ enum { ASN_IA5STRING = 22, ASN_UTCTIME, ASN_GENERALIZEDTIME, - ASN_GENERAL_STRING = 27, + ASN_VISIBLE_STRING = 26, + ASN_GENERAL_STRING, ASN_BMPSTRING = 30 }; diff --git a/crypto/keyformat/crl.c b/crypto/keyformat/crl.c index 5f19f82..cdbbf40 100644 --- a/crypto/keyformat/crl.c +++ b/crypto/keyformat/crl.c @@ -785,9 +785,13 @@ int32_t psX509AuthenticateCRL(psX509Cert_t *CA, psX509Crl_t *CRL, } } else if (sigType == PS_ECC) { int32_t status; +#ifdef USE_ECC rc = psEccDsaVerify(pkiPool, &CA->publicKey.key.ecc, CRL->sigHash, CRL->sigHashLen, CRL->sig, CRL->sigLen, &status, NULL); +#else + rc = PS_DISABLED_FEATURE_FAIL; +#endif /* USE_ECC */ if (status != 1) { psTraceCrypto("Unable to verify ECDSA CRL signature\n"); return PS_CERT_AUTH_FAIL_SIG; @@ -928,7 +932,6 @@ int32 psX509ParseCRL(psPool_t *pool, psX509Crl_t **crl, unsigned char *crlBin, lcrl->nextUpdate[timelen] = '\0'; p += timelen; - /* TODO: Confirm here if this is already expired */ } @@ -1089,6 +1092,7 @@ int32 psX509ParseCRL(psPool_t *pool, psX509Crl_t **crl, unsigned char *crlBin, #endif /* ENABLE_MD5_SIGNED_CERTS */ #ifdef ENABLE_SHA1_SIGNED_CERTS case SHA1_HASH_SIZE: + psSha1PreInit(&hashCtx.sha1); psSha1Init(&hashCtx.sha1); psSha1Update(&hashCtx.sha1, sigStart, (uint32)(sigEnd - sigStart)); psSha1Final(&hashCtx.sha1, lcrl->sigHash); @@ -1096,6 +1100,7 @@ int32 psX509ParseCRL(psPool_t *pool, psX509Crl_t **crl, unsigned char *crlBin, #endif /* ENABLE_SHA1_SIGNED_CERTS */ #ifdef USE_SHA256 case SHA256_HASH_SIZE: + psSha256PreInit(&hashCtx.sha256); psSha256Init(&hashCtx.sha256); psSha256Update(&hashCtx.sha256, sigStart, (uint32)(sigEnd - sigStart)); psSha256Final(&hashCtx.sha256, lcrl->sigHash); @@ -1103,6 +1108,7 @@ int32 psX509ParseCRL(psPool_t *pool, psX509Crl_t **crl, unsigned char *crlBin, #endif /* USE_SHA256 */ #ifdef USE_SHA384 case SHA384_HASH_SIZE: + psSha384PreInit(&hashCtx.sha384); psSha384Init(&hashCtx.sha384); psSha384Update(&hashCtx.sha384, sigStart, (uint32)(sigEnd - sigStart)); psSha384Final(&hashCtx.sha384, lcrl->sigHash); @@ -1110,6 +1116,7 @@ int32 psX509ParseCRL(psPool_t *pool, psX509Crl_t **crl, unsigned char *crlBin, #endif /* USE_SHA384 */ #ifdef USE_SHA512 case SHA512_HASH_SIZE: + psSha512PreInit(&hashCtx.sha512); psSha512Init(&hashCtx.sha512); psSha512Update(&hashCtx.sha512, sigStart, (uint32)(sigEnd - sigStart)); psSha512Final(&hashCtx.sha512, lcrl->sigHash); @@ -1130,9 +1137,7 @@ int32 psX509ParseCRL(psPool_t *pool, psX509Crl_t **crl, unsigned char *crlBin, If the provided cert has a URL based CRL Distribution point, return that. The url and urlLen point directly into the cert structure so must not be modified. - - TODO: This should return all URL dist points in the cert. Not just first -*/ + */ int32 psX509GetCRLdistURL(psX509Cert_t *cert, char **url, uint32_t *urlLen) { x509GeneralName_t *gn; diff --git a/crypto/keyformat/pkcs.c b/crypto/keyformat/pkcs.c index aac3b02..19f6de8 100644 --- a/crypto/keyformat/pkcs.c +++ b/crypto/keyformat/pkcs.c @@ -283,7 +283,6 @@ int32 pkcs8ParsePrivBin(psPool_t *pool, unsigned char *buf, int32 size, (unsigned char*)salt, 8, icount, (unsigned char*)desKeyBin, DES3_KEYLEN); psDes3Init(&ctx.des3, (unsigned char*)iv, desKeyBin); - /* TODO: possible some compilers will not like this const removal */ psDes3Decrypt(&ctx.des3, p, (unsigned char*)p, len); /* @security SECURITY - we zero out des3 key when done with it */ memset_s(&ctx, sizeof(psCipherContext_t), 0x0, sizeof(psCipherContext_t)); @@ -1017,21 +1016,7 @@ static int32 parseSafeContents(psPool_t *pool, unsigned char *password, /* Attributes are at the end of the data */ while (p != safeLen) { #ifdef PARSE_PKCS12_SAFE_ATTRIBS - /* - TODO: incomplete parse - - PKCS12Attribute ::= SEQUENCE { - attrId ATTRIBUTE.&id ({PKCS12AttrSet}), - attrValues SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId}) - } -- This type is compatible with the X.500 type ’Attribute’ - - PKCS12AttrSet ATTRIBUTE ::= { - PKCS 12 V1.0: PERSONAL INFORMATION EXCHANGE SYNTAX 9 - friendlyName | -- from PKCS #9 - localKeyId, -- from PKCS #9 - ... -- Other attributes are allowed - } - */ + /**/ if ((rc = getAsnSet(&p, (int32)(end - p), &attriblen)) < 0) { return rc; } diff --git a/crypto/keyformat/x509.c b/crypto/keyformat/x509.c index dfca460..b01736c 100644 --- a/crypto/keyformat/x509.c +++ b/crypto/keyformat/x509.c @@ -57,13 +57,28 @@ /* Distinguished Name attributes */ +#define ATTRIB_COMMON_NAME 3 +#define ATTRIB_SURNAME 4 +#define ATTRIB_SERIALNUMBER 5 #define ATTRIB_COUNTRY_NAME 6 #define ATTRIB_LOCALITY 7 +#define ATTRIB_STATE_PROVINCE 8 +#define ATTRIB_STREET_ADDRESS 9 #define ATTRIB_ORGANIZATION 10 #define ATTRIB_ORG_UNIT 11 +#define ATTRIB_TITLE 12 +#define ATTRIB_POSTAL_ADDRESS 16 +#define ATTRIB_TELEPHONE_NUMBER 20 +#define ATTRIB_NAME 41 +#define ATTRIB_GIVEN_NAME 42 +#define ATTRIB_INITIALS 43 +#define ATTRIB_GEN_QUALIFIER 44 #define ATTRIB_DN_QUALIFIER 46 -#define ATTRIB_STATE_PROVINCE 8 -#define ATTRIB_COMMON_NAME 3 +#define ATTRIB_PSEUDONYM 65 + +#define ATTRIB_DOMAIN_COMPONENT 25 +#define ATTRIB_UID 26 +#define ATTRIB_EMAIL 27 /** Enumerate X.509 milestones for issuedBefore() api */ typedef enum { @@ -118,7 +133,12 @@ static const struct { OID_LIST(id_kp, id_kp_emailProtection), OID_LIST(id_kp, id_kp_timeStamping), OID_LIST(id_kp, id_kp_OCSPSigning), - + /* policyIdentifiers */ + OID_LIST(id_qt, id_qt_cps), + OID_LIST(id_qt, id_qt_unotice), + /* accessDescriptors */ + OID_LIST(id_ad, id_ad_caIssuers), + OID_LIST(id_ad, id_ad_ocsp), /* List terminator */ OID_LIST(0, 0), }; @@ -482,6 +502,42 @@ static int32 getRsaPssParams(const unsigned char **pp, int32 size, } #endif +/******************************************************************************/ +/* + Get the public key (SubjectPublicKeyInfo) in DER format from a psX509Cert_t. + + Precondition: the certificate must have been parsed with psX509ParseCert or + psX509ParseCertFile with the CERT_STORE_UNPARSED_BUFFER flag set. + */ +PSPUBLIC int32 psX509GetCertPublicKeyDer(psX509Cert_t *cert, + unsigned char *der_out, + uint16_t *der_out_len) +{ + if (!cert || !der_out || !der_out_len) { + return PS_ARG_FAIL; + } + if (cert->publicKeyDerOffsetIntoUnparsedBin == 0 + || cert->publicKeyDerLen == 0) { + psTraceCrypto("No DER format public key stored in this cert. " \ + "CERT_STORE_DN_BUFFER flag was not used when parsing?"); + return PS_ARG_FAIL; + } + + if (*der_out_len < cert->publicKeyDerLen) { + psTraceCrypto("Output buffer is too small"); + *der_out_len = cert->publicKeyDerLen; + return PS_OUTPUT_LENGTH; + } + + memcpy(der_out, + cert->unparsedBin + cert->publicKeyDerOffsetIntoUnparsedBin, + cert->publicKeyDerLen); + + *der_out_len = cert->publicKeyDerLen; + + return PS_SUCCESS; +} + /******************************************************************************/ /* Parse an X509 v3 ASN.1 certificate stream @@ -498,7 +554,7 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, psX509Cert_t **outcert, int32 flags) { psX509Cert_t *cert; - const unsigned char *p, *end, *far_end, *certStart; + const unsigned char *p, *end, *far_end, *certStart, *tbsCertStart; uint16_t len; uint32_t oneCertLen; int32 parsing, rc; @@ -507,8 +563,9 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, psDigestContext_t hashCtx; const unsigned char *certEnd; uint16_t certLen, plen; -#endif - + const unsigned char *p_subject_pubkey_info; + size_t subject_pubkey_info_header_len; +#endif /* USE_CERT_PARSE */ /* Allocate the cert structure right away. User MUST always call psX509FreeCert regardless of whether this function succeeds. @@ -563,6 +620,7 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, #ifdef ENABLE_CA_CERT_HASH /* We use the cert_sha1_hash type for the Trusted CA Indication so run a SHA1 has over the entire Certificate DER encoding. */ + psSha1PreInit(&hashCtx.sha1); psSha1Init(&hashCtx.sha1); psSha1Update(&hashCtx.sha1, certStart, oneCertLen + (int32)(p - certStart)); @@ -570,7 +628,7 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, #endif #ifdef USE_CERT_PARSE - certStart = p; + tbsCertStart = p; /* TBSCertificate ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, @@ -592,7 +650,7 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, return rc; } certEnd = p + len; - certLen = certEnd - certStart; + certLen = certEnd - tbsCertStart; /* Version ::= INTEGER { v1(0), v2(1), v3(2) } @@ -603,9 +661,19 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, return rc; } if (cert->version != 2) { +#ifndef ALLOW_VERSION_1_ROOT_CERT_PARSE psTraceIntCrypto("ERROR: non-v3 certificate version %d insecure\n", cert->version); return PS_PARSE_FAIL; +#else + if (cert->version != 0 && cert->version != 1) { + psTraceIntCrypto("ERROR: unsupported certificate version: %d\n", + cert->version); + } + /* Allow locally stored, trusted version 1 and version 2 certificates + to be parsed. The SSL layer code will still reject v1 and v2 + certificates that arrive over-the-wire. */ +#endif /* ALLOW_VERSION_1_ROOT_CERT_PARSE */ } /* CertificateSerialNumber ::= INTEGER @@ -710,10 +778,17 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } */ + p_subject_pubkey_info = p; + + cert->publicKeyDerOffsetIntoUnparsedBin = (uint16_t)(p - certStart); + if ((rc = getAsnSequence(&p, (uint32)(end - p), &len)) < 0) { psTraceCrypto("Couldn't get ASN sequence for pubKeyAlgorithm\n"); return rc; } + subject_pubkey_info_header_len = (p - p_subject_pubkey_info); + cert->publicKeyDerLen = len + subject_pubkey_info_header_len; + if ((rc = getAsnAlgorithmIdentifier(&p, (uint32)(end - p), &cert->pubKeyAlgorithm, &plen)) < 0) { psTraceCrypto("Couldn't parse algorithm id for pubKeyAlgorithm\n"); @@ -766,7 +841,7 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, cert->pubKeyAlgorithm); return PS_UNSUPPORTED_FAIL; } - + #ifdef USE_OCSP /* A sha1 hash of the public key is useful for OCSP */ memcpy(cert->sha1KeyHash, sha1KeyHash, SHA1_HASH_SIZE); @@ -801,9 +876,9 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, if (cert->subject.commonName == NULL && cert->subject.country == NULL && cert->subject.state == NULL && - cert->subject.locality == NULL && cert->subject.organization == NULL && cert->subject.orgUnit == NULL && + cert->subject.domainComponent == NULL && cert->extensions.san == NULL) { psTraceCrypto("Error. Cert has no name information\n"); return PS_PARSE_FAIL; @@ -859,13 +934,13 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, #ifdef USE_MD2 case OID_MD2_RSA_SIG: psMd2Init(&hashCtx.md2); - psMd2Update(&hashCtx.md2, certStart, certLen); + psMd2Update(&hashCtx.md2, tbsCertStart, certLen); psMd2Final(&hashCtx.md2, cert->sigHash); break; #endif case OID_MD5_RSA_SIG: psMd5Init(&hashCtx.md5); - psMd5Update(&hashCtx.md5, certStart, certLen); + psMd5Update(&hashCtx.md5, tbsCertStart, certLen); psMd5Final(&hashCtx.md5, cert->sigHash); break; #endif @@ -874,8 +949,9 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, #ifdef USE_ECC case OID_SHA1_ECDSA_SIG: #endif + psSha1PreInit(&hashCtx.sha1); psSha1Init(&hashCtx.sha1); - psSha1Update(&hashCtx.sha1, certStart, certLen); + psSha1Update(&hashCtx.sha1, tbsCertStart, certLen); psSha1Final(&hashCtx.sha1, cert->sigHash); break; #endif @@ -884,8 +960,9 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, #ifdef USE_ECC case OID_SHA256_ECDSA_SIG: #endif + psSha256PreInit(&hashCtx.sha256); psSha256Init(&hashCtx.sha256); - psSha256Update(&hashCtx.sha256, certStart, certLen); + psSha256Update(&hashCtx.sha256, tbsCertStart, certLen); psSha256Final(&hashCtx.sha256, cert->sigHash); break; #endif @@ -894,8 +971,9 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, #ifdef USE_ECC case OID_SHA384_ECDSA_SIG: #endif + psSha384PreInit(&hashCtx.sha384); psSha384Init(&hashCtx.sha384); - psSha384Update(&hashCtx.sha384, certStart, certLen); + psSha384Update(&hashCtx.sha384, tbsCertStart, certLen); psSha384Final(&hashCtx.sha384, cert->sigHash); break; #endif @@ -904,8 +982,9 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, #ifdef USE_ECC case OID_SHA512_ECDSA_SIG: #endif + psSha512PreInit(&hashCtx.sha512); psSha512Init(&hashCtx.sha512); - psSha512Update(&hashCtx.sha512, certStart, certLen); + psSha512Update(&hashCtx.sha512, tbsCertStart, certLen); psSha512Final(&hashCtx.sha512, cert->sigHash); break; #endif @@ -915,35 +994,39 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, #ifdef ENABLE_MD5_SIGNED_CERTS case PKCS1_MD5_ID: psMd5Init(&hashCtx.md5); - psMd5Update(&hashCtx.md5, certStart, certLen); + psMd5Update(&hashCtx.md5, tbsCertStart, certLen); psMd5Final(&hashCtx.md5, cert->sigHash); break; #endif #ifdef ENABLE_SHA1_SIGNED_CERTS case PKCS1_SHA1_ID: + psSha1PreInit(&hashCtx.sha1); psSha1Init(&hashCtx.sha1); - psSha1Update(&hashCtx.sha1, certStart, certLen); + psSha1Update(&hashCtx.sha1, tbsCertStart, certLen); psSha1Final(&hashCtx.sha1, cert->sigHash); break; #endif #ifdef USE_SHA256 case PKCS1_SHA256_ID: + psSha256PreInit(&hashCtx.sha256); psSha256Init(&hashCtx.sha256); - psSha256Update(&hashCtx.sha256, certStart, certLen); + psSha256Update(&hashCtx.sha256, tbsCertStart, certLen); psSha256Final(&hashCtx.sha256, cert->sigHash); break; #endif #ifdef USE_SHA384 case PKCS1_SHA384_ID: + psSha384PreInit(&hashCtx.sha384); psSha384Init(&hashCtx.sha384); - psSha384Update(&hashCtx.sha384, certStart, certLen); + psSha384Update(&hashCtx.sha384, tbsCertStart, certLen); psSha384Final(&hashCtx.sha384, cert->sigHash); break; #endif #ifdef USE_SHA512 case PKCS1_SHA512_ID: + psSha512PreInit(&hashCtx.sha512); psSha512Init(&hashCtx.sha512); - psSha512Update(&hashCtx.sha512, certStart, certLen); + psSha512Update(&hashCtx.sha512, tbsCertStart, certLen); psSha512Final(&hashCtx.sha512, cert->sigHash); break; #endif @@ -1003,11 +1086,40 @@ int32 psX509ParseCert(psPool_t *pool, const unsigned char *pp, uint32 size, return (int32)(p - pp); } +static void freeOrgUnitList(x509OrgUnit_t *orgUnit, psPool_t *allocPool) +{ + x509OrgUnit_t *ou; + while (orgUnit != NULL) { + ou = orgUnit; + orgUnit = ou->next; + psFree(ou->name, allocPool); + psFree(ou, allocPool); + } +} + +static void freeDomainComponentList(x509DomainComponent_t *domainComponent, + psPool_t *allocPool) +{ + x509DomainComponent_t *dc; + while (domainComponent != NULL) { + dc = domainComponent; + domainComponent = dc->next; + psFree(dc->name, allocPool); + psFree(dc, allocPool); + } +} + #ifdef USE_CERT_PARSE void x509FreeExtensions(x509v3extensions_t *extensions) { x509GeneralName_t *active, *inc; +#if defined(USE_FULL_CERT_PARSE) || defined(USE_CERT_GEN) + x509PolicyQualifierInfo_t *qual_info, *qual_info_inc; + x509PolicyInformation_t *pol_info, *pol_info_inc; + x509policyMappings_t *pol_map, *pol_map_inc; + x509authorityInfoAccess_t *authInfo, *authInfoInc; +#endif /* USE_FULL_CERT_PARSE || USE_CERT_GEN */ if (extensions == NULL) { return; @@ -1021,6 +1133,28 @@ void x509FreeExtensions(x509v3extensions_t *extensions) active = inc; } } +#if defined(USE_FULL_CERT_PARSE) || defined(USE_CERT_GEN) + if (extensions->issuerAltName) { + active = extensions->issuerAltName; + while (active != NULL) { + inc = active->next; + psFree(active->data, extensions->pool); + psFree(active, extensions->pool); + active = inc; + } + } + + if (extensions->authorityInfoAccess) { + authInfo = extensions->authorityInfoAccess; + while (authInfo != NULL) { + authInfoInc = authInfo->next; + psFree(authInfo->ocsp, extensions->pool); + psFree(authInfo->caIssuers, extensions->pool); + psFree(authInfo, extensions->pool); + authInfo = authInfoInc; + } + } +#endif /* USE_FULL_CERT_PARSE || USE_CERT_GEN */ #ifdef USE_CRL if (extensions->crlNum) { @@ -1061,20 +1195,159 @@ void x509FreeExtensions(x509v3extensions_t *extensions) if (extensions->ak.keyId) psFree(extensions->ak.keyId, extensions->pool); if (extensions->ak.serialNum) psFree(extensions->ak.serialNum, extensions->pool); - if (extensions->ak.attribs.commonName) - psFree(extensions->ak.attribs.commonName, extensions->pool); - if (extensions->ak.attribs.country) psFree(extensions->ak.attribs.country, - extensions->pool); - if (extensions->ak.attribs.state) psFree(extensions->ak.attribs.state, - extensions->pool); - if (extensions->ak.attribs.locality) - psFree(extensions->ak.attribs.locality, extensions->pool); - if (extensions->ak.attribs.organization) - psFree(extensions->ak.attribs.organization, extensions->pool); - if (extensions->ak.attribs.orgUnit) psFree(extensions->ak.attribs.orgUnit, - extensions->pool); - if (extensions->ak.attribs.dnenc) psFree(extensions->ak.attribs.dnenc, - extensions->pool); + psX509FreeDNStruct(&extensions->ak.attribs, extensions->pool); + +#if defined(USE_FULL_CERT_PARSE) || defined(USE_CERT_GEN) + pol_info = extensions->certificatePolicy.policy; + while (pol_info != NULL) { + /* Free PolicyInformation member variables. */ + pol_info_inc = pol_info->next; + psFree(pol_info->policyOid, extensions->pool); + qual_info = pol_info->qualifiers; + while (qual_info != NULL) { + /* Free QualifierInfo member variables. */ + qual_info_inc = qual_info->next; + psFree(qual_info->cps, extensions->pool); + psFree(qual_info->unoticeOrganization, extensions->pool); + psFree(qual_info->unoticeExplicitText, extensions->pool); + psFree(qual_info, extensions->pool); + qual_info = qual_info_inc; + } + psFree(pol_info, extensions->pool); + pol_info = pol_info_inc; + } + + pol_map = extensions->policyMappings; + while (pol_map != NULL) { + pol_map_inc = pol_map->next; + psFree(pol_map->issuerDomainPolicy, extensions->pool); + psFree(pol_map->subjectDomainPolicy, extensions->pool); + psFree(pol_map, extensions->pool); + pol_map = pol_map_inc; + } +#endif /* USE_FULL_CERT_PARSE || USE_CERT_GEN */ +} + +int32_t psX509GetNumDomainComponents(const x509DNattributes_t *DN) +{ + x509DomainComponent_t *dc; + int32_t res = 0; + + if (DN == NULL) + return PS_ARG_FAIL; + + if (DN->domainComponent == NULL) + return 0; + + res = 1; + dc = DN->domainComponent; + while(dc->next != NULL) { + dc = dc->next; + res++; + } + + return res; +} + +x509DomainComponent_t* psX509GetDomainComponent(const x509DNattributes_t *DN, + int32_t index) +{ + x509DomainComponent_t *dc; + int32_t i; + + if (DN == NULL || DN->domainComponent == NULL || index < 0) + return NULL; + + /* + Note: the DC list is in reverse order. The last item + (i.e the item with largest index) is at the list head. + */ + + i = psX509GetNumDomainComponents(DN) - 1; /* Largest index. */ + if (i < 0) + return NULL; + + dc = DN->domainComponent; + if (i == index) + return dc; + + while(dc->next != NULL) { + dc = dc->next; + i--; + if (i < 0) + return NULL; + if (i == index) + return dc; + } + + return NULL; +} + +int32_t psX509GetConcatenatedDomainComponent(const x509DNattributes_t *DN, + char **out_str, + size_t *out_str_len) +{ + x509DomainComponent_t *dc; + int32_t i = 0; + uint16_t total_len = 0; + int32_t num_dcs = 0; + int32_t pos = 0; + + if (DN == NULL || out_str == NULL) + return PS_ARG_FAIL; + + num_dcs = psX509GetNumDomainComponents(DN); + if (num_dcs == 0) { + *out_str = NULL; + *out_str_len = 0; + return PS_SUCCESS; + } + + for (i = 0; i < num_dcs; i++) { + dc = psX509GetDomainComponent(DN, i); + if (dc == NULL) + return PS_FAILURE; + total_len += dc->len - DN_NUM_TERMINATING_NULLS; + /* We will add a dot between the components. */ + if (i != (num_dcs - 1)) + total_len += 1; + } + + total_len += DN_NUM_TERMINATING_NULLS; + + *out_str = psMalloc(NULL, total_len); + if (*out_str == NULL) + return PS_MEM_FAIL; + memset(*out_str, 0, total_len); + + /* The top-level DC is usually listed first. So we start from the + other end. */ + pos = 0; + for (i = num_dcs - 1; i >= 0; i--) { + dc = psX509GetDomainComponent(DN, i); + if (dc == NULL) { + psFree(*out_str, NULL); + *out_str = NULL; + return PS_FAILURE; + } + memcpy(*out_str + pos, dc->name, + dc->len - DN_NUM_TERMINATING_NULLS); + pos += dc->len - DN_NUM_TERMINATING_NULLS; + if (i != 0) { + strncpy(*out_str + pos, ".", 1); + pos++; + } + } + + if (pos != total_len - DN_NUM_TERMINATING_NULLS) { + psFree(*out_str, NULL); + *out_str = NULL; + return PS_FAILURE; + } + + *out_str_len = (size_t)total_len; + + return PS_SUCCESS; } #endif /* USE_CERT_PARSE */ @@ -1238,20 +1511,7 @@ int32_t psX509ValidateGeneralName(const char *n) /******************************************************************************/ /* - Parses a sequence of GeneralName types - TODO: the actual types should be parsed. Just copying data blob - - GeneralName ::= CHOICE { - otherName [0] OtherName, - rfc822Name [1] IA5String, - dNSName [2] IA5String, - x400Address [3] ORAddress, - directoryName [4] Name, - ediPartyName [5] EDIPartyName, - uniformResourceIdentifier [6] IA5String, - iPAddress [7] OCTET STRING, - registeredID [8] OBJECT IDENTIFIER } -*/ + Parses a sequence of GeneralName types*/ static int32_t parseGeneralNames(psPool_t *pool, const unsigned char **buf, uint16_t len, const unsigned char *extEnd, x509GeneralName_t **name, int16_t limit) @@ -1289,7 +1549,6 @@ static int32_t parseGeneralNames(psPool_t *pool, const unsigned char **buf, } prevName->next = psMalloc(pool, sizeof(x509GeneralName_t)); if (prevName->next == NULL) { - /* TODO: free the list */ return PS_MEM_FAIL; } activeName = prevName->next; @@ -1313,9 +1572,10 @@ static int32_t parseGeneralNames(psPool_t *pool, const unsigned char **buf, psTraceCrypto("ASN parse error SAN otherName\n"); return PS_PARSE_FAIL; } - if (*(p++) != ASN_OID || - getAsnLength(&p, (int32)(extEnd - p), &activeName->oidLen) < 0 || - (uint32)(extEnd - p) < activeName->oidLen) { + if (*(p++) != ASN_OID + || getAsnLength(&p, (int32)(extEnd - p), &activeName->oidLen) < 0 + || (uint32)(extEnd - p) < activeName->oidLen + || activeName->oidLen > sizeof(activeName->oid)) { psTraceCrypto("ASN parse error SAN otherName oid\n"); return -1; @@ -1547,7 +1807,7 @@ static void psTraceOid(uint32_t oid[MAX_OID_LEN], uint8_t oidlen) found = 0; for (j = 0; oid_list[j].oid[0] != 0 && !found; j++) { for (i = 0; i < oidlen; i++) { - if ((uint16_t)(oid[i] & 0xFFFF) != oid_list[j].oid[i]) { + if ((uint8_t)(oid[i] & 0xFF) != oid_list[j].oid[i]) { break; } if ((i + 1) == oidlen) { @@ -1567,6 +1827,601 @@ static void psTraceOid(uint32_t oid[MAX_OID_LEN], uint8_t oidlen) X509v3 extensions */ +#ifdef USE_FULL_CERT_PARSE +static +int32_t parsePolicyQualifierInfo(psPool_t *pool, + const unsigned char *p, + const unsigned char *extEnd, + uint16_t fullExtLen, + x509PolicyQualifierInfo_t *qualInfo, + uint16_t *qual_info_len) +{ + uint32_t oid[MAX_OID_LEN] = {0}; + uint8_t oidlen; + oid_e noid; + uint16_t len; + const unsigned char *qualifierStart, *qualifierEnd; + const unsigned char *noticeNumbersEnd; + int i; + int32_t noticeNumber; + + qualifierStart = p; + + /* Parse a PolicyQualifierInfo. */ + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing certificatePolicies extension\n"); + return PS_PARSE_FAIL; + } + *qual_info_len = len + (p - qualifierStart); + qualifierEnd = qualifierStart + *qual_info_len; + + /* Parse policyQualifierId. */ + if (len < 1 || *p++ != ASN_OID) { + psTraceCrypto("Malformed policy qualifier header\n"); + return PS_PARSE_FAIL; + } + if (getAsnLength(&p, fullExtLen, &len) < 0 || + fullExtLen < len) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + if ((oidlen = psParseOid(p, len, oid)) < 1) { + psTraceCrypto("Malformed extension OID\n"); + return PS_PARSE_FAIL; + } + /* PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )*/ + noid = psFindOid(oid, oidlen); + p += len; + if (noid == oid_id_qt_cps) { + if (*p++ != ASN_IA5STRING) { + psTraceCrypto("Malformed extension OID\n"); + return PS_PARSE_FAIL; + } + if (getAsnLength(&p, fullExtLen, &len) < 0 || + fullExtLen < len) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + qualInfo->cps = psMalloc(pool, len+1); + qualInfo->cpsLen = len; + memcpy(qualInfo->cps, + p, len); + qualInfo->cps[len] = 0; /* Store as C string. */ + p += len; + } else if(noid == oid_id_qt_unotice) { + + /* UserNotice ::= SEQUENCE { + noticeRef NoticeReference OPTIONAL, + explicitText DisplayText OPTIONAL } */ + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing certificatePolicies extension\n"); + return PS_PARSE_FAIL; + } + if (len == 0 || p >= qualifierEnd) { + /* No optional noticeRef or explicitText. + Nothing left to parse. */ + return PS_SUCCESS; + } + if (*p == (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + /* NoticeReference ::= SEQUENCE { + organization DisplayText, + noticeNumbers SEQUENCE OF INTEGER } */ + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing certificatePolicies extension\n"); + return PS_PARSE_FAIL; + } + /* Parse explicitText. */ + if (*p != ASN_UTF8STRING && + *p != ASN_VISIBLE_STRING && + *p != ASN_BMPSTRING && + *p != ASN_IA5STRING) { + psTraceCrypto("Error parsing certificatePolicies extension." \ + "Only UTF8String, IA5String, BMPString and " \ + "VisibleString are supported in NoticeReferences.\n"); + return PS_PARSE_FAIL; + } + qualInfo->unoticeOrganizationEncoding = *p; + p++; + /* Parse organization. */ + if (getAsnLength(&p, fullExtLen, &len) < 0 || + fullExtLen < len) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + qualInfo->unoticeOrganization = psMalloc(pool, len+1); + if (qualInfo->unoticeOrganization == NULL) + return PS_MEM_FAIL; + qualInfo->unoticeOrganizationLen = len; + memcpy(qualInfo->unoticeOrganization, p, len); + qualInfo->unoticeOrganization[len] = 0; /* Store as C string. */ + p += len; + /* Parse noticeNumbers. */ + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing certificatePolicies extension\n"); + return PS_PARSE_FAIL; + } + noticeNumbersEnd = p+len; + i = 0; + while (p != noticeNumbersEnd) { + if (i == MAX_UNOTICE_NUMBERS) { + psTraceCrypto("Too many UserNoticeNumbers.\n"); + return PS_PARSE_FAIL; + } + if (getAsnInteger(&p, len, ¬iceNumber) < 0) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + qualInfo->unoticeNumbers[i] = noticeNumber; + i++; + } + qualInfo->unoticeNumbersLen = i; + } + if (p >= qualifierEnd) { + /* The UserNotice contained noticeRef, but not explicitText. */ + return PS_SUCCESS; + } + /* Parse explicitText. */ + if (*p != ASN_UTF8STRING && + *p != ASN_VISIBLE_STRING && + *p != ASN_BMPSTRING && + *p != ASN_IA5STRING) { + psTraceCrypto("Error parsing certificatePolicies extension." \ + "Only UTF8String, IA5String, BMPString and " \ + "VisibleString are supported in explicitText.\n"); + return PS_PARSE_FAIL; + } + qualInfo->unoticeExplicitTextEncoding = *p; + p++; + if (getAsnLength(&p, fullExtLen, &len) < 0 || + fullExtLen < len) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + qualInfo->unoticeExplicitText = psMalloc(pool, len+1); + if (qualInfo->unoticeExplicitText == NULL) + return PS_MEM_FAIL; + qualInfo->unoticeExplicitTextLen = len; + memcpy(qualInfo->unoticeExplicitText, p, len); + qualInfo->unoticeExplicitText[len] = 0; /* Store as C string. */ + p += len; + } else { + psTraceCrypto("Unsupported policyQualifierId\n"); + return PS_PARSE_FAIL; + } + + return PS_SUCCESS; +} + +static +int32_t parsePolicyInformation(psPool_t *pool, + const unsigned char *p, + const unsigned char *extEnd, + uint16_t fullExtLen, + x509PolicyInformation_t *polInfo, + uint16_t *pol_info_len) +{ + uint32_t oid[MAX_OID_LEN] = {0}; + uint8_t oidlen; + uint16_t len; + const unsigned char *qualifierEnd; + const unsigned char *polInfoStart, *polInfoEnd; + x509PolicyQualifierInfo_t *qualInfo; + uint16_t qualInfoLen; + int i; + + polInfoStart = p; + + /* + PolicyInformation ::= SEQUENCE { + policyIdentifier CertPolicyId, + policyQualifiers SEQUENCE SIZE (1..MAX) OF + PolicyQualifierInfo OPTIONAL } + */ + + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing certificatePolicies extension\n"); + return PS_PARSE_FAIL; + } + *pol_info_len = len + (p-polInfoStart); + polInfoEnd = polInfoStart + *pol_info_len; + + /* Parse CertPolicyId. */ + if (*p++ != ASN_OID) { + psTraceCrypto("Malformed extension header\n"); + return PS_PARSE_FAIL; + } + if (getAsnLength(&p, fullExtLen, &len) < 0 || + fullExtLen < len) { + psTraceCrypto("Malformed extension length\n"); + return PS_PARSE_FAIL; + } + if ((oidlen = psParseOid(p, len, oid)) < 1) { + psTraceCrypto("Malformed extension OID\n"); + return PS_PARSE_FAIL; + } + p += len; + if (oidlen == 0 || oidlen > MAX_OID_LEN) { + psTraceCrypto("Malformed extension OID\n"); + return PS_PARSE_FAIL; + } + + /* Store the policy ID. */ + polInfo->policyOid = psMalloc(pool, oidlen*sizeof(uint32_t)); + if (polInfo->policyOid == NULL) + return PS_MEM_FAIL; + for (i = 0; i < oidlen; i++) { + polInfo->policyOid[i] = oid[i]; + } + polInfo->policyOidLen = oidlen; + + if ((p >= polInfoEnd) || + (*p != (ASN_SEQUENCE | ASN_CONSTRUCTED))) { + /* No optional PolicyQualifierInfos. */ + return PS_SUCCESS; + } + + /* Parse policyQualifiers := SEQUENCE SIZE (1..MAX) OF + PolicyQualifierInfo OPTIONAL*/ + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing certificatePolicies extension\n"); + return PS_PARSE_FAIL; + } + qualifierEnd = p + len; + + polInfo->qualifiers = psMalloc(pool, sizeof(x509PolicyQualifierInfo_t)); + if (polInfo->qualifiers == NULL) + return PS_MEM_FAIL; + memset(polInfo->qualifiers, 0, sizeof(x509PolicyQualifierInfo_t)); + qualInfo = polInfo->qualifiers; + + /* Parse initial PolicyQualifierInfo. */ + if (parsePolicyQualifierInfo(pool, + p, + extEnd, + fullExtLen, + qualInfo, + &qualInfoLen) < 0) { + return PS_PARSE_FAIL; + } + p += qualInfoLen; + + /* More PolicyQualifierInfos? */ + while ((p < qualifierEnd) + && (p < extEnd) + && (*p == (ASN_SEQUENCE | ASN_CONSTRUCTED))) { + qualInfo->next = psMalloc(pool, sizeof(x509PolicyQualifierInfo_t)); + if (qualInfo->next == NULL) + return PS_MEM_FAIL; + memset(qualInfo->next, 0, sizeof(x509PolicyQualifierInfo_t)); + qualInfo = qualInfo->next; + + if (parsePolicyQualifierInfo(pool, + p, + extEnd, + fullExtLen, + qualInfo, + &qualInfoLen) < 0) { + return PS_PARSE_FAIL; + } + p += qualInfoLen; + } + + return PS_SUCCESS; +} + +static +int32_t parsePolicyConstraints(psPool_t *pool, + const unsigned char *p, + const unsigned char *extEnd, + x509policyConstraints_t *policyConstraints, + uint16_t *polConstraintsLen) +{ + uint16_t len; + const unsigned char *polConstraintsStart, *polConstraintsEnd; + unsigned char tag; + int num_ints = 0; + + /* + PolicyConstraints ::= SEQUENCE { + requireExplicitPolicy [0] SkipCerts OPTIONAL, + inhibitPolicyMapping [1] SkipCerts OPTIONAL } + + SkipCerts ::= INTEGER (0..MAX) + */ + + polConstraintsStart = p; + + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing policyConstraints extension\n"); + return PS_PARSE_FAIL; + } + polConstraintsEnd = p + len; + *polConstraintsLen = (polConstraintsEnd - polConstraintsStart); + + if (len == 0) { + /* Empty PolicyConstraints. This is allowed by RFC 5280: + "The behavior of clients that encounter an empty policy + constraints field is not addressed in this profile.*/ + return PS_SUCCESS; + } + + /* Parse up to 2 SkipCerts INTEGERS with context-specific tags 0 and 1. */ + while( num_ints < 2 && (*p == ASN_CONTEXT_SPECIFIC || + *p == (ASN_CONTEXT_SPECIFIC + 1)) ) { + tag = *p++; + if (getAsnLength(&p, (uint32)(polConstraintsEnd - p), &len) < 0 || + (uint32)(polConstraintsEnd - p) < len) { + psTraceCrypto("getAsnLength failure in policyConstraints parsing\n"); + return PS_PARSE_FAIL; + } + /* We only accept single-octet SkipCerts values. Should be enough + for all reasonable applications. */ + if (len != 1) { + psTraceCrypto("Too large SkipCerts value in PolicyConstraints.\n"); + return PS_PARSE_FAIL; + } + if (tag == ASN_CONTEXT_SPECIFIC) + policyConstraints->requireExplicitPolicy = (int32_t)*p; + else + policyConstraints->inhibitPolicyMappings = (int32_t)*p; + p += len; + ++num_ints; + } + + if (p != polConstraintsEnd) { + psTraceCrypto("Error parsing policyConstraints extension\n"); + return PS_PARSE_FAIL; + } + + return PS_SUCCESS; +} + +static +int32_t parsePolicyMappings(psPool_t *pool, + const unsigned char *p, + const unsigned char *extEnd, + x509policyMappings_t *policyMappings, + uint16_t *polMappingsLen) +{ + uint32_t oid[MAX_OID_LEN] = {0}; + uint16_t len, oidlen; + const unsigned char *polMappingsStart, *polMappingsEnd; + x509policyMappings_t *pol_map; + int i; + int num_mappings = 0; + + /* + PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + issuerDomainPolicy CertPolicyId, + subjectDomainPolicy CertPolicyId } + */ + + polMappingsStart = p; + + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing policyMappings extension\n"); + return PS_PARSE_FAIL; + } + polMappingsEnd = p + len; + *polMappingsLen = (polMappingsEnd - polMappingsStart); + + pol_map = policyMappings; + while (p < polMappingsEnd && + *p == (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + + if (num_mappings > 0) { + pol_map->next = psMalloc(pool, sizeof(x509policyMappings_t)); + if (pol_map->next == NULL) + return PS_MEM_FAIL; + memset(pol_map->next, 0, sizeof(x509policyMappings_t)); + pol_map = pol_map->next; + } + + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing policyMappings extension\n"); + return PS_PARSE_FAIL; + } + + /* Parse issuerDomainPolicy OID. */ + if (*p++ != ASN_OID) { + psTraceCrypto("Malformed extension header\n"); + return PS_PARSE_FAIL; + } + + if (getAsnLength(&p, (uint32)(polMappingsEnd - p), &len) < 0 || + (uint32)(polMappingsEnd - p) < len) { + psTraceCrypto("getAsnLength failure in policyMappings parsing\n"); + return PS_PARSE_FAIL; + } + memset(oid, 0, sizeof(oid)); + if ((oidlen = psParseOid(p, len, oid)) < 1) { + psTraceCrypto("Malformed extension OID\n"); + return PS_PARSE_FAIL; + } + p += len; + + pol_map->issuerDomainPolicy = psMalloc(pool, len*sizeof(uint32_t)); + memset(pol_map->issuerDomainPolicy, 0, len*sizeof(uint32_t)); + + for (i = 0; i < oidlen; i++) { + pol_map->issuerDomainPolicy[i] = oid[i]; + } + pol_map->issuerDomainPolicyLen = len; + + /* Parse subjectDomainPolicy OID. */ + if (*p++ != ASN_OID) { + psTraceCrypto("Malformed extension header\n"); + return PS_PARSE_FAIL; + } + + if (getAsnLength(&p, (uint32)(polMappingsEnd - p), &len) < 0 || + (uint32)(polMappingsEnd - p) < len) { + psTraceCrypto("getAsnLength failure in policyMappings parsing\n"); + return PS_PARSE_FAIL; + } + memset(oid, 0, sizeof(oid)); + if ((oidlen = psParseOid(p, len, oid)) < 1) { + psTraceCrypto("Malformed extension OID\n"); + return PS_PARSE_FAIL; + } + p += len; + + pol_map->subjectDomainPolicy = psMalloc(pool, len*sizeof(uint32_t)); + memset(pol_map->subjectDomainPolicy, 0, len*sizeof(uint32_t)); + + for (i = 0; i < oidlen; i++) { + pol_map->subjectDomainPolicy[i] = oid[i]; + } + pol_map->subjectDomainPolicyLen = len; + + ++num_mappings; + } + + if (p != polMappingsEnd) { + psTraceCrypto("Error parsing policyMappings extension\n"); + return PS_PARSE_FAIL; + } + + return PS_SUCCESS; +} + +static +int32_t parseAuthorityInfoAccess(psPool_t *pool, + const unsigned char *p, + const unsigned char *extEnd, + x509authorityInfoAccess_t **authInfo, + uint16_t *authInfoLen) +{ + uint16_t len, oidlen, adLen; + const unsigned char *authInfoStart, *authInfoEnd; + x509authorityInfoAccess_t *pAuthInfo; + uint32_t oid[MAX_OID_LEN] = {0}; + oid_e noid; + int first_entry = 0; + + authInfoStart = p; +/* + + id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } + + AuthorityInfoAccessSyntax ::= + SEQUENCE SIZE (1..MAX) OF AccessDescription + + AccessDescription ::= SEQUENCE { + accessMethod OBJECT IDENTIFIER, + accessLocation GeneralName } + + id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } + + id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } + + id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } +*/ + + /* AuthorityInfoAccessSyntax. */ + if (getAsnSequence(&p, (int32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing authKeyId extension\n"); + return PS_PARSE_FAIL; + } + + authInfoEnd = p + len; + *authInfoLen = (authInfoEnd - authInfoStart); + + if (*authInfo == NULL) { + *authInfo = psMalloc(pool, sizeof(x509authorityInfoAccess_t)); + if (*authInfo == NULL) + return PS_MEM_FAIL; + memset(*authInfo, 0, sizeof(x509authorityInfoAccess_t)); + first_entry = 1; + } + + pAuthInfo = *authInfo; + + while (p < authInfoEnd && + *p == (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + + /* Find the end of the list. */ + while (pAuthInfo->next != NULL) { + pAuthInfo = pAuthInfo->next; + } + if (!first_entry) { + /* Malloc space for a new entry. */ + pAuthInfo->next = psMalloc(pool, + sizeof(x509authorityInfoAccess_t)); + if (pAuthInfo->next == NULL) + return PS_MEM_FAIL; + memset(pAuthInfo->next, 0, + sizeof(x509authorityInfoAccess_t)); + pAuthInfo = pAuthInfo->next; + } else + first_entry = 0; + + /* AccessDescription. */ + if (getAsnSequence(&p, (int32)(extEnd - p), &adLen) < 0) { + psTraceCrypto("Error parsing authKeyId extension\n"); + return PS_PARSE_FAIL; + } + /* accessMethod. */ + if (*p++ != ASN_OID) { + psTraceCrypto("Malformed extension header\n"); + return PS_PARSE_FAIL; + } + if (getAsnLength(&p, (uint32)(authInfoEnd - p), &len) < 0 || + (uint32)(authInfoEnd - p) < len) { + psTraceCrypto("getAsnLength failure in authInfo parsing\n"); + return PS_PARSE_FAIL; + } + memset(oid, 0, sizeof(oid)); + if ((oidlen = psParseOid(p, len, oid)) < 1) { + psTraceCrypto("Malformed extension OID\n"); + return PS_PARSE_FAIL; + } + noid = psFindOid(oid, oidlen); + p += len; + if (noid != oid_id_ad_caIssuers && + noid != oid_id_ad_ocsp) { + psTraceCrypto("Unsupported AccessDescription: " \ + "only oid_ad_caIssuers and id_ad_ocsp " \ + "are supported. \n"); + return PS_PARSE_FAIL; + } + /* accessLocation. */ + switch (*p++) { + case (ASN_CONTEXT_SPECIFIC + 6): + /* uniformResourceIdentifier [6] IA5String. */ + if (getAsnLength(&p, (uint32)(authInfoEnd - p), &len) < 0 || + (uint32)(authInfoEnd - p) < len) { + psTraceCrypto("getAsnLength failure in authInfo parsing\n"); + return PS_PARSE_FAIL; + } + if (noid == oid_id_ad_ocsp) { + pAuthInfo->ocsp = psMalloc(pool, len); + if (pAuthInfo->ocsp == NULL) + return PS_MEM_FAIL; + memcpy(pAuthInfo->ocsp, p, len); + pAuthInfo->ocspLen = len; + p += len; + } else { /* oid_id_ad_caIssuers */ + pAuthInfo->caIssuers = psMalloc(pool, len); + if (pAuthInfo->caIssuers == NULL) + return PS_MEM_FAIL; + memcpy(pAuthInfo->caIssuers, p, len); + pAuthInfo->caIssuersLen = len; + p += len; + } + break; + default: + psTraceCrypto("Unsupported string type in AUTH_INFO ACC " \ + "(only uniformResourceIdenfitier is " \ + "supported). \n"); + return PS_PARSE_FAIL; + } + } /* Next AccessDescription, if any. */ + + return PS_SUCCESS; +} +#endif /* USE_FULL_CERT_PARSE */ + int32_t getExplicitExtensions(psPool_t *pool, const unsigned char **pp, uint16_t inlen, int32_t expVal, x509v3extensions_t *extensions, uint8_t known) @@ -1582,13 +2437,17 @@ int32_t getExplicitExtensions(psPool_t *pool, const unsigned char **pp, uint16_t subExtLen; const unsigned char *subSave; int32_t nc = 0; -#endif + x509PolicyInformation_t *pPolicy; + const unsigned char *policiesEnd; +#endif /* USE_FULL_CERT_PARSE */ end = p + inlen; if (inlen < 1) { return PS_ARG_FAIL; } extensions->pool = pool; + extensions->bc.cA = CA_UNDEFINED; + if (known) { goto KNOWN_EXT; } @@ -1723,9 +2582,13 @@ KNOWN_EXT: if (*p > 0 && *p != 0xFF) { psTraceCrypto("Warning: cA TRUE should be 0xFF\n"); } - extensions->bc.cA = *p++; + if (*p > 0) + extensions->bc.cA = CA_TRUE; + else + extensions->bc.cA = CA_FALSE; + p++; } else { - extensions->bc.cA = 0; + extensions->bc.cA = CA_UNDEFINED; } /* Now need to check if there is a path constraint. Only makes @@ -2019,6 +2882,15 @@ KNOWN_EXT: } } break; + case OID_ENUM(id_pe_authorityInfoAccess): + if (parseAuthorityInfoAccess(pool, p, + extEnd, + &extensions->authorityInfoAccess, + &len) < 0) { + return PS_PARSE_FAIL; + } + p += len; + break; #endif /* USE_CRL */ #endif /* FULL_CERT_PARSE */ @@ -2048,7 +2920,7 @@ KNOWN_EXT: psTraceCrypto("Error keyLen in authKeyId extension\n"); return PS_PARSE_FAIL; } - extensions->ak.keyId =psMalloc(pool, extensions->ak.keyLen); + extensions->ak.keyId = psMalloc(pool, extensions->ak.keyLen); if (extensions->ak.keyId == NULL) { psError("Mem allocation err: extensions->ak.keyId\n"); return PS_MEM_FAIL; @@ -2116,13 +2988,89 @@ KNOWN_EXT: memcpy(extensions->sk.id, p, extensions->sk.len); p = p + extensions->sk.len; break; +#ifdef USE_FULL_CERT_PARSE - /* These extensions are known but not handled */ case OID_ENUM(id_ce_certificatePolicies): - case OID_ENUM(id_ce_policyMappings): - case OID_ENUM(id_ce_issuerAltName): - case OID_ENUM(id_ce_subjectDirectoryAttributes): +/* + certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation +*/ + /* Parse certificatePolicies := SEQUENCE SIZE (1..MAX) OF + PolicyInformation. */ + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing certificatePolicies extension\n"); + return PS_PARSE_FAIL; + } + policiesEnd = p + len; + extensions->certificatePolicy.policy + = psMalloc(pool, sizeof(x509PolicyInformation_t)); + memset(extensions->certificatePolicy.policy, 0, + sizeof(x509PolicyInformation_t)); + pPolicy = extensions->certificatePolicy.policy; + + /* Parse a single PolicyInformation. */ + if (parsePolicyInformation(pool, p, extEnd, fullExtLen, + pPolicy, &len) < 0) { + return PS_PARSE_FAIL; + } + p += len; + + /* Parse further PolicyInformations, if present. */ + while ((p < policiesEnd) + && (p < extEnd) + && (*p == (ASN_SEQUENCE | ASN_CONSTRUCTED))) { + + pPolicy->next = psMalloc(pool, sizeof(x509PolicyInformation_t)); + memset(pPolicy->next, 0, sizeof(x509PolicyInformation_t)); + pPolicy = pPolicy->next; + if (parsePolicyInformation(pool, p, extEnd, fullExtLen, + pPolicy, &len) < 0) { + return PS_PARSE_FAIL; + } + p += len; + } /* End or PolicyInformation parsing. */ + break; case OID_ENUM(id_ce_policyConstraints): + if (parsePolicyConstraints(pool, p, + extEnd, + &extensions->policyConstraints, + &len) < 0) { + return PS_PARSE_FAIL; + } + p += len; + break; + case OID_ENUM(id_ce_policyMappings): + extensions->policyMappings = psMalloc(pool, + sizeof(x509policyMappings_t)); + memset(extensions->policyMappings, 0, sizeof(x509policyMappings_t)); + if (parsePolicyMappings(pool, p, + extEnd, + extensions->policyMappings, + &len) < 0) { + return PS_PARSE_FAIL; + } + + p += len; + break; + case OID_ENUM(id_ce_issuerAltName): + if (getAsnSequence(&p, (uint32)(extEnd - p), &len) < 0) { + psTraceCrypto("Error parsing issuerAltName extension\n"); + return PS_PARSE_FAIL; + } + /* NOTE: The final limit parameter was introduced for this + case because a well known search engine site sends back + about 7 KB worth of subject alt names and that has created + memory problems for a couple users. Set the -1 here to + something reasonable (5) if you've found yourself here + for this memory reason */ + if (parseGeneralNames(pool, &p, len, extEnd, &extensions->issuerAltName, + -1) < 0) { + psTraceCrypto("Error parsing altSubjectName names\n"); + return PS_PARSE_FAIL; + } + break; +#endif /* USE_FULL_CERT_PARSE */ + /* These extensions are known but not handled */ + case OID_ENUM(id_ce_subjectDirectoryAttributes): case OID_ENUM(id_ce_inhibitAnyPolicy): case OID_ENUM(id_ce_freshestCRL): case OID_ENUM(id_pe_subjectInfoAccess): @@ -2568,7 +3516,8 @@ static int32_t getImplicitBitString(psPool_t *pool, const unsigned char **pp, } p++; - if (getAsnLength(&p, len, bitLen) < 0) { + if (getAsnLength(&p, len, bitLen) < 0 + || *bitLen < 2) { psTraceCrypto("Malformed implicitBitString\n"); return PS_PARSE_FAIL; } @@ -2599,9 +3548,12 @@ int32_t psX509GetDNAttributes(psPool_t *pool, const unsigned char **pp, { const unsigned char *p = *pp; const unsigned char *dnEnd, *dnStart, *moreInSetPtr; + x509OrgUnit_t *orgUnit; + x509DomainComponent_t *domainComponent; int32 id, stringType, checkHiddenNull, moreInSet; uint16_t llen, setlen, arcLen; char *stringOut; + uint32_t i; #ifdef USE_SHA1 psSha1_t hash; #elif defined(USE_SHA256) @@ -2660,6 +3612,7 @@ MORE_IN_SET: /* id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} id-at-commonName OBJECT IDENTIFIER ::= {id-at 3} + id-at-serialNumber OBJECT IDENTIFIER ::= {id-at 5} id-at-countryName OBJECT IDENTIFIER ::= {id-at 6} id-at-localityName OBJECT IDENTIFIER ::= {id-at 7} id-at-stateOrProvinceName OBJECT IDENTIFIER ::= {id-at 8} @@ -2669,15 +3622,65 @@ MORE_IN_SET: *pp = p; /* Currently we are skipping OIDs not of type {joint-iso-ccitt(2) ds(5) 4} + (domainComponent is currently the only exception). However, we could be dealing with an OID we MUST support per RFC. - domainComponent is one such example. */ if (dnEnd - p < 2) { psTraceCrypto("Malformed DN attributes 4\n"); return PS_LIMIT_FAIL; } + + /* + Check separately for domainComponent and uid, since those do not + start with the 0x5504 (id-at) pattern the code below expects. + */ + /* + Note: According to RFC 5280, "... implementations of this + specification MUST be prepared to receive the domainComponent + attribute, as defined in [RFC4519]." + */ + if (arcLen == 10 && + *p == 0x09 && + *(p+1) == 0x92 && + *(p+2) == 0x26 && + *(p+3) == 0x89 && + *(p+4) == 0x93 && + *(p+5) == 0xf2 && + *(p+6) == 0x2c && + *(p+7) == 0x64 && + *(p+8) == 0x01) { + if (*(p+9) == 0x19) { + p += 10; + id = ATTRIB_DOMAIN_COMPONENT; + goto oid_parsing_done; + } +#ifdef USE_EXTRA_DN_ATTRIBUTES + else if (*(p+9) == 0x01) { + p += 10; + id = ATTRIB_UID; + goto oid_parsing_done; + } +#endif /* USE_EXTRA_DN_ATTRIBUTES */ + } +#ifdef USE_EXTRA_DN_ATTRIBUTES + if (arcLen == 9 && + *p == 0x2a && + *(p+1) == 0x86 && + *(p+2) == 0x48 && + *(p+3) == 0x86 && + *(p+4) == 0xf7 && + *(p+5) == 0x0d && + *(p+6) == 0x01 && + *(p+7) == 0x09 && + *(p+8) == 0x01) { + p += 9; + id = ATTRIB_EMAIL; + goto oid_parsing_done; + } +#endif /* USE_EXTRA_DN_ATTRIBUTES */ + /* check id-at */ - if ((*p++ != 85) || (*p++ != 4) ) { + if ((*p++ != 85) || (*p++ != 4)) { /* OIDs we are not parsing */ p = *pp; /* @@ -2703,6 +3706,7 @@ MORE_IN_SET: return PS_LIMIT_FAIL; } id = (int32)*p++; + oid_parsing_done: /* Done with OID parsing */ stringType = (int32)*p++; @@ -2728,18 +3732,19 @@ MORE_IN_SET: case ASN_T61STRING: case ASN_BMPSTRING: case ASN_BIT_STRING: - stringOut = psMalloc(pool, llen + 2); + stringOut = psMalloc(pool, llen + DN_NUM_TERMINATING_NULLS); if (stringOut == NULL) { psError("Memory allocation error in getDNAttributes\n"); return PS_MEM_FAIL; } memcpy(stringOut, p, llen); /* - Terminate with 2 null chars to support standard string - manipulations with any potential unicode types. + Terminate with DN_NUM_TERMINATING_NULLS null chars to support + standard string manipulations with any potential unicode types. */ - stringOut[llen] = '\0'; - stringOut[llen + 1] = '\0'; + for (i = 0; i < DN_NUM_TERMINATING_NULLS; i++) { + stringOut[llen + i] = '\0'; + } if (checkHiddenNull) { if ((uint32)strlen(stringOut) != llen) { @@ -2750,7 +3755,7 @@ MORE_IN_SET: } p = p + llen; - llen += 2; /* Add the two null bytes for length assignments */ + llen += DN_NUM_TERMINATING_NULLS; /* Add null bytes for length assignments */ break; default: psTraceIntCrypto("Unsupported DN attrib type %d\n", stringType); @@ -2766,22 +3771,6 @@ MORE_IN_SET: attribs->countryType = (short)stringType; attribs->countryLen = (short)llen; break; - case ATTRIB_STATE_PROVINCE: - if (attribs->state) { - psFree(attribs->state, pool); - } - attribs->state = stringOut; - attribs->stateType = (short)stringType; - attribs->stateLen = (short)llen; - break; - case ATTRIB_LOCALITY: - if (attribs->locality) { - psFree(attribs->locality, pool); - } - attribs->locality = stringOut; - attribs->localityType = (short)stringType; - attribs->localityLen = (short)llen; - break; case ATTRIB_ORGANIZATION: if (attribs->organization) { psFree(attribs->organization, pool); @@ -2791,12 +3780,29 @@ MORE_IN_SET: attribs->organizationLen = (short)llen; break; case ATTRIB_ORG_UNIT: - if (attribs->orgUnit) { - psFree(attribs->orgUnit, pool); + orgUnit = psMalloc(pool, sizeof(x509OrgUnit_t)); + orgUnit->name = stringOut; + orgUnit->type = (short)stringType; + orgUnit->len = llen; + /* Push the org unit onto the front of the list */ + orgUnit->next = attribs->orgUnit; + attribs->orgUnit = orgUnit; + break; + case ATTRIB_DN_QUALIFIER: + if (attribs->dnQualifier) { + psFree(attribs->dnQualifier, pool); } - attribs->orgUnit = stringOut; - attribs->orgUnitType = (short)stringType; - attribs->orgUnitLen = (short)llen; + attribs->dnQualifier = stringOut; + attribs->dnQualifierType = (short)stringType; + attribs->dnQualifierLen = (short)llen; + break; + case ATTRIB_STATE_PROVINCE: + if (attribs->state) { + psFree(attribs->state, pool); + } + attribs->state = stringOut; + attribs->stateType = (short)stringType; + attribs->stateLen = (short)llen; break; case ATTRIB_COMMON_NAME: if (attribs->commonName) { @@ -2806,6 +3812,131 @@ MORE_IN_SET: attribs->commonNameType = (short)stringType; attribs->commonNameLen = (short)llen; break; + case ATTRIB_SERIALNUMBER: + if (attribs->serialNumber) { + psFree(attribs->serialNumber, pool); + } + attribs->serialNumber = stringOut; + attribs->serialNumberType = (short)stringType; + attribs->serialNumberLen = (short)llen; + break; + case ATTRIB_DOMAIN_COMPONENT: + domainComponent = psMalloc(pool, sizeof(x509DomainComponent_t)); + domainComponent->name = stringOut; + domainComponent->type = (short)stringType; + domainComponent->len = llen; + /* Push the org unit onto the front of the list */ + domainComponent->next = attribs->domainComponent; + attribs->domainComponent = domainComponent; + break; +#ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + case ATTRIB_LOCALITY: + if (attribs->locality) { + psFree(attribs->locality, pool); + } + attribs->locality = stringOut; + attribs->localityType = (short)stringType; + attribs->localityLen = (short)llen; + break; + case ATTRIB_TITLE: + if (attribs->title) { + psFree(attribs->title, pool); + } + attribs->title = stringOut; + attribs->titleType = (short)stringType; + attribs->titleLen = (short)llen; + break; + case ATTRIB_SURNAME: + if (attribs->surname) { + psFree(attribs->surname, pool); + } + attribs->surname = stringOut; + attribs->surnameType = (short)stringType; + attribs->surnameLen = (short)llen; + break; + case ATTRIB_GIVEN_NAME: + if (attribs->givenName) { + psFree(attribs->givenName, pool); + } + attribs->givenName = stringOut; + attribs->givenNameType = (short)stringType; + attribs->givenNameLen = (short)llen; + break; + case ATTRIB_INITIALS: + if (attribs->initials) { + psFree(attribs->initials, pool); + } + attribs->initials = stringOut; + attribs->initialsType = (short)stringType; + attribs->initialsLen = (short)llen; + break; + case ATTRIB_PSEUDONYM: + if (attribs->pseudonym) { + psFree(attribs->pseudonym, pool); + } + attribs->pseudonym = stringOut; + attribs->pseudonymType = (short)stringType; + attribs->pseudonymLen = (short)llen; + break; + case ATTRIB_GEN_QUALIFIER: + if (attribs->generationQualifier) { + psFree(attribs->generationQualifier, pool); + } + attribs->generationQualifier = stringOut; + attribs->generationQualifierType = (short)stringType; + attribs->generationQualifierLen = (short)llen; + break; +#endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ +#ifdef USE_EXTRA_DN_ATTRIBUTES + case ATTRIB_STREET_ADDRESS: + if (attribs->streetAddress) { + psFree(attribs->streetAddress, pool); + } + attribs->streetAddress = stringOut; + attribs->streetAddressType = (short)stringType; + attribs->streetAddressLen = (short)llen; + break; + case ATTRIB_POSTAL_ADDRESS: + if (attribs->postalAddress) { + psFree(attribs->postalAddress, pool); + } + attribs->postalAddress = stringOut; + attribs->postalAddressType = (short)stringType; + attribs->postalAddressLen = (short)llen; + break; + case ATTRIB_TELEPHONE_NUMBER: + if (attribs->telephoneNumber) { + psFree(attribs->telephoneNumber, pool); + } + attribs->telephoneNumber = stringOut; + attribs->telephoneNumberType = (short)stringType; + attribs->telephoneNumberLen = (short)llen; + break; + case ATTRIB_UID: + if (attribs->uid) { + psFree(attribs->uid, pool); + } + attribs->uid = stringOut; + attribs->uidType = (short)stringType; + attribs->uidLen = (short)llen; + break; + case ATTRIB_NAME: + if (attribs->name) { + psFree(attribs->name, pool); + } + attribs->name = stringOut; + attribs->nameType = (short)stringType; + attribs->nameLen = (short)llen; + break; + case ATTRIB_EMAIL: + if (attribs->email) { + psFree(attribs->email, pool); + } + attribs->email = stringOut; + attribs->emailType = (short)stringType; + attribs->emailLen = (short)llen; + break; +#endif /* USE_EXTRA_DN_ATTRIBUTES */ default: /* Not a MUST support, so just ignore unknown */ psFree(stringOut, pool); @@ -2818,10 +3949,12 @@ MORE_IN_SET: } /* Hash is used to quickly compare DNs */ #ifdef USE_SHA1 + psSha1PreInit(&hash); psSha1Init(&hash); psSha1Update(&hash, dnStart, (dnEnd - dnStart)); psSha1Final(&hash, (unsigned char*)attribs->hash); #else + psSha256PreInit(&hash); psSha256Init(&hash); psSha256Update(&hash, dnStart, (dnEnd - dnStart)); psSha256Final(&hash, (unsigned char*)attribs->hash); @@ -2836,13 +3969,33 @@ MORE_IN_SET: */ void psX509FreeDNStruct(x509DNattributes_t *dn, psPool_t *allocPool) { - if (dn->country) psFree(dn->country, allocPool); - if (dn->state) psFree(dn->state, allocPool); - if (dn->locality) psFree(dn->locality, allocPool); - if (dn->organization) psFree(dn->organization, allocPool); - if (dn->orgUnit) psFree(dn->orgUnit, allocPool); - if (dn->commonName) psFree(dn->commonName, allocPool); - if (dn->dnenc) psFree(dn->dnenc, allocPool); + psFree(dn->dnenc, allocPool); + + psFree(dn->country, allocPool); + psFree(dn->organization, allocPool); + freeOrgUnitList(dn->orgUnit, allocPool); + psFree(dn->dnQualifier, allocPool); + psFree(dn->state, allocPool); + psFree(dn->commonName, allocPool); + psFree(dn->serialNumber, allocPool); + freeDomainComponentList(dn->domainComponent, allocPool); +#ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + psFree(dn->locality, allocPool); + psFree(dn->title, allocPool); + psFree(dn->surname, allocPool); + psFree(dn->givenName, allocPool); + psFree(dn->initials, allocPool); + psFree(dn->pseudonym, allocPool); + psFree(dn->generationQualifier, allocPool); +#endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ +#ifdef USE_EXTRA_DN_ATTRIBUTES + psFree(dn->streetAddress, allocPool); + psFree(dn->postalAddress, allocPool); + psFree(dn->telephoneNumber, allocPool); + psFree(dn->uid, allocPool); + psFree(dn->name, allocPool); + psFree(dn->email, allocPool); +#endif /* USE_EXTRA_DN_ATTRIBUTES */ } @@ -2954,7 +4107,7 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, Certificate authority constraint only available in version 3 certs. Only parsing version 3 certs by default though. */ - if ((ic->version > 1) && (ic->extensions.bc.cA <= 0)) { + if ((ic->version > 1) && (ic->extensions.bc.cA != CA_TRUE)) { if (sc != ic) { psTraceCrypto("Issuer does not have basicConstraint CA permissions\n"); sc->authStatus = PS_CERT_AUTH_FAIL_BC; @@ -3374,10 +4527,133 @@ static int32_t x509ConfirmSignature(const unsigned char *sigHash, return PS_SUCCESS; } #endif /* USE_RSA */ + /******************************************************************************/ #endif /* USE_CERT_PARSE */ #ifdef USE_OCSP + +/******************************************************************************/ + +static unsigned parse_digits(const unsigned char **c_p, + unsigned digits, + unsigned minimum, + unsigned maximum) +{ + const unsigned char *c = *c_p; + unsigned result = 0; + + while(digits) { + if (*c < '0' || *c > '9') + return (unsigned) -1; + result *= 10; + result += *c - '0'; + c++; + digits--; + } + + *c_p = c; + + if (result < minimum || result > maximum) + return (unsigned) -1; + + return result; +} + +/** + Verify a string has (nearly) valid date range format and length. + Optionally output it in struct tm format. + */ +static unsigned char parsedate_ocsp(const unsigned char *p, + unsigned int time_type, + unsigned int time_len, + struct tm *target) +{ + unsigned year, month, mday, hour, min, sec; + const unsigned char *c = p; + if (time_type != ASN_GENERALIZEDTIME) + return 0; + /* Format shall be YYYYMMDDHHMMSSZ (according to RFC 5280). */ + if (time_len != 15) + return 0; + + year = parse_digits(&c, 4, 1900, 2999); + if (year == (unsigned) -1) + return 0; + + month = parse_digits(&c, 2, 1, 12); + if (month == (unsigned) -1) + return 0; + + mday = parse_digits(&c, 2, 1, 31); + if (mday == (unsigned) -1) + return 0; + + hour = parse_digits(&c, 2, 0, 23); + if (hour == (unsigned) -1) + return 0; + + min = parse_digits(&c, 2, 0, 59); + if (min == (unsigned) -1) + return 0; + + /* Allow up-to 2 leap seconds. */ + sec = parse_digits(&c, 2, 0, 61); + if (sec == (unsigned) -1) + return 0; + + /* Time zone must be UTC (Zulu). */ + if (*c != 'Z') + return 0; + + if (target) { + /* Zeroize all fields as some systems have extra fields + in struct tm. */ + memset(target, 0, sizeof(*target)); + target->tm_year = (int) year - 1900; + target->tm_mon = (int) month - 1; + target->tm_mday = (int) mday; + target->tm_hour = (int) hour; + target->tm_min = (int) min; + target->tm_sec = (int) sec; + /* Note: target->tm_wday and target->tm_yday are not set. */ + } + return 1; +} + +static int32_t parse_nonce_ext(const unsigned char *p, size_t sz, + psBuf_t *nonceExtension) +{ + psParseBuf_t pb; + psParseBuf_t extensions; + psParseBuf_t extension; + + memset(nonceExtension, 0, sizeof(psBuf_t)); + if (psParseBufFromStaticData(&pb, p, sz) == PS_SUCCESS) { + if (psParseBufTryReadTagSub(&pb, &extensions, 0xA1)) { + while(psParseBufTryReadSequenceSub(&extensions, + &extension)) { + psParseBuf_t sub; + psParseBufReadSequenceSub(&extension, &sub); + if (psParseBufTrySkipBytes( + &sub, + (const unsigned char *) + "\x06\x09\x2b\x06\x01\x05" + "\x05\x07\x30\x01\x02", 11)) { + psParseBufReadTagRef( + &sub, nonceExtension, 0x04); + } + psParseBufFinish(&sub); + if (psParseBufFinish(&extension) != PS_SUCCESS) + break; + } + psParseBufFinish(&extensions); + } + } + return PS_SUCCESS; /* No parsing errors detected. */ +} + + static int32_t parseSingleResponse(uint32_t len, const unsigned char **cp, const unsigned char *end, mOCSPSingleResponse_t *res) { @@ -3456,21 +4732,36 @@ static int32_t parseSingleResponse(uint32_t len, const unsigned char **cp, revoked [1] IMPLICIT RevokedInfo, unknown [2] IMPLICIT UnknownInfo } */ + memset(res->revocationTime, 0, sizeof(res->revocationTime)); + res->revocationReason = 0; if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 0)) { res->certStatus = 0; p += 2; } else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { res->certStatus = 1; - psTraceCrypto("OCSP CertStatus is revoked. Skipping details\n"); + psTraceCrypto("OCSP CertStatus is revoked.\n"); /* RevokedInfo ::= SEQUENCE { revocationTime GeneralizedTime, revocationReason [0] EXPLICIT CRLReason OPTIONAL } */ - if (getAsnSequence(&p, (int32)(end - p), &glen) < 0) { + p += 1; + if (getAsnLength(&p, (int32)(end - p), &glen) < 0) { psTraceCrypto("Initial parseSingleResponse parse failure\n"); return PS_PARSE_FAIL; } - /* skip it */ + /* 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 */ p += glen; } else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) { res->certStatus = 2; @@ -3496,18 +4787,25 @@ static int32_t parseSingleResponse(uint32_t len, const unsigned char **cp, p += glen; /* nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, */ - - if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + res->nextUpdate = NULL; + res->nextUpdateLen = 0; + if ((uint32)(end - p) >= 2 && + *p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { p++; if (getAsnLength(&p, (uint32)(end - p), &glen) < 0 || (uint32)(end - p) < glen) { return PS_PARSE_FAIL; } - p += glen; /* SKIPPING */ + if (*p == ASN_GENERALIZEDTIME && glen > 2) { + res->nextUpdate = p + 2; + res->nextUpdateLen = glen - 2; + } + p += glen; } - + /* singleExtensions [1] EXPLICIT Extensions OPTIONAL */ - if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + if ((uint32)(end - p) >= 2 && + *p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { p++; if (getAsnLength(&p, (uint32)(end - p), &glen) < 0 || (uint32)(end - p) < glen) { @@ -3619,11 +4917,13 @@ static int32_t parseBasicOCSPResponse(psPool_t *pool, uint32_t len, psTraceCrypto("Malformed producedAt in ResponseData\n"); return PS_PARSE_FAIL; } - psAssert(glen <= 20); /* TODO: length hardcoded in structure */ + /* Perform quick parsing on data. */ + if (parsedate_ocsp(p, ASN_GENERALIZEDTIME, glen, NULL) == 0) + return PS_PARSE_FAIL; res->timeProducedLen = glen; res->timeProduced = p; p += glen; - + /* responses SEQUENCE OF SingleResponse, */ if (getAsnSequence(&p, (int32)(end - p), &glen) < 0) { psTraceCrypto("Initial SingleResponse parse failure\n"); @@ -3648,9 +4948,10 @@ static int32_t parseBasicOCSPResponse(psPool_t *pool, uint32_t len, } } } - /* responseExtensions [1] EXPLICIT Extensions OPTIONAL } */ if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + if (parse_nonce_ext(p, end - p, &res->nonce) != PS_SUCCESS) + return PS_PARSE_FAIL; p++; if (getAsnLength(&p, (uint32)(end - p), &glen) < 0 || (uint32)(end - p) < glen) { @@ -3820,7 +5121,7 @@ int32_t parseOCSPResponse(psPool_t *pool, int32_t len, unsigned char **cp, psTraceCrypto("Error parsing UserKeyingMaterial\n"); return PS_PARSE_FAIL; } - + /* ResponseBytes ::= SEQUENCE { responseType OBJECT IDENTIFIER, response OCTET STRING } @@ -3849,6 +5150,7 @@ int32_t parseOCSPResponse(psPool_t *pool, int32_t len, unsigned char **cp, signature BIT STRING, certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } */ + memset(response, 0, sizeof(*response)); if (parseBasicOCSPResponse(pool, blen, &p, end, response) < 0) { psTraceCrypto("parseBasicOCSPResponse failure\n"); return PS_PARSE_FAIL; @@ -3868,75 +5170,233 @@ int32_t parseOCSPResponse(psPool_t *pool, int32_t len, unsigned char **cp, return PS_SUCCESS; } -/* Diff the current time against the OCSP timestamp and confirm it's not - longer than the user is willing to trust */ -static int16_t checkOCSPtimestamp(mOCSPResponse_t *response) -{ - /* GeneralizedTime values MUST be - expressed in Greenwich Mean Time (Zulu) and MUST include seconds - (i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds - is zero. GeneralizedTime values MUST NOT include fractional seconds. - */ -#ifdef POSIX - struct tm mytime; - time_t currrawtime, myrawtime; - double diffsecs; - const unsigned char *c; - - /* timeProduced here is the producedAt of the response which is the - time the signature was generated */ - c = response->timeProduced; - - /* Goal is to create time_t from this GeneralizedTime to perform a - diff against current time (also a time_t) */ - memset(&mytime, 0x0, sizeof(struct tm)); - mytime.tm_year = 1000 * (c[0] - '0') + 100 * (c[1] - '0') + - 10 * (c[2] - '0') + (c[3] - '0'); c += 4; - mytime.tm_year -= 1900; - mytime.tm_mon = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; - mytime.tm_mon--; /* month is 0 based for some reason */ - mytime.tm_mday = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; - mytime.tm_hour = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; - mytime.tm_min = 10 * (c[0] - '0') + (c[1] - '0'); c += 2; - mytime.tm_sec = 10 * (c[0] - '0') + (c[1] - '0'); - - /* If there is no timegm on the platform, maybe there will be a mktime - which will interpret 'mytime' as local time rather than GMT. This - change will cause a margin of error in the difftime below if - the current time is not adjusted for GMT */ - //myrawtime = mktime(&mytime); /* margin of error will exist */ - myrawtime = timegm(&mytime); /* Adds missing members of mytime */ - - /* current time */ - time(&currrawtime); +/* Check validity of OCSP response and obtain the date stamps from it. - diffsecs = difftime(currrawtime, myrawtime); - - if (diffsecs < 0 || diffsecs > OCSP_VALID_TIME_WINDOW) { - return PS_LIMIT_FAIL; + If time_now is not provided, the current time will be requested from + the oeprating system. + This function extracts data information from parsed OCSP response. + Because the dates in mOCSPResponse_t are references to memory containing + binary OCSP response, that memory must not have been released before calling + this function. time_linger is useful to deal with the fact that the + peer and this host may have tiny difference in their clocks. + + @param response Pointer to OCSP response structure (from parseOCSPResponse) + @param index The index of OCSP single response to handle (0 for the first). + @param timeNow A pointer to structure filled in with gmtime(), structure + initialized to all zero or NULL. + @param producedAt If non-NULL Will be filled in with time the structure + was produced. + @param thisUpdate If non-NULL Will be filled in with time the OCSP + information was updated (usually the same as producedAt). + @param nextUpdate If non-NULL Will be filled in with time the OCSP + information needs to be updated. + @param time_linger Amout of flexibility in comparison of times. + Recommended value: PS_OCSP_TIME_LINGER (120) + @retval PS_SUCCESS If the dates were extracted from response and the + response in comparison with timeNow is valid. + @retval PS_TIMEOUT_FAIL The datas were extracted from response, but + the response has timed out. (Or the response is too far in future.) + @retval PS_PARSE_FAIL If error occurred parsing the data information in + the request. + */ +int32_t checkOCSPResponseDates(mOCSPResponse_t *response, + int index, + struct tm *timeNow, + struct tm *producedAt, + struct tm *thisUpdate, + struct tm *nextUpdate, + int time_linger) +{ + struct tm tmp, tmp2, tmp3, tmp4; + unsigned char ok = 1; + int32 err; + mOCSPSingleResponse_t *subjectResponse; + + if (index >= MAX_OCSP_RESPONSES) + return PS_ARG_FAIL; + + if (timeNow == NULL) { + memset(&tmp, 0, sizeof tmp); + timeNow = &tmp; } - return PS_SUCCESS; - -#else -/* Warn if we are skipping the date validation checks. */ -#ifdef WIN32 -#pragma message("OCSP DATE VALIDITY NOT SUPPORTED ON THIS PLATFORM.") -#else -#warning "OCSP DATE VALIDITY NOT SUPPORTED ON THIS PLATFORM." -#endif - return PS_SUCCESS; -#endif /* POSIX */ + + if (timeNow->tm_year == 0) { + /* The structure appears not filled in, use gmtime() to + get the current time. */ + time_t time_seconds = time(NULL); + struct tm *new_tm = gmtime(&time_seconds); + if (new_tm == NULL) + return PS_FAIL; + memcpy(timeNow, new_tm, sizeof(struct tm)); + } + + if (thisUpdate == NULL) + thisUpdate = &tmp2; + + if (nextUpdate == NULL) + nextUpdate = &tmp3; + + if (producedAt == NULL) + producedAt = &tmp4; + + ok &= parsedate_ocsp(response->timeProduced, + ASN_GENERALIZEDTIME, + response->timeProducedLen, + producedAt); + + subjectResponse = &response->singleResponse[index]; + + if (subjectResponse->thisUpdate) + ok &= parsedate_ocsp(subjectResponse->thisUpdate, + ASN_GENERALIZEDTIME, + subjectResponse->thisUpdateLen, + thisUpdate); + else + ok = 0; + + if (subjectResponse->nextUpdate != NULL) { + ok &= parsedate_ocsp(subjectResponse->nextUpdate, + ASN_GENERALIZEDTIME, + subjectResponse->nextUpdateLen, + nextUpdate); + } else { + /* If there is no next update, the server supports + continous updates and nextUpdate time is considered + identical to the this update time. */ + ok &= parsedate_ocsp(subjectResponse->thisUpdate, + ASN_GENERALIZEDTIME, + subjectResponse->thisUpdateLen, + nextUpdate); + } + + if (ok == 1) { + /* Convert times to seconds for comparison. + These also fill in additional fields in tm, like + current day. */ + time_t thisUpdateTime = timegm(thisUpdate); + time_t nextUpdateTime = timegm(nextUpdate); + time_t nextUpdateTimeNew; + time_t nowTime = timegm(timeNow); + (void)timegm(producedAt); + + /* Move thisUpdate_time linger seconds back. */ + if (thisUpdateTime > time_linger) + thisUpdateTime -= time_linger; + else + thisUpdateTime = 0; + + /* Move nextUpdate_time linger seconds to future. + This is not done for times very close to end of + representable time range, such as Y2K38 (on 32-bit + devices). */ + nextUpdateTimeNew = nextUpdateTime + time_linger; + if (nextUpdateTimeNew > nextUpdateTime) + nextUpdateTime = nextUpdateTimeNew; + + if (thisUpdateTime <= nowTime && nowTime <= nextUpdateTime) + err = PS_SUCCESS; + else + err = PS_TIMEOUT_FAIL; + } else { + err = PS_PARSE_FAIL; + } + return err; } -int32_t validateOCSPResponse(psPool_t *pool, psX509Cert_t *trustedOCSP, - psX509Cert_t *srvCerts, mOCSPResponse_t *response) + +/* Diff the current time against the OCSP timestamp and confirm it's not + longer than the user is willing to trust */ +static int32_t checkOCSPtimestamp(mOCSPResponse_t *response, int index) { + return checkOCSPResponseDates(response, index, NULL, NULL, NULL, NULL, + PS_OCSP_TIME_LINGER); +} + +/* Partial OCSP request parser: just locate nonceExtension if present. */ +static int32_t parseOcspReq(const void *data, size_t datalen, + psBuf_t *nonceExtension) +{ + psParseBuf_t pb; + psParseBuf_t ocspRequest; + psParseBuf_t tbsRequest; + psParseBuf_t extensions; + psParseBuf_t extension; + psParseBuf_t requestList; + psParseBuf_t request; + psParseBuf_t requestCert; + psParseBuf_t requestCertContent; + int rc; + + rc = psParseBufFromStaticData(&pb, data, datalen); + if (rc != PS_SUCCESS) + return rc; + psParseBufReadSequenceSub(&pb, &ocspRequest); + /* Ensure subbuffer is advanced and main buffer is not. */ + psParseBufReadSequenceSub(&ocspRequest, &tbsRequest); + /* Ignore version number (v1 == 0) if present. */ + psParseBufTrySkipBytes(&tbsRequest, (const unsigned char *) + "\xA0\x03\x02\x01\x00", 5); + /* Skip requestorName if present. */ + psParseBufTrySkipTag(&tbsRequest, 0xA1); + /* Skip requestList (must be present with at least one request). */ + psParseBufReadSequenceSub(&tbsRequest, &requestList); + psParseBufReadSequenceSub(&requestList, &request); + psParseBufReadSequenceSub(&request, &requestCert); + psParseBufReadSequenceSub(&requestCert, &requestCertContent); + psParseBufFinish(&requestCertContent); + psParseBufFinish(&requestCert); + psParseBufFinish(&request); + psParseBufFinish(&requestList); + if (psParseBufTryReadTagSub(&tbsRequest, &extensions, 0xA2)) { + while(psParseBufTryReadSequenceSub(&extensions, &extension)) { + psParseBuf_t sub; + psParseBufReadSequenceSub(&extension, &sub); + if (psParseBufTrySkipBytes( + &sub, + (const unsigned char *) + "\x06\x09\x2b\x06\x01\x05" + "\x05\x07\x30\x01\x02", 11)) { + psParseBufReadTagRef( + &sub, nonceExtension, 0x04); + } + psParseBufFinish(&sub); + if (psParseBufFinish(&extension) != PS_SUCCESS) + break; + } + psParseBufFinish(&extensions); + } + psParseBufFinish(&tbsRequest); + return psParseBufFinish(&ocspRequest); +} + +int32_t validateOCSPResponse_ex(psPool_t *pool, psX509Cert_t *trustedOCSP, + psX509Cert_t *srvCerts, mOCSPResponse_t *response, + psValidateOCSPResponseOptions_t *vOpts + ) +{ + static psValidateOCSPResponseOptions_t vOptsDefault; psX509Cert_t *curr, *issuer, *subject, *ocspResIssuer; mOCSPSingleResponse_t *subjectResponse; unsigned char sigOut[MAX_HASH_SIZE]; int32 sigOutLen, sigType, index; psPool_t *pkiPool = NULL; - + bool knownFlag = false; + bool revocationFlag = false; + psBuf_t nonceExtReq = { NULL }; + + /* use default validation options if not specified. */ + if (vOpts == NULL) { + vOpts = &vOptsDefault; + } + + /* Find interesting options from request. */ + if (vOpts->request) { + int rc = parseOcspReq(vOpts->request, vOpts->requestLen, + &nonceExtReq); + if (rc != PS_SUCCESS) + return PS_ARG_FAIL; + } + /* Find the OCSP cert that signed the response. First place to look is within the OCSPResponse itself */ issuer = NULL; @@ -4058,17 +5518,33 @@ int32_t validateOCSPResponse(psPool_t *pool, psX509Cert_t *trustedOCSP, /* If the response is reporting that this cert is bad right in the status, just return that immediately and stop the connection */ - if (subjectResponse->certStatus != 0) { - psTraceCrypto("ERROR: OCSP info: server cert is revoked!\n"); - return PS_FAILURE; + if (subjectResponse->certStatus == 0) { + knownFlag = true; + revocationFlag = false; + } else if (subjectResponse->certStatus == 1) { + knownFlag = true; + revocationFlag = true; + /* Server is revoked, but still check rest of + the response. */ } - + /* Is the response within the acceptable time window */ - if (checkOCSPtimestamp(response) < 0) { + if (checkOCSPtimestamp(response, index) != PS_SUCCESS) { psTraceCrypto("ERROR: OCSP response older than threshold\n"); return PS_FAILURE; } - + + /* Check if nonces match. */ + if (nonceExtReq.buf && vOpts->nonceMatch) { + if (response->nonce.buf == NULL) + *(vOpts->nonceMatch) = false; /* No nonce in response. */ + else + /* Compare nonces. */ + *(vOpts->nonceMatch) = + psBufEq(&nonceExtReq, + &response->nonce); + } + #if 0 /* The issuer here is pointing to the cert that signed the OCSPRespose and that is not necessarily the parent of the subject cert we are looking at. If we want to include this test, we'd need to @@ -4170,9 +5646,45 @@ int32_t validateOCSPResponse(psPool_t *pool, psX509Cert_t *trustedOCSP, } #endif + if (vOpts->knownFlag) + *(vOpts->knownFlag) = knownFlag; + + if (knownFlag == false) { + /* The certificate is not known. */ + return PS_FAILURE; + } else { + if (vOpts->revocationFlag) + *(vOpts->revocationFlag) = revocationFlag; + + if (vOpts->revocationTime) { + if (parsedate_ocsp( + subjectResponse->revocationTime, + ASN_GENERALIZEDTIME, + sizeof(subjectResponse->revocationTime), + vOpts->revocationTime)) + (void)timegm(vOpts->revocationTime); + } + + if (vOpts->revocationReason) + *(vOpts->revocationReason) = + subjectResponse->revocationReason; + + /* Function fails if certificate was revoked. */ + if (revocationFlag) + return PS_FAILURE; + } + /* Was able to successfully confirm OCSP signature for our subject */ return PS_SUCCESS; } + +int32_t validateOCSPResponse(psPool_t *pool, psX509Cert_t *trustedOCSP, + psX509Cert_t *srvCerts, + mOCSPResponse_t *response) { + return validateOCSPResponse_ex(pool, trustedOCSP, srvCerts, response, + NULL); +} + #endif /* USE_OCSP */ #endif /* USE_X509 */ diff --git a/crypto/keyformat/x509.h b/crypto/keyformat/x509.h index 8744512..5e2d9e4 100644 --- a/crypto/keyformat/x509.h +++ b/crypto/keyformat/x509.h @@ -60,37 +60,116 @@ enum { the connection to fail. SECURITY - Uncomment at your own risk */ /* #define ALLOW_UNKNOWN_CRITICAL_EXTENSIONS */ +/* Support for multiple organizational units */ +typedef struct x509OrgUnit { + struct x509OrgUnit *next; + char *name; + short type; + uint16_t len; +} x509OrgUnit_t; + +/* Support for multiple domainComponents */ +typedef struct x509DomainComponent { + struct x509DomainComponent *next; + char *name; + short type; + uint16_t len; +} x509DomainComponent_t; + +/* Number of null-bytes to terminate parsed string-type DN attributes with. */ +#define DN_NUM_TERMINATING_NULLS 2 + /* DN attributes are used outside the X509 area for cert requests, which have been included in the RSA portions of the code */ typedef struct { + /* MUST support according to RFC 5280: */ char *country; - char *state; - char *locality; char *organization; - char *orgUnit; + x509OrgUnit_t *orgUnit; + char *dnQualifier; + char *serialNumber; + char *state; char *commonName; + x509DomainComponent_t *domainComponent; +#ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + char *locality; + char *title; + char *surname; + char *givenName; + char *initials; + char *pseudonym; + char *generationQualifier; +#endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ +#ifdef USE_EXTRA_DN_ATTRIBUTES + char *streetAddress; + char *postalAddress; + char *telephoneNumber; + char *uid; + char *name; + char *email; +#endif /* USE_EXTRA_DN_ATTRIBUTES */ char hash[MAX_HASH_SIZE]; char *dnenc; /* CERT_STORE_DN_BUFFER */ uint16_t dnencLen; + /* MUST support according to RFC 5280: */ short countryType; uint16_t countryLen; short stateType; uint16_t stateLen; - short localityType; - uint16_t localityLen; short organizationType; uint16_t organizationLen; - short orgUnitType; - uint16_t orgUnitLen; + short dnQualifierType; + uint16_t dnQualifierLen; short commonNameType; uint16_t commonNameLen; + short serialNumberType; + uint16_t serialNumberLen; + short domainComponentType; + uint16_t domainComponentLen; +#ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + short localityType; + uint16_t localityLen; + short titleType; + uint16_t titleLen; + short surnameType; + uint16_t surnameLen; + short givenNameType; + uint16_t givenNameLen; + short initialsType; + uint16_t initialsLen; + short pseudonymType; + uint16_t pseudonymLen; + short generationQualifierType; + uint16_t generationQualifierLen; +#endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ +#ifdef USE_EXTRA_DN_ATTRIBUTES + short streetAddressType; + uint16_t streetAddressLen; + short postalAddressType; + uint16_t postalAddressLen; + short telephoneNumberType; + uint16_t telephoneNumberLen; + short uidType; + uint16_t uidLen; + short nameType; + uint16_t nameLen; + short emailType; + uint16_t emailLen; +#endif /* USE_EXTRA_DN_ATTRIBUTES */ + } x509DNattributes_t; +typedef enum { + CA_FALSE = 0, + CA_UNDEFINED = 127, + CA_TRUE = 255 +} x509bcCAValue_t; + typedef struct { - int32 cA; - int32 pathLenConstraint; + x509bcCAValue_t cA; + int32 pathLenConstraint; } x509extBasicConstraints_t; typedef struct psGeneralNameEntry { @@ -114,6 +193,13 @@ typedef struct psGeneralNameEntry { struct psGeneralNameEntry *next; } x509GeneralName_t; +#define MAX_OID_LEN 16 /**< Maximum number of segments in OID */ + +#define MAX_POLICY_ATTRIB_LEN 512 +#define MAX_NUM_QUAL_INFOS 10 +#define MAX_POLICIES 10 +#define MAX_UNOTICE_NUMBERS 5 + typedef struct { unsigned char *id; uint16_t len; @@ -127,18 +213,64 @@ typedef struct { uint16_t serialNumLen; } x509extAuthKeyId_t; -#ifdef USE_FULL_CERT_PARSE +#if defined(USE_FULL_CERT_PARSE) || defined(USE_CERT_GEN) typedef struct { x509GeneralName_t *permitted; x509GeneralName_t *excluded; } x509nameConstraints_t; -#endif /* USE_FULL_CERT_PARSE */ - + +typedef struct x509PolicyQualifierInfo_t { + char *cps; + char *unoticeOrganization; + char *unoticeExplicitText; + int32_t unoticeNumbers[MAX_UNOTICE_NUMBERS]; + uint16_t cpsLen; + uint16_t unoticeOrganizationLen; + uint16_t unoticeExplicitTextLen; + uint16_t unoticeNumbersLen; + int unoticeExplicitTextEncoding; + int unoticeOrganizationEncoding; + struct x509PolicyQualifierInfo_t *next; +} x509PolicyQualifierInfo_t; + +typedef struct x509PolicyInformation_t { + uint32_t *policyOid; + uint16_t policyOidLen; + x509PolicyQualifierInfo_t *qualifiers; + struct x509PolicyInformation_t *next; +} x509PolicyInformation_t; + +typedef struct x509certificatePolicies_t { + x509PolicyInformation_t *policy; +} x509certificatePolicies_t; + +typedef struct x509policyConstraints_t { + int32_t requireExplicitPolicy; + int32_t inhibitPolicyMappings; +} x509policyConstraints_t; + +typedef struct x509policyMappings_t { + uint32_t *issuerDomainPolicy; + uint32_t *subjectDomainPolicy; + uint16_t issuerDomainPolicyLen; + uint16_t subjectDomainPolicyLen; + struct x509policyMappings_t *next; +} x509policyMappings_t; + +typedef struct x509authorityInfoAccess_t { + char *ocsp; + char *caIssuers; + uint16_t ocspLen; + uint16_t caIssuersLen; + struct x509authorityInfoAccess_t *next; +} x509authorityInfoAccess_t; + +#endif /* USE_FULL_CERT_PARSE || USE_CERT_GEN */ + /******************************************************************************/ /* OID parsing and lookup. */ -#define MAX_OID_LEN 16 /**< Maximum number of segments in OID */ /* X.509 Certificate Extension OIDs @@ -189,6 +321,9 @@ enum { */ #define id_pxix 1,3,6,1,5,5,7 +/* anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificate-policies 0 } */ +#define id_anyPolicy 2,5,29,32,0 + /* The following key usage purposes are defined: @@ -237,6 +372,19 @@ enum { id_kp_OCSPSigning = 9, }; +/* + id-ad id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } + + id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } + + id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } +*/ +#define id_ad id_pxix,48 +enum { + id_ad_ocsp = 1, + id_ad_caIssuers = 2 +}; + /* id-pe OBJECT IDENTIFIER ::= { id-pkix 1 } @@ -249,6 +397,21 @@ enum { id_pe_subjectInfoAccess = 11, }; +/* + -- policyQualifierIds for Internet policy qualifiers + + id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + + PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) +*/ +#define id_qt id_pxix,2 +enum { + id_qt_cps = 1, + id_qt_unotice = 2 +}; + #define OID_ENUM(A) oid_##A typedef enum { OID_ENUM(0) = 0, @@ -280,6 +443,12 @@ typedef enum { OID_ENUM(id_kp_emailProtection), OID_ENUM(id_kp_timeStamping), OID_ENUM(id_kp_OCSPSigning), + /* Internet policy qualifiers */ + OID_ENUM(id_qt_cps), + OID_ENUM(id_qt_unotice), + /* AccessDescriptions. */ + OID_ENUM(id_ad_caIssuers), + OID_ENUM(id_ad_ocsp), } oid_e; /* Make the flag value, given the enum above */ @@ -313,19 +482,24 @@ typedef struct { psPool_t *pool; x509extBasicConstraints_t bc; x509GeneralName_t *san; + x509GeneralName_t *issuerAltName; uint32 critFlags; /* EXT_CRIT_FLAG(EXT_KEY_USE) */ uint32 keyUsageFlags; /* KEY_USAGE_ */ uint32 ekuFlags; /* EXT_KEY_USAGE_ */ x509extSubjectKeyId_t sk; x509extAuthKeyId_t ak; -#ifdef USE_FULL_CERT_PARSE +#if defined(USE_FULL_CERT_PARSE) || defined(USE_CERT_GEN) x509nameConstraints_t nameConstraints; -#endif /* USE_FULL_CERT_PARSE */ + x509certificatePolicies_t certificatePolicy; + x509policyConstraints_t policyConstraints; + x509policyMappings_t *policyMappings; + x509authorityInfoAccess_t *authorityInfoAccess; +#endif /* USE_FULL_CERT_PARSE || USE_CERT_GEN */ #ifdef USE_CRL x509GeneralName_t *crlDist; unsigned char *crlNum; int32 crlNumLen; -#endif +#endif /* USE_CRL */ } x509v3extensions_t; #endif /* USE_CERT_PARSE */ @@ -402,6 +576,8 @@ typedef struct psCert { #endif unsigned char *unparsedBin; /* see psX509ParseCertFile */ uint16_t binLen; + uint16_t publicKeyDerOffsetIntoUnparsedBin; + uint16_t publicKeyDerLen; struct psCert *next; } psX509Cert_t; @@ -419,9 +595,47 @@ extern int32_t getExplicitExtensions(psPool_t *pool, const unsigned char **pp, uint8_t known); extern void x509FreeExtensions(x509v3extensions_t *extensions); extern int32_t psX509ValidateGeneralName(const char *n); + +/** Get the number of domainComponents in a distinguished name (DN). */ +extern int32_t psX509GetNumDomainComponents(const x509DNattributes_t *DN); + +/** Get a pointer to a domain component. + + @param[in] DN The DN struct from which to fetch the domainComponent. + Callet must NOT free this. + @param[in] index The index of the domainComponent in the order they + appear in the DER encoding. +*/ +extern x509DomainComponent_t* psX509GetDomainComponent(const x509DNattributes_t *DN, + int32_t index); + +/** Get the concatenation of all domainComponents in a DN as a C string. + + This function returns the concanated domainComponents as a string terminated + with DN_NUM_TERMINATING_NULLS NULL characters. The output string will + contain the components in the reverse order compared to the order in which + they were encoded in the certificate. Usually, this will result in the + usual print order, i.e. top-level component (.com, .org, ...) last. + + @param[in] DN The DN struct from which to fetch the domainComponent. + @param[out] out_str The concanated domainComponents as a string. This + function will malloc a string of suitable length. The caller is responsible + for freeing it. + @param[out] out_str_len Length of the returned string. +*/ +extern int32_t psX509GetConcatenatedDomainComponent(const x509DNattributes_t *DN, + char **out_str, + size_t *out_str_len); #endif /* USE_CERT_PARSE */ #ifdef USE_OCSP +#include +#include + +/* The default value of allowed mismatch in times in OCSP messages and the local + clock. */ +#define PS_OCSP_TIME_LINGER (120) + /* The OCSP structure members point directly into an OCSPResponse stream. They are validated immediately after the parse so if a change request requires these fields to persist, this will all have to change */ @@ -432,8 +646,12 @@ typedef struct { const unsigned char *certIdSerial; short certIdSerialLen; short certStatus; + unsigned char revocationTime[15]; + unsigned char revocationReason; const unsigned char *thisUpdate; short thisUpdateLen; + const unsigned char *nextUpdate; + short nextUpdateLen; } mOCSPSingleResponse_t; #define MAX_OCSP_RESPONSES 3 @@ -449,16 +667,74 @@ typedef struct { unsigned char hashResult[MAX_HASH_SIZE]; uint16_t hashLen; psX509Cert_t *OCSPResponseCert; /* Allocated to hsPool */ + psBuf_t nonce; /* Pointer to response. */ } mOCSPResponse_t; +typedef enum { + PS_CRLREASON_UNSPECIFIED = 0, + PS_CRLREASON_KEY_COMPROMISE = 1, + PS_CRLREASON_CA_COMPROMISE = 2, + PS_CRLREASON_AFFILIATION_CHANGED = 3, + PS_CRLREASON_SUPERSEDED = 4, + PS_CRLREASON_CESSATION_OF_OPERATION = 5, + PS_CRLREASON_CERTIFICATE_HOLD = 6, + /* value 7 is not used according to RFC 5280. */ + PS_CRLREASON_REMOVE_FROM_CRL = 8, + PS_CRLREASON_PRIVILEGE_WITHDRAWN = 9, + PS_CRLREASON_AA_COMPROMISE = 10 +} x509CrlReason_t; + +typedef struct { + /* Will be set to 1 if status is known, 0 if not. */ + bool *knownFlag; + /* Will be set to 1 if revoked, 0 if ok. */ + bool *revocationFlag; + /* If response included nonce or both request and response were + without nonce, then set this flag. Requires request+requestLen to + be provided. */ + bool *nonceMatch; + /* Will indicate revocation time (note: timezone = UTC). */ + struct tm *revocationTime; + /* Will indicate revocation reason. */ + x509CrlReason_t *revocationReason; + const void *request; + size_t requestLen; +} psValidateOCSPResponseOptions_t; + extern int32_t parseOCSPResponse(psPool_t *pool, int32_t len, unsigned char **cp, unsigned char *end, mOCSPResponse_t *response); + +extern int32_t checkOCSPResponseDates(mOCSPResponse_t *response, + int index, + struct tm *time_now, + struct tm *producedAt, + struct tm *thisUpdate, + struct tm *nextUpdate, + int time_linger); + extern int32_t validateOCSPResponse(psPool_t *pool, psX509Cert_t *trustedOCSP, psX509Cert_t *srvCerts, mOCSPResponse_t *response); +extern int32_t validateOCSPResponse_ex(psPool_t *pool, psX509Cert_t *trustedOCSP, + psX509Cert_t *srvCerts, mOCSPResponse_t *response, psValidateOCSPResponseOptions_t *vOpts); extern int32_t matrixSslWriteOCSPRequest(psPool_t *pool, psX509Cert_t *cert, psX509Cert_t *certIssuer, unsigned char **request, uint32_t *requestLen, int32_t flags); + +typedef struct { + int32_t flags; + const psBuf_t *requesterId; /* Optional requestor id. */ + const psBuf_t *requestExtensions; /* Optional request extensions. */ +} matrixSslWriteOCSPRequestInfo_t; + +#define MATRIXSSL_WRITE_OCSP_REQUEST_FLAG_NONCE 1 /* Use nonce. */ + +extern int32_t matrixSslWriteOCSPRequestExt( + psPool_t *pool, psX509Cert_t *cert, + psX509Cert_t *certIssuer, unsigned char **request, + uint32_t *requestLen, + matrixSslWriteOCSPRequestInfo_t *info); + #endif /******************************************************************************/ diff --git a/crypto/layer/layer.h b/crypto/layer/layer.h index d258bfa..2e8c2a4 100644 --- a/crypto/layer/layer.h +++ b/crypto/layer/layer.h @@ -55,6 +55,15 @@ #if defined(USE_AES_GCM) #define USE_MATRIX_AES_GCM #endif +#if defined(USE_AES_CMAC) + #define USE_MATRIX_AES_CMAC +#endif +#if defined(USE_AES_WRAP) + #define USE_MATRIX_AES_WRAP +#endif +#if defined(USE_AES_CTR) + #define USE_MATRIX_AES_CTR +#endif #ifdef USE_CHACHA20_POLY1305 #ifndef USE_LIBSODIUM_CRYPTO diff --git a/crypto/layer/matrix.c b/crypto/layer/matrix.c index 426f999..0f17ee0 100644 --- a/crypto/layer/matrix.c +++ b/crypto/layer/matrix.c @@ -1,5 +1,5 @@ /** - * @file matrixcrypto.c + * @file matrix.c * @version $Format:%h%d$ * * Matrix Crypto Initialization and utility layer. @@ -63,6 +63,9 @@ int32_t psCryptoOpen(const char *config) psError("pscore open failure\n"); return PS_FAILURE; } +#ifdef USE_FLPS_BINDING + flps_binding(); +#endif /* USE_FLPS_BINDING */ psOpenPrng(); #ifdef USE_CRL psCrlOpen(); diff --git a/crypto/math/pstm.c b/crypto/math/pstm.c index cf47e8e..9022bda 100644 --- a/crypto/math/pstm.c +++ b/crypto/math/pstm.c @@ -34,6 +34,8 @@ #include "../cryptoApi.h" +#include /* toupper() */ + #if defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) || defined(USE_MATRIX_DH) || defined(USE_CL_RSA) || defined(USE_CL_DH) || defined(USE_QUICK_ASSIST_RSA) || defined(USE_QUICK_ASSIST_ECC) static int32_t pstm_mul_2d(const pstm_int *a, int16_t b, pstm_int *c); @@ -52,7 +54,7 @@ static int32_t pstm_mul_2d(const pstm_int *a, int16_t b, pstm_int *c); int32_t pstm_init_size(psPool_t *pool, pstm_int *a, uint16_t size) { uint16_t x; - + if (size > PSTM_MAX_SIZE) { return PSTM_MEM; } @@ -485,9 +487,7 @@ int32_t pstm_read_asn(psPool_t *pool, const unsigned char **pp, uint16_t len, return PS_SUCCESS; } -#ifdef USE_ECC - -#include /* toupper() */ +#if defined USE_ECC || defined USE_DH || defined USE_CERT_GEN /******************************************************************************/ /** @@ -513,6 +513,9 @@ int32_t pstm_add_d(psPool_t *pool, const pstm_int *a, pstm_digit b, pstm_int *c) return res; } +#endif /* defined USE_ECC || defined USE_DH || defined USE_CERT_GEN */ +#ifdef USE_ECC + /* chars used in radix (base) conversions */ const static unsigned char pstm_s_rmap[64] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; @@ -555,14 +558,11 @@ int32_t pstm_read_radix(psPool_t *pool, pstm_int *a, while (len > 0) { /* if the radix < 36 the conversion is case insensitive this allows - numbers like 1AB and 1ab to represent the same value [e.g. in hex] - @note This casting avoids gcc -Wchar-subscripts compiler warnings - for toupper. The prototype for toupper() is strange because - the value must be in the range of unsigned char, and yet it - accepts and returns an int. + numbers like 1AB and 1ab to represent the same value [e.g. in hex]. */ ch = ((radix < 36) ? - (unsigned char)toupper((int)*buf) : (unsigned char)*buf); + (unsigned char)toupper((unsigned char)*buf) : + (unsigned char)*buf); for (y = 0; y < 64; y++) { if (ch == pstm_s_rmap[y]) { break; @@ -1651,6 +1651,7 @@ int32_t pstm_mod(psPool_t *pool, const pstm_int *a, const pstm_int *b, pstm_int return err; } +#ifdef USE_MATRIX_RSA /******************************************************************************/ /* d = a * b (mod c) @@ -1936,6 +1937,7 @@ LBL_M: pstm_clear(&M[1]); LBL_RES:pstm_clear(&res); return err; } +#endif /* USE_MATRIX_RSA */ /******************************************************************************/ /** @@ -2351,7 +2353,7 @@ top: } /* if not zero goto step 4 */ - if (sanity++ > 1000) { + if (sanity++ > 4096) { res = PS_LIMIT_FAIL; goto LBL_D; } diff --git a/crypto/pubkey/dh.c b/crypto/pubkey/dh.c index 9308918..a8944df 100644 --- a/crypto/pubkey/dh.c +++ b/crypto/pubkey/dh.c @@ -315,10 +315,12 @@ int32_t psDhGenKeyInts(psPool_t *pool, uint16_t keysize, if (key == NULL) { return PS_ARG_FAIL; } + /* Detect parameters with too small g. */ if (pstm_count_bits(g) < 2) { return PS_ARG_FAIL; } + privsize = keysize; #ifndef USE_LARGE_DH_PRIVATE_KEYS /* @@ -433,6 +435,7 @@ int32_t psDhGenSharedSecret(psPool_t *pool, if ((err = pstm_read_unsigned_bin(&p, pBin, pBinLen)) != PS_SUCCESS) { goto error; } + /* Check key->pub is within correct range 2 <= pub < p - 1. */ if (pstm_count_bits(&pubKey->pub) < 2) { err = PS_FAILURE; @@ -445,6 +448,7 @@ int32_t psDhGenSharedSecret(psPool_t *pool, err = PS_FAILURE; goto error; } + if ((err = pstm_exptmod(pool, &pubKey->pub, &privKey->priv, &p, &tmp)) != PS_SUCCESS) { goto error; diff --git a/crypto/pubkey/ecc.c b/crypto/pubkey/ecc.c index 66fa8dd..c17d2d7 100644 --- a/crypto/pubkey/ecc.c +++ b/crypto/pubkey/ecc.c @@ -680,6 +680,7 @@ int32_t psEccParsePrivKey(psPool_t *pool, uint32_t oid; int32_t asnInt; uint16_t len; + size_t privkey_len; buf = keyBuf; end = buf + keyBufLen; @@ -701,6 +702,8 @@ int32_t psEccParsePrivKey(psPool_t *pool, psTraceCrypto("Expecting private key octet string\n"); return PS_FAILURE; } + privkey_len = len; + psEccInitKey(pool, key, curve); if (pstm_init_for_read_unsigned_bin(pool, &key->k, len) != PS_SUCCESS) { goto L_FAIL; @@ -785,6 +788,21 @@ int32_t psEccParsePrivKey(psPool_t *pool, } buf += len; } + /* Try to parse 'implicitly' encoded optional public key with no + DER header, i.e. assume that all the remaining bytes are public + key bytes. This is not valid ASN.1, but sometimes appears in + practice and parsing it is a requirement for some users. */ + if (buf < end && + *buf == ANSI_UNCOMPRESSED && /* Uncompressed is the only format we support. */ + ((end-(buf+1)) == privkey_len*2)) /* Pubkey must be 2x privkey size. */ + { + if (psEccX963ImportKey(pool, buf, (end-buf), key, key->curve) < 0) { + psTraceCrypto("Unable to parse ECC pubkey from cert\n"); + goto L_FAIL; + } + buf += (end-buf); + } + /* Should be at the end */ if (end != buf) { /* If this stream came from an encrypted file, there could be @@ -1641,9 +1659,7 @@ static int32_t eccProjectiveAddPoint(psPool_t *pool, const psEccPoint_t *P, if ((err = pstm_copy(&P->z, &z)) != PS_SUCCESS) { goto done; } /* - Pre-allocated digit. Used for mul, sqr, AND reduce - TODO: haven't fully explored max paDlen -*/ + Pre-allocated digit. Used for mul, sqr, AND reduce*/ paDlen = (modulus->used * 2 + 1) * sizeof(pstm_digit); if ((paD = psMalloc(pool, paDlen)) == NULL) { err = PS_MEM_FAIL; @@ -1914,9 +1930,7 @@ static int32_t eccProjectiveDblPoint(psPool_t *pool, const psEccPoint_t *P, } /* - Pre-allocated digit. Used for mul, sqr, AND reduce - TODO: haven't fully explored max possible paDlen -*/ + Pre-allocated digit. Used for mul, sqr, AND reduce*/ paDlen = (modulus->used*2+1) * sizeof(pstm_digit); if ((paD = psMalloc(pool, paDlen)) == NULL) { err = PS_MEM_FAIL; @@ -2588,8 +2602,8 @@ int32_t psEccDsaSign(psPool_t *pool, const psEccKey_t *privKey, sLen = pstm_unsigned_bin_size(&s); /* Signatures can be smaller than the keysize but keep it sane */ - if (((rLen + 2) >= privKey->curve->size) && - ((sLen + 2) >= privKey->curve->size)) { + if (((rLen + 6) >= privKey->curve->size) && + ((sLen + 6) >= privKey->curve->size)) { if (pstm_iszero(&s) == PS_FALSE) { break; } diff --git a/crypto/pubkey/pubkey.c b/crypto/pubkey/pubkey.c index 75dd98a..3184126 100644 --- a/crypto/pubkey/pubkey.c +++ b/crypto/pubkey/pubkey.c @@ -125,7 +125,7 @@ int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer, char *keyfile, { psRsaKey_t *rsakey; psEccKey_t *ecckey; - int keytype; + int keytype = 1; unsigned char *keyBuf; int32 keyBufLen; @@ -133,8 +133,10 @@ int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer, char *keyfile, rsakey = &privkey->key.rsa; ecckey = &privkey->key.ecc; if (pemOrDer == 1) { + /* PEM file. */ if (pkcs1ParsePrivFile(pool, keyfile, password, rsakey) < PS_SUCCESS) { + /* psEccParsePrivFile will also try pkcs8ParsePrivBin. */ if (psEccParsePrivFile(pool, keyfile, password, ecckey) < PS_SUCCESS) { psTraceStrCrypto("Unable to parse private key file %s\n", @@ -146,22 +148,42 @@ int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer, char *keyfile, keytype = 1; } } else { + /* DER file. */ if (psGetFileBuf(pool, keyfile, &keyBuf, &keyBufLen) < PS_SUCCESS) { psTraceStrCrypto("Unable to open private key file %s\n", keyfile); return -1; } + /* A raw RSAPrivateKey? */ if (psRsaParsePkcs1PrivKey(pool, keyBuf, keyBufLen, rsakey) < PS_SUCCESS) { + /* A raw ECPrivateKey? */ if (psEccParsePrivKey(pool, keyBuf, keyBufLen, ecckey, NULL) < PS_SUCCESS) { - psTraceCrypto("Unable to parse private key\n"); - psFree(keyBuf, pool); - return -1; +#ifdef USE_PKCS8 + /* A PKCS #8 PrivateKeyInfo containing an ECPrivateKey? */ + if (pkcs8ParsePrivBin(pool, keyBuf, keyBufLen, password, + privkey)) { +#endif /* USE_PKCS8 */ + /* Nothing worked. */ + psTraceCrypto("Unable to parse private key. " \ + "Supported formats are RSAPrivateKey, " \ + "ECPrivateKey and PKCS #8.\n"); + psFree(keyBuf, pool); + return -1; + } +#ifdef USE_PKCS8 + if (privkey->type == PS_RSA) + keytype = 1; + else if (privkey->type == PS_ECC) + keytype = 2; + goto parsed; +#endif /* USE_PKCS8 */ } keytype = 2; } else { keytype = 1; } +parsed: psFree(keyBuf, pool); } diff --git a/crypto/pubkey/pubkey.h b/crypto/pubkey/pubkey.h index 7ef23c4..79de100 100644 --- a/crypto/pubkey/pubkey.h +++ b/crypto/pubkey/pubkey.h @@ -159,6 +159,7 @@ enum PACKED { enum PACKED { PS_NOKEY = 0, PS_RSA, + PS_DSA, PS_ECC, PS_DH }; @@ -167,7 +168,8 @@ enum PACKED { enum PACKED { RSA_TYPE_SIG = 5, ECDSA_TYPE_SIG, - RSAPSS_TYPE_SIG + RSAPSS_TYPE_SIG, + DSA_TYPE_SIG }; /** diff --git a/crypto/pubkey/rsa.c b/crypto/pubkey/rsa.c index a6cba99..fa44a8d 100644 --- a/crypto/pubkey/rsa.c +++ b/crypto/pubkey/rsa.c @@ -345,6 +345,7 @@ int32_t psRsaParseAsnPubKey(psPool_t *pool, Standard RSA form - SHA-1 hash of the value of the BIT STRING subjectPublicKey [excluding the tag, length, and number of unused bits] */ + psSha1PreInit(&dc.sha1); psSha1Init(&dc.sha1); psSha1Update(&dc.sha1, p, keylen - 1); psSha1Final(&dc.sha1, sha1KeyHash); diff --git a/crypto/test/Makefile b/crypto/test/Makefile index 985005e..8df62b9 100755 --- a/crypto/test/Makefile +++ b/crypto/test/Makefile @@ -22,18 +22,13 @@ include $(MATRIXSSL_ROOT)/common.mk # Linked files STATICS:=../libcrypt_s.a $(MATRIXSSL_ROOT)/core/libcore_s.a -DIRS:=rsaperf eccperf dhperf - -.PHONY: $(DIRS) clean - all: compile -compile: $(OBJS) $(EXE) $(DIRS) - -# Note this requires MAKECMDGOALS to be defined by make, -# otherwise clean target doesn't work -$(DIRS): - $(MAKE) $(MAKECMDGOALS) --directory=$@ +compile: $(OBJS) $(EXE) + if [ -e rsaperf ]; then $(MAKE) --directory=rsaperf; fi + if [ -e eccperf ]; then $(MAKE) --directory=eccperf; fi + if [ -e dhperf ]; then $(MAKE) --directory=dhperf; fi + if [ -e clperf ]; then $(MAKE) --directory=clperf; fi # Additional Dependencies $(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) @@ -44,6 +39,10 @@ $(SPEED_EXE): $(SPEED_SRC:.c=.o) $(STATICS) $(VECTOR_EXE): $(VECTOR_SRC:.c=.o) $(STATICS) $(CC) -o $@ $^ $(LDFLAGS) -clean: $(DIRS) +clean: rm -f $(EXE) $(OBJS) + if [ -e rsaperf ]; then $(MAKE) clean --directory=rsaperf;fi + if [ -e eccperf ]; then $(MAKE) clean --directory=eccperf;fi + if [ -e dhperf ]; then $(MAKE) clean --directory=dhperf;fi + if [ -e clperf ]; then $(MAKE) clean --directory=clperf;fi diff --git a/crypto/test/algorithmTest.c b/crypto/test/algorithmTest.c index be2091d..3dff677 100644 --- a/crypto/test/algorithmTest.c +++ b/crypto/test/algorithmTest.c @@ -804,6 +804,7 @@ int32 psAesTestGCM(void) if ((memcmp(ciphertext, tests[i].ct, tests[i].ptlen) != 0) || (memcmp(tag, tests[i].tag, 16) != 0)) { printf("FAILED: memcmp mismatch\n"); + res = PS_FAILURE; } else { printf("PASSED\n"); } @@ -977,6 +978,211 @@ int32 psAesTestGCM(void) } #endif /* USE_AES_GCM */ +#ifdef USE_AES_CTR +int32 psAesTestCTR(void) +{ + static struct { + int32 keylen, msglen; + unsigned char key[32], IV[16], pt[64], ct[64]; + } tests[] = { + /* 128-bit key, 16-byte pt */ + { + 16, 16, + {0xAE,0x68,0x52,0xF8,0x12,0x10,0x67,0xCC,0x4B,0xF7,0xA5,0x76,0x55,0x77,0xF3,0x9E }, + {0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + {0x53,0x69,0x6E,0x67,0x6C,0x65,0x20,0x62,0x6C,0x6F,0x63,0x6B,0x20,0x6D,0x73,0x67 }, + {0xE4,0x09,0x5D,0x4F,0xB7,0xA7,0xB3,0x79,0x2D,0x61,0x75,0xA3,0x26,0x13,0x11,0xB8 }, + }, + + /* 128-bit key, 36-byte pt */ + { + 16, 36, + {0x76,0x91,0xBE,0x03,0x5E,0x50,0x20,0xA8,0xAC,0x6E,0x61,0x85,0x29,0xF9,0xA0,0xDC }, + {0x00,0xE0,0x01,0x7B,0x27,0x77,0x7F,0x3F,0x4A,0x17,0x86,0xF0,0x00,0x00,0x00,0x00 }, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 0x20,0x21,0x22,0x23}, + {0xC1,0xCF,0x48,0xA8,0x9F,0x2F,0xFD,0xD9,0xCF,0x46,0x52,0xE9,0xEF,0xDB,0x72,0xD7, + 0x45,0x40,0xA4,0x2B,0xDE,0x6D,0x78,0x36,0xD5,0x9A,0x5C,0xEA,0xAE,0xF3,0x10,0x53, + 0x25,0xB2,0x07,0x2F }, + }, + }; + + int err, x; + unsigned char buf[64]; + psAesCtr_t ctr; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + _psTraceInt(" AES-CTR-%d known vector test... ", tests[x].keylen * 8); + if ((err = psAesInitExCTR(&ctr, tests[x].IV, tests[x].key, + tests[x].keylen, CTR_COUNTER_BIG_ENDIAN|LTC_CTR_RFC3686, + PS_AES_ENCRYPT)) != PS_SUCCESS) { + _psTraceInt("FAILED: psAesInitExCTR %d\n", err); + return err; + } + psAesEncryptCTR(&ctr, (unsigned char*)tests[x].pt, buf, + tests[x].msglen); + if (memcmp(buf, tests[x].ct, tests[x].msglen) != 0) { + _psTrace("FAILED: memcmp\n"); + } else { + _psTrace("PASSED\n"); + } + psAesClearCTR(&ctr); + } + return PS_SUCCESS; +} +#endif /* USE_AES_CTR */ + +#ifdef USE_AES_CMAC +int32 psAesTestCmac(void) +{ + int32 err; + static struct { + int32 keylen, ptlen; + unsigned char key[32], pt[64], ct[16]; + } tests[] = { + { 16, 16, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, + 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, + 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, + 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } + }, + { 16, 40, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, + 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, + 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, + 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, + 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, + { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, 0x30, 0xca, + 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } + }, + { 16, 64, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, + 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, + 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, + 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, + 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, + 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, + 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, + 0x6c, 0x37, 0x10 }, + { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, + 0x17, 0x79, 0x36, 0x3c, 0xfe } + }, + { 24, 16, + { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, + 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, + 0x2c, 0x6b, 0x7b}, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, + 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, 0x06, 0x62, 0xf6, + 0x5e, 0x61, 0x7c, 0x51, 0x84 } + }, + { 32, 40, + { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, + 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, + 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, + 0xf4}, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, + 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, + 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, + 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, + { 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2, 0x32, 0xf5, + 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6 } + } + }; + + int32 i; + unsigned char cmac[16]; + + for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) { + _psTraceInt(" AES CMAC %d known vector test... ", tests[i].keylen * 8); + if ((err = matrixCmacGenerate(NULL, tests[i].key, tests[i].keylen, + tests[i].pt, tests[i].ptlen, cmac)) != PS_SUCCESS) { + _psTraceInt("FAILED: matrixCmacGenerate %d\n", err); + return err; + } + if (memcmp(cmac, tests[i].ct, 16) != 0) { + _psTrace("FAILED: memcmp\n"); + } else { + _psTrace("PASSED\n"); + } + } + return 0; +} +#endif /* USE_AES_CMAC */ + +#ifdef USE_AES_WRAP +int32 psAesTestWrap(void) +{ + int32 err; + static struct { + int32 keylen, ptlen; + unsigned char key[32], pt[32], ct[32]; + } tests[] = { + { 16, 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, + { 0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47, 0xae, + 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82, 0x9d, 0x3e, + 0x86, 0x23, 0x71, 0xd2, 0xcf, 0xe5} + }, + { 24, 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, + { 0x96, 0x77, 0x8b, 0x25, 0xae, 0x6c, 0xa4, 0x35, 0xf9, + 0x2b, 0x5b, 0x97, 0xc0, 0x50, 0xae, 0xd2, 0x46, 0x8a, + 0xb8, 0xa1, 0x7a, 0xd8, 0x4e, 0x5d } + }, + { 32, 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, + { 0x64, 0xe8, 0xc3, 0xf9, 0xce, 0x0f, 0x5b, 0xa2, 0x63, + 0xe9, 0x77, 0x79, 0x05, 0x81, 0x8a, 0x2a, 0x93, 0xc8, + 0x19, 0x1e, 0x7d, 0x6e, 0x8a, 0xe7} + } + }; + + int32_t i; + uint32_t woutlen, uoutlen; + unsigned char unwrapped[32]; + unsigned char wrapped[32]; + + for (i = 0; i < (uint32_t)(sizeof(tests)/sizeof(tests[0])); i++) { + _psTraceInt(" AES KEY WRAP %d known vector test... ", tests[i].keylen * 8); + if ((err = psAesWrap(tests[i].key, tests[i].keylen, tests[i].pt, + tests[i].ptlen, wrapped, &woutlen)) != PS_SUCCESS) { + _psTraceInt("FAILED: psAesWrap %d\n", err); + return err; + } + if ((err = psAesUnwrap(tests[i].key, tests[i].keylen, wrapped, + woutlen, unwrapped, &uoutlen)) != PS_SUCCESS) { + _psTraceInt("FAILED: psAesWrap %d\n", err); + return err; + } + if (memcmp(wrapped, tests[i].ct, woutlen) != 0 || + memcmp(unwrapped, tests[i].pt, uoutlen) != 0) { + _psTrace("FAILED: memcmp\n"); + } else { + _psTrace("PASSED\n"); + } + } + return 0; +} +#endif /* USE_AES_WRAP */ + #endif /* USE_AES */ #if 0 @@ -1651,6 +1857,7 @@ int32 psSha1Test(void) for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0])); i++) { _psTraceInt(" SHA-1 known vector test %d... ", i + 1); + psSha1PreInit(&md); psSha1Init(&md); psSha1Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg)); psSha1Final(&md, tmp); @@ -1713,6 +1920,7 @@ int32 psSha256Test2(void) } memset(hash, 0, sizeof(hash)); + psSha256PreInit(&md); /* Pre-init before first use. */ psSha256Init(&md); psSha256Update(&md, array, 65536); psSha256Final(&md, hash); @@ -1724,6 +1932,7 @@ int32 psSha256Test2(void) } memset(hash, 0, sizeof(hash)); + psSha256PreInit(&md2); /* Pre-init before first use. */ psSha256Init(&md2); psSha256Update(&md2, array2, 65536); psSha256Final(&md2, hash); @@ -1735,6 +1944,7 @@ int32 psSha256Test2(void) } memset(hash, 0, sizeof(hash)); + psSha256PreInit(&md3); /* Pre-init before first use. */ psSha256Init(&md3); psSha256Update(&md3, array3, 65536); psSha256Final(&md3, hash); @@ -2121,6 +2331,7 @@ int32 psSha256Test(void) for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0])); i++) { _psTraceInt(" SHA-256 known vector test %d... ", i + 1); + psSha256PreInit(&md); psSha256Init(&md); psSha256Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg)); @@ -2231,6 +2442,7 @@ int32 psSha512Test(void) for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { _psTraceInt(" SHA-512 known vector test %d... ", i + 1); + psSha512PreInit(&md); psSha512Init(&md); psSha512Update(&md, (unsigned char *)tests[i].msg, (uint32)strlen(tests[i].msg)); psSha512Final(&md, tmp); @@ -2275,6 +2487,7 @@ int32 psSha384Test(void) for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { _psTraceInt(" SHA-384 known vector test %d... ", i + 1); + psSha384PreInit(&md); psSha384Init(&md); psSha384Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg)); psSha384Final(&md, tmp); @@ -2332,6 +2545,7 @@ int32 psMd5Sha1Test(void) for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0])); i++) { _psTraceInt(" MD5SHA1 known vector test %d... ", i + 1); + psMd5Sha1PreInit(&md); psMd5Sha1Init(&md); psMd5Sha1Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg)); psMd5Sha1Final(&md, tmp); @@ -4619,6 +4833,15 @@ static test_t tests[] = { #ifdef USE_AES_GCM {psAesTestGCM, "***** AES-GCM TESTS *****"}, #endif +#ifdef USE_AES_WRAP +{psAesTestWrap, "***** AES WRAP TEST *****"}, +#endif +#ifdef USE_AES_CMAC +{psAesTestCmac, "***** AES CMAC TEST *****"}, +#endif +#ifdef USE_AES_CTR +{psAesTestCTR, "***** AES-CTR TESTS *****"}, +#endif #else {NULL, "AES"}, #endif diff --git a/crypto/test/eccperf/eccperf.c b/crypto/test/eccperf/eccperf.c index 032ed4a..2cd7aba 100644 --- a/crypto/test/eccperf/eccperf.c +++ b/crypto/test/eccperf/eccperf.c @@ -78,9 +78,7 @@ #define PS_OH sizeof(psPool_t) -/* - TODO: Not tuned to smallest K for EACH key size. -*/ +/**/ #define POOL_SIGN_192 (8 * 1024) + PS_OH #define POOL_VERIFY_192 (8 * 1024) + PS_OH #define POOL_MAKE_KEY_192 (8 * 1024) + PS_OH diff --git a/crypto/test/hmac_test_vectors.h b/crypto/test/hmac_test_vectors.h index 3cfe874..9571560 100644 --- a/crypto/test/hmac_test_vectors.h +++ b/crypto/test/hmac_test_vectors.h @@ -5,27 +5,29 @@ * HMAC test vectors for crypto harness. */ /* - * Copyright (c) 2015 INSIDE Secure Corporation + * Copyright (c) 2015-2016 INSIDE Secure Corporation * All Rights Reserved * - * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF INSIDE. + * The latest version of this code is available at http://www.matrixssl.org * - * Please do not edit this file without first consulting INSIDE support. - * Unauthorized changes to this file are not supported by INSIDE. + * 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. * - * The copyright notice above does not evidence any actual or intended - * publication of such source code. + * 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 Module contains Proprietary Information of INSIDE and should be - * treated as Confidential. + * 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. * - * The information in this file is provided for the exclusive use of the - * licensees of INSIDE. Such users have the right to use, modify, - * and incorporate this code into products for purposes authorized by the - * license agreement provided they include this notice and the associated - * copyright notice with any such product. - * - * The information in this file is provided "AS IS" without warranty. + * 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 */ /******************************************************************************/ diff --git a/crypto/test/rsaperf/rsaperf.c b/crypto/test/rsaperf/rsaperf.c index 1ade58f..7a86ed7 100644 --- a/crypto/test/rsaperf/rsaperf.c +++ b/crypto/test/rsaperf/rsaperf.c @@ -416,12 +416,7 @@ int main(int argc, char **argv) passing the output as the basis for the input each time. */ in = out; -/* - TODO: The reason the out pointer switches back and forth is because - if the same addr is used for in and out, there is no change to - the data (after the first time?) even though the encryption - seems to happen. WHY IS THIS? -*/ +/**/ if (iter % 2) { out = saveout; } else { @@ -449,7 +444,6 @@ int main(int argc, char **argv) } memset(in, 0x0, keysize); - /* TODO: find a good way to time more than a single decrypt */ psGetTime(&start, NULL); /* coverity[swapped_arguments] */ if (psRsaDecryptPub(pool, &privkey, out, keysize, in, sizeof(sigdata), pkaInfo) < 0) { @@ -482,12 +476,7 @@ int main(int argc, char **argv) passing the output as the basis for the input each time. */ in = out; -/* - TODO: The reason the out pointer switches back and forth is because - if the same addr is used for in and out, there is no change to - the data (after the first time?) even though the encryption - seems to happen. WHY IS THIS? -*/ +/**/ if (iter % 2) { out = saveout; } else { @@ -505,9 +494,7 @@ int main(int argc, char **argv) #endif /* ENCRYPT_OP */ #ifdef DECRYPT_OP -/* - TODO: find a good way to time more than a single decrypt -*/ +/**/ if (in == out) { out = saveout; } diff --git a/crypto/test/throughputTest.c b/crypto/test/throughputTest.c index b96b298..69781ee 100644 --- a/crypto/test/throughputTest.c +++ b/crypto/test/throughputTest.c @@ -458,6 +458,12 @@ int32 psAesTestGCM(void) } #endif /* USE_AES_GCM */ +#ifdef USE_AES_CTR +int32 psAesTestCTR(void) +{ + return PS_SUCCESS; +} +#endif /* USE_AES_CTR */ #endif /* USE_AES */ /******************************************************************************/ @@ -778,6 +784,9 @@ static test_t tests[] = { #ifdef USE_AES_GCM {psAesTestGCM, "***** AES-GCM TESTS *****"}, #endif +#ifdef USE_AES_CTR +{psAesTestCTR, "***** AES-CTR TESTS *****"}, +#endif #else {NULL, "AES"}, #endif diff --git a/doc/MatrixSSL_API.pdf b/doc/MatrixSSL_API.pdf index adb3461..ffdf352 100644 Binary files a/doc/MatrixSSL_API.pdf and b/doc/MatrixSSL_API.pdf differ diff --git a/matrixssl/Makefile b/matrixssl/Makefile index 30efe1c..ddc67a4 100755 --- a/matrixssl/Makefile +++ b/matrixssl/Makefile @@ -35,9 +35,9 @@ compile: $(OBJS) $(STATIC) $(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile *.h # Build the static library -# Redirect stderr to null so we don't see the 'empty file' warnings + $(STATIC): $(OBJS) - $(AR) -rcuv $@ $^ 2>/dev/null + $(AR) -rcu $@ $^ clean: rm -f $(STATIC) $(OBJS) diff --git a/matrixssl/cipherSuite.c b/matrixssl/cipherSuite.c index d80b002..fd3ec6e 100644 --- a/matrixssl/cipherSuite.c +++ b/matrixssl/cipherSuite.c @@ -2231,15 +2231,11 @@ int32 chooseCipherSuite(ssl_t *ssl, unsigned char *listStart, int32 listLen) In this flexible server case, the SNI callback function is NOT USED. - - TODO: To comply with spec the server SHALL include an SNI - extension if it was used to help select keys. Maybe just - always send it in this flexible case? */ + */ wantKey.serverName = ssl->expectedName; #ifdef USE_TLS_1_2 wantKey.hashAlg = ssl->hashSigAlg; #else - /* TODO: WHAT DO WE DO FOR NON TLS 1.2? */ wantKey.hashAlg = 0; #endif #ifdef USE_ECC_CIPHER_SUITE @@ -2250,7 +2246,6 @@ int32 chooseCipherSuite(ssl_t *ssl, unsigned char *listStart, int32 listLen) #endif #ifndef USE_ONLY_PSK_CIPHER_SUITE - /* TODO: This was wrapped for compile-time purposes */ /* Invoke the user's callback */ givenKey = (ssl->sec.pubkeyCb)(ssl, &wantKey); #endif diff --git a/matrixssl/extDecode.c b/matrixssl/extDecode.c index d0e7327..7aac49f 100644 --- a/matrixssl/extDecode.c +++ b/matrixssl/extDecode.c @@ -89,7 +89,7 @@ int32 parseClientHelloExtensions(ssl_t *ssl, unsigned char **cp, unsigned short extLen = *c << 8; c++; /* Total length of list, in bytes */ extLen += *c; c++; /* extLen must be minimum 2 b type 2 b len and 0 b value */ - if ((uint32)(end - c) < extLen || extLen < 4) { + if ((uint32)(end - c) != extLen || extLen < 4) { ssl->err = SSL_ALERT_DECODE_ERROR; psTraceInfo("Invalid extension header len\n"); return MATRIXSSL_ERROR; @@ -214,7 +214,9 @@ static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext #ifdef USE_ECC_CIPHER_SUITE unsigned short dataLen, curveId; uint32 ecFlags; -#endif /* USE_ECC_CIPHER_SUITE */ +#elif defined USE_OCSP + unsigned short dataLen; +#endif /* USE_ECC_CIPHER_SUITE || USE_OCSP */ #ifdef USE_TLS_1_2 unsigned short tmpLen; #endif @@ -241,7 +243,6 @@ static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; return MATRIXSSL_ERROR; } - /* TODO: User can disable? */ ssl->extFlags.extended_master_secret = 1; break; @@ -929,8 +930,7 @@ static int ServerHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext psTraceInfo("Server sent bad ECPointFormatList\n"); return MATRIXSSL_ERROR; } - extLen--; /* TODO: check that one of these bytes is 0 - (uncompressed point support) */ + extLen--; break; #endif /* USE_ECC_CIPHER_SUITE */ diff --git a/matrixssl/hsDecode.c b/matrixssl/hsDecode.c index 771fd6a..e58e1c4 100644 --- a/matrixssl/hsDecode.c +++ b/matrixssl/hsDecode.c @@ -34,7 +34,12 @@ #include "matrixsslApi.h" +#ifdef USE_ECC #define USE_ECC_EPHEMERAL_KEY_CACHE +#endif + +#define COMPRESSION_METHOD_NULL 0x0 +#define COMPRESSION_METHOD_DEFLATE 0x1 /* Errors from these routines must either be MATRIXSSL_ERROR or PS_MEM_FAIL */ @@ -44,9 +49,10 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) { unsigned char *suiteStart, *suiteEnd; - unsigned char compareMin, compareMaj, suiteLen, compLen, serverHighestMinor; + unsigned char compareMin, compareMaj, compLen, serverHighestMinor; + uint32 suiteLen; uint32 resumptionOnTrack, cipher = 0; - int32 rc; + int32 rc, i; unsigned char *c; #ifdef USE_ECC_CIPHER_SUITE const psEccCurve_t *curve; @@ -71,7 +77,18 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) ssl->reqMajVer = *c; c++; ssl->reqMinVer = *c; c++; - + +#ifndef USE_SSL_PROTOCOL_VERSIONS_OTHER_THAN_3 + /* RFC 5246 Suggests to accept all RSA minor versions, but only + major version 0x03 (SSLv3, TLS 1.0, TLS 1.1, TLS 1.2, TLS 1.3 etc) */ + if (ssl->reqMajVer != 0x03 && ssl->reqMajVer != DTLS_MAJ_VER) { + /* Consider invalid major version protocol version error. */ + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Won't support client's SSL major version\n"); + return MATRIXSSL_ERROR; + } +#endif /* USE_SSL_PROTOCOL_VERSIONS_OTHER_THAN_3 */ + /* Client should always be sending highest supported protocol. Server will reply with a match or a lower version if enabled (or forced). */ if (ssl->majVer != 0) { @@ -347,6 +364,7 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) } } } + /* Compression parameters */ if (end - c < 1) { ssl->err = SSL_ALERT_DECODE_ERROR; @@ -359,6 +377,19 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) psTraceInfo("Invalid compression header length\n"); return MATRIXSSL_ERROR; } + /* Per TLS RFCs proposing null compression is MUST. Check the other end + has proposed null compression (amongst possible other choices). */ + for (i = 0; i < compLen; i++) { + if (c[i] == COMPRESSION_METHOD_NULL) { + break; + } + } + if (i == compLen) { + /* Note, also catches compLen == 0 */ + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("No compression.null proposed\n"); + return MATRIXSSL_ERROR; + } #ifdef USE_ZLIB_COMPRESSION while (compLen > 0) { /* Client wants it and we have it. Enable if we're not already @@ -1127,7 +1158,7 @@ int32 parseCertificateVerify(ssl_t *ssl, c = *cp; rc = 0; - + PS_VARIABLE_SET_BUT_UNUSED(rc); /* Note: Only used ifdef USE_ECC. */ psTraceHs(">>> Server parsing CERTIFICATE_VERIFY message\n"); #ifdef USE_TLS_1_2 @@ -2899,6 +2930,18 @@ SKIP_CERT_CHAIN_INIT: } return MATRIXSSL_ERROR; } +#ifdef ALLOW_VERSION_1_ROOT_CERT_PARSE + /* When ALLOW_VERSION_1_ROOT_CERT_PARSE is defined, + psX509ParseCert lets version 1 certificates through, in + order to support loading of locally trusted v1 root + certs. This means that we need to explicitly reject v1 + certificates sent to us by the peer. They cannot be + trusted due to missing Basic Constraints, etc. */ + if (cert->version != 2) { + psX509FreeCert(cert); + ssl->err = SSL_ALERT_BAD_CERTIFICATE; + } +#endif /* ALLOW_VERSION_1_ROOT_CERT_PARSE */ c += parseLen; if (i++ == 0) { diff --git a/matrixssl/matrixssl.c b/matrixssl/matrixssl.c index 3ce6a10..37bc51a 100644 --- a/matrixssl/matrixssl.c +++ b/matrixssl/matrixssl.c @@ -133,6 +133,8 @@ int32_t matrixSslOpenWithConfig(const char *config) shared = PS_SHARED; #else shared = 0; + /* To prevent warning if multithreading support is disabled. */ + PS_VARIABLE_SET_BUT_UNUSED(shared); #endif memset(g_sessionTable, 0x0, sizeof(sslSessionEntry_t) * SSL_SESSION_TABLE_SIZE); @@ -168,9 +170,7 @@ void matrixSslClose(void) #ifdef USE_SERVER_SIDE_SSL int i; - if (psLockMutex(&g_sessionTableLock) < 0) { - psTraceInfo("Warning: closing lock mutex failed\n"); - } + psLockMutex(&g_sessionTableLock); for (i = 0; i < SSL_SESSION_TABLE_SIZE; i++) { if (g_sessionTable[i].inUse > 1) { psTraceInfo("Warning: closing while session still in use\n"); @@ -178,9 +178,7 @@ void matrixSslClose(void) } memset(g_sessionTable, 0x0, sizeof(sslSessionEntry_t) * SSL_SESSION_TABLE_SIZE); - if (psUnlockMutex(&g_sessionTableLock) < 0) { - psTraceInfo("Warning: closing unlock mutex failed\n"); - } + psUnlockMutex(&g_sessionTableLock); psDestroyMutex(&g_sessionTableLock); #ifdef USE_SHARED_SESSION_CACHE if (munmap(g_sessionTable, @@ -206,7 +204,9 @@ int32_t matrixSslNewKeys(sslKeys_t **keys, void *memAllocUserPtr) { psPool_t *pool = NULL; sslKeys_t *lkeys; +#if defined(USE_ECC) || defined(REQUIRE_DH_PARAMS) int32_t rc; +#endif lkeys = psMalloc(pool, sizeof(sslKeys_t)); if (lkeys == NULL) { @@ -386,6 +386,7 @@ int32 matrixSslLoadPkcs12(sslKeys_t *keys, const unsigned char *certFile, return PS_ARG_FAIL; } pool = keys->pool; + PS_POOL_USED(pool); if (macPass == NULL) { mPass = (unsigned char*)importPass; @@ -432,77 +433,6 @@ int32 matrixSslLoadRsaKeys(sslKeys_t *keys, const char *certFile, /******************************************************************************/ #ifdef USE_ECC -/** - Generate and cache an ephemeral ECC key for later use in ECDHE key exchange. - @param[out] keys Keys structure to hold ephemeral keys - @param[in] curve ECC curve to generate key on, or NULL to generate for all - supported curves. - @param[in] hwCtx Context for hardware crypto. -*/ -int32_t matrixSslGenEphemeralEcKey(sslKeys_t *keys, psEccKey_t *ecc, - const psEccCurve_t *curve, void *hwCtx) -{ -#if ECC_EPHEMERAL_CACHE_USAGE > 0 - psTime_t t; -#endif - int32_t rc; - - psAssert(keys && curve); -#if ECC_EPHEMERAL_CACHE_USAGE > 0 - psGetTime(&t, keys->poolUserPtr); - (void)psLockMutex(&keys->cache.lock); - if (keys->cache.eccPrivKey.curve != curve) { - psTraceStrInfo("Generating ephemeral %s key (new curve)\n", - curve->name); - goto L_REGEN; - } - if (keys->cache.eccPrivKeyUse > ECC_EPHEMERAL_CACHE_USAGE) { - psTraceStrInfo("Generating ephemeral %s key (usage exceeded)\n", - curve->name); - goto L_REGEN; - } - if (psDiffMsecs(keys->cache.eccPrivKeyTime, t, keys->poolUserPtr) > - (1000 * ECC_EPHEMERAL_CACHE_SECONDS)) { - psTraceStrInfo("Generating ephemeral %s key (time exceeded)\n", - curve->name); - goto L_REGEN; - } - keys->cache.eccPrivKeyUse++; - rc = PS_SUCCESS; - if (ecc) { - rc = psEccCopyKey(ecc, &keys->cache.eccPrivKey); - } - (void)psUnlockMutex(&keys->cache.lock); - return rc; -L_REGEN: - if (keys->cache.eccPrivKeyUse) { - /* We use eccPrivKeyUse == 0 as a flag to note the key not allocated */ - psEccClearKey(&keys->cache.eccPrivKey); - keys->cache.eccPrivKeyUse = 0; - } - rc = psEccGenKey(keys->pool, &keys->cache.eccPrivKey, curve, hwCtx); - if (rc < 0) { - (void)psUnlockMutex(&keys->cache.lock); - return rc; - } - keys->cache.eccPrivKeyTime = t; - keys->cache.eccPrivKeyUse = 1; - rc = PS_SUCCESS; - if (ecc) { - rc = psEccCopyKey(ecc, &keys->cache.eccPrivKey); - } - (void)psUnlockMutex(&keys->cache.lock); - return rc; -#else - /* Not using ephemeral caching. */ - if (ecc) { - rc = psEccGenKey(keys->pool, ecc, curve, hwCtx); - return rc; - } - rc = PS_SUCCESS; - return rc; -#endif /* ECC_EPHEMERAL_CACHE_USAGE > 0 */ -} /******************************************************************************/ @@ -689,6 +619,77 @@ int32 matrixSslLoadEcKeysMem(sslKeys_t *keys, const unsigned char *certBuf, CAbuf, CAlen, PS_ECC); } +/** + Generate and cache an ephemeral ECC key for later use in ECDHE key exchange. + @param[out] keys Keys structure to hold ephemeral keys + @param[in] curve ECC curve to generate key on, or NULL to generate for all + supported curves. + @param[in] hwCtx Context for hardware crypto. +*/ +int32_t matrixSslGenEphemeralEcKey(sslKeys_t *keys, psEccKey_t *ecc, + const psEccCurve_t *curve, void *hwCtx) +{ +#if ECC_EPHEMERAL_CACHE_USAGE > 0 + psTime_t t; +#endif + int32_t rc; + + psAssert(keys && curve); +#if ECC_EPHEMERAL_CACHE_USAGE > 0 + psGetTime(&t, keys->poolUserPtr); + (void)psLockMutex(&keys->cache.lock); + if (keys->cache.eccPrivKey.curve != curve) { + psTraceStrInfo("Generating ephemeral %s key (new curve)\n", + curve->name); + goto L_REGEN; + } + if (keys->cache.eccPrivKeyUse > ECC_EPHEMERAL_CACHE_USAGE) { + psTraceStrInfo("Generating ephemeral %s key (usage exceeded)\n", + curve->name); + goto L_REGEN; + } + if (psDiffMsecs(keys->cache.eccPrivKeyTime, t, keys->poolUserPtr) > + (1000 * ECC_EPHEMERAL_CACHE_SECONDS)) { + psTraceStrInfo("Generating ephemeral %s key (time exceeded)\n", + curve->name); + goto L_REGEN; + } + keys->cache.eccPrivKeyUse++; + rc = PS_SUCCESS; + if (ecc) { + rc = psEccCopyKey(ecc, &keys->cache.eccPrivKey); + } + (void)psUnlockMutex(&keys->cache.lock); + return rc; +L_REGEN: + if (keys->cache.eccPrivKeyUse) { + /* We use eccPrivKeyUse == 0 as a flag to note the key not allocated */ + psEccClearKey(&keys->cache.eccPrivKey); + keys->cache.eccPrivKeyUse = 0; + } + rc = psEccGenKey(keys->pool, &keys->cache.eccPrivKey, curve, hwCtx); + if (rc < 0) { + (void)psUnlockMutex(&keys->cache.lock); + return rc; + } + keys->cache.eccPrivKeyTime = t; + keys->cache.eccPrivKeyUse = 1; + rc = PS_SUCCESS; + if (ecc) { + rc = psEccCopyKey(ecc, &keys->cache.eccPrivKey); + } + (void)psUnlockMutex(&keys->cache.lock); + return rc; +#else + /* Not using ephemeral caching. */ + if (ecc) { + rc = psEccGenKey(keys->pool, ecc, curve, hwCtx); + return rc; + } + rc = PS_SUCCESS; + return rc; +#endif /* ECC_EPHEMERAL_CACHE_USAGE > 0 */ +} #endif /* USE_ECC */ @@ -832,7 +833,8 @@ int32_t matrixSslLoadOCSPResponse(sslKeys_t *keys, return PS_ARG_FAIL; } pool = keys->pool; - + PS_POOL_USED(pool); + /* Overwrite/Update any response being set */ if (keys->OCSPResponseBuf != NULL) { psFree(keys->OCSPResponseBuf, pool); @@ -1082,7 +1084,6 @@ int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys, if (flags & SSL_FLAGS_SERVER) { #ifndef USE_PSK_CIPHER_SUITE if (keys == NULL) { - /* TODO: test not correct if coming from matrixSslNewServer */ psTraceInfo("NULL keys parameter passed to matrixSslNewSession\n"); return PS_ARG_FAIL; } diff --git a/matrixssl/matrixsslApi.c b/matrixssl/matrixsslApi.c index 127df96..3a7910a 100644 --- a/matrixssl/matrixsslApi.c +++ b/matrixssl/matrixsslApi.c @@ -1133,9 +1133,6 @@ int32 matrixSslProcessedData(ssl_t *ssl, unsigned char **ptbuf, uint32 *ptlen) if (ssl->flags & SSL_FLAGS_AEAD_R) { /* This overhead was removed from rec.len after the decryption to keep buffer logic working. */ - /* TODO: This is for checking async or not. If async, this length - tweak never happens. Need a more generic way to look for - blocking or not */ ctlen += AEAD_TAG_LEN(ssl) + AEAD_NONCE_LEN(ssl); } memmove(ssl->inbuf, ssl->inbuf + ctlen, ssl->inlen); diff --git a/matrixssl/matrixsslCheck.h b/matrixssl/matrixsslCheck.h index c2ba8a7..70edfe4 100644 --- a/matrixssl/matrixsslCheck.h +++ b/matrixssl/matrixsslCheck.h @@ -71,7 +71,7 @@ extern "C" { #error "USE_SHARED_SESSION_CACHE only implemented for POSIX platforms." #endif #ifndef USE_MULTITHREADING -#error "USE_MULTITHREADING required for USE_SHARED_MESSAGE_CACHE." +#error "USE_MULTITHREADING required for USE_SHARED_SESSION_CACHE." #endif #endif diff --git a/matrixssl/matrixssllib.h b/matrixssl/matrixssllib.h index fa7475c..0e0dd55 100644 --- a/matrixssl/matrixssllib.h +++ b/matrixssl/matrixssllib.h @@ -1678,10 +1678,19 @@ extern int32_t eccSuitesSupported(const ssl_t *ssl, #ifdef USE_MATRIXSSL_STATS extern void matrixsslUpdateStat(ssl_t *ssl, int32_t type, int32_t value); #else +#ifdef __GNUC__ +static __inline +void matrixsslUpdateStat(ssl_t *ssl __attribute__((__unused__)), + int32_t type __attribute__((__unused__)), + int32_t value __attribute__((__unused__))) +{ +} +#else static __inline void matrixsslUpdateStat(ssl_t *ssl, int32_t type, int32_t value) { } +#endif #endif /* USE_MATRIXSSL_STATS */ #ifdef __cplusplus diff --git a/matrixssl/opensslApi.c b/matrixssl/opensslApi.c deleted file mode 100644 index a2b02d7..0000000 --- a/matrixssl/opensslApi.c +++ /dev/null @@ -1,1608 +0,0 @@ -/** - * @file opensslApi.c - * @version $Format:%h%d$ - * - * An OpenSSL interface to MatrixSSL. - */ -/* - * 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 - */ -/******************************************************************************/ - -#include -#include -#include "matrixsslApi.h" - -#ifdef USE_MATRIX_OPENSSL_LAYER - - -/******************************************************************************/ -/* Always returns 1 */ -int SSL_library_init(void) -{ - eeTrace("Enter SSL_library_init\n"); - if (matrixSslOpen() < 0) { - psTraceInfo("Error opening MatrixSSL library via SSL_library_init\n"); - } - eeTrace("Exit SSL_library_init\n"); - return 1; -} - - - -/******************************************************************************/ -/* SSL is an sslConn_t of which SSL_CTX (ssl_t) is a member */ -SSL *SSL_new(SSL_CTX *ctx) -{ - SSL *cp; - eeTrace("Enter SSL_new\n"); - - if ((cp = psMalloc(MATRIX_NO_POOL, sizeof(SSL))) == NULL) { - psTraceInfo("Memory allocation error in SSL_new\n"); - return NULL; - } - memset(cp, 0x0, sizeof(SSL)); - - cp->ctx = ctx; - eeTrace("Exit SSL_new\n"); - return cp; -} - -/******************************************************************************/ -/* Counterpart to SSL_new */ -void SSL_free(SSL *cp) -{ - SSL_CTX *ctx; - eeTrace("Enter SSL_free\n"); - ctx = cp->ctx; - if (ctx->ssl) { - matrixSslDeleteSession(ctx->ssl); - ctx->ssl = NULL; - } - psFree(cp, MATRIX_NO_POOL); - memset(cp, 0x0, sizeof(SSL)); - eeTrace("Exit SSL_free\n"); -} - -/******************************************************************************/ -/* A SSL_CTX is an ssl_t */ -SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) -{ - SSL_CTX *ctx; - - eeTrace("Enter SSL_CTX_new\n"); - if ((ctx = psMalloc(MATRIX_NO_POOL, sizeof(SSL_CTX))) == NULL) { - psTraceInfo("Memory allocation error in SSL_CTX_new\n"); - return NULL; - } - memset(ctx, 0x0, sizeof(SSL_CTX)); - if (matrixSslNewKeys(&ctx->keys, NULL) < 0) { - psTraceInfo("matrixSslNewKeys error in SSL_CTX_new\n"); - psFree(ctx, MATRIX_NO_POOL); - return NULL; - } - eeTrace("Exit SSL_CTX_new\n"); - return ctx; -} - -/******************************************************************************/ -void SSL_CTX_free(SSL_CTX *ctx) -{ - eeTrace("Enter SSL_CTX_free\n"); - matrixSslDeleteKeys(ctx->keys); - if (ctx->ssl) { - psTraceInfo("ERROR: ssl_t session not deleted prior to SSL_CTX_free\n"); - } - psFree(ctx, MATRIX_NO_POOL); - eeTrace("Exit SSL_CTX_free\n"); -} - -/* SSL_CTX_set_options() and SSL_set_options() return the new options - bitmask after adding options. */ -long SSL_CTX_set_options(SSL_CTX *ctx, long options) -{ - uTrace("TODO: SSL_CTX_set_options\n"); - return options; -} - -/* SSL_CTX_set_cipher_list() and SSL_set_cipher_list() return 1 if any - cipher could be selected and 0 on complete failure. */ -int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) -{ - uTrace("TODO: SSL_CTX_set_cipher_list\n"); - return 1; -} - -/* SSL_CTX_load_verify_locations() specifies the locations for ctx, at which - CA certificates for verification purposes are located. The certificates - available via CAfile and CApath are trusted. -*/ -int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, - const char *CApath) -{ - uTrace("TODO: SSL_CTX_load_verify_locations\n"); - /* 0 on failure. 1 on success */ - return 0; -} - -/******************************************************************************/ -/* - 0 is failure. 1 is good -*/ -int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) -{ - uTrace("TODO: SSL_CTX_use_certificate_file\n"); - return 1; -} - -X509 *SSL_get_certificate(SSL *ssl) -{ - SSL_CTX *ctx = ssl->ctx; - - eeTrace("Enter SSL_get_certificate\n"); - if (ctx == NULL || ctx->keys == NULL) { - return NULL; - } - eeTrace("Exit SSL_get_certificate\n"); - return ctx->keys->cert; -} - -EVP_PKEY *X509_get_pubkey(X509 *cert) -{ - eeTrace("Enter X509_get_pubkey\n"); - eeTrace("Exit X509_get_pubkey\n"); - return &cert->publicKey; -} - -int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) -{ - uTrace("TODO: EVP_PKEY_copy_parameters\n"); - /* "returns 1 for success and 0 for failure." */ - return 0; -} - -EVP_PKEY *EVP_PKEY_new(void) -{ - psPubKey_t *pubKey; - eeTrace("Enter EVP_PKEY_new\n"); - eeTrace("Exit EVP_PKEY_new\n"); - if (psNewPubKey(NULL, PS_NONE, &pubKey) == PS_SUCCESS) { - return pubKey; - } else { - return NULL; - } -} - -void EVP_PKEY_free(EVP_PKEY *key) -{ - eeTrace("Enter EVP_PKEY_free\n"); - psClearPubKey(key); - psFree(key, NULL); - eeTrace("Exit EVP_PKEY_free\n"); -} - -EVP_PKEY *SSL_get_privatekey(SSL *ssl) -{ - SSL_CTX *ctx = ssl->ctx; - eeTrace("Enter SSL_get_privatekey\n"); - if (ctx == NULL || ctx->keys == NULL) { - return NULL; - } - eeTrace("Exit SSL_get_privatekey\n"); - return &ctx->keys->privKey; -} - -#ifdef USE_RSA -/******************************************************************************/ -/* - MADE THIS FUNCTION UP! - 0 is failure. 1 is good -*/ -int SSL_CTX_load_rsa_key_material(SSL_CTX *ctx, const char *cert, - const char *privkey, const char *CAfile) -{ -#ifdef MATRIX_USE_FILE_SYSTEM - eeTrace("Enter SSL_CTX_load_rsa_key_material\n"); - if (matrixSslLoadRsaKeys(ctx->keys, cert, privkey, NULL, CAfile) != 0) { - psTraceInfo("matrixSslLoadRsaKeys error in openssl module\n"); - return 0; - } - eeTrace("Exit SSL_CTX_load_rsa_key_material\n"); - return 1; -#else - uTrace("TODO: SSL_CTX_load_rsa_key_material\n"); - return 0; -#endif -} -#endif /* REQUIRE_RSA */ - -/******************************************************************************/ -/* FUTURE */ -int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) -{ - uTrace("TODO: SSL_CTX_use_PrivateKey_file\n"); - return 1; -} - -int SSL_CTX_check_private_key(const SSL_CTX *ctx) -{ - uTrace("TODO: SSL_CTX_check_private_key\n"); - return 1; -} - - -/******************************************************************************/ -/* FUTURE */ -void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, int (*pem_password_cb)(char*, - int, int, void*)) -{ - uTrace("TODO: SSL_CTX_set_default_passwd_cb\n"); -} - -/******************************************************************************/ -/* FUTURE */ -int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) -{ - uTrace("TODO: SSL_CTX_use_certificate_chain_file\n"); - return 1; -} - -void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, - int (*verify_callback)(int, X509_STORE_CTX *)) -{ - eeTrace("Enter SSL_CTX_set_verify\n"); - ctx->verify_callback = verify_callback; - eeTrace("Exit SSL_CTX_set_verify\n"); -} - -X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) -{ - eeTrace("Enter SSL_CTX_get_cert_store\n"); - if (ctx->keys == NULL) { - return NULL; - } - eeTrace("Exit SSL_CTX_get_cert_store\n"); - return ctx->keys->cert; -} - - -/******************************************************************************/ -void SSL_load_error_strings(void) -{ - uTrace("TODO: SSL_load_error_strings\n"); -} -/******************************************************************************/ -void *SSLv23_server_method(void) -{ - uTrace("TODO: SSLv23_server_method\n"); - return NULL; -} -/******************************************************************************/ -void *SSLv23_client_method(void) -{ - uTrace("TODO: SSLv23_client_method\n"); - return NULL; -} -void *SSLv2_client_method(void) -{ - uTrace("DEPRECATED\n"); - return NULL; -} -void *SSLv3_client_method(void) -{ - uTrace("TODO: SSLv3_client_method\n"); - return NULL; -} - -/******************************************************************************/ -int SSL_set_fd(SSL *cp, int fd) -{ - eeTrace("Enter SSL_set_fd\n"); - cp->fd = fd; - eeTrace("Exit SSL_set_fd\n"); - return 1; -} - -/******************************************************************************/ -/* - 1 - The TLS/SSL handshake was successfully completed, a TLS/SSL connection - has been established. - 0 - The TLS/SSL handshake was not successful but was shut down controlled - and by the specifications of the TLS/SSL protocol. Call SSL_get_error() - with the return value ret to find out the reason. - <0 - The TLS/SSL handshake was not successful, because a fatal error - occurred either at the protocol level or a connection failure occurred. - The shutdown was not clean. -*/ -int SSL_do_handshake(SSL *cp) -{ - int32 rc, transferred, len, done; - ssl_t *ssl; - unsigned char *buf; - - eeTrace("Enter SSL_do_handshake\n"); - -// BK HACK - printf("CHANGING SOCKET TO BLOCKING MODE\n"); - setSocketBlock(cp->fd); -// END BK HACK - - ssl = cp->ctx->ssl; - done = 0; - -WRITE_MORE: - while ((len = matrixSslGetOutdata(ssl, &buf)) > 0) { - transferred = socketWrite(cp->fd, buf, len); - if (transferred <= 0) { - psTraceInfo("Socket send failed... exiting\n"); - rc = transferred; - goto L_CLOSE_ERR; - } else { - /* Indicate that we've written > 0 bytes of data */ - if ((rc = matrixSslSentData(ssl, transferred)) < 0) { - goto L_CLOSE_ERR; - } - if (rc == MATRIXSSL_REQUEST_CLOSE) { - /* We've sent an alert that we are closing */ - eeTrace("Exit SSL_do_handshake 1\n"); - return 0; /* Controlled disconnect */ - } - if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { - /* Client - resumed handshake success - Server - standard handshake success */ - if (ssl->outlen > 0) { - /* Issue here is that SentData returns HANDSHAKE_COMPLETE - when any part of FINISHED message is sent. If this - was a partial send of the FINISHED message we'll need - another pass (or two) to send the remainder */ - done = 1; - } else { - eeTrace("Exit SSL_do_handshake 2\n"); - return 1; - } - } - if (rc == MATRIXSSL_SUCCESS && done == 1 && ssl->outlen == 0) { - eeTrace("Exit SSL_do_handshake 3\n"); - return 1; - } - /* SSL_REQUEST_SEND and SSL_SUCCESS are handled by loop logic */ - } - } -READ_MORE: - if ((len = matrixSslGetReadbuf(ssl, &buf)) <= 0) { - rc = len; - goto L_CLOSE_ERR; - } - if ((transferred = socketRead(cp->fd, buf, len)) < 0) { - psTraceInfo("Socket recv failed... exiting\n"); - rc = transferred; - goto L_CLOSE_ERR; - } - /* If EOF, remote socket closed */ - if (transferred == 0) { - rc = 0; /* Consider this a clean shutdown from client perspective */ - goto L_CLOSE_ERR; - } - if ((rc = matrixSslReceivedData(ssl, (int32)transferred, &buf, - (uint32*)&len)) < 0) { - psTraceInfo("matrixSslReceivedData failure... exiting\n"); - goto L_CLOSE_ERR; - } - -PROCESS_MORE: - switch (rc) { - case MATRIXSSL_HANDSHAKE_COMPLETE: - eeTrace("Exit SSL_do_handshake 4\n"); - return 1; /* Normal handshake success */ - case MATRIXSSL_APP_DATA: - if (!(ssl->flags & SSL_FLAGS_SERVER)) { - /* Client should never see any app data during connection */ - psTraceInfo("Got app data during handshake.. exiting\n"); - rc = PS_UNSUPPORTED_FAIL; - goto L_CLOSE_ERR; - } - /* Case of session resumption with immediate application data - tacked on the end of the client's FINISHED message */ - cp->resumedAppDataLen = len; - cp->appRecLen = len; -#ifdef USE_TLS_1_1 - if (ssl->flags & SSL_FLAGS_TLS_1_1) { - /* ReceivedData is giving good lengths and pointers of the - record itself but we need to add the explicit IV back - in beause we're processing this later */ - cp->outBufOffset = ssl->enBlockSize; - cp->resumedAppDataLen += ssl->enBlockSize; - cp->appRecLen += ssl->enBlockSize; - } -#endif - eeTrace("Exit SSL_do_handshake 5\n"); - return 1; - case MATRIXSSL_REQUEST_SEND: - goto WRITE_MORE; - case MATRIXSSL_REQUEST_RECV: - goto READ_MORE; - case MATRIXSSL_RECEIVED_ALERT: - /* The first byte of the buffer is the level */ - /* The second byte is the description */ - if (*buf == SSL_ALERT_LEVEL_FATAL) { - psTraceIntInfo("Fatal SSL alert: %d, closing connection\n", - *(buf + 1)); - rc = 0; /* Consider it a clean disconnect */ - goto L_CLOSE_ERR; - } - /* Closure alert is normal (and best) way to close */ - if (*(buf + 1) == SSL_ALERT_CLOSE_NOTIFY) { - rc = 0; /* A truly graceful disconnect */ - goto L_CLOSE_ERR; - } - psTraceIntInfo("Warning alert: %d\n", *(buf + 1)); - if ((rc = matrixSslProcessedData(ssl, &buf, (uint32*)&len)) == 0) { - /* No more data in buffer. Might as well read for more. */ - goto READ_MORE; - } - goto PROCESS_MORE; - default: - /* Will never be hit due to rc < 0 test at ReceivedData level */ - goto L_CLOSE_ERR; - } - -L_CLOSE_ERR: - matrixSslDeleteSession(ssl); - cp->ctx->ssl = NULL; - eeTrace("Exit SSL_do_handshake 6\n"); - return rc; -} - -#ifdef USE_SERVER_SIDE_SSL -/******************************************************************************/ -/* - Server side. Accept an incomming SSL connection request. -*/ -int32 SSL_accept(SSL *cp) -{ - ssl_t *ssl; - int32 rc; - sslSessOpts_t options; - - eeTrace("Enter SSL_accept\n"); - memset(&options, 0x0, sizeof(sslSessOpts_t)); -#ifdef USE_CLIENT_AUTH - if ((rc = matrixSslNewServerSession(&ssl, cp->ctx->keys, SSL_cert_auth, - &options)) < 0){ - psTraceIntInfo("matrixSslNewServerSession failed: %d\n", rc); - return rc; - } - ssl->verify_callback = cp->ctx->verify_callback; -#else - if ((rc = matrixSslNewServerSession(&ssl, cp->ctx->keys, NULL, &options)) - < 0){ - psTraceIntInfo("matrixSslNewServerSession failed: %d\n", rc); - return rc; - } -#endif - - cp->ctx->ssl = ssl; - rc = SSL_do_handshake(cp); - eeTrace("Exit SSL_accept\n"); - return rc; -} -#endif - - -#ifdef USE_CLIENT_SIDE_SSL -/******************************************************************************/ -/* - Client side SSL handshake - - OpenSSL return codes: - - 1 - The TLS/SSL handshake was successfully completed, a TLS/SSL connection - has been established. - 0 - The TLS/SSL handshake was not successful but was shut down controlled - and by the specifications of the TLS/SSL protocol. Call SSL_get_error() - with the return value ret to find out the reason. - <0 - The TLS/SSL handshake was not successful, because a fatal error - occurred either at the protocol level or a connection failure occurred. - The shutdown was not clean. -*/ -int32 SSL_connect(SSL *cp) -{ - int32 rc; - ssl_t *ssl; - sslSessOpts_t options; - - eeTrace("Enter SSL_connect\n"); - if (cp->ctx->ssl != NULL) { - if (matrixSslHandshakeIsComplete(cp->ctx->ssl)) { - if (matrixSslEncodeRehandshake(cp->ctx->ssl, NULL, NULL, 0, 0, 0) - < 0) { - psTraceInfo("matrixSslEncodeRehandshake failed\n"); - return -1; - } - } else { - psTraceInfo("ERROR: SSL_connect called on existing SSL\n"); - return -1; - } - } else { -/* HACK - If no keys yet, load some defaults */ - if (cp->ctx->keys->CAcerts == NULL) { - printf("YEAH, DIDN'T HAVE ANY CA CERTS\n"); - SSL_CTX_load_rsa_key_material(cp->ctx, NULL, NULL, - "testkeys/RSA/1024_RSA_CA.pem"); - } else { - printf("HMMMM... why do we have keys\n"); - } -/* END HACK */ - memset(&options, 0x0, sizeof(sslSessOpts_t)); - rc = matrixSslNewClientSession(&ssl, cp->ctx->keys, NULL, NULL, 0, - SSL_cert_auth, NULL, NULL, NULL, &options); - if (rc != MATRIXSSL_REQUEST_SEND) { - psTraceInfo("New client session failed... exiting\n"); - return 0; - } - cp->ctx->ssl = ssl; - } - - if ((rc = SSL_do_handshake(cp)) <= 0) { - cp->ctx->ssl = NULL; - } - eeTrace("Exit SSL_connect\n"); - return rc; - -} -#endif - -/******************************************************************************/ -/* - OpenSSL return codes - - >0 The read operation was successful; the return value is the number - of bytes actually read from the TLS/SSL connection. - - 0 The read operation was not successful. The reason may either be a clean - shutdown due to a ``close notify'' alert sent by the peer. It is also - possible, that the peer simply shut down the underlying transport and - the shutdown is incomplete. - - <0 The read operation was not successful, because either an error occurred - or action must be taken by the calling process. -*/ -int32 SSL_get_data(SSL *cp, unsigned char **ptBuf, int *ptBufLen) -{ - ssl_t *ssl; - unsigned char *ctBuf; - int32 readLen, rc; - int transferred; - - eeTrace("Enter SSL_get_data\n"); - ssl = cp->ctx->ssl; -/* - There are a few ways data might already be available to read for a - server here. They are triggered on whether there is any length for - incoming data. -*/ - if (ssl->inlen > 0) { - if (cp->resumedAppDataLen) { - /* This case is when a session resumption handshake takes place - and the client sends application data in the same flight as - the FINISHED message. In this case, the application data has - already been decrypted and is just waiting to be picked off */ - *ptBuf = ssl->inbuf; - *ptBufLen = ssl->inlen; - ssl->inlen = 0; - cp->resumedAppDataLen = 0; - eeTrace("Exit SSL_get_data 1\n"); - return *ptBufLen; - } else if (ssl->fragTotal) { - goto READ_MORE; /* ALLOW_STREAMING_APP_DATA_DECRYPT */ - } else { - /* This case is the Chrome false start where application data has - been sent in the middle of the handshake. MatrixSSL has not - yet decrypted the data in this case so we do that now. */ - rc = matrixSslReceivedData(ssl, 0, ptBuf, (uint32*)ptBufLen); - goto PROCESS_MORE; - } - } - -READ_MORE: - if ((readLen = matrixSslGetReadbuf(ssl, &ctBuf)) <= 0) { - return readLen; - } - if ((transferred = socketRead(cp->fd, ctBuf, readLen)) < 0) { - psTraceInfo("Socket recv failed... exiting\n"); - return transferred; - } - /* If EOF, remote socket closed */ - if (transferred == 0) { - psTraceInfo("Server disconnected\n"); - eeTrace("Exit SSL_get_data 2\n"); - return 0; /* Consider this a clean shutdown from client perspective */ - } - if ((rc = matrixSslReceivedData(ssl, (int32)transferred, ptBuf, - (uint32*)ptBufLen)) < 0) { - psTraceInfo("matrixSslReceivedData failure... exiting\n"); - return rc; - } - -PROCESS_MORE: - switch (rc) { - case MATRIXSSL_APP_DATA: - if (*ptBufLen == 0) { - /* Eat any zero length records that come across. OpenSSL server - is likely sending some */ - rc = matrixSslProcessedData(ssl, ptBuf, (uint32*)ptBufLen); - goto PROCESS_MORE; - } - eeTrace("Exit SSL_get_data 3\n"); - return *ptBufLen; - case MATRIXSSL_REQUEST_SEND: - SSL_do_handshake(cp); - psTraceInfo("Peer requested a re-handshake\n"); - goto READ_MORE; - case MATRIXSSL_REQUEST_RECV: - goto READ_MORE; - case MATRIXSSL_RECEIVED_ALERT: - /* The first byte of the buffer is the level */ - /* The second byte is the description */ - if (**ptBuf == SSL_ALERT_LEVEL_FATAL) { - psTraceIntInfo("Fatal SSL alert: %d, closing connection\n", - *(*ptBuf + 1)); - eeTrace("Exit SSL_get_data 4\n"); - return 0; /* Actually a clean disconnect */ - } - /* Closure alert is normal (and best) way to close */ - if (*(*ptBuf + 1) == SSL_ALERT_CLOSE_NOTIFY) { - eeTrace("Exit SSL_get_data 5\n"); - return 0; /* Graceful disconnect */ - } - psTraceIntInfo("Warning alert: %d\n", *(*ptBuf + 1)); - if ((rc = matrixSslProcessedData(ssl, ptBuf, (uint32*)ptBufLen)) - == 0) { - /* No more data in buffer. Might as well read for more. */ - goto READ_MORE; - } - goto PROCESS_MORE; - default: - /* MATRIXSSL_HANDSHAKE_COMPLETE */ - /* Will never be hit due to rc < 0 test at ReceivedData level */ - return -1; - } - - eeTrace("Exit SSL_get_data 6\n"); - return -1; /* How to get here? */ -} - -/******************************************************************************/ -/* Not an OpenSSL function */ -/* TODO: return codes. <0 is failure */ -int SSL_processed_data(SSL *cp, unsigned char **ptBuf, int *ptBufLen) -{ - int32 rc; - - eeTrace("Enter SSL_processed_data\n"); - rc = matrixSslProcessedData(cp->ctx->ssl, ptBuf, (uint32*)ptBufLen); - -PROCESS_MORE: - /* MATRIXSSL_SUCCESS or MATRIXSSL_APP_DATA are expected */ - if (rc == MATRIXSSL_RECEIVED_ALERT) { - if (*(*ptBuf + 1) == SSL_ALERT_CLOSE_NOTIFY) { - psTraceInfo("Received close_notify alert from server\n"); - } else { - psTraceInfo("Received unexpected alert from server\n"); - } - rc = matrixSslProcessedData(cp->ctx->ssl, ptBuf, (uint32*)ptBufLen); - goto PROCESS_MORE; - } else if (rc == MATRIXSSL_REQUEST_RECV) { - if (SSL_get_data(cp, ptBuf, ptBufLen) <= 0) { - psTraceInfo("Unable to get next record\n"); - return PS_FAILURE; - } - if (ptBuf == NULL) { - /* always expecting a full record out of here */ - psTraceInfo("Is this a possible case??\n"); - } - } else if (rc != MATRIXSSL_SUCCESS && rc != MATRIXSSL_APP_DATA) { - psTraceIntInfo("!!!!!! Handle this case %d !!!!!! \n", rc); - return PS_UNSUPPORTED_FAIL; - } - eeTrace("Exit SSL_processed_data\n"); - return *ptBufLen; -} - -/* Test if SSL_read has buffered data */ -int SSL_pending(const SSL *ssl) -{ - eeTrace("Enter SSL_pending\n"); - /* Three places data could be waiting */ - /* Anything in the ssl_t inlen means there is data */ - if (ssl->ctx->ssl->inlen > 0) { - eeTrace("Exit SSL_pending 1\n"); - return ssl->ctx->ssl->inlen; - } - /* Corner case of app data following a FINISHED message that doesn't - get pulled out in SSL_do_handshake */ - if (ssl->resumedAppDataLen > 0) { - eeTrace("Exit SSL_pending 2\n"); - return ssl->resumedAppDataLen; - } - /* Partial record still sitting in inbuf */ - eeTrace("Exit SSL_pending 3\n"); - return ssl->appRecLen - ssl->outBufOffset; -} - -/******************************************************************************/ -/* - OpenSSL return codes - - >0 The read operation was successful; the return value is the number - of bytes actually read from the TLS/SSL connection. - - 0 The read operation was not successful. The reason may either be a clean - shutdown due to a ``close notify'' alert sent by the peer. It is also - possible, that the peer simply shut down the underlying transport and - the shutdown is incomplete. - - <0 The read operation was not successful, because either an error occurred - or action must be taken by the calling process. -*/ -int32 SSL_read(SSL *cp, void *userBufPtr, int userBufLen) -{ - ssl_t *ssl; - unsigned char *readBuf, *ptBuf, *userBuf; - int32 readLen, leftover, bytes, rc; - uint32 nextRecLen, ptBufLen; - int transferred; - - eeTrace("Enter SSL_read\n"); - ssl = cp->ctx->ssl; - userBuf = (unsigned char*)userBufPtr; - -/* - There are a few ways data might already be available to read for a - server here. Two are triggered on whether there is any length for - incoming data. -*/ - if (ssl->inlen > 0) { - if (cp->resumedAppDataLen) { - /* This case is when a session resumption handshake takes place - and the client sends application data in the same flight as - the FINISHED message. In this case, the application data has - already been decrypted and is just waiting to be picked off. - The ssl->inlen > 0 indicates the is also more unencrypted - data after this decrypted record. Seen to happen in TLS 1.0 - when 1 byte BEAST workaround record is sent */ - cp->appRecLen = cp->resumedAppDataLen; - cp->outBufOffset = 0; - cp->resumedAppDataLen = 0; - } else { - /* This case is the Chrome false start where application data has - been sent in the middle of the handshake. MatrixSSL has not - yet decrypted the data in this case so we do that now. */ - rc = matrixSslReceivedData(ssl, 0, &ptBuf, &ptBufLen); - goto PROCESS_MORE; - } - } - -/* - Always send any remainder first -*/ - leftover = cp->appRecLen - cp->outBufOffset; - if (leftover > 0) { - bytes = (int32)min(userBufLen, leftover); - memcpy(userBuf, ssl->inbuf + cp->outBufOffset, bytes); - cp->outBufOffset += bytes; - if (cp->outBufOffset == cp->appRecLen) { - cp->outBufOffset = cp->appRecLen = 0; - SSL_processed_data(cp, &ptBuf, (int*)&ptBufLen); - if (ptBufLen > 0) { - /* Make this the next 'leftover' */ - cp->appRecLen = ptBufLen; - } - } - eeTrace("Exit SSL_read 1\n"); - return bytes; - } - - -READ_MORE: - if ((readLen = matrixSslGetReadbuf(ssl, &readBuf)) <= 0) { - return readLen; - } - if ((transferred = socketRead(cp->fd, readBuf, readLen)) < 0) { - psTraceInfo("Socket recv failed... exiting\n"); - return transferred; - } - /* If EOF, remote socket closed */ - if (transferred == 0) { - psTraceInfo("Server disconnected\n"); - eeTrace("Exit SSL_read 2\n"); - return 0; /* Consider this a clean shutdown from client perspective */ - } - if ((rc = matrixSslReceivedData(ssl, (int32)transferred, &ptBuf, - &ptBufLen)) < 0) { - psTraceInfo("matrixSslReceivedData failure... exiting\n"); - return rc; - } - -PROCESS_MORE: - switch (rc) { - case MATRIXSSL_APP_DATA: - - if (ptBufLen == 0) { - /* Eat any zero length records that come across. OpenSSL server - is likely sending some */ - rc = matrixSslProcessedData(ssl, &ptBuf, &ptBufLen); - goto PROCESS_MORE; - } - /* Always a full app data record here but need to know if user - can accept the whole thing in one pass */ - if (ptBufLen <= userBufLen) { - memcpy(userBuf, ptBuf, ptBufLen); - /* Have a full record so update that it's processed */ - SSL_processed_data(cp, &ptBuf, (int*)&nextRecLen); - if (nextRecLen > 0) { - cp->appRecLen = nextRecLen; - } - eeTrace("Exit SSL_read 3\n"); - return ptBufLen; - } else { - cp->appRecLen = ptBufLen; - memcpy(userBuf, ptBuf, userBufLen); - cp->outBufOffset += userBufLen; - eeTrace("Exit SSL_read 4\n"); - return userBufLen; - } - case MATRIXSSL_REQUEST_SEND: - /* If the library is telling us there is data to send, this must - be a re-handshake. (this could also be an alert that is being - sent but SSL_do_handshake will handle this scenario as well) */ - if (SSL_do_handshake(cp) <= 0) { - return -1; - } - goto READ_MORE; - case MATRIXSSL_REQUEST_RECV: - goto READ_MORE; - case MATRIXSSL_RECEIVED_ALERT: - /* The first byte of the buffer is the level */ - /* The second byte is the description */ - if (*ptBuf == SSL_ALERT_LEVEL_FATAL) { - psTraceIntInfo("Fatal SSL alert: %d, closing connection\n", - *(ptBuf + 1)); - eeTrace("Exit SSL_read 5\n"); - return 0; /* Actually a clean disconnect */ - } - /* Closure alert is normal (and best) way to close */ - if (*(ptBuf + 1) == SSL_ALERT_CLOSE_NOTIFY) { - eeTrace("Exit SSL_read 6\n"); - return 0; /* Graceful disconnect */ - } - psTraceIntInfo("Warning alert: %d\n", *(ptBuf + 1)); - if ((rc = matrixSslProcessedData(ssl, &ptBuf, &ptBufLen)) == 0){ - /* No more data in buffer. Might as well read for more. */ - goto READ_MORE; - } - goto PROCESS_MORE; - default: - /* MATRIXSSL_HANDSHAKE_COMPLETE */ - /* Will never be hit due to rc < 0 test at ReceivedData level */ - return -1; - } - - eeTrace("Exit SSL_read 7\n"); - return -1; /* How to get here? */ -} - - -/******************************************************************************/ -/* - OpenSSL return codes - - >0 The write operation was successful, the return value is the number of - bytes actually written to the TLS/SSL connection. - 0 The write operation was not successful. Probably the underlying - connection was closed - <0 The write operation was not successful, because either an error - occurred or action must be taken by the calling process. -*/ -int32 SSL_write(SSL *cp, const void *inbufPtr, int32 inlen) -{ - ssl_t *ssl; - unsigned char *buf; - int transferred; - const char *inbuf; - int32 len, bytesSent = 0; - - eeTrace("Enter SSL_write\n"); - inbuf = (char*)inbufPtr; - ssl = cp->ctx->ssl; - - if (inbuf != NULL) { /* A NULL inbuf means internal buffer needs to flush */ - /* Test if inbuf falls without our buffer to determine - what option they have choosen */ - if (((int32)inbuf >= (int32)ssl->outbuf) && - ((int32)inbuf < (int32)(ssl->outbuf + ssl->outsize))) { - matrixSslEncodeWritebuf(ssl, inlen); - - } else { - matrixSslEncodeToOutdata(ssl, (unsigned char*)inbuf, inlen); - } - } - - while ((len = matrixSslGetOutdata(ssl, &buf)) > 0) { - transferred = socketWrite(cp->fd, buf, len); - if (transferred <= 0) { - psTraceInfo("Socket send failed... exiting\n"); - return transferred; - } else { - bytesSent += transferred; - /* Indicate that we've written > 0 bytes of data */ - if (matrixSslSentData(ssl, transferred) < 0) { - return -1; - } - /* SSL_REQUEST_SEND and SSL_SUCCESS are handled by loop logic */ - } - } - eeTrace("Exit SSL_write\n"); - return bytesSent; -} - - -/******************************************************************************/ -/* - Send a CLOSE_NOTIFY alert and delete a session that was opened with - SSL_accept or SSL_connect -*/ -void SSL_shutdown(SSL *cp) -{ - ssl_t *ssl; - unsigned char *buf; - int32 len; - - eeTrace("Enter SSL_shutdown\n"); - ssl = cp->ctx->ssl; - - if ((ssl != NULL) && (cp->fd > 0)) { - - setSocketNonblock(cp->fd); - /* Quick attempt to send a closure alert, don't worry about failure */ - if (matrixSslEncodeClosureAlert(ssl) >= 0) { - if ((len = matrixSslGetOutdata(ssl, &buf)) > 0) { - if ((len = socketWrite(cp->fd, buf, len)) > 0) { - matrixSslSentData(ssl, len); - } - } - } - matrixSslDeleteSession(ssl); - cp->ctx->ssl = NULL; - } - cp->fd = 0; - eeTrace("Exit SSL_shutdown\n"); -} - -/* "SSL_peek - Copy the data in the SSL buffer into the buffer - passed to this API" */ -int SSL_peek(SSL *s, void *buf, int num) -{ - uTrace("TODO: SSL_peek\n"); - return 0; -} - -/* "SSL_set_connect_state() sets ssl to work in client mode. - - SSL_set_accept_state() sets ssl to work in server mode." */ -void SSL_set_connect_state(SSL *ssl) -{ - uTrace("TODO: SSL_set_connect_state\n"); - return; -} - -/* SSL_set_session() sets session to be used when the TLS/SSL connection is - to be established. SSL_set_session() is only useful for TLS/SSL clients. - When the session is set, the reference count of session is incremented by - 1. If the session is not reused, the reference count is decremented again - during SSL_connect(). Whether the session was reused can be queried with - the SSL_session_reused call. - - If there is already a session set inside ssl (because it was set with - SSL_set_session() before or because the same ssl was already used for a - connection), SSL_SESSION_free() will be called for that session. */ -int SSL_set_session(SSL *ssl, SSL_SESSION *session) -{ - uTrace("TODO: SSL_set_session\n"); - /* 0 is failure. 1 is success */ - return 1; -} - -void SSL_SESSION_free(SSL_SESSION *session) -{ - uTrace("TODO: SSL_SESSION_free\n"); - return; -} - -SSL_SESSION *SSL_get_session(const SSL *ssl) -{ - eeTrace("Enter SSL_get_session\n"); - eeTrace("Exit SSL_get_session\n"); - return ssl; -} - -SSL_CIPHER *SSL_get_cipher(const SSL *ssl) -{ - ssl_t *lssl = ssl->ctx->ssl; - eeTrace("Enter SSL_get_cipher\n"); - if (lssl == NULL) { - return NULL; - } - eeTrace("Exit SSL_get_cipher\n"); - return lssl->cipher; -} - -X509 *SSL_get_peer_cert_chain(const SSL *s) -{ - ssl_t *lssl = s->ctx->ssl; - eeTrace("Enter SSL_get_peer_cert_chain\n"); - if (lssl == NULL) { - return NULL; - } - eeTrace("Exit SSL_get_peer_cert_chain\n"); - return lssl->sec.cert; -} - -X509 *SSL_get_peer_certificate(const SSL *s) -{ - ssl_t *lssl = s->ctx->ssl; - eeTrace("Enter SSL_get_peer_certificate\n"); - if (lssl == NULL) { - return NULL; - } - eeTrace("Exit SSL_get_peer_certificate\n"); - return lssl->sec.cert; -} - -/* SSL_get_verify_result() returns the result of the verification of the X509 - certificate presented by the peer, if any. */ -long SSL_get_verify_result(const SSL *ssl) -{ - ssl_t *lssl = ssl->ctx->ssl; - eeTrace("Enter SSL_get_verify_result\n"); - - /* X509_V_OK if verification succeeded or no peer cert presented */ - - eeTrace("Exit SSL_get_verify_result\n"); - return lssl->sec.cert->authStatus; -} - -/* X509_verify_cert_error_string() returns a human readable error string for - verification error n. */ -const char *X509_verify_cert_error_string(long n) -{ - /* Return string of authStatus (n) */ - uTrace("TODO: X509_verify_cert_error_string\n"); - return NULL; -} - -int SSL_version(SSL *ssl) -{ - ssl_t *lssl = ssl->ctx->ssl; - eeTrace("Enter SSL_version\n"); - eeTrace("Exit SSL_version\n"); - if (lssl->minVer == SSL3_MIN_VER) { - return SSL3_VERSION; - } else if (lssl->minVer == TLS_MIN_VER) { - return TLS1_VERSION; - } else if (lssl->minVer == TLS_1_1_MIN_VER) { - return TLS1_1_VERSION; - } else if (lssl->minVer == TLS_1_2_MIN_VER) { - return TLS1_2_VERSION; - } else { - return SSL2_VERSION; - } - -} -/******************************************************************************/ -/* - MatrixSSL err - - "SSL_get_error() returns a result code (suitable for the C "switch" - statement) for a preceding call to SSL_connect(), SSL_accept(), - SSL_do_handshake(), SSL_read(), SSL_peek(), or SSL_write() on ssl. The - value returned by that TLS/SSL I/O function must be passed to - SSL_get_error() in parameter ret. - - In addition to ssl and ret, SSL_get_error() inspects the current thread's - OpenSSL error queue. Thus, SSL_get_error() must be used in the same thread - that performed the TLS/SSL I/O operation, and no other OpenSSL function - calls should appear in between. The current thread's error queue must be - empty before the TLS/SSL I/O operation is attempted, or SSL_get_error() - will not work reliably." - - These are what callers will be expecting!! - - #define SSL_ERROR_NONE 0 - #define SSL_ERROR_SSL 1 - #define SSL_ERROR_WANT_READ 2 - #define SSL_ERROR_WANT_WRITE 3 - #define SSL_ERROR_WANT_X509_LOOKUP 4 - #define SSL_ERROR_SYSCALL 5 - #define SSL_ERROR_ZERO_RETURN 6 - #define SSL_ERROR_WANT_CONNECT 7 - #define SSL_ERROR_WANT_ACCEPT 8 -*/ -int SSL_get_error(const SSL *cp, int ret) -{ - eeTrace("Enter SSL_get_error\n"); - if (cp->ctx->ssl) { - eeTrace("Exit SSL_get_error\n"); - return cp->ctx->ssl->err; - } - return 0; -} - - -/* Invoke the users registered callback if exists */ -int32 SSL_cert_auth(ssl_t *ssl, psX509Cert_t *cert, int32 alert) -{ - eeTrace("Enter SSL_cert_auth\n"); - if (ssl->verify_callback) { - alert = ssl->verify_callback(alert, cert); - } - eeTrace("Exit SSL_cert_auth\n"); - - printf("HARD CODE SUCCESS RETURN FROM CERT CBACK\n"); - return 0; - //return alert; -} - - -/******************************************************************************/ -/* Mongoose web server wants */ - -int CRYPTO_num_locks(void) -{ - uTrace("TODO: CRYPTO_num_locks\n"); - return 1; -} - -void CRYPTO_set_locking_callback(void (*cb)(int, int, const char *, int)) -{ - uTrace("TODO: CRYPTO_set_locking_callback\n"); -} - -extern void CRYPTO_set_id_callback(unsigned long (*cb)(void)) -{ - uTrace("TODO: CRYPTO_set_id_callback\n"); -} - -unsigned long ERR_get_error(void) -{ - uTrace("TODO: ERR_get_error\n"); - return 0; -} - -char *ERR_error_string(unsigned long x, char *y) -{ - uTrace("TODO: ERR_error_string\n"); - return "unimplemented"; -} -/* End Mongoose */ - -void ERR_free_strings(void) -{ - uTrace("TODO: ERR_free_strings\n"); - return; -} - -void ERR_remove_state(unsigned long pid) -{ - uTrace("TODO: ERR_remove_state\n"); - return; -} - -void ERR_clear_error(void) -{ - uTrace("TODO: ERR_clear_error\n"); - return; -} - -unsigned long ERR_peek_error(void) -{ - uTrace("TODO: ERR_peek_error\n"); - return 0; -} - -/******************************************************************************/ -/* cURL wants */ - -/* Uses 'max_bytes' from the file to add to the PRNG. There is no context - parameter here so we'd need to create a global one if this family of - APIs are implemented. It looks like maybe RAND_set_rand_engine could be - used as an initialization point, but it looks like there is also a default - RAND engine so couldn't rely on that necessarily */ -int RAND_load_file(const char *filename, long max_bytes) -{ - uTrace("TODO: RAND_load_file\n"); - return (int)max_bytes; -} - -void RAND_add(const void *buf, int num, int entropy) -{ - uTrace("TODO: RAND_add\n"); -} - -/* "generates a default path for the random seed file. buf points to a buffer - of size num in which to store the filename. The seed file is $RANDFILE if - that environment variable is set, $HOME/.rnd otherwise. If $HOME is not - set either, or num is too small for the path name, an error occurs. */ -const char *RAND_file_name(char *buf, size_t num) -{ - uTrace("TODO: RAND_file_name\n"); - return NULL; -} - -int RAND_status(void) -{ - uTrace("TODO: RAND_status\n"); - return 1; -} - -int RAND_bytes(unsigned char *buf, int num) -{ - int rc; - eeTrace("Enter RAND_bytes\n"); - rc = (int)psGetEntropy(buf, (int)num, NULL); - eeTrace("Exit RAND_bytes\n"); - return rc; -} - -/* - typedef struct { - sslBuf_t *buf; - int type; - } BIO_METHOD; - - typedef struct { - BIO_METHOD *method; - } BIO; -*/ - -BIO *BIO_new(BIO_METHOD *type) -{ - BIO *new; - - eeTrace("Enter BIO_new\n"); - new = psMalloc(NULL, sizeof(BIO)); - if (new == NULL) { - return NULL; - } - new->method = type; - eeTrace("Exit BIO_new\n"); - return new; -} - -int BIO_free(BIO *a) -{ - BIO_METHOD *method; - - eeTrace("Enter BIO_free\n"); - if (a == NULL) { - return 0; - } - method = a->method; - if (method->buf) { - if (method->buf->buf) { - psFree(method->buf->buf, NULL); - } - psFree(method->buf, NULL); - } - psFree(method, NULL); - memset_s(method, sizeof(BIO), 0x0, sizeof(BIO_METHOD)); - - psFree(a, NULL); - eeTrace("Exit BIO_free\n"); - return 1; -} - -BIO_METHOD *BIO_s_mem(void) -{ - BIO_METHOD *new; - psBuf_t *buf; - - eeTrace("Enter BIO_s_mem\n"); - - new = psMalloc(NULL, sizeof(BIO_METHOD)); - if (new == NULL) { - return NULL; - } - buf = psMalloc(NULL, sizeof(psBuf_t)); - if (buf == NULL) { - psFree(new, NULL); - return NULL; - } - buf->start = buf->end = buf->buf = psMalloc(NULL, DEFAULT_BIO_BUF_LEN); - if (buf->start == NULL) { - psFree(new, NULL); - psFree(buf, NULL); - return NULL; - } - buf->size = DEFAULT_BIO_BUF_LEN; - - new->type = BIO_S_MEM_TYPE; - new->buf = buf; - eeTrace("Exit BIO_s_mem\n"); - return new; -} - - -void BIO_get_mem_ptr(BIO *b, BUF_MEM **pp) -{ - eeTrace("Enter BIO_get_mem_ptr\n"); - *pp = NULL; - if (b == NULL) { - return; - } - (*pp)->data = b->method->buf->start; - (*pp)->length = (b->method->buf->end - b->method->buf->start); - eeTrace("Exit BIO_get_mem_ptr\n"); -} - -int PEM_write_bio_X509(BIO *bp, X509 *x) -{ - /* Copy x.509 to BIO */ - uTrace("TODO: PEM_write_bio_X509\n"); - return 0; -} - -int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags) -{ - /* Copy x.509 name to BIO */ - uTrace("TODO: X509_NAME_print_ex\n"); - return 0; -} - -X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) -{ - eeTrace("Enter X509_STORE_CTX_get_current_cert\n"); - eeTrace("Exit X509_STORE_CTX_get_current_cert\n"); - return ctx; -} - -X509_NAME * X509_get_subject_name(X509 *a) -{ - eeTrace("Enter X509_get_subject_name\n"); - eeTrace("Exit X509_get_subject_name\n"); - return &a->subject; -} - -char * X509_NAME_oneline(X509_NAME *a,char *buf,int size) -{ - uTrace("TODO: X509_NAME_oneline\n"); - return NULL; -} - -int sk_X509_num(X509 *certs) -{ - eeTrace("Enter sk_X509_num\n"); - X509 *next = certs; - int i = 1; - - while (next->next) { - i++; - next = next->next; - } - eeTrace("Exit sk_X509_num\n"); - return i; -} - -X509 *sk_X509_value(X509 *cert, int i) -{ - X509 *cur = cert; - - eeTrace("Enter sk_X509_value\n"); - /* TODO: this is using a zero based count */ - while (i > 0) { - cur = cur->next; - i++; - } - eeTrace("Exit sk_X509_value\n"); - return cur; -} - -/* Related to STACK_OF. Our extension structure isn't a list. It's just - one big struct that holds all the ones we care about */ -int sk_X509_EXTENSION_num(X509_EXTENSION *ext) -{ - uTrace("TODO: sk_X509_EXTENSION_num\n"); - return 1; /* Never a list */ -} - -X509_EXTENSION *sk_X509_EXTENSION_value(X509_EXTENSION *ext, int i) -{ - uTrace("TODO: sk_X509_EXTENSION_value\n"); - return ext; -} - -ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex) -{ - /* Hmm... how would we map our current extension to an "object" */ - uTrace("TODO: X509_EXTENSION_get_object\n"); - return NULL; -} - -int X509_EXTENSION_get_critical(X509_EXTENSION *ex) -{ - eeTrace("Enter X509_EXTENSION_get_critical\n"); - eeTrace("Exit X509_EXTENSION_get_critical\n"); - return ex->critFlags; -} - -int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, - int indent) -{ - uTrace("TODO: X509V3_EXT_print\n"); - return 0; -} - -/********/ -void OPENSSL_load_builtin_modules(void) -{ - uTrace("TODO: OPENSSL_load_builtin_modules\n"); - return; -} - - -int CONF_modules_load_file(const char *filename, const char *appname, - unsigned long flags) -{ - psTraceInfo("There is no configuration file for MatrixSSL\n"); - return 0; -} - -void EVP_cleanup(void) -{ - uTrace("TODO: EVP_cleanup\n"); - return; -} - -void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx) -{ - uTrace("TODO: X509_get_ext_d2i\n"); - return NULL; -} - -/* X509_NAME_get_index_by_NID() and X509_NAME_get_index_by_OBJ() retrieve the - next index matching nid or obj after lastpos. lastpos should initially be - set to -1. If there are no more entries -1 is returned. */ -int X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos) -{ - /* NID_commonName is nid */ - uTrace("TODO: X509_NAME_get_index_by_NID\n"); - return 0; -} - -X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc) -{ - uTrace("TODO: X509_NAME_get_entry\n"); - return NULL; -} - -ASN1_STRING * X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne) -{ - uTrace("TODO: X509_NAME_ENTRY_get_data\n"); - return NULL; -} - -X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) -{ - uTrace("TODO: X509_STORE_add_lookup\n"); - return NULL; -} - -X509_LOOKUP_METHOD *X509_LOOKUP_file(void) -{ - uTrace("TODO: X509_LOOKUP_file\n"); - return NULL; -} - -int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) -{ - uTrace("TODO: X509_STORE_set_flags\n"); - return 0; -} - -int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) -{ - uTrace("TODO: X509_load_crl_file\n"); - return 0; -} - - -void GENERAL_NAMES_free(GENERAL_NAME *name) -{ - uTrace("TODO: GENERAL_NAMES_free\n"); - return; -} - -const GENERAL_NAME *sk_GENERAL_NAME_value(GENERAL_NAME *altnames, int i) -{ - uTrace("TODO: sk_GENERAL_NAME_value\n"); - return NULL; -} - -int sk_GENERAL_NAME_num(GENERAL_NAME *names) -{ - uTrace("TODO: sk_GENERAL_NAME_num\n"); - return 0; -} - -unsigned char * ASN1_STRING_data(ASN1_STRING *x) -{ - eeTrace("Enter ASN1_STRING_data\n"); - eeTrace("Exit ASN1_STRING_data\n"); - return x->data; -} - -size_t ASN1_STRING_length(ASN1_STRING *x) -{ - eeTrace("Enter ASN1_STRING_length\n"); - eeTrace("Exit ASN1_STRING_length\n"); - return x->length; -} - -int ASN1_STRING_type(ASN1_STRING *x) -{ - eeTrace("Enter ASN1_STRING_type\n"); - eeTrace("Exit ASN1_STRING_type\n"); - return x->type; -} - -int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in) -{ - eeTrace("Enter ASN1_STRING_to_UTF8\n"); - eeTrace("Exit ASN1_STRING_to_UTF8\n"); - *out = in->data; - return 0; -} - -int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) -{ - uTrace("TODO: ASN1_STRING_print\n"); - return 0; -} - -/* i2t_ASN1_OBJECT tries to find the LN (long name) associated with the - ASN1_OBJECT a and puts it in the buffer buf, or up to buf_len bytes of it, - at any rate. If no LN can be found, then the OID (a->data) is written out - into buf instead, in "##.##.##" format, where the ## are digits. If there - is room, the string written into buf is null-termnated. The number of - bytes written into buf is returned. */ -int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a) -{ - uTrace("TODO: i2t_ASN1_OBJECT\n"); - memcpy(buf, a, buf_len); - return buf_len; -} - -#endif /* USE_MATRIX_OPENSSL_LAYER */ diff --git a/matrixssl/opensslApi.h b/matrixssl/opensslApi.h deleted file mode 100644 index 5d8d6db..0000000 --- a/matrixssl/opensslApi.h +++ /dev/null @@ -1,399 +0,0 @@ -/** - * @file opensslApi.h - * @version $Format:%h%d$ - * - * An OpenSSL interface to MatrixSSL. - */ -/* - * 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_SSLAPI -#define _h_SSLAPI - -#ifdef __cplusplus -extern "C" { -#endif - -#include "opensslSocket.h" - -#ifdef USE_MATRIX_OPENSSL_LAYER - -#define ENABLE_ENTRY_EXIT_TRACE -#define ENABLE_UNIMPLEMENTED_TRACE - -#ifdef ENABLE_ENTRY_EXIT_TRACE -#define eeTrace _psTrace -#else -#define eeTrace -#endif - -#ifdef ENABLE_UNIMPLEMENTED_TRACE -#define uTrace _psTrace -#else -#define uTrace -#endif - - -typedef psX509Cert_t X509_STORE_CTX; -typedef psX509Cert_t X509_STORE; -typedef psX509Cert_t X509; -typedef x509DNattributes_t X509_NAME; -typedef psPubKey_t EVP_PKEY; -typedef void X509_LOOKUP; -typedef x509v3extensions_t X509_EXTENSION; - -/* Lookup CRLs */ -#define X509_V_FLAG_CRL_CHECK 0x4 -/* Lookup CRLs for whole chain */ -#define X509_V_FLAG_CRL_CHECK_ALL 0x8 - -typedef struct { - sslCertCb_t method; -} X509_LOOKUP_METHOD; - -typedef struct { - psX509Cert_t *cert_info; -} X509_CINF; /* cert info */ - -#define X509_FILETYPE_PEM 1 -#define X509_V_OK 0 - -typedef struct { - sslKeys_t *keys; - int (*verify_callback)(int, X509_STORE_CTX *); - ssl_t *ssl; -} SSL_CTX; - -typedef struct { - SSL_CTX *ctx; - sslSessionId_t *resume; -// sslKeys_t *keys; - int32 fd; - int32 outBufOffset; - int32 appRecLen; - int32 resumedAppDataLen; -} SSL; - -typedef sslCipherSpec_t SSL_CIPHER; - -/***/ - -#define STACK_OF(x) x - - -/*** BIO ***/ - -typedef struct { - sslBuf_t *buf; - int type; -} BIO_METHOD; - -typedef struct { - BIO_METHOD *method; -} BIO; - -#define BIO_S_MEM_TYPE 1 - -typedef struct { - int length; - unsigned char *data; -} BUF_MEM; - -typedef SSL SSL_SESSION; -typedef void SSL_METHOD; -#define SSL_METHOD_QUAL - -/* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options - * are 'ored' with SSL_VERIFY_PEER if they are desired */ -#define SSL_VERIFY_NONE 0x00 -#define SSL_VERIFY_PEER 0x01 -#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 -#define SSL_VERIFY_CLIENT_ONCE 0x04 - -#define SSL_FILETYPE_PEM 1 -#define SSL_FILETYPE_ASN1 2 -#define SSL_FILETYPE_ENGINE 3 -#define SSL_FILETYPE_PKCS12 4 - -/* CONF_MFLAGS_IGNORE_MISSING_FILE if set will make CONF_load_modules_file() - ignore missing configuration files. Normally a missing configuration file - return an error. */ -#define CONF_MFLAGS_IGNORE_MISSING_FILE 1 - -/* The options XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_CPLUS_SPC, - XN_FLAG_SEP_SPLUS_SPC and XN_FLAG_SEP_MULTILINE determine the field - separators to use. Two distinct separators are used between distinct - RelativeDistinguishedName components and separate values in the same RDN - for a multi-valued RDN. Multi-valued RDNs are currently very rare so the - second separator will hardly ever be used */ -#define XN_FLAG_SEP_COMMA_PLUS 1 -#define XN_FLAG_SEP_CPLUS_SPC 2 -#define XN_FLAG_SEP_SPLUS_SPC 3 -#define XN_FLAG_SEP_MULTILINE 4 - - -#define SSL_ERROR_NONE 0 -#define SSL_ERROR_SSL 1 -#define SSL_ERROR_WANT_READ 2 -#define SSL_ERROR_WANT_WRITE 3 -#define SSL_ERROR_WANT_X509_LOOKUP 4 -#define SSL_ERROR_SYSCALL 5 -#define SSL_ERROR_ZERO_RETURN 6 -#define SSL_ERROR_WANT_CONNECT 7 -#define SSL_ERROR_WANT_ACCEPT 8 - -#define SSL2_VERSION 0x0002 -#define SSL3_VERSION 0x0300 -#define TLS1_VERSION 0x0301 -#define TLS1_1_VERSION 0x0302 -#define TLS1_2_VERSION 0x0303 - -#define NID_subject_alt_name 85 -#define NID_commonName 13 - -#define SSL_OP_ALL 0x80000BFFL -#define SSL_OP_NO_SSLv2 0x01000000L -#define SSL_OP_NO_SSLv3 0x02000000L -#define SSL_OP_NO_TLSv1 0x04000000L -#define SSL_OP_NO_TLSv1_2 0x08000000L -#define SSL_OP_NO_TLSv1_1 0x10000000L - - -typedef struct asn1_string_st -{ - int length; - int type; - unsigned char *data; -} ASN1_STRING; - -typedef unsigned char* ASN1_OBJECT; -typedef ASN1_STRING ASN1_UTCTIME; -typedef ASN1_STRING ASN1_INTEGER; -typedef ASN1_STRING ASN1_TIME; -#define V_ASN1_UTF8STRING ASN_UTF8STRING - -typedef struct GENERAL_NAME_st { - -#define GEN_OTHERNAME 0 -#define GEN_EMAIL 1 -#define GEN_DNS 2 -#define GEN_X400 3 -#define GEN_DIRNAME 4 -#define GEN_EDIPARTY 5 -#define GEN_URI 6 -#define GEN_IPADD 7 -#define GEN_RID 8 - -int type; -union { - ASN1_STRING *ptr; - ASN1_STRING *otherName; /* otherName */ - ASN1_STRING *rfc822Name; - ASN1_STRING *dNSName; - ASN1_STRING *x400Address; - ASN1_STRING *directoryName; - ASN1_STRING *ediPartyName; - ASN1_STRING *uniformResourceIdentifier; - ASN1_STRING *iPAddress; - ASN1_STRING *registeredID; - - /* Old names */ - ASN1_STRING *ip; /* iPAddress */ - ASN1_STRING *dirn; /* dirn */ - ASN1_STRING *ia5;/* rfc822Name, dNSName, uniformResourceIdentifier */ - ASN1_STRING *rid; /* registeredID */ - ASN1_STRING *other; /* x400Address */ -} d; -} GENERAL_NAME; - - - - - /* OpenSSL API */ -int SSL_library_init(void); -#define OpenSSL_add_ssl_algorithms() SSL_library_init() -#define SSLeay_add_ssl_algorithms() SSL_library_init() -#define OpenSSL_add_all_algorithms() SSL_library_init() -void SSL_load_error_strings(void); -void ERR_free_strings(void); -void ERR_remove_state(unsigned long pid); -void ERR_clear_error(void); -unsigned long ERR_peek_error(void); -int CONF_modules_load_file(const char *filename, const char *appname, - unsigned long flags); -void EVP_cleanup(void); - -long SSL_CTX_set_options(SSL_CTX *ctx, long options); -int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str); -int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, - const char *CApath); -int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); -int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); -int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); -int SSL_CTX_check_private_key(const SSL_CTX *ctx); -X509 *SSL_get_certificate(SSL *ssl); -EVP_PKEY *X509_get_pubkey(X509 *cert); -EVP_PKEY *SSL_get_privatekey(SSL *s); -long SSL_get_verify_result(const SSL *ssl); -int SSL_get_error(const SSL *cp, int ret); -SSL_CIPHER *SSL_get_cipher(const SSL *ssl); -X509 *SSL_get_peer_cert_chain(const SSL *s); -X509 *SSL_get_peer_certificate(const SSL *s); - -EVP_PKEY *EVP_PKEY_new(void); -void EVP_PKEY_free(EVP_PKEY *key); -int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from); - -void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, - int (*pem_password_cb)(char*, int, int, void*)); -int SSL_CTX_load_rsa_key_material(SSL_CTX *ctx, const char *cert, - const char *privkey, const char *CAfile); /* not openssl */ -void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, - int (*verify_callback)(int, X509_STORE_CTX *)); -X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx); - -SSL *SSL_new(SSL_CTX *ctx); -void SSL_free(SSL *cp); -SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth); -void SSL_CTX_free(SSL_CTX *ctx); - -void SSL_SESSION_free(SSL_SESSION *session); - -void *SSLv23_server_method(void); -void *SSLv23_client_method(void); -void *SSLv2_client_method(void); -void *SSLv3_client_method(void); -int SSL_set_fd(SSL *cp, int fd); - -int SSL_accept(SSL *cp); -int SSL_connect(SSL *cp); -int SSL_do_handshake(SSL *cp); - -int SSL_get_data(SSL *cp, unsigned char **ptBuf, int *ptBufLen); -int SSL_processed_data(SSL *cp, unsigned char **ptBuf, int *ptBufLen); - -int SSL_pending(const SSL *ssl); -int SSL_read(SSL *cp, void *userBuf, int userBufLen); -int SSL_write(SSL *cp, const void *inbuf, int32 inlen); -void SSL_shutdown(SSL *cp); - -int32 SSL_cert_auth(ssl_t *ssl, psX509Cert_t *cert, int32 alert); - -int SSL_peek(SSL *s, void *buf, int num); -void SSL_set_connect_state(SSL *ssl); -int SSL_set_session(SSL *ssl, SSL_SESSION *session); -SSL_SESSION *SSL_get_session(const SSL *ssl); - - -int SSL_version(SSL *ssl); - -#define DEFAULT_BIO_BUF_LEN 1024 -BIO *BIO_new(BIO_METHOD *type); -int BIO_free(BIO *a); -BIO_METHOD *BIO_s_mem(void); -void BIO_get_mem_ptr(BIO *b,BUF_MEM **pp); - -typedef psDigestContext_t MD5_CTX; -#define MD5_Init psMd5Init -#define MD5_Update psMd5Update -#define MD5_Final(a, b) psMd5Final(b, a) - - - -int PEM_write_bio_X509(BIO *bp, X509 *x); - - -typedef x509DNattributes_t X509_NAME_ENTRY; -int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags); -int X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos); -X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc); -ASN1_STRING * X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne); -X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); -X509_NAME * X509_get_subject_name(X509 *a); -char * X509_NAME_oneline(X509_NAME *a,char *buf,int size); -X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); -int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); -X509_LOOKUP_METHOD *X509_LOOKUP_file(void); -int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); -int sk_X509_EXTENSION_num(X509_EXTENSION *ext); -int sk_X509_num(X509 *certs); -X509_EXTENSION *sk_X509_EXTENSION_value(X509_EXTENSION *ext, int i); -ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex); -int X509_EXTENSION_get_critical(X509_EXTENSION *ex); -int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, - int indent); -X509 *sk_X509_value(X509 *cert, int i); - -const char *X509_verify_cert_error_string(long n); - -void OPENSSL_load_builtin_modules(void); - - -/* Mongoose web server no-ops */ -int CRYPTO_num_locks(void); -void CRYPTO_set_locking_callback(void (*cb)(int, int, const char *, int)); -void CRYPTO_set_id_callback(unsigned long (*cb)(void)); -unsigned long ERR_get_error(void); -char *ERR_error_string(unsigned long x, char *y); - - -/* cURL no-ops */ -int RAND_load_file(const char *filename, long max_bytes); -void RAND_add(const void *buf, int num, int entropy); -int RAND_status(void); -const char *RAND_file_name(char *buf, size_t num); -int RAND_bytes(unsigned char *buf, int num); - - - - -void * X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); -const GENERAL_NAME *sk_GENERAL_NAME_value(GENERAL_NAME *altnames, int i); -int sk_GENERAL_NAME_num(GENERAL_NAME *names); -void GENERAL_NAMES_free(GENERAL_NAME *name); - - -unsigned char * ASN1_STRING_data(ASN1_STRING *x); -size_t ASN1_STRING_length(ASN1_STRING *x); -int ASN1_STRING_type(ASN1_STRING *x); -int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in); -int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a); -int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v); - - -#define OPENSSL_malloc(x) psMalloc(NULL, x) -#define OPENSSL_free(x) psFree(x, NULL) -#ifdef __cplusplus -} -#endif - -#endif /* USE_MATRIX_OPENSSL_LAYER */ -#endif /* _h_SSLAPI */ - -/******************************************************************************/ diff --git a/matrixssl/opensslSocket.c b/matrixssl/opensslSocket.c deleted file mode 100644 index 3c8331d..0000000 --- a/matrixssl/opensslSocket.c +++ /dev/null @@ -1,315 +0,0 @@ -/** - * @file opensslSocket.c - * @version $Format:%h%d$ - * - * BSD socket implementation for supporting SSL_read, SSL_write, etc.... - */ -/* - * 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 - */ -/******************************************************************************/ - -#include -#include - -#include "opensslSocket.h" - -#ifdef USE_MATRIX_OPENSSL_LAYER -/******************************************************************************/ -/* - Client side. Open a socket connection to a remote ip and port. - This code is not specific to SSL. -*/ -int socketConnect(char *ip, short port, int *err) -{ - struct sockaddr_in addr; - int fd, rc; - - eeTrace("Enter socketConnect\n"); - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - psTraceInfo("Error creating socket\n"); - *err = getSocketError(); - return SOCKET_ERROR; - } -/* - Make sure the socket is not inherited by exec'd processes - Set the REUSEADDR flag to minimize the number of sockets in TIME_WAIT -*/ - fcntl(fd, F_SETFD, FD_CLOEXEC); - rc = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); - setSocketNodelay(fd); -/* - Turn on blocking mode for the connecting socket -*/ - setSocketBlock(fd); - - memset((char *) &addr, 0x0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(ip); - rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); -#if WIN - if (rc != 0) { -#else - if (rc < 0) { -#endif - *err = getSocketError(); - return SOCKET_ERROR; - } - eeTrace("Exit socketConnect\n"); - return fd; -} - -/******************************************************************************/ -/* - Server side. Set up a listen socket. This code is not specific to SSL. -*/ -int socketListen(short port, int *err) -{ - struct sockaddr_in addr; - int fd; - int32 rc; - - eeTrace("Enter socketListen\n"); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - psTraceInfo("Error creating listen socket\n"); - *err = getSocketError(); - return SOCKET_ERROR; - } -/* - Make sure the socket is not inherited by exec'd processes - Set the REUSE flag to minimize the number of sockets in TIME_WAIT -*/ - fcntl(fd, F_SETFD, FD_CLOEXEC); - rc = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc)); - - if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - psTraceInfo("Can't bind socket. Port in use or insufficient privilege\n"); - *err = getSocketError(); - return SOCKET_ERROR; - } - if (listen(fd, SOMAXCONN) < 0) { - psTraceInfo("Error listening on socket\n"); - *err = getSocketError(); - return SOCKET_ERROR; - } - printf("Listening for SSL connections on port %d\n", port); - eeTrace("Exit socketListen\n"); - return fd; -} - -/******************************************************************************/ -/* - Server side. Accept a new socket connection off our listen socket. - This code is not specific to SSL. -*/ -int socketAccept(int listenfd, int32 *err) -{ - struct sockaddr_in addr; - int fd; - unsigned int len; - - eeTrace("Enter socketAccept\n"); -/* - Wait(blocking)/poll(non-blocking) for an incoming connection -*/ - len = sizeof(addr); - if ((fd = accept(listenfd, (struct sockaddr *)&addr, &len)) - == SOCKET_ERROR) { - *err = getSocketError(); - if (*err != WOULD_BLOCK) { - psTraceIntInfo("Error %d accepting new socket\n", (int)*err); - } - return SOCKET_ERROR; - } -/* - fd is the newly accepted socket. Disable Nagle on this socket. - Set blocking mode as default -*/ -/* fprintf(stdout, "Connection received from %d.%d.%d.%d\n", - addr.sin_addr.S_un.S_un_b.s_b1, - addr.sin_addr.S_un.S_un_b.s_b2, - addr.sin_addr.S_un.S_un_b.s_b3, - addr.sin_addr.S_un.S_un_b.s_b4); -*/ - setSocketNodelay(fd); - setSocketBlock(fd); - eeTrace("Exit socketAccept\n"); - return fd; -} - -/******************************************************************************/ -/* - Set the socket to non blocking mode and perform a few extra tricks - to make sure the socket closes down cross platform -*/ -void socketClose(int sock) -{ - char buf[32]; - - eeTrace("Enter socketClose\n"); - if (sock != SOCKET_ERROR) { - setSocketNonblock(sock); - if (shutdown(sock, 1) >= 0) { - while (recv(sock, buf, sizeof(buf), 0) > 0); - } - close(sock); - } - eeTrace("Exit socketClose\n"); -} - -//#define FRAG_TEST -#ifdef FRAG_TEST -/******************************************************************************/ -/* - INTERNAL FUNCTION - Randomly send less than the requested number of bytes - Simulates a slow or congested network interface that may fragment records - */ -static int32 fragSend(int fd, unsigned char *buf, int32 len, int32 flags) -{ - unsigned char c; - int32 nlen; - struct timespec rqtp; - - rqtp.tv_sec = 0; - rqtp.tv_nsec = 1000000000 >> 4; /* 1/16 second */ - nlen = len; - if (nlen > 10) { - psGetEntropy(&c, 1, NULL); - nlen = (int32)c; - if (nlen == 0) { - nlen++; - } else if (nlen > len) { - //nlen = (unsigned char)len; - nlen = 10; - } - } - printf("sending fragment %d/%d bytes\n", nlen, len); - len = send(fd, buf, nlen, flags); - /* Sleep to give time for network to flush */ - nanosleep(&rqtp, NULL); - return len; -} -#endif /* TEST */ - -/******************************************************************************/ -/* - Perform a blocking write of data to a socket -*/ -int socketWrite(int sock, unsigned char *out, int len) -{ - ssize_t bytes; - - eeTrace("Enter socketWrite\n"); - printf("Trying to write %d bytes on sock %d\n", len, sock); -#ifdef FRAG_TEST - bytes = fragSend(sock, out, len, MSG_NOSIGNAL); -#else - bytes = send(sock, out, len, MSG_NOSIGNAL); -#endif - if (bytes == SOCKET_ERROR) { - return -1; - } - printf("send return code %d\n", (int)bytes); - eeTrace("Exit socketWrite\n"); - - return (int)bytes; -} - -/******************************************************************************/ -/* - Perform a blocking socket read -*/ -int socketRead(int sock, unsigned char *in, int available) -{ - ssize_t bytes; - - eeTrace("Enter socketRead\n"); - bytes = recv(sock, in, available, MSG_NOSIGNAL); - if (bytes == SOCKET_ERROR) { - return -1; - } - eeTrace("Exit socketRead\n"); - return (int)bytes; -} - -/******************************************************************************/ -/* - Turn on socket blocking mode (and set CLOEXEC on LINUX for kicks). -*/ -void setSocketBlock(int sock) -{ -#ifdef WIN32 - int32 block = 0; - ioctlsocket(sock, FIONBIO, &block); -#endif -#ifdef POSIX - fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) & ~O_NONBLOCK); - fcntl(sock, F_SETFD, FD_CLOEXEC); -#endif -} - -/******************************************************************************/ -/* - Turn off socket blocking mode. -*/ -void setSocketNonblock(int sock) -{ -#ifdef WIN32 - int32 block = 1; - ioctlsocket(sock, FIONBIO, &block); -#endif -#ifdef POSIX - fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK); -#endif -} - -/******************************************************************************/ -/* - Disable the Nagle algorithm for less latency in RPC - http://www.faqs.org/rfcs/rfc896.html - http://www.w3.org/Protocols/HTTP/Performance/Nagle/ -*/ -void setSocketNodelay(int sock) -{ -#ifdef WIN32 - BOOL tmp = TRUE; -#endif -#ifdef POSIX - int32 tmp = 1; -#endif /* WIN32 */ - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp)); -} - -#endif /* USE_MATRIX_OPENSSL_LAYER */ -/******************************************************************************/ - diff --git a/matrixssl/opensslSocket.h b/matrixssl/opensslSocket.h deleted file mode 100644 index eaeddbd..0000000 --- a/matrixssl/opensslSocket.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @file opensslSocket.h - * @version $Format:%h%d$ - * - * BSD socket implementation for openssl layer to MatrixSSL. - */ -/* - * 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_SSLSOCKET -#define _h_SSLSOCKET - -#ifdef __cplusplus -extern "C" { -#endif - -#include "matrixsslApi.h" - -#ifdef USE_MATRIX_OPENSSL_LAYER - -#include -#include -#include -#include - -/* - OS specific includes and macros -*/ -#ifdef WIN32 - #include - #include - #define fcntl(A, B, C) - #define MSG_NOSIGNAL 0 - #define WOULD_BLOCK WSAEWOULDBLOCK - #define getSocketError() WSAGetLastError() -#else - typedef int WSADATA; - #define WSAStartup(A, B) - #define WSACleanup() - #define getSocketError() errno -#endif - -#ifdef POSIX - #include - #include - #include - #include -#ifdef OSX - #include - #define MSG_NOSIGNAL 0 -#endif /* OSX */ -#endif /* POSIX */ - -#define SOCKET_ERROR -1 -#define WOULD_BLOCK EAGAIN - -#ifdef NEEDED - #define MAKEWORD(A, B) - #define SOCKET_ERRORCKET -1 -#endif /* old stuff */ - -/* - sslRead and sslWrite status values -*/ -#define SSLSOCKET_EOF 0x1 -#define SSLSOCKET_CLOSE_NOTIFY 0x2 - -/* - Socket apis -*/ - -extern void socketClose(int sock); -extern int socketWrite(int sock, unsigned char *out, int len); -extern int socketRead(int sock, unsigned char *in, int available); - -extern int socketListen(short port, int *err); -extern int socketAccept(int listenfd, int *err); -extern int socketConnect(char *ip, short port, int *err); -extern void socketShutdown(int sock); - -extern void setSocketBlock(int sock); -extern void setSocketNonblock(int sock); -extern void setSocketNodelay(int sock); - - -#ifdef __cplusplus -} -#endif - -#endif /* USE_MATRIX_OPENSSL_LAYER */ -#endif /* _h_SSLSOCKET */ - -/******************************************************************************/ diff --git a/matrixssl/sslDecode.c b/matrixssl/sslDecode.c index c4872cf..5a279a0 100644 --- a/matrixssl/sslDecode.c +++ b/matrixssl/sslDecode.c @@ -243,8 +243,27 @@ decodeMore: *error = PS_PROTOCOL_FAIL; return MATRIXSSL_ERROR; } - } + } else /* Note: The else branch (not DTLS) is below, + in code outside USE_DTLS */ #endif /* USE_DTLS */ +#ifndef USE_SSL_PROTOCOL_VERSIONS_OTHER_THAN_3 + { + /* RFC 5246 Suggests to accept all RSA minor versions, + but only major version 0x03 (SSLv3, TLS 1.0, + TLS 1.1, TLS 1.2, TLS 1.3 etc) */ + if (ssl->rec.majVer != 0x03) { + /* Consider invalid major version protocol + version error. */ + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo( + "Won't support client's SSL major version\n"); + return MATRIXSSL_ERROR; + } + } +#else + { } /* No check for rec.MajVer. */ +#endif /* USE_SSL_PROTOCOL_VERSIONS_OTHER_THAN_3 */ + ssl->rec.len = *c << 8; c++; ssl->rec.len += *c; c++; } else { @@ -796,7 +815,6 @@ ADVANCE_TO_APP_DATA: /* Run this helper regardless of error status thus far */ rc = addCompressCount(ssl, padLen); if (macError == 0) { -#ifndef USE_CL_DIGESTS psDigestContext_t md; unsigned char tmp[128]; switch (ssl->deMacSize) { @@ -834,11 +852,6 @@ ADVANCE_TO_APP_DATA: psAssert(0); break; } -#else - /* With FIPS implementation, - psHmacSha*Tls functions shall be used to - mitigate Lucky13. */ -#endif /* USE_CL_DIGESTS */ } } #endif /* LUCKY13 */ @@ -2131,6 +2144,11 @@ SKIP_HSHEADER_PARSE: #ifdef USE_SERVER_SIDE_SSL case SSL_HS_CLIENT_HELLO: psAssert(rc == 0); /* checking to see if this is the correct default */ + if (c + hsLen != end) { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Invalid length for Client Hello.\n"); + return MATRIXSSL_ERROR; + } rc = parseClientHello(ssl, &c, end); /* SSL_PROCESS_DATA is a valid code to indicate the end of a flight */ if (rc < 0 && rc != SSL_PROCESS_DATA) { diff --git a/matrixssl/sslEncode.c b/matrixssl/sslEncode.c index 7f73d79..8fb3db8 100644 --- a/matrixssl/sslEncode.c +++ b/matrixssl/sslEncode.c @@ -2250,7 +2250,6 @@ static int32 encryptFlight(ssl_t *ssl, unsigned char **end) } if (ssl->flags & SSL_FLAGS_NONCE_W) { - /* TODO: what about app data records? delayed seq needed? */ out.start = out.buf = out.end = msg->start - ssl->recordHeadLen - TLS_EXPLICIT_NONCE_LEN; #ifdef USE_DTLS @@ -4787,9 +4786,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, cookieLen = 0; #ifdef USE_DTLS if (ssl->flags & SSL_FLAGS_DTLS) { -/* - TODO: DTLS make sure a block cipher suite is being used -*/ + /* TODO DTLS make sure a block cipher suite is being used */ if (ssl->haveCookie) { cookieLen = ssl->cookieLen + 1; /* account for length byte */ } else { @@ -5939,12 +5936,24 @@ static int32 nowDoCvPka(ssl_t *ssl, psBuf_t *out) #ifdef USE_TLS_1_2 /* Tweak if needed */ if (ssl->flags & SSL_FLAGS_TLS_1_2) { - if (pka->inlen == SHA1_HASH_SIZE) { + switch(pka->inlen) { +#ifdef USE_SHA1 + case SHA1_HASH_SIZE: sslSha1SnapshotHSHash(ssl, msgHash); - } else if (pka->inlen == SHA384_HASH_SIZE) { + break; +#endif +#ifdef USE_SHA384 + case SHA384_HASH_SIZE: sslSha384SnapshotHSHash(ssl, msgHash); - } else if (pka->inlen == SHA512_HASH_SIZE) { + break; +#endif +#ifdef USE_SHA512 + case SHA512_HASH_SIZE: sslSha512SnapshotHSHash(ssl, msgHash); + break; +#endif + default: + break; } #ifdef USE_DTLS ssl->ecdsaSizeChange = 0; diff --git a/matrixssl/test/Makefile b/matrixssl/test/Makefile index 2ceb884..67ae884 100755 --- a/matrixssl/test/Makefile +++ b/matrixssl/test/Makefile @@ -9,24 +9,33 @@ TEST_SRC:=sslTest.c CERT_SRC:=certValidate.c SRC:=$(TEST_SRC) $(CERT_SRC) +# Linked files +STATIC:=../libssl_s.a $(MATRIXSSL_ROOT)/crypto/libcrypt_s.a $(MATRIXSSL_ROOT)/core/libcore_s.a + include $(MATRIXSSL_ROOT)/common.mk +# Include possible additional MatrixSSL test program build instructions +-include Makefile.add + # Generated files CERT_EXE:=certValidate$(E) TEST_EXE:=sslTest$(E) -# Linked files -STATIC:=../libssl_s.a $(MATRIXSSL_ROOT)/crypto/libcrypt_s.a $(MATRIXSSL_ROOT)/core/libcore_s.a +ifeq '$(CL_NO_PKCS)' '' +CFLAGS+=-DUSE_CL_PKCS -DUSE_CL_CERTLIB +endif # Generate map file with sections and C source reference for sslTest ifndef MATRIX_DEBUG ifeq (,$(findstring -apple,$(CCARCH))) +ifeq (,$(findstring -android,$(CCARCH))) LDFLAGS += \ -Wl,--cref \ -Wl,-s \ -Wl,-Map="$@.map" endif endif +endif all: compile @@ -42,5 +51,9 @@ $(CERT_EXE):$(CERT_SRC:.c=.o) $(STATIC) $(CC) -o $@ $^ $(LDFLAGS) clean: - rm -f $(TEST_EXE) $(CERT_EXE) $(OBJS) *.map + rm -f $(TEST_EXE) $(CERT_EXE) $(OBJS) $(CLEAN_EXTRA_FILES) *.map + +# Allows to check configuration options. +parse-config: + echo '#include "matrixsslConfig.h"' | $(CC) $(CFLAGS) -dM -E -x c - diff --git a/matrixssl/version.h b/matrixssl/version.h index fdda73b..4592687 100644 --- a/matrixssl/version.h +++ b/matrixssl/version.h @@ -1,22 +1,17 @@ -/** - * @file version.h - * @version $Format:%h%d$ - * - * Autogenerated version file. - */ /* - Copyright 2016 INSIDE Secure Corporation -*/ + Copyright 2016 INSIDE Secure Corporation + This file is auto-generated +*/ #ifndef _h_MATRIXSSL_VERSION #define _h_MATRIXSSL_VERSION #ifdef __cplusplus extern "C" { #endif -#define MATRIXSSL_VERSION "3.8.4-OPEN" +#define MATRIXSSL_VERSION "3.8.6-OPEN" #define MATRIXSSL_VERSION_MAJOR 3 #define MATRIXSSL_VERSION_MINOR 8 -#define MATRIXSSL_VERSION_PATCH 4 +#define MATRIXSSL_VERSION_PATCH 6 #define MATRIXSSL_VERSION_CODE "OPEN" #ifdef __cplusplus diff --git a/testkeys/DH/3072_DH_PARAMS.h b/testkeys/DH/3072_DH_PARAMS.h index 0e0665f..4d004fa 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 d0de69b..6d098c7 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. */ diff --git a/testkeys/EC/192_EC.h b/testkeys/EC/192_EC.h index d9f6c0e..e7cf756 100644 --- a/testkeys/EC/192_EC.h +++ b/testkeys/EC/192_EC.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/192_EC.h + * @file 192_EC.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/192_EC_CA.h b/testkeys/EC/192_EC_CA.h index 6c4d4fe..b260508 100644 --- a/testkeys/EC/192_EC_CA.h +++ b/testkeys/EC/192_EC_CA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/192_EC_CA.h + * @file 192_EC_CA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/192_EC_KEY.h b/testkeys/EC/192_EC_KEY.h index 288b5ff..3fc868d 100644 --- a/testkeys/EC/192_EC_KEY.h +++ b/testkeys/EC/192_EC_KEY.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/192_EC_KEY.h + * @file 192_EC_KEY.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/224_EC.h b/testkeys/EC/224_EC.h index 2485a7d..3e29e02 100644 --- a/testkeys/EC/224_EC.h +++ b/testkeys/EC/224_EC.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/224_EC.h + * @file 224_EC.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/224_EC_CA.h b/testkeys/EC/224_EC_CA.h index 53343d5..b35d3ea 100644 --- a/testkeys/EC/224_EC_CA.h +++ b/testkeys/EC/224_EC_CA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/224_EC_CA.h + * @file 224_EC_CA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/224_EC_KEY.h b/testkeys/EC/224_EC_KEY.h index 8ff9ce7..896d6b9 100644 --- a/testkeys/EC/224_EC_KEY.h +++ b/testkeys/EC/224_EC_KEY.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/224_EC_KEY.h + * @file 224_EC_KEY.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/256_EC.h b/testkeys/EC/256_EC.h index 858ea40..934c68e 100644 --- a/testkeys/EC/256_EC.h +++ b/testkeys/EC/256_EC.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/256_EC.h + * @file 256_EC.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/256_EC_CA.h b/testkeys/EC/256_EC_CA.h index ca478e4..98f0be0 100644 --- a/testkeys/EC/256_EC_CA.h +++ b/testkeys/EC/256_EC_CA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/256_EC_CA.h + * @file 256_EC_CA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/256_EC_KEY.h b/testkeys/EC/256_EC_KEY.h index 1c96100..fe3e7ce 100644 --- a/testkeys/EC/256_EC_KEY.h +++ b/testkeys/EC/256_EC_KEY.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/256_EC_KEY.h + * @file 256_EC_KEY.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/384_EC.h b/testkeys/EC/384_EC.h index 150ae70..9924d49 100644 --- a/testkeys/EC/384_EC.h +++ b/testkeys/EC/384_EC.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/384_EC.h + * @file 384_EC.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/384_EC_CA.h b/testkeys/EC/384_EC_CA.h index 01ef80e..0669c1f 100644 --- a/testkeys/EC/384_EC_CA.h +++ b/testkeys/EC/384_EC_CA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/384_EC_CA.h + * @file 384_EC_CA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/384_EC_KEY.h b/testkeys/EC/384_EC_KEY.h index 54960e2..82cf9ef 100644 --- a/testkeys/EC/384_EC_KEY.h +++ b/testkeys/EC/384_EC_KEY.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/384_EC_KEY.h + * @file 384_EC_KEY.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/521_EC.h b/testkeys/EC/521_EC.h index b3b8023..b99a26d 100644 --- a/testkeys/EC/521_EC.h +++ b/testkeys/EC/521_EC.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/521_EC.h + * @file 521_EC.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/521_EC_CA.h b/testkeys/EC/521_EC_CA.h index 7008a81..59dc16b 100644 --- a/testkeys/EC/521_EC_CA.h +++ b/testkeys/EC/521_EC_CA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/521_EC_CA.h + * @file 521_EC_CA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/EC/521_EC_KEY.h b/testkeys/EC/521_EC_KEY.h index 9bf6d1a..0a4c347 100644 --- a/testkeys/EC/521_EC_KEY.h +++ b/testkeys/EC/521_EC_KEY.h @@ -1,5 +1,5 @@ /** - * @file testkeys/EC/521_EC_KEY.h + * @file 521_EC_KEY.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/RSA/1024_RSA.h b/testkeys/RSA/1024_RSA.h index 1a42186..18bd0f2 100644 --- a/testkeys/RSA/1024_RSA.h +++ b/testkeys/RSA/1024_RSA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/RSA/1024_RSA.h + * @file 1024_RSA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/RSA/1024_RSA_CA.h b/testkeys/RSA/1024_RSA_CA.h index ca7841d..dd56289 100644 --- a/testkeys/RSA/1024_RSA_CA.h +++ b/testkeys/RSA/1024_RSA_CA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/RSA/1024_RSA_CA.h + * @file 1024_RSA_CA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/RSA/1024_RSA_KEY.h b/testkeys/RSA/1024_RSA_KEY.h index 7f969d6..6527b87 100644 --- a/testkeys/RSA/1024_RSA_KEY.h +++ b/testkeys/RSA/1024_RSA_KEY.h @@ -1,5 +1,5 @@ /** - * @file testkeys/RSA/1024_RSA_KEY.h + * @file 1024_RSA_KEY.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/RSA/2048_RSA.h b/testkeys/RSA/2048_RSA.h index 89f7ba9..fcbbdfe 100644 --- a/testkeys/RSA/2048_RSA.h +++ b/testkeys/RSA/2048_RSA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/RSA/2048_RSA.h + * @file 2048_RSA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/RSA/2048_RSA_CA.h b/testkeys/RSA/2048_RSA_CA.h index 334ac81..1794f7d 100644 --- a/testkeys/RSA/2048_RSA_CA.h +++ b/testkeys/RSA/2048_RSA_CA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/RSA/2048_RSA_CA.h + * @file 2048_RSA_CA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/RSA/2048_RSA_KEY.h b/testkeys/RSA/2048_RSA_KEY.h index 774ad7b..94d07ed 100644 --- a/testkeys/RSA/2048_RSA_KEY.h +++ b/testkeys/RSA/2048_RSA_KEY.h @@ -1,5 +1,5 @@ /** - * @file testkeys/RSA/2048_RSA_KEY.h + * @file 2048_RSA_KEY.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/RSA/4096_RSA.h b/testkeys/RSA/4096_RSA.h index c2b8703..ebac3b7 100644 --- a/testkeys/RSA/4096_RSA.h +++ b/testkeys/RSA/4096_RSA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/RSA/4096_RSA.h + * @file 4096_RSA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/RSA/4096_RSA_CA.h b/testkeys/RSA/4096_RSA_CA.h index 992e6aa..608b2c1 100644 --- a/testkeys/RSA/4096_RSA_CA.h +++ b/testkeys/RSA/4096_RSA_CA.h @@ -1,5 +1,5 @@ /** - * @file testkeys/RSA/4096_RSA_CA.h + * @file 4096_RSA_CA.h * @version $Format:%h%d$ * * Auto generated from PEM file. diff --git a/testkeys/RSA/4096_RSA_KEY.h b/testkeys/RSA/4096_RSA_KEY.h index 5adda09..1246d0a 100644 --- a/testkeys/RSA/4096_RSA_KEY.h +++ b/testkeys/RSA/4096_RSA_KEY.h @@ -1,6 +1,6 @@ /** * @file 4096_RSA_KEY.h - * @version $Format:%h%d$ + * @version 33bf525ff52f (default) * * Auto generated from PEM file. */ diff --git a/testkeys/ocsp/VeriSignCA.pem b/testkeys/ocsp/VeriSignCA.pem deleted file mode 100644 index 707ff08..0000000 --- a/testkeys/ocsp/VeriSignCA.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- diff --git a/testkeys/ocsp/VeriSignIntermediate.pem b/testkeys/ocsp/VeriSignIntermediate.pem deleted file mode 100644 index 4e13f43..0000000 --- a/testkeys/ocsp/VeriSignIntermediate.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFODCCBCCgAwIBAgIQUT+5dDhwtzRAQY0wkwaZ/zANBgkqhkiG9w0BAQsFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB+MQsw -CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV -BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVjIENs -YXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAstgFyhx0LbUXVjnFSlIJluhL2AzxaJ+aQihiw6UwU35VEYJb -A3oNL+F5BMm0lncZgQGUWfm893qZJ4Itt4PdWid/sgN6nFMl6UgfRk/InSn4vnlW -9vf92Tpo2otLgjNBEsPIPMzWlnqEIRoiBAMnF4scaGGTDw5RgDMdtLXO637QYqzu -s3sBdO9pNevK1T2p7peYyo2qRA4lmUoVlqTObQJUHypqJuIGOmNIrLRM0XWTUP8T -L9ba4cYY9Z/JJV3zADreJk20KQnNDz0jbxZKgRb78oMQw7jW2FUyPfG9D72MUpVK -Fpd6UiFjdS8W+cRmvvW1Cdj/JwDNRHxvSz+w9wIDAQABo4IBYzCCAV8wEgYDVR0T -AQH/BAgwBgEB/wIBADAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vczEuc3ltY2Iu -Y29tL3BjYTMtZzUuY3JsMA4GA1UdDwEB/wQEAwIBBjAvBggrBgEFBQcBAQQjMCEw -HwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wawYDVR0gBGQwYjBgBgpg -hkgBhvhFAQc2MFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20v -Y3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vcnBhMCkG -A1UdEQQiMCCkHjAcMRowGAYDVQQDExFTeW1hbnRlY1BLSS0xLTUzNDAdBgNVHQ4E -FgQUX2DPYZBV34RDFIpgKrL1evRDGO8wHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnz -Qzn6Aq8zMTMwDQYJKoZIhvcNAQELBQADggEBAF6UVkndji1l9cE2UbYD49qecxny -H1mrWH5sJgUs+oHXXCMXIiw3k/eG7IXmsKP9H+IyqEVv4dn7ua/ScKAyQmW/hP4W -Ko8/xabWo5N9Q+l0IZE1KPRj6S7t9/Vcf0uatSDpCr3gRRAMFJSaXaXjS5HoJJtG -QGX0InLNmfiIEfXzf+YzguaoxX7+0AjiJVgIcWjmzaLmFN5OUiQt/eV5E1PnXi8t -TRttQBVSK/eHiXgSgW7ZTaoteNTCLD0IX4eRnh8OsN4wUmSGiaqdZpwOdgyA8nTY -Kvi4Os7X1g8RvmurFPW9QaAiY4nxug9vKWNmLT+sjHLF+8fk1A/yO0+MKcc= ------END CERTIFICATE-----