diff --git a/Makefile b/Makefile index 8f2ff21..a400823 100644 --- a/Makefile +++ b/Makefile @@ -81,19 +81,19 @@ clean-config: # Set non-fips configuration (standard configuration for MatrixSSL commercial) # and build all libraries all-nonfips: - make nonfips-config + $(MAKE) nonfips-config $(MAKE) --directory=core $(MAKE) --directory=crypto $(MAKE) --directory=matrixssl - if [ -e crypto/cms ]; then $(MAKE) --directory=crypto/cms;fi - if [ -e matrixssh ]; then if make --directory=crypto parse-config | grep -q '#define USE_AES_CTR' && make --directory=crypto parse-config | grep -q '#define USE_DH'; then $(MAKE) --directory=matrixssh;fi;fi + if $(MAKE) --directory=crypto parse-config | grep -q '#define USE_CMS'; then $(MAKE) --directory=crypto/cms;fi + if [ -e matrixssh ]; then if $(MAKE) --directory=crypto parse-config | grep -q '#define USE_AES_CTR' && $(MAKE) --directory=crypto parse-config | grep -q '#define USE_DH'; then $(MAKE) --directory=matrixssh;fi;fi # Set non-fips configuration and build tests test-nonfips: - make nonfips-config + $(MAKE) nonfips-config $(MAKE) --directory=crypto/test $(MAKE) --directory=matrixssl/test - if [ -e crypto/cms ]; then $(MAKE) --directory=crypto/cms/test;fi + if $(MAKE) --directory=crypto parse-config | grep -q '#define USE_CMS'; then $(MAKE) --directory=crypto/cms;fi # Find out if MatrixSSL FIPS Edition is present ifeq (,$(wildcard configs/fips*/matrixsslConfig.h)) @@ -116,78 +116,78 @@ endif # Omit ECC (Only support RSA and DH, using MatrixSSL stock crypto) all-noecc: - make $(CONFIG_NONFIPS_PREFIX)noecc-config - make all + $(MAKE) $(CONFIG_NONFIPS_PREFIX)noecc-config + $(MAKE) all # Only support RSA (MatrixSSL stock crypto) all-rsaonly: - make $(CONFIG_NONFIPS_PREFIX)rsaonly-config - make all + $(MAKE) $(CONFIG_NONFIPS_PREFIX)rsaonly-config + $(MAKE) all # Only support RSA (MatrixSSL stock crypto) all-psk: - make $(CONFIG_NONFIPS_PREFIX)psk-config - make all + $(MAKE) $(CONFIG_NONFIPS_PREFIX)psk-config + $(MAKE) all # A commonly recommended set of options for MatrixSSL using stock crypto, # for the most common TLS use cases. This configuration disables # DH and 3DES options in rare use (which is typically considered good for # security). all-tls: - make $(CONFIG_NONFIPS_PREFIX)tls-config - make all + $(MAKE) $(CONFIG_NONFIPS_PREFIX)tls-config + $(MAKE) all # These configurations are specific to FIPS version of MatrixSSL. # The targets are only available on MatrixSSL FIPS Edition. # Set fips only configuration and build all libraries all-fips: - make fipsonly-config - make all + $(MAKE) fipsonly-config + $(MAKE) all # Set nonfips only configuration and build all libraries all-cl-nonfips: - make cl-nonfips-config - make all + $(MAKE) cl-nonfips-config + $(MAKE) all # Set combined fips/nonfips configuration and build all libraries all-combined: - make combined-config - make all + $(MAKE) combined-config + $(MAKE) all # Set combined-default-nonfips configuration and build all libraries all-combined-default-nonfips: - make combined-default-nonfips-config - make all + $(MAKE) combined-default-nonfips-config + $(MAKE) all # Set combined fips/nonfips configuration with maximum algorithm # support, and build all libraries all-combined-fulltest: - make combined-fulltest-config - make all + $(MAKE) combined-fulltest-config + $(MAKE) all all-openssl-compat: - make openssl-compat-config - make all + $(MAKE) openssl-compat-config + $(MAKE) all ifneq (,$(findstring clean,$(MAKECMDGOALS))) SUBARGS:=clean endif # Set fips only configuration and build tests test-fips: - make fipsonly-config - make test + $(MAKE) fipsonly-config + $(MAKE) test # Set combined fips/nonfips only configuration and build tests test-combined: - make combined-config - make test + $(MAKE) combined-config + $(MAKE) test # Set combined nonfips/fips configuration and build tests test-combined-default-nonfips: - make combined-default-nonfips-config - make test + $(MAKE) combined-default-nonfips-config + $(MAKE) test .PHONY: all libs tests apps clean @@ -209,15 +209,15 @@ test: tests libs: $(MAKE) --directory=core - if make --directory=crypto parse-config | grep -q -e '#define USE_FIPS_CRYPTO' -e '#define USE_CL_CRYPTO'; then $(MAKE) --directory=crypto-cl; else $(MAKE) --directory=crypto; fi - if make --directory=crypto parse-config | grep -q '#define USE_CMS'; then $(MAKE) --directory=crypto/cms;fi + if $(MAKE) --directory=crypto parse-config | grep -q -e '#define USE_FIPS_CRYPTO' -e '#define USE_CL_CRYPTO'; then $(MAKE) --directory=crypto-cl; else $(MAKE) --directory=crypto; fi + if $(MAKE) --directory=crypto parse-config | grep -q '#define USE_CMS'; then $(MAKE) --directory=crypto/cms;fi $(MAKE) --directory=matrixssl - if [ -e matrixssh ]; then if make --directory=crypto parse-config | grep -q '#define USE_AES_CTR' && make --directory=crypto parse-config | grep -q '#define USE_DH'; then $(MAKE) --directory=matrixssh;fi;fi + if [ -e matrixssh ]; then if $(MAKE) --directory=crypto parse-config | grep -q '#define USE_AES_CTR' && $(MAKE) --directory=crypto parse-config | grep -q '#define USE_DH'; then $(MAKE) --directory=matrixssh;fi;fi tests: $(MAKE) --directory=crypto/test $(MAKE) --directory=matrixssl/test - if make --directory=crypto parse-config | grep -q '#define USE_CMS'; then $(MAKE) --directory=crypto/cms/test;fi + if $(MAKE) --directory=crypto parse-config | grep -q '#define USE_CMS'; then $(MAKE) --directory=crypto/cms/test;fi # Note apps is also a direct subdirectory #ifdef MATRIXSSL_COMMERCIAL @@ -231,8 +231,11 @@ apps_crypto: #endif /* MATRIXSSL_COMMERCIAL */ -apps: $(APPS_ADDITIONAL) - if make --directory=matrixssl parse-config | grep -q '#define USE_ZLIB_COMPRESSION'; then EXTRA_LDFLAGS=-lz $(MAKE) --directory=apps/ssl; else $(MAKE) --directory=apps/ssl; fi; +apps_common: + $(MAKE) --directory=apps/common + +apps: apps_common $(APPS_ADDITIONAL) + $(MAKE) --directory=apps/ssl $(MAKE) --directory=apps/dtls clean: @@ -244,6 +247,7 @@ clean: $(MAKE) clean --directory=matrixssl/test if [ -e crypto-cl ]; then $(MAKE) clean --directory=crypto-cl;fi if [ -e crypto/cms ]; then $(MAKE) clean --directory=crypto/cms;fi + $(MAKE) clean --directory=apps/common $(MAKE) clean --directory=apps/ssl $(MAKE) clean --directory=apps/dtls if [ -e apps/crypto ];then $(MAKE) clean --directory=apps/crypto;fi diff --git a/apps/dtls/Makefile b/apps/dtls/Makefile index 6d8527b..0ac66f0 100644 --- a/apps/dtls/Makefile +++ b/apps/dtls/Makefile @@ -35,6 +35,9 @@ STATIC:=\ $(MATRIXSSL_ROOT)/crypto/libcrypt_s.a \ $(MATRIXSSL_ROOT)/core/libcore_s.a +STATIC_CLIENT:=\ + $(MATRIXSSL_ROOT)/apps/common/client_common_s.a + CIPHER_OPTION=ID_RSA # The default cipher option CFLAGS+=-D$(CIPHER_OPTION) @@ -53,7 +56,7 @@ $(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) $(SERVER_EXE): $(SERVER_SRC:.c=.o) $(STATIC) $(CC) -o $@ $^ $(LDFLAGS) -$(CLIENT_EXE): $(CLIENT_SRC:.c=.o) $(STATIC) +$(CLIENT_EXE): $(CLIENT_SRC:.c=.o) $(STATIC) $(STATIC_CLIENT) $(CC) -o $@ $^ $(LDFLAGS) clean: diff --git a/apps/dtls/dtlsClient.c b/apps/dtls/dtlsClient.c index 4366057..cf4f83f 100644 --- a/apps/dtls/dtlsClient.c +++ b/apps/dtls/dtlsClient.c @@ -36,6 +36,7 @@ /* Currently this example uses _psTrace for tracing, so osdep.h is needed: */ #include "core/osdep.h" #include "core/psUtil.h" +#include "../common/client_common.h" #if defined(USE_DTLS) && defined(USE_CLIENT_SIDE_SSL) @@ -66,151 +67,6 @@ typedef struct # define ALLOW_ANON_CONNECTIONS 1 # define USE_HEADER_KEYS -/* - If supporting client authentication, pick ONE identity to auto select a - certificate and private key that support desired algorithms. - */ -/* #define ID_RSA / * RSA Certificate and Key * / */ -/* #define ID_ECDH_ECDSA / * EC Certificate and Key * / */ -/* #define ID_ECDH_RSA / * EC Key with RSA signed certificate * / */ - -# if !defined(ID_RSA) && !defined(ID_ECDH_ECDSA) && !defined(ID_ECDH_RSA) -/* Choose a default identity based on which algorithms are supported. */ -# ifdef USE_RSA_CIPHER_SUITE -# define ID_RSA -# else -# ifdef USE_ECC_CIPHER_SUITE -# define ID_ECDH_ECDSA -# else -# error "Please enable either RSA or ECC for client" -# endif /* USE_ECC_CIPHER_SUITE */ -# endif /* USE_RSA_CIPHER_SUITE */ -# endif /* !ID_RSA && !ID_ECDH_ECDSA && !ID_ECDH_RSA */ - -/* If the algorithm type is supported, load a CA for it */ -# ifdef USE_HEADER_KEYS -/* CAs */ -# ifdef USE_RSA_CIPHER_SUITE -# include "testkeys/RSA/ALL_RSA_CAS.h" -# ifdef USE_ECC_CIPHER_SUITE -# include "testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.h" -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - -# if defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) -# include "testkeys/EC/ALL_EC_CAS.h" -# endif /* USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192.h" -# endif /* !USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ - -# if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224.h" -# endif /* USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ - -# if defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P521.h" -# endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.h" -# endif /* !USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.h" -# endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ - -# if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.h" -# endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.h" -# endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ - -# endif /* USE_ECC_CIPHER_SUITE */ - -/* Identity Certs and Keys for use with Client Authentication */ -# ifdef ID_RSA -# define EXAMPLE_RSA_KEYS -# include "testkeys/RSA/1024_RSA.h" -# include "testkeys/RSA/1024_RSA_KEY.h" -# include "testkeys/RSA/2048_RSA.h" -# include "testkeys/RSA/2048_RSA_KEY.h" -# include "testkeys/RSA/3072_RSA.h" -# include "testkeys/RSA/3072_RSA_KEY.h" -# include "testkeys/RSA/4096_RSA.h" -# include "testkeys/RSA/4096_RSA_KEY.h" -# endif - -# ifdef ID_ECDH_ECDSA -# define EXAMPLE_EC_KEYS -# include "testkeys/EC/384_EC.h" -# include "testkeys/EC/384_EC_KEY.h" -# endif - -# ifdef ID_ECDH_RSA -# define EXAMPLE_ECDH_RSA_KEYS -# include "testkeys/ECDH_RSA/521_ECDH-RSA.h" -# include "testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h" -# endif - -/* File-based keys */ -# else -/* CAs */ -# ifdef USE_RSA_CIPHER_SUITE -static char rsaCAFile[] = "testkeys/RSA/ALL_RSA_CAS.pem"; -# ifdef USE_ECC_CIPHER_SUITE -static char ecdhRsaCAFile[] = "testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.pem"; -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - -# if defined(USE_SECP192R1) && defined(USE_SECP521R1) -static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS.pem"; -# endif /* USE_SECP192R1 && USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && defined(USE_SECP521R1) -static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS_EXCEPT_P192.pem"; -# endif /* USE_SECP192R1 && USE_SECP521R1 */ - -# if defined(USE_SECP192R1) && !defined(USE_SECP521R1) -static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS_EXCEPT_P521.pem"; -# endif /* USE_SECP192R1 && USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && !defined(USE_SECP521R1) -static char ecCAFile[] = "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.pem"; -# endif /* USE_SECP192R1 && USE_SECP521R1 */ - -# endif /* USE_ECC_CIPHER_SUITE */ - -/* Identity Certs and Keys for use with Client Authentication */ -# ifdef ID_RSA -# define EXAMPLE_RSA_KEYS -static char rsaCertFile[] = "testkeys/RSA/2048_RSA.pem"; -static char rsaPrivkeyFile[] = "testkeys/RSA/2048_RSA_KEY.pem"; -# endif - -# ifdef ID_ECDH_ECDSA -# define EXAMPLE_EC_KEYS -static char ecCertFile[] = "testkeys/EC/384_EC.pem"; -static char ecPrivkeyFile[] = "testkeys/EC/384_EC_KEY.pem"; -# endif - -# ifdef ID_ECDH_RSA -# define EXAMPLE_ECDH_RSA_KEYS -static char ecdhRsaCertFile[] = "testkeys/ECDH_RSA/521_ECDH-RSA.pem"; -static char ecdhRsaPrivkeyFile[] = "testkeys/ECDH_RSA/521_ECDH-RSA_KEY.pem"; -# endif - -# endif /* USE_HEADER_KEYS */ - -# ifdef USE_PSK_CIPHER_SUITE -# include "testkeys/PSK/psk.h" -# endif - /* Test rehandshakes */ @@ -229,7 +85,7 @@ extern int opterr; static char g_ip[16]; static char g_path[256]; static int g_port, g_new, g_resumed, g_ciphers; -static int g_key_len, g_disableCertNameChk; +static int g_disableCertNameChk; static uint16_t g_cipher[16]; /****************************** Local Functions *******************************/ @@ -642,23 +498,52 @@ static void usage(void) "\n" "where option can be one of the following:\n" "\n" - "-c - Comma separated list of ciphers nums\n" + "-c - Comma separated list of ciphers numbers\n" + "--ciphers - Path to certificate authority file\n" + "--ca \n" "-d - Disable server certicate name/addr chk\n" - "-h - Print usage and exit\n" + "--no-name-check\n" + "-h - Help, print usage and exit\n" + "--help\n" "-k - RSA keyLen (if using client auth)\n" + "--rsa-key-len\n" + " - Must be one of 1024, 2048 or 4096\n" "-n - Num of new (full handshake) sessions\n" + "--handshakes \n" "-p - Port number for DTLS server\n" + "--port \n" "-r - Num of resumed DTLS sesssions\n" + "--resumed \n" "-s - IP address of server machine/interface\n" + "--server \n" # ifdef DTLS_PACKET_LOSS_TEST "-l - Reciprocal of packet loss probability\n" + "--packet-loss \n" " (for packet loss simulation tests)\n" # endif /* DTLS_PACKET_LOSS_TEST */ # ifdef DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE "-x - Run test, where the client tries to change\n" " the cipher spec during a re-handshake and\n" " the CHANGE_CIPHER_SPEC message is lost.\n" + "--drop-change-cipher-spec\n" # endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ + "--no-cert - Unset client certificate\n" + "--cert \n" + " - Path to client certificate file\n" + "--key - Path to client private key file\n" + "--keytype \n" + " - Specify format of client certificate:\n" + " any (detect key and signature type)\n" + " rsa (for RSA keys)\n" + " ec (for EC keys ECDSA signature)\n" + " ecrsa (for EC keys with RSA signature)\n" "\n" "where -s is a required option (i.e. has no current default, and\n" "serverPortNum is usually 443 or 4433. The cipherList is a comma separated list\n" @@ -721,7 +606,7 @@ static int32 parse_cipher_list(char *cipherListString, encountered OR a request for help is seen (i.e. '-h' option). */ static int32 process_cmd_options(int32 argc, char **argv) { - int optionChar, key_len, numCiphers, g_ip_set; + int optionChar, key_len, numCiphers; char *cipherListString; /* Set some default options: */ @@ -729,23 +614,64 @@ static int32 process_cmd_options(int32 argc, char **argv) memset(g_ip, 0, sizeof(g_ip)); memset(g_path, 0, sizeof(g_path)); - g_ip_set = 0; + strcpy(g_ip, "127.0.0.1"); g_ciphers = 1; g_cipher[0] = 47; g_disableCertNameChk = 0; - g_key_len = 1024; + g_key_len = 2048; g_new = 1; g_port = 4433; g_resumed = 1; + /* External certificate validation not supported with DTLS client */ + g_enable_ext_cv_sig_op = 0; + opterr = 0; - while ((optionChar = getopt(argc, argv, "c:dhk:n:p:r:s:l:x")) != -1) + + const char *optstring = "C:c:dhk:n:p:r:s:l:x"; + +#ifdef USE_GETOPT_LONG +#define ARG_NO_CERT 1 +#define ARG_CERT 2 +#define ARG_KEY 3 +#define ARG_KEYTYPE 4 + + static struct option long_options[] = + { + {"ciphers", required_argument, NULL, 'c'}, + {"ca", required_argument, NULL, 'C'}, + {"no-name-check", no_argument, NULL, 'd'}, + {"help", no_argument, NULL, 'h'}, + {"rsa-key-len", required_argument, NULL, 'k'}, + {"handshakes", required_argument, NULL, 'n'}, + {"port", required_argument, NULL, 'p'}, + {"resumed", required_argument, NULL, 'r'}, + {"server", required_argument, NULL, 's'}, + {"packet-loss", required_argument, NULL, 'l'}, + {"drop-change-cipher-spec", no_argument, NULL, 'x'}, + {"no-cert", no_argument, NULL, ARG_NO_CERT}, + {"cert", required_argument, NULL, ARG_CERT}, + {"key", required_argument, NULL, ARG_KEY}, + {"keytype", required_argument, NULL, ARG_KEYTYPE}, + {0, 0, 0, 0} + }; + + int opt_index = 0; + + while ((optionChar = getopt_long(argc, argv, optstring, long_options, &opt_index)) != -1) +#else + while ((optionChar = getopt(argc, argv, optstring)) != -1) +#endif { switch (optionChar) { case '?': return -1; + case 'C': + g_clientconfig.ca_file = optarg; + clientconfigUseFileKeys(); + break; case 'c': /* Convert the cipherListString into an array of cipher numbers. */ @@ -792,7 +718,6 @@ static int32 process_cmd_options(int32 argc, char **argv) break; case 's': - g_ip_set = 1; strncpy(g_ip, optarg, 15); break; @@ -817,69 +742,49 @@ static int32 process_cmd_options(int32 argc, char **argv) break; # endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ # endif /* DTLS_PACKET_LOSS_TEST */ - } - } - if (g_ip_set == 0) - { - printf("The -s option is currently required!\n"); - return -1; +#ifdef USE_GETOPT_LONG +/* Additional options not supported through short arguments */ + + case ARG_CERT: + g_clientconfig.cert_file = optarg; + clientconfigUseFileKeys(); + break; + + case ARG_NO_CERT: + g_clientconfig.cert_file = NULL; + g_clientconfig.privkey_file = optarg; + clientconfigUseFileKeys(); + break; + + case ARG_KEY: + g_clientconfig.privkey_file = optarg; + clientconfigUseFileKeys(); + break; + + case ARG_KEYTYPE: + if (strcmp("any", optarg) == 0) { + g_clientconfig.load_key = &loadKeysFromFile; + } else if (strcmp("rsa", optarg) == 0) { + g_clientconfig.load_key = &loadRsaKeysFromFile; + } else if (strcmp("ec", optarg) == 0) { + g_clientconfig.load_key = &loadECDH_ECDSAKeysFromFile; + } else if (strcmp("ecrsa", optarg) == 0) { + g_clientconfig.load_key = &loadECDHRsaKeysFromFile; + } else { + printf("Invalid option: %s\n", optarg); + return -1; + } + + g_clientconfig.loadKeysFromMemory = 0; + break; +#endif /* USE_GETOPT_LONG */ + } } return 0; } -# if defined(USE_HEADER_KEYS) && defined(ID_RSA) -static int32 loadRsaKeys(uint32 key_len, sslKeys_t *keys, - unsigned char *CAstream, int32 CAstreamLen) -{ - int32 rc; - - if (key_len == 1024) - { - _psTrace("Using 1024 bit RSA private key\n"); - rc = matrixSslLoadRsaKeysMem(keys, RSA1024, sizeof(RSA1024), - RSA1024KEY, sizeof(RSA1024KEY), CAstream, CAstreamLen); - } - else if (key_len == 2048) - { - _psTrace("Using 2048 bit RSA private key\n"); - rc = matrixSslLoadRsaKeysMem(keys, RSA2048, sizeof(RSA2048), - RSA2048KEY, sizeof(RSA2048KEY), CAstream, CAstreamLen); - } - else if (key_len == 3072) - { - _psTrace("Using 3072 bit RSA private key\n"); - rc = matrixSslLoadRsaKeysMem(keys, RSA3072, sizeof(RSA3072), - RSA3072KEY, sizeof(RSA3072KEY), CAstream, CAstreamLen); - } - else if (key_len == 4096) - { - _psTrace("Using 4096 bit RSA private key\n"); - rc = matrixSslLoadRsaKeysMem(keys, RSA4096, sizeof(RSA4096), - RSA4096KEY, sizeof(RSA4096KEY), CAstream, CAstreamLen); - } - else - { - rc = -1; - psAssert((key_len == 1024) || (key_len == 2048) || (key_len == 3072) - || (key_len == 4096)); - } - - if (rc < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream, NULL); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - } - - return rc; -} -# endif /******************************************************************************/ /* @@ -890,16 +795,18 @@ static int32 loadRsaKeys(uint32 key_len, sslKeys_t *keys, */ int32 main(int32 argc, char **argv) { - int32 rc, CAstreamLen; + int32 rc; sslKeys_t *keys; sslSessionId_t *sid; - unsigned char *CAstream; int32 rv; # ifdef WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(1, 1), &wsaData); # endif + + clientconfigInitialize(); + if ((rc = matrixSslOpen()) < 0) { _psTrace("MatrixSSL library init failure. Exiting\n"); @@ -915,6 +822,7 @@ int32 main(int32 argc, char **argv) if (0 != process_cmd_options(argc, argv)) { usage(); + clientconfigFree(); return 0; } printf("client https://%s:%d%s " @@ -922,188 +830,10 @@ int32 main(int32 argc, char **argv) g_ip, g_port, g_path, g_new, g_resumed, g_key_len, g_ciphers); -# ifndef USE_ONLY_PSK_CIPHER_SUITE -# ifdef USE_HEADER_KEYS -/* - In-memory based keys - Build the CA list first for potential client auth usage - */ - CAstreamLen = 0; -# ifdef USE_RSA_CIPHER_SUITE - CAstreamLen += sizeof(RSACAS); -# ifdef USE_ECC_CIPHER_SUITE - CAstreamLen += sizeof(ECDHRSACAS); -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - CAstreamLen += sizeof(ECCAS); -# endif -# if defined(USE_RSA_CIPHER_SUITE) || defined(USE_ECC_CIPHER_SUITE) - CAstream = psMalloc(NULL, CAstreamLen); -# else - CAstream = NULL; -# endif - - CAstreamLen = 0; -# ifdef USE_RSA_CIPHER_SUITE - memcpy(CAstream, RSACAS, sizeof(RSACAS)); - CAstreamLen += sizeof(RSACAS); -# ifdef USE_ECC_CIPHER_SUITE - memcpy(CAstream + CAstreamLen, ECDHRSACAS, sizeof(ECDHRSACAS)); - CAstreamLen += sizeof(ECDHRSACAS); -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - memcpy(CAstream + CAstreamLen, ECCAS, sizeof(ECCAS)); - CAstreamLen += sizeof(ECCAS); -# endif - -# ifdef ID_RSA - rc = loadRsaKeys(g_key_len, keys, CAstream, CAstreamLen); - if (rc < 0) + if (!clientconfigLoadKeys(keys)) { - return rc; + return EXIT_FAILURE; } -# endif - -# ifdef ID_ECDH_RSA - if ((rc = matrixSslLoadEcKeysMem(keys, ECDHRSA521, sizeof(ECDHRSA521), - ECDHRSA521KEY, sizeof(ECDHRSA521KEY), CAstream, CAstreamLen)) < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream, NULL); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return rc; - } -# endif - -# ifdef ID_ECDH_ECDSA - if ((rc = matrixSslLoadEcKeysMem(keys, EC384, sizeof(EC384), - EC384KEY, sizeof(EC384KEY), CAstream, CAstreamLen)) < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream, NULL); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return rc; - } -# endif - - if (CAstream) - { - psFree(CAstream, NULL); - } - -# else -/* - File based keys - */ - CAstreamLen = 0; -# ifdef USE_RSA_CIPHER_SUITE - CAstreamLen += (int32) strlen(rsaCAFile) + 1; -# ifdef USE_ECC_CIPHER_SUITE - CAstreamLen += (int32) strlen(ecdhRsaCAFile) + 1; -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - CAstreamLen += (int32) strlen(ecCAFile) + 1; -# endif - if (CAstreamLen > 0) - { - CAstream = psMalloc(NULL, CAstreamLen); - memset(CAstream, 0x0, CAstreamLen); - } - else - { - CAstream = NULL; - } - - CAstreamLen = 0; -# ifdef USE_RSA_CIPHER_SUITE - memcpy(CAstream, rsaCAFile, strlen(rsaCAFile)); - CAstreamLen += strlen(rsaCAFile); -# ifdef USE_ECC_CIPHER_SUITE - memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; - memcpy(CAstream + CAstreamLen, ecdhRsaCAFile, strlen(ecdhRsaCAFile)); - CAstreamLen += strlen(ecdhRsaCAFile); -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - if (CAstreamLen > 0) - { - memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; - } - memcpy(CAstream + CAstreamLen, ecCAFile, strlen(ecCAFile)); -# endif - -/* Load Identiy */ -# ifdef EXAMPLE_RSA_KEYS - if ((rc = matrixSslLoadRsaKeys(keys, rsaCertFile, rsaPrivkeyFile, NULL, - (char *) CAstream)) < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return rc; - } -# endif - -# ifdef EXAMPLE_ECDH_RSA_KEYS - if ((rc = matrixSslLoadEcKeys(keys, ecdhRsaCertFile, ecdhRsaPrivkeyFile, - NULL, (char *) CAstream)) < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return rc; - } -# endif - -# ifdef EXAMPLE_EC_KEYS - if ((rc = matrixSslLoadEcKeys(keys, ecCertFile, ecPrivkeyFile, NULL, - (char *) CAstream)) < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return rc; - } -# endif - - if (CAstream) - { - psFree(CAstream); - } -# endif /* USE_HEADER_KEYS */ -# endif /* USE_ONLY_PSK_CIPHER_SUITE */ - -# ifdef USE_PSK_CIPHER_SUITE - for (rc = 0; rc < PSK_HEADER_TABLE_COUNT; rc++) - { - matrixSslLoadPsk(keys, - PSK_HEADER_TABLE[rc].key, sizeof(PSK_HEADER_TABLE[rc].key), - PSK_HEADER_TABLE[rc].id, sizeof(PSK_HEADER_TABLE[rc].id)); - } -# endif /* USE_PSK_CIPHER_SUITE */ rv = MATRIXSSL_ERROR; @@ -1145,6 +875,8 @@ out_main: matrixSslDeleteKeys(keys); matrixSslClose(); + clientconfigFree(); + # ifdef WIN32 _psTrace("Press any key to close"); getchar(); diff --git a/apps/dtls/dtlsCommon.h b/apps/dtls/dtlsCommon.h index 5da80e5..d657694 100644 --- a/apps/dtls/dtlsCommon.h +++ b/apps/dtls/dtlsCommon.h @@ -43,6 +43,10 @@ # include /* Defines EWOULDBLOCK, etc. */ # ifdef POSIX +# define USE_GETOPT_LONG +# ifdef USE_GETOPT_LONG +# include +# endif # include # include /* Defines AF_INET, etc. */ # include /* sockaddr */ diff --git a/apps/dtls/dtlsServer.c b/apps/dtls/dtlsServer.c index 1360236..533436f 100644 --- a/apps/dtls/dtlsServer.c +++ b/apps/dtls/dtlsServer.c @@ -854,7 +854,7 @@ int main(int argc, char **argv) const char *addrstr; addrstr = getaddrstring((struct sockaddr *) &inaddr, 1); psTraceIntDtls("Read %d bytes ", recvLen); - psTraceStrDtls("from %s\n", (char *) addrstr); + _psTraceStr("from %s\n", (char *) addrstr); psFree(addrstr, NULL); } # endif diff --git a/apps/ssl/Makefile b/apps/ssl/Makefile index 70ad43e..70a2a8a 100644 --- a/apps/ssl/Makefile +++ b/apps/ssl/Makefile @@ -31,6 +31,13 @@ endif CFLAGS+=$(CFLAGS_INTERNAL) LDFLAGS+=$(LDFLAGS_INTERNAL) +# Extra dependencies +MATRIXSSL_CONFIG:=$(shell make parse-config --directory $(MATRIXSSL_ROOT)/matrixssl) + +ifneq (,$(findstring USE_ZLIB_COMPRESSION, $(MATRIXSSL_CONFIG))) +LDFLAGS+=-lz +endif + include $(MATRIXSSL_ROOT)/common.mk # Linked files @@ -40,6 +47,9 @@ STATIC:=\ $(MATRIXSSL_ROOT)/core/libcore_s.a \ $(STATIC_INTERNAL) +STATIC_CLIENT:=\ + $(MATRIXSSL_ROOT)/apps/common/client_common_s.a + # Allow selecting the client auth identity (ID_RSA, ID_ECDH_ECDSA, # etc.) via an environment variable. ifneq '$(CIPHER_OPTION)' '' @@ -54,7 +64,7 @@ $(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile $(wildcard *.h) $(SERVER_EXE): $(SERVER_SRC:.c=.o) $(STATIC) $(CC) -o $@ $^ $(LDFLAGS) $(CFLAGS) -$(CLIENT_EXE): $(CLIENT_SRC:.c=.o) $(STATIC) +$(CLIENT_EXE): $(CLIENT_SRC:.c=.o) $(STATIC) $(STATIC_CLIENT) $(CC) -o $@ $^ $(LDFLAGS) $(CFLAGS) $(NET_EXE): $(NET_SRC:.c=.o) $(STATIC) diff --git a/apps/ssl/client.c b/apps/ssl/client.c index 886d805..bc4d68d 100644 --- a/apps/ssl/client.c +++ b/apps/ssl/client.c @@ -39,7 +39,12 @@ #include #include "app.h" #ifndef WIN32 -# include +# define USE_GETOPT_LONG +# ifdef USE_GETOPT_LONG +# include +# else +# include +# endif #else # include "XGetopt.h" #endif @@ -47,6 +52,7 @@ /* Currently this example uses _psTrace for tracing, so osdep.h is needed: */ #include "core/osdep.h" #include "core/psUtil.h" +# include "../common/client_common.h" #ifdef USE_CLIENT_SIDE_SSL @@ -58,218 +64,17 @@ # endif # endif -/* - If supporting client authentication, pick ONE identity to auto select a - certificate and private key that support desired algorithms. - */ -/* #define ID_RSA */ /* RSA Certificate and Key */ -/* #define ID_ECDH_ECDSA */ /* EC Certificate and Key */ -/* #define ID_ECDH_RSA */ /* EC Key with RSA signed certificate */ - -# if !defined(ID_RSA) && !defined(ID_ECDH_ECDSA) && !defined(ID_ECDH_RSA) -/* Choose a default identity based on which algorithms are supported. */ -# ifdef USE_RSA_CIPHER_SUITE -# define ID_RSA -# else -# ifdef USE_ECC_CIPHER_SUITE -# define ID_ECDH_ECDSA -# else -# ifndef USE_PSK_CIPHER_SUITE -# error "Please enable either RSA or ECC for client when not using PSK" -# endif /* !USE_PSK_CIPHER_SUITE */ -# endif /* USE_ECC_CIPHER_SUITE */ -# endif /* USE_RSA_CIPHER_SUITE */ -# endif /* !ID_RSA && !ID_ECDH_ECDSA && !ID_ECDH_RSA */ - -# define USE_HEADER_KEYS # define ALLOW_ANON_CONNECTIONS 0 # define CRL_MAX_LENGTH 1048576 /* Maximum length for CRL: 1 megabyte. */ -/* If the algorithm type is supported, load a CA for it */ -# ifdef USE_ECC_CIPHER_SUITE - -/* - If ALLOW_CA_BUNDLE_PARTIAL_PARSE is defined, we can simply try to load - all EC CA certs, even if we are not able to parse all of them. -*/ -# ifdef ALLOW_CA_BUNDLE_PARTIAL_PARSE -# ifdef USE_HEADER_KEYS -# include "testkeys/EC/ALL_EC_CAS.h" -# else -static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS.pem"; -# endif /* USE_HEADER_KEYS */ -# else /* !(ALLOW_CA_BUNDLE_PARTIAL_PARSE) */ -/* - If ALLOW_CA_BUNDLE_PARTIAL_PARSE is not defined, we need the following, - ugly code to load only those CA bundles, where each cert is supported - by the present configuration. -*/ -# if defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) -# ifdef USE_HEADER_KEYS -# include "testkeys/EC/ALL_EC_CAS.h" -# else -static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS.pem"; -# endif /* USE_HEADER_KEYS */ -# endif /* USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && defined(USE_SECP521R1) -# ifdef USE_HEADER_KEYS -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192.h" -# else -static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P192.pem"; -# endif /* USE_HEADER_KEYS */ -# endif /* !USE_SECP192R1 && USE_SECP224R1 && USE_SECP521R1 */ - -# if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) -# ifdef USE_HEADER_KEYS -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224.h" -# else -static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P224.pem"; -# endif /* USE_HEADER_KEYS */ -# endif /* USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ - -# if defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) -# ifdef USE_HEADER_KEYS -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P521.h" -# else -static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P521.pem"; -# endif /* USE_HEADER_KEYS */ -# endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && defined(USE_SECP521R1) -# ifdef USE_HEADER_KEYS -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.h" -# else -static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P224.pem"; -# endif /* USE_HEADER_KEYS */ -# endif /* !USE_SECP192R1 && !USE_SECP224R1 && USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && defined(USE_SECP224R1) && !defined(USE_SECP521R1) -# ifdef USE_HEADER_KEYS -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.h" -# else -static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P192_AND_P521.pem"; -# endif /* USE_HEADER_KEYS */ -# endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ - -# if defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) -# ifdef USE_HEADER_KEYS -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.h" -# else -static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P224_AND_P521.pem"; -# endif /* USE_HEADER_KEYS */ -# endif /* USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ - -# if !defined(USE_SECP192R1) && !defined(USE_SECP224R1) && !defined(USE_SECP521R1) -# ifdef USE_HEADER_KEYS -# include "testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.h" -# else -static char ecCAFile[] = "../../testkeys/EC/ALL_EC_CAS_EXCEPT_P192_P224_AND_P521.pem"; -# endif /* USE_HEADER_KEYS */ -# endif /* !USE_SECP192R1 && USE_SECP224R1 && !USE_SECP521R1 */ - -#endif /* ALLOW_CA_BUNDLE_PARTIAL_PARSE */ - -# ifndef USE_HEADER_KEYS -/* - Pointer to filename. We shall increment this when we need to - skip over the ../../ prefix. - */ -static char *pEcCAFile = ecCAFile; -# endif /* !USE_HEADER_KEYS */ - -# endif /* USE_ECC_CIPHER_SUITE */ - -# ifdef USE_HEADER_KEYS -/* CAs */ -# ifdef USE_RSA_CIPHER_SUITE -# include "testkeys/RSA/ALL_RSA_CAS.h" -# ifdef USE_ECC_CIPHER_SUITE -# include "testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.h" -# endif -# endif - -/* Identity Certs and Keys for use with Client Authentication */ -# ifdef ID_RSA -# define EXAMPLE_RSA_KEYS -# include "testkeys/RSA/1024_RSA.h" -# include "testkeys/RSA/1024_RSA_KEY.h" -# include "testkeys/RSA/2048_RSA.h" -# include "testkeys/RSA/2048_RSA_KEY.h" -# include "testkeys/RSA/3072_RSA.h" -# include "testkeys/RSA/3072_RSA_KEY.h" -# include "testkeys/RSA/4096_RSA.h" -# include "testkeys/RSA/4096_RSA_KEY.h" -# endif - -# ifdef ID_ECDH_ECDSA -# define EXAMPLE_EC_KEYS -# include "testkeys/EC/384_EC.h" -# include "testkeys/EC/384_EC_KEY.h" -# endif - -# ifdef ID_ECDH_RSA -# define EXAMPLE_ECDH_RSA_KEYS -# include "testkeys/ECDH_RSA/521_ECDH-RSA.h" -# include "testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h" -# endif - -/* File-based keys */ -# else /* USE_HEADER_KEYS */ -/* CAs */ -# ifdef USE_RSA_CIPHER_SUITE -static char rsaCAFile[] = "../../testkeys/RSA/ALL_RSA_CAS.pem"; -static char *pRsaCAFile = rsaCAFile; -# ifdef USE_ECC_CIPHER_SUITE -static char ecdhRsaCAFile[] = "../../testkeys/ECDH_RSA/ALL_ECDH-RSA_CAS.pem"; -static char *pEcdhRsaCAFile = ecdhRsaCAFile; -# endif -# endif - -/* Identity Certs and Keys for use with Client Authentication */ -# ifdef ID_RSA -# define EXAMPLE_RSA_KEYS -static char rsaCertFile[] = "../../testkeys/RSA/2048_RSA.pem"; -static char rsaPrivkeyFile[] = "../../testkeys/RSA/2048_RSA_KEY.pem"; -static char *pRsaCertFile = rsaCertFile; -static char *pRsaPrivkeyFile = rsaPrivkeyFile; -# endif - -# ifdef ID_ECDH_ECDSA -# define EXAMPLE_EC_KEYS -static char ecCertFile[] = "../../testkeys/EC/384_EC.pem"; -static char ecPrivkeyFile[] = "../../testkeys/EC/384_EC_KEY.pem"; -static char *pEcCertFile = ecCertFile; -static char *pEcPrivkeyFile = ecPrivkeyFile; -# endif - -# ifdef ID_ECDH_RSA -# define EXAMPLE_ECDH_RSA_KEYS -static char ecdhRsaCertFile[] = "../../testkeys/ECDH_RSA/521_ECDH-RSA.pem"; -static char ecdhRsaPrivkeyFile[] = "../../testkeys/ECDH_RSA/521_ECDH-RSA_KEY.pem"; -static char *pEcdhRsaCertFile = ecdhRsaCertFile; -static char *pEcdhRsaPrivkeyFile = ecdhRsaPrivkeyFile; -# endif - /* #define REHANDSHAKE_TEST */ # ifdef REHANDSHAKE_TEST static int g_rehandshakeFlag = 0; # endif -static char *g_ca_file; -# endif /* USE_HEADER_KEYS */ - -/* - No file-based keys for PSK. - Include psk.h even when USE_HEADER_KEYS is not defined. - */ -# ifdef USE_PSK_CIPHER_SUITE -/* Defines PSK_HEADER_TABLE and PSK_HEADER_TABLE_COUNT */ -# include "../../testkeys/PSK/psk.h" -# endif - /********************************** Globals ***********************************/ static unsigned char g_httpRequestHdr[] = "GET %s HTTP/1.0\r\n" + "Host: %s\r\n" "User-Agent: MatrixSSL/" MATRIXSSL_VERSION "\r\n" "Accept: */*\r\n" "Content-Length: 0\r\n" @@ -284,7 +89,8 @@ extern int opterr; static char g_ip[16]; static char g_path[256]; static int g_port, g_new, g_resumed, g_ciphers, g_version, g_closeServer; -static int g_key_len, g_disableCertNameChk; +static int g_min_version, g_max_version, g_version_range_set; +static int g_disableCertNameChk; static int g_max_verify_depth; static uint16_t g_cipher[16]; static int g_trace; @@ -292,6 +98,12 @@ static int g_keepalive; static uint32_t g_bytes_requested; static uint8_t g_send_closure_alert; +static int g_print_http_response; + +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING +static const char *g_on_demand_cert_file = "testkeys/RSA/3072_RSA.pem"; +static const char *g_on_demand_key_file = "testkeys/RSA/3072_RSA_KEY.pem"; +# endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ struct g_sslstats { @@ -300,16 +112,6 @@ struct g_sslstats int64 datatime; }; -# ifndef USE_HEADER_KEYS -/* - Are we in MatrixSSL root dir? If yes, we shall to skip - the "../.." prefix in the key and cert filenames. - */ -static int g_at_matrixssl_root = 0; -# endif /* USE_HEADER_KEYS */ - -static int g_enable_ext_cv_sig_op = 0; - /********************************** Defines ***********************************/ /****************************** Local Functions *******************************/ @@ -350,6 +152,9 @@ static void fetchSavedCRL(psX509Cert_t *potentialIssuers); # ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING # endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */ +static void sslstatsPrintTime(const struct g_sslstats* stats, int conn_count); +static void addTimeDiff(int64 *t, psTime_t t1, psTime_t t2); + /******************************************************************************/ /* Make a secure HTTP request to a defined IP and port @@ -396,42 +201,48 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid, return PS_PLATFORM_FAIL; } -# ifdef SSL_FLAGS_SSLV3 - /* Corresponds to version 3.g_version */ - switch (g_version) - { - case 0: - sessionFlag = SSL_FLAGS_SSLV3; - break; - case 1: - sessionFlag = SSL_FLAGS_TLS_1_0; - break; - case 2: - sessionFlag = SSL_FLAGS_TLS_1_1; - break; - case 3: - sessionFlag = SSL_FLAGS_TLS_1_2; - break; - default: - sessionFlag = SSL_FLAGS_TLS_1_0; - break; - } -# else - /* MatrixSSL <= 3.4.2 don't support setting version on request */ - sessionFlag = 0; -# endif - memset(&options, 0x0, sizeof(sslSessOpts_t)); - options.versionFlag = sessionFlag; + + if (g_version_range_set) + { + rc = matrixSslSessOptsSetClientTlsVersionRange(&options, + g_min_version, + g_max_version); + if (rc < 0) + { + return rc; + } + } + else + { +# ifdef SSL_FLAGS_SSLV3 + /* Corresponds to version 3.g_version */ + switch (g_version) + { + case 0: + sessionFlag = SSL_FLAGS_SSLV3; + break; + case 1: + sessionFlag = SSL_FLAGS_TLS_1_0; + break; + case 2: + sessionFlag = SSL_FLAGS_TLS_1_1; + break; + case 3: + sessionFlag = SSL_FLAGS_TLS_1_2; + break; + default: + sessionFlag = SSL_FLAGS_TLS_1_0; + break; + } +# else + /* MatrixSSL <= 3.4.2 don't support setting version on request */ + sessionFlag = 0; +# endif + options.versionFlag = sessionFlag; + } + options.userPtr = keys; - /* options.maxFragLen = 512; */ - /* options.truncHmac = PS_TRUE; */ - /* options.ticketResumption = PS_TRUE; */ - /* options.ecFlags |= SSL_OPT_SECP521R1; */ - /* options.ecFlags |= SSL_OPT_SECP384R1; */ - /* options.ecFlags |= SSL_OPT_SECP256R1; */ - /* options.ecFlags |= SSL_OPT_SECP224R1; */ - /* options.ecFlags |= SSL_OPT_SECP192R1; */ # ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING # endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */ # ifdef TEST_KEEP_PEER_CERTS @@ -441,13 +252,6 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid, if (g_max_verify_depth != 0) options.validateCertsOpts.max_verify_depth = g_max_verify_depth; - /* - Do not allow the server to pick different version than what - we select here. Break the connection attempt with a protocol_version - alert if ServerHello.server_version < ClientHello.client_version. - */ - options.clientRejectVersionDowngrade = 1; - matrixSslNewHelloExtension(&extension, NULL); matrixSslCreateSNIext(NULL, (unsigned char *) g_ip, (uint32) strlen(g_ip), &ext, &extLen); @@ -561,42 +365,60 @@ READ_MORE: (uint32 *) &len)) < 0) { psGetTime(&t2, NULL); +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + if (rc == PS_PENDING && matrixSslNeedClientCert(ssl)) + { + _psTrace("Loading client cert and key in response to " \ + "CertificateRequest\n"); + if (ssl->keys->cert) + { + psX509FreeCert(ssl->keys->cert); + ssl->keys->cert = NULL; + } + if (ssl->keys->privKey.keysize > 0) + { + psClearPubKey(&ssl->keys->privKey); + } + if (matrixSslLoadKeys(ssl->keys, + g_on_demand_cert_file, + g_on_demand_key_file, + NULL, NULL, NULL) < 0) + { + _psTrace("matrixSslLoadKeys failed\n"); + exit(EXIT_FAILURE); + } + (void)matrixSslClientCertUpdated(ssl); + + /* Retry now that we have the cert and the priv key. */ + rc = matrixSslReceivedData(ssl, (int32) transferred, &buf, + (uint32 *) &len); + if (rc < 0) + { + _psTrace("Retry failed\n"); + } + goto WRITE_MORE; + } +# endif # ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING # endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */ if (ssl->hsState == SSL_HS_DONE) { -# ifdef USE_HIGHRES_TIME - stats->datatime += psDiffUsecs(t1, t2); -# else - stats->datatime += psDiffMsecs(t1, t2, NULL); -# endif + addTimeDiff(&stats->datatime, t1, t2); } else { -# ifdef USE_HIGHRES_TIME - stats->hstime += psDiffUsecs(t1, t2); -# else - stats->hstime += psDiffMsecs(t1, t2, NULL); -# endif + addTimeDiff(&stats->hstime, t1, t2); } goto L_CLOSE_ERR; } psGetTime(&t2, NULL); if (ssl->hsState == SSL_HS_DONE) { -# ifdef USE_HIGHRES_TIME - stats->datatime += psDiffUsecs(t1, t2); -# else - stats->datatime += psDiffMsecs(t1, t2, NULL); -# endif + addTimeDiff(&stats->datatime, t1, t2); } else { -# ifdef USE_HIGHRES_TIME - stats->hstime += psDiffUsecs(t1, t2); -# else - stats->hstime += psDiffMsecs(t1, t2, NULL); -# endif + addTimeDiff(&stats->hstime, t1, t2); } PROCESS_MORE: @@ -712,6 +534,15 @@ PROCESS_MORE: if (g_trace) { psTraceBytes("HTTP DATA", buf, len); + if (g_print_http_response) + { + char *resp_str = psMalloc(NULL, len+1); + + psMem2Str(resp_str, buf, len); + resp_str[len] = '\0'; + _psTraceStr("%s", resp_str); + free(resp_str); + } } rc = matrixSslProcessedData(ssl, &buf, (uint32 *) &len); if (rc < 0) @@ -781,14 +612,6 @@ L_CLOSE_ERR: { _psTrace("FAIL: No HTTP Response\n"); } - else - { -/* - printf("Received %d bytes %d usecs, state %d\n", - stats->rbytes, (int)stats->hstime, (int)stats->datatime, - ssl->hsState); - */ - } matrixSslDeleteSession(ssl); if (g_keepalive == 0) { @@ -841,14 +664,13 @@ static int32 httpWriteRequest(ssl_t *ssl) return MATRIXSSL_REQUEST_SEND; } - requested = strlen((char *) g_httpRequestHdr) + strlen(g_path) + 1; + requested = strlen((char *) g_httpRequestHdr) + strlen(g_path) + strlen(g_ip) + 1; if ((available = matrixSslGetWritebuf(ssl, &buf, requested)) < 0) { return PS_MEM_FAIL; } requested = min(requested, available); - snprintf((char *) buf, requested, (char *) g_httpRequestHdr, g_path); - + snprintf((char *) buf, requested, (char *) g_httpRequestHdr, g_path, g_ip); if (g_trace) { @@ -861,80 +683,6 @@ static int32 httpWriteRequest(ssl_t *ssl) return MATRIXSSL_REQUEST_SEND; } -# ifdef ID_RSA -# ifdef USE_HEADER_KEYS -static int32 loadRsaKeys(uint32 key_len, sslKeys_t *keys, - unsigned char *CAstream, int32 CAstreamLen) -{ - int32 rc; - const unsigned char *key_buf = NULL; - const unsigned char *cert_buf = NULL; - int32 key_buf_len = 0; - int32 cert_buf_len = 0; - - if (key_len == 1024) - { - _psTrace("Using 1024 bit RSA private key\n"); - cert_buf = RSA1024; - cert_buf_len = sizeof(RSA1024); - key_buf = RSA1024KEY; - key_buf_len = sizeof(RSA1024KEY); - } - else if (key_len == 2048) - { - _psTrace("Using 2048 bit RSA private key\n"); - cert_buf = RSA2048; - cert_buf_len = sizeof(RSA2048); - key_buf = RSA2048KEY; - key_buf_len = sizeof(RSA2048KEY); - } - else if (key_len == 3072) - { - _psTrace("Using 3072 bit RSA private key\n"); - cert_buf = RSA3072; - cert_buf_len = sizeof(RSA3072); - key_buf = RSA3072KEY; - key_buf_len = sizeof(RSA3072KEY); - } - else if (key_len == 4096) - { - _psTrace("Using 4096 bit RSA private key\n"); - cert_buf = RSA4096; - cert_buf_len = sizeof(RSA4096); - key_buf = RSA4096KEY; - key_buf_len = sizeof(RSA4096KEY); - } - else - { - _psTraceInt("Unsupported RSA private key size: %u\n", key_len); - return PS_FAILURE; - } - - if (g_enable_ext_cv_sig_op) - { - key_buf = NULL; - key_buf_len = 0; - } - - rc = matrixSslLoadRsaKeysMem(keys, cert_buf, cert_buf_len, - key_buf, key_buf_len, CAstream, CAstreamLen); - - if (rc < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream, NULL); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - } - - return rc; -} -# endif /* USE_HEADER_KEYS */ -# endif /* ID_RSA */ - static void usage(void) { printf( @@ -943,38 +691,74 @@ static void usage(void) "Options can be one or more of the following:\n" "\n" "-a - Disable sending closure alerts\n" + "--no-alerts\n" "-b - Client request size\n" + "--request-bytes \n" " Generates an HTTPS request after TLS negotiation\n" " Uses URL path of '/bytes?'\n" " Mutually exclusive with '-u' flag\n" "-c - Comma separated list of ciphers numbers\n" + "--ciphers - Path to certificate authority file\n" + "--ca \n" "-d - Disable server certicate name/addr chk\n" + "--no-name-check\n" + "-e - Enable/disable external certificate verification\n" + "--external-verify - RSA keyLen\n" + "--help\n" + "-k - RSA keyLen (if using client auth)\n" + "--rsa-key-len\n" " - Must be one of 1024, 2048 or 4096\n" "-K - Keepalive (Re-use socket after TLS session close)\n" + "--keep-alive\n" "-n - Num of new (full handshake) sessions\n" + "--handshakes \n" " - Default 1\n" + "-m - Maximum depth for certificate verification\n" + "--depth \n" "-p - Port number for SSL/TLS server\n" + "--port \n" " - Default 4433 (HTTPS is 443)\n" "-r - Num of resumed SSL/TLS sesssions\n" + "--resumed \n" " - Default 0\n" "-s - IP address of server machine/interface\n" + "--server \n" " - Default 127.0.0.1 (localhost)\n" + "-t - Enable printing of HTTP response\n" + "--response\n" "-u - URL path, eg. '/index.html'\n" + "--url \n" " Generates an HTTPS request after TLS negotiation\n" " Mutually exclusive with '-b' flag\n" "-V - SSL/TLS version to use\n" + "--tls \n" " - '0' SSL 3.0\n" " - '1' TLS 1.0\n" " - '2' TLS 1.1\n" " - '3' TLS 1.2 (default)\n" + "--tls-version-range ,\n" + " Set TLS version range, e.g.\n" + " 2,3 for TLS 1.1 - TLS 1.2\n" + "--no-cert - Unset client certificate\n" + "--cert \n" + " - Path to client certificate file\n" + "--key - Path to client private key file\n" + "--keytype \n" + " - Specify format of client certificate:\n" + " any (detect key and signature type)\n" + " rsa (for RSA keys)\n" + " ec (for EC keys ECDSA signature)\n" + " ecrsa (for EC keys with RSA signature)\n" "\n"); } @@ -1036,7 +820,7 @@ static int32 process_cmd_options(int32 argc, char **argv) g_ciphers = 0; g_cipher[0] = 0; g_disableCertNameChk = 0; - g_key_len = 1024; + g_key_len = 2048; g_new = 1; g_port = 4433; g_resumed = 0; @@ -1044,7 +828,53 @@ static int32 process_cmd_options(int32 argc, char **argv) g_keepalive = 0; opterr = 0; - while ((optionChar = getopt(argc, argv, "ab:C:c:de:hk:Km:n:p:r:s:u:V:")) != -1) + + const char *optstring = "ab:C:c:de:hk:Km:n:p:r:s:tu:V:"; + +#ifdef USE_GETOPT_LONG +#define ARG_NO_CERT 1 +#define ARG_CERT 2 +#define ARG_KEY 3 +#define ARG_KEYTYPE 4 +#define ARG_ON_DEMAND_CERT 5 +#define ARG_ON_DEMAND_KEY 6 +#define ARG_TLS_VERSION_RANGE 7 + + static struct option long_options[] = + { + {"no-alerts", no_argument, NULL, 'a'}, + {"request-bytes", required_argument, NULL, 'b'}, + {"ciphers", required_argument, NULL, 'c'}, + {"ca", required_argument, NULL, 'C'}, + {"no-name-check", no_argument, NULL, 'd'}, + {"external-verify", required_argument, NULL, 'e'}, + {"help", no_argument, NULL, 'h'}, + {"rsa-key-len", required_argument, NULL, 'k'}, + {"keep-alive", no_argument, NULL, 'K'}, + {"handshakes", required_argument, NULL, 'n'}, + {"depth", required_argument, NULL, 'm'}, + {"port", required_argument, NULL, 'p'}, + {"resumed", required_argument, NULL, 'r'}, + {"server", required_argument, NULL, 's'}, + {"response", no_argument, NULL, 't'}, + {"url", required_argument, NULL, 'u'}, + {"tls", required_argument, NULL, 'V'}, + {"tls-version-range", required_argument, NULL, ARG_TLS_VERSION_RANGE}, + {"no-cert", no_argument, NULL, ARG_NO_CERT}, + {"cert", required_argument, NULL, ARG_CERT}, + {"key", required_argument, NULL, ARG_KEY}, + {"on-demand-cert", required_argument, NULL, ARG_ON_DEMAND_CERT}, + {"on-demand-key", required_argument, NULL, ARG_ON_DEMAND_KEY}, + {"keytype", required_argument, NULL, ARG_KEYTYPE}, + {0, 0, 0, 0} + }; + + int opt_index = 0; + + while ((optionChar = getopt_long(argc, argv, optstring, long_options, &opt_index)) != -1) +#else + while ((optionChar = getopt(argc, argv, optstring)) != -1) +#endif { switch (optionChar) { @@ -1067,12 +897,8 @@ static int32 process_cmd_options(int32 argc, char **argv) break; case 'C': -#ifdef USE_HEADER_KEYS - printf("USE_HEADER_KEYS not compatible with CA file option\n"); -#else - g_ca_file = optarg; - printf("Using CA file: %s\n", g_ca_file); -#endif + g_clientconfig.ca_file = optarg; + clientconfigUseFileKeys(); break; case 'c': @@ -1124,6 +950,10 @@ static int32 process_cmd_options(int32 argc, char **argv) g_port = atoi(optarg); break; + case 't': + g_print_http_response = 1; + break; + case 'r': g_resumed = atoi(optarg); break; @@ -1151,12 +981,117 @@ static int32 process_cmd_options(int32 argc, char **argv) } g_version = version; break; + +#ifdef USE_GETOPT_LONG +/* Additional options not supported through short arguments */ + + case ARG_CERT: + g_clientconfig.cert_file = optarg; + clientconfigUseFileKeys(); + break; + + case ARG_NO_CERT: + g_clientconfig.cert_file = NULL; + g_clientconfig.privkey_file = optarg; + clientconfigUseFileKeys(); + break; + + case ARG_KEY: + g_clientconfig.privkey_file = optarg; + clientconfigUseFileKeys(); + break; + + case ARG_KEYTYPE: + if (strcmp("any", optarg) == 0) { + g_clientconfig.load_key = &loadKeysFromFile; + } else if (strcmp("rsa", optarg) == 0) { + g_clientconfig.load_key = &loadRsaKeysFromFile; + } else if (strcmp("ec", optarg) == 0) { + g_clientconfig.load_key = &loadECDH_ECDSAKeysFromFile; + } else if (strcmp("ecrsa", optarg) == 0) { + g_clientconfig.load_key = &loadECDHRsaKeysFromFile; + } else { + printf("Invalid option: %s\n", optarg); + return -1; + } + + g_clientconfig.loadKeysFromMemory = 0; + break; + + case ARG_TLS_VERSION_RANGE: + { + const char *versionRangeStr; + + versionRangeStr = optarg; + if (strlen(versionRangeStr) != 3) + { + printf("Invalid version range string: %s\n", + versionRangeStr); + return -1; + } + g_min_version = atoi(&versionRangeStr[0]); + g_max_version = atoi(&versionRangeStr[2]); + if (!matrixSslTlsVersionRangeSupported(g_min_version, + g_max_version)) + { + printf("Unsupported version range: %s\n", + versionRangeStr); + return -1; + } + g_version_range_set = 1; + } + break; + + case ARG_ON_DEMAND_CERT: +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + g_on_demand_cert_file = optarg; +# else + printf("Please enable USE_EXT_CLIENT_CERT_KEY_LOADING " \ + "in matrixsslConfig.h for --on-demand-cert\n"); +# endif + break; + + case ARG_ON_DEMAND_KEY: +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + g_on_demand_key_file = optarg; +# else + printf("Please enable USE_EXT_CLIENT_CERT_KEY_LOADING " \ + "in matrixsslConfig.h for --on-demand-key\n"); +# endif + break; +#endif /* USE_GETOPT_LONG */ } + } return 0; } +static void sslstatsPrintTime(const struct g_sslstats* stats, int conn_count) +{ +# ifdef USE_HIGHRES_TIME + printf("%d usec (%d avg usec/conn SSL handshake overhead)\n", + (int) stats->hstime, (int) (stats->hstime / conn_count)); + printf("%d usec (%d avg usec/conn SSL data overhead)\n", + (int) stats->datatime, (int) (stats->datatime / conn_count)); +# else + printf("%d msec (%d avg msec/conn SSL handshake overhead)\n", + (int) stats->hstime, (int) (stats->hstime / conn_count)); + printf("%d msec (%d avg msec/conn SSL data overhead)\n", + (int) stats->datatime, (int) (stats->datatime / conn_count)); +# endif +} + +static void addTimeDiff(int64 *t, psTime_t t1, psTime_t t2) +{ +# ifdef USE_HIGHRES_TIME + *t += psDiffUsecs(t1, t2); +# else + *t += psDiffMsecs(t1, t2, NULL); +# endif +} + + /******************************************************************************/ /* Main routine. Initialize SSL keys and structures, and make two SSL @@ -1166,20 +1101,14 @@ static int32 process_cmd_options(int32 argc, char **argv) */ int32 main(int32 argc, char **argv) { - int32 rc, CAstreamLen, i, exit_code; + int32 rc, i, exit_code; sslKeys_t *keys; sslSessionId_t *sid = NULL; struct g_sslstats stats; - unsigned char *CAstream; # if defined(USE_HEADER_KEYS) && !defined(ID_RSA) const unsigned char *key_buf; int32 key_buf_len; # endif /* USE_HEADER_KEYS && !ID_RSA */ -# ifndef USE_HEADER_KEYS - unsigned char *tmp_buf; - int32 tmp_buf_len; - char *pCA; -# endif /* USE_HEADER_KEYS */ # ifdef WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(1, 1), &wsaData); @@ -1187,6 +1116,8 @@ int32 main(int32 argc, char **argv) exit_code = 0; + clientconfigInitialize(); + if ((rc = matrixSslOpen()) < 0) { _psTrace("MatrixSSL library init failure. Exiting\n"); @@ -1202,6 +1133,7 @@ int32 main(int32 argc, char **argv) if (0 != process_cmd_options(argc, argv)) { usage(); + clientconfigFree(); return 0; } @@ -1229,277 +1161,10 @@ int32 main(int32 argc, char **argv) g_ciphers, g_strver[g_version]); } -# ifndef USE_ONLY_PSK_CIPHER_SUITE -# ifdef USE_HEADER_KEYS -/* - In-memory based keys - Build the CA list first for potential client auth usage - */ - CAstreamLen = 0; -# ifdef USE_RSA_CIPHER_SUITE - CAstreamLen += sizeof(RSACAS); -# ifdef USE_ECC_CIPHER_SUITE - CAstreamLen += sizeof(ECDHRSACAS); -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - CAstreamLen += sizeof(ECCAS); -# endif -# if defined(USE_RSA_CIPHER_SUITE) || defined(USE_ECC_CIPHER_SUITE) - CAstream = psMalloc(NULL, CAstreamLen); -# else - CAstream = NULL; -# endif - - CAstreamLen = 0; -# ifdef USE_RSA_CIPHER_SUITE - memcpy(CAstream, RSACAS, sizeof(RSACAS)); - CAstreamLen += sizeof(RSACAS); -# ifdef USE_ECC_CIPHER_SUITE - memcpy(CAstream + CAstreamLen, ECDHRSACAS, sizeof(ECDHRSACAS)); - CAstreamLen += sizeof(ECDHRSACAS); -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - memcpy(CAstream + CAstreamLen, ECCAS, sizeof(ECCAS)); - CAstreamLen += sizeof(ECCAS); -# endif - - -# ifdef ID_RSA - rc = loadRsaKeys(g_key_len, keys, CAstream, CAstreamLen); - if (rc < 0) + if (!clientconfigLoadKeys(keys)) { return EXIT_FAILURE; } -# endif - -# ifdef ID_ECDH_RSA - if (g_enable_ext_cv_sig_op) - { - key_buf = NULL; - key_buf_len = 0; - } - else - { - key_buf = ECDHRSA521KEY; - key_buf_len = sizeof(ECDHRSA521KEY); - } - - if ((rc = matrixSslLoadEcKeysMem(keys, ECDHRSA521, sizeof(ECDHRSA521), - key_buf, key_buf_len, (unsigned char *) CAstream, - CAstreamLen)) < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream, NULL); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return EXIT_FAILURE; - } -# endif - -# ifdef ID_ECDH_ECDSA - if (g_enable_ext_cv_sig_op) - { - key_buf = NULL; - key_buf_len = 0; - } - else - { - key_buf = EC384KEY; - key_buf_len = sizeof(EC384KEY); - } - - if ((rc = matrixSslLoadEcKeysMem(keys, EC384, sizeof(EC384), - key_buf, key_buf_len, (unsigned char *) CAstream, - CAstreamLen)) < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream, NULL); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return EXIT_FAILURE; - } -# endif - - if (CAstream) - { - psFree(CAstream, NULL); - } - -# else -/* - File based keys - */ - rc = psGetFileBuf(NULL, "testkeys/RSA/2048_RSA.pem", &tmp_buf, &tmp_buf_len); - if (rc >= 0) - { - g_at_matrixssl_root = 1; - } - else - { - g_at_matrixssl_root = 0; - } - psFree(tmp_buf, NULL); - - CAstreamLen = 0; -# ifdef USE_RSA_CIPHER_SUITE - if (g_at_matrixssl_root) - { - pRsaCAFile += 6; - } - CAstreamLen += (int32) strlen(pRsaCAFile) + 1; -# ifdef USE_ECC_CIPHER_SUITE - if (g_at_matrixssl_root) - { - pEcdhRsaCAFile += 6; - } - CAstreamLen += (int32) strlen(pEcdhRsaCAFile) + 1; -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - if (g_at_matrixssl_root) - { - pEcCAFile += 6; - } - CAstreamLen += (int32) strlen(pEcCAFile) + 1; -# endif - if (CAstreamLen > 0) - { - CAstream = psMalloc(NULL, CAstreamLen); - memset(CAstream, 0x0, CAstreamLen); - } - else - { - CAstream = NULL; - } - - CAstreamLen = 0; -# ifdef USE_RSA_CIPHER_SUITE - memcpy(CAstream, pRsaCAFile, strlen(pRsaCAFile)); - CAstreamLen += strlen(pRsaCAFile); -# ifdef USE_ECC_CIPHER_SUITE - memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; - memcpy(CAstream + CAstreamLen, pEcdhRsaCAFile, strlen(pEcdhRsaCAFile)); - CAstreamLen += strlen(pEcdhRsaCAFile); -# endif -# endif -# ifdef USE_ECC_CIPHER_SUITE - if (CAstreamLen > 0) - { - memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; - } - memcpy(CAstream + CAstreamLen, pEcCAFile, strlen(pEcCAFile)); -# endif - -/* Load Identity */ -# ifdef EXAMPLE_RSA_KEYS - if (g_at_matrixssl_root) - { - pRsaCertFile += 6; - pRsaPrivkeyFile += 6; - } - if (g_enable_ext_cv_sig_op) - { - pRsaPrivkeyFile = NULL; - } - if (g_ca_file != NULL) - pCA = g_ca_file; - else - pCA = (char*)CAstream; - - if ((rc = matrixSslLoadRsaKeys(keys, pRsaCertFile, pRsaPrivkeyFile, - NULL, pCA) < 0)) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream, NULL); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return EXIT_FAILURE; - } -# endif /* EXAMPLE_RSA_KEYS */ - -# ifdef EXAMPLE_ECDH_RSA_KEYS - if (g_at_matrixssl_root) - { - pEcdhRsaCertFile += 6; - pEcdhRsaPrivkeyFile += 6; - } - - if (g_enable_ext_cv_sig_op) - { - pEcdhRsaPrivkeyFile = NULL; - } - - if (g_ca_file != NULL) - pCA = g_ca_file; - else - pCA = (char*)CAstream; - - if ((rc = matrixSslLoadEcKeys(keys, pEcdhRsaCertFile, pEcdhRsaPrivkeyFile, - NULL, pCA)) < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream, NULL); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return EXIT_FAILURE; - } -# endif /* EXAMPLE_ECDH_RSA_KEYS */ - -# ifdef EXAMPLE_EC_KEYS - if (g_at_matrixssl_root) - { - pEcCertFile += 6; - pEcPrivkeyFile += 6; - } - - if (g_enable_ext_cv_sig_op) - { - pEcPrivkeyFile = NULL; - } - - if ((rc = matrixSslLoadEcKeys(keys, pEcCertFile, pEcPrivkeyFile, NULL, - (char *) CAstream)) < 0) - { - _psTrace("No certificate material loaded. Exiting\n"); - if (CAstream) - { - psFree(CAstream, NULL); - } - matrixSslDeleteKeys(keys); - matrixSslClose(); - return EXIT_FAILURE; - } -# endif /* EXAMPLE_EC_KEYS */ - - if (CAstream) - { - psFree(CAstream, NULL); - } -# endif /* USE_HEADER_KEYS */ -# endif /* USE_ONLY_PSK_CIPHER_SUITE */ - -# ifdef USE_PSK_CIPHER_SUITE - for (rc = 0; rc < PSK_HEADER_TABLE_COUNT; rc++) - { - matrixSslLoadPsk(keys, - PSK_HEADER_TABLE[rc].key, sizeof(PSK_HEADER_TABLE[rc].key), - PSK_HEADER_TABLE[rc].id, sizeof(PSK_HEADER_TABLE[rc].id)); - } -# endif /* USE_PSK_CIPHER_SUITE */ # ifdef USE_CRL /* One initialization step that can be taken is to run through the CA @@ -1560,17 +1225,7 @@ int32 main(int32 argc, char **argv) psAssert(g_bytes_requested * g_new == stats.rbytes); } printf("%d bytes received\n", stats.rbytes); -# ifdef USE_HIGHRES_TIME - printf("%d usec (%d avg usec/conn SSL handshake overhead)\n", - (int) stats.hstime, (int) (stats.hstime / g_new)); - printf("%d usec (%d avg usec/conn SSL data overhead)\n", - (int) stats.datatime, (int) (stats.datatime / g_new)); -# else - printf("%d msec (%d avg msec/conn SSL handshake overhead)\n", - (int) stats.hstime, (int) (stats.hstime / g_new)); - printf("%d msec (%d avg msec/conn SSL data overhead)\n", - (int) stats.datatime, (int) (stats.datatime / g_new)); -# endif + sslstatsPrintTime(&stats, g_new); memset(&stats, 0x0, sizeof(struct g_sslstats)); printf("=== %d resumed connections ===\n", g_resumed); @@ -1601,17 +1256,7 @@ int32 main(int32 argc, char **argv) psAssert(g_bytes_requested * g_resumed == stats.rbytes); } printf("\n%d bytes received\n", stats.rbytes); -# ifdef USE_HIGHRES_TIME - printf("%d usec (%d avg usec/conn SSL handshake overhead)\n", - (int) stats.hstime, (int) (stats.hstime / g_resumed)); - printf("%d usec (%d avg usec/conn SSL data overhead)\n", - (int) stats.datatime, (int) (stats.datatime / g_resumed)); -# else - printf("%d msec (%d avg msec/conn SSL handshake overhead)\n", - (int) stats.hstime, (int) (stats.hstime / g_resumed)); - printf("%d msec (%d avg msec/conn SSL data overhead)\n", - (int) stats.datatime, (int) (stats.datatime / g_resumed)); -# endif + sslstatsPrintTime(&stats, g_resumed); } out: @@ -1620,6 +1265,8 @@ out: matrixSslDeleteKeys(keys); matrixSslClose(); + clientconfigFree(); + if (rc == MATRIXSSL_SUCCESS) { printf("TLS handshake complete.\n"); @@ -1672,7 +1319,6 @@ static void closeConn(ssl_t *ssl, SOCKET fd) if (fd != INVALID_SOCKET && g_keepalive == 0) { - /* printf("Closing socket from closeConn\n"); */ close(fd); } } @@ -1906,9 +1552,6 @@ RETRY_CRL_TEST_ONCE: goto RETRY_CRL_TEST_ONCE; # else /* MIDHANSHAKE_CRL_FETCH */ - /* if (next->extensions.ak.keyId) { */ - /* psTraceBytes("cert ak", next->extensions.ak.keyId, 20); */ - /* } */ _psTrace("Cert expects CRL. Failing handshake to go fetch it\n"); /* A more typical case if CRL testing is expected to be done is to halt the handshake now, go out and fetch the CRLs and @@ -2508,14 +2151,6 @@ static SOCKET lsocketConnect(char *ip, int32 port, int32 *err) printf("SO_RCVBUF: %d\n", rc); } # endif -# ifdef POSIX -/* rc = 1; */ -/* setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&rc, sizeof(rc)); */ -/* fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); */ -# elif defined(WIN32) -/* rc = 1; / * 1 for non-block, 0 for block * / */ -/* ioctlsocket(fd, FIONBIO, &rc); */ -# endif # ifdef __APPLE__ /* MAC OS X */ rc = 1; setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *) &rc, sizeof(rc)); diff --git a/apps/ssl/net.c b/apps/ssl/net.c index 9bac512..6c3e899 100644 --- a/apps/ssl/net.c +++ b/apps/ssl/net.c @@ -433,12 +433,12 @@ int do_dialog_client(const char *host, const char *port) } /* The MatrixSSL certificate validation callback. */ +# ifdef USE_CLIENT_SIDE_SSL static int32 ssl_cert_auth(ssl_t *ssl, psX509Cert_t *cert, int32 alert) { return MATRIXSSL_SUCCESS; } -# ifdef USE_CLIENT_SIDE_SSL static int32 extensionCb(ssl_t *ssl, uint16_t extType, uint8_t extLen, void *e) { @@ -642,14 +642,12 @@ int do_dialog_server(const char *host, const char *port) return 2; } -# ifdef USE_STATELESS_SESSION_TICKETS +# if defined(USE_SERVER_SIDE_SSL) && defined(USE_STATELESS_SESSION_TICKETS) static int32 sessTicketCb(void *keys, unsigned char name[16], short found); static unsigned char sessTicketSymKey[32] = { 0 }; static unsigned char sessTicketMacKey[32] = { 0 }; -# endif -# ifdef USE_STATELESS_SESSION_TICKETS int32 sessTicketCb(void *keys, unsigned char name[16], short found) { if (found) @@ -661,7 +659,7 @@ int32 sessTicketCb(void *keys, unsigned char name[16], short found) return matrixSslLoadSessionTicketKeys((sslKeys_t *) keys, name, sessTicketSymKey, 32, sessTicketMacKey, 32); } -# endif +# endif /* USE_SERVER_SIDE_SSL && USE_STATELESS_SESSION_TICKETS */ # ifdef USE_SERVER_SIDE_SSL int do_dialog_server_tls(const char *host, const char *port, diff --git a/apps/ssl/runClient.sh b/apps/ssl/runClient.sh index e2a9f9e..6f8a8f0 100755 --- a/apps/ssl/runClient.sh +++ b/apps/ssl/runClient.sh @@ -16,8 +16,8 @@ CIPHER_SUITE="47" #AES128-SHA #CIPHER_SUITE="57" #DHE_RSA AES256-SHA #CIPHER_SUITE="49195" #ECDHE_ECDSA-AES128-GCM-SHA256 #CIPHER_SUITE="49196" #ECDHE_ECDSA-AES256-GCM-SHA384 -#CIPHER_SUITE="52243" #TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -#CIPHER_SUITE="52244" #TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 +#CIPHER_SUITE="52392" #TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 +#CIPHER_SUITE="52393" #TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 fi if [ "X$PROTOCOL_VERSION" = "X" ] @@ -28,7 +28,12 @@ PROTOCOL_VERSION="3" #TLS1.2 fi IPADDR="127.0.0.1" + +if [ "X$PORT" = "X" ] +then PORT="4433" +fi + NEW_SESSIONS="1" RESUMED_SESSIONS="0" BYTES="1024" diff --git a/apps/ssl/server.c b/apps/ssl/server.c index 9b11b5a..3dfc9dc 100644 --- a/apps/ssl/server.c +++ b/apps/ssl/server.c @@ -66,6 +66,12 @@ const static char g_defaultCAFile[] = "testkeys/RSA/2048_RSA_CA.pem"; const static char g_defaultDHParamFile[] = "testkeys/DH/1024_DH_PARAMS.pem"; # endif +# ifdef USE_REHANDSHAKING +static int g_doSelfInitiatedRehandshakeTest; +static int g_numRehandshakes; +static int g_maxRehandshakes; +# endif + /********************************** Defines ***********************************/ # define SSL_TIMEOUT 45000 /* In milliseconds */ @@ -86,7 +92,8 @@ const static char g_defaultDHParamFile[] = "testkeys/DH/1024_DH_PARAMS.pem"; static DLListEntry g_conns; static int32 g_exitFlag; static int g_port; -static int g_version; +static int g_min_version; +static int g_max_version; static int g_disabledCiphers; static uint16_t g_disabledCipher[SSL_MAX_DISABLED_CIPHERS]; @@ -168,6 +175,13 @@ void SNIcallback(void *ssl, char *hostname, int32 hostnameLen, *newKeys = lssl->keys; } +int32 setProtocolVersions(sslSessOpts_t *options) +{ + return matrixSslSessOptsSetServerTlsVersionRange(options, + g_min_version, + g_max_version); +} + /******************************************************************************/ /** Display connections per second (if more than 0), at most once per second @@ -312,6 +326,11 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd) memset(&options, 0x0, sizeof(sslSessOpts_t)); options.userPtr = keys; /* options.extendedMasterSecret = 1; / * Require * / */ + if (setProtocolVersions(&options) < 0) + { + close(fd); + return PS_ARG_FAIL; + } if ((rc = matrixSslNewServerSession(&cp->ssl, keys, NULL, &options)) < 0) @@ -320,7 +339,6 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd) continue; } matrixSslRegisterSNICallback(cp->ssl, SNIcallback); - cp->fd = fd; cp->timeout = SSL_TIMEOUT; psGetTime(&cp->time, NULL); @@ -383,6 +401,26 @@ WRITE_MORE: { /* If the protocol is server initiated, send data here */ g_handshakes++; +# ifdef USE_REHANDSHAKING + if (g_doSelfInitiatedRehandshakeTest && + g_numRehandshakes < g_maxRehandshakes) + { + /* Full rehandshake */ + printf("Server initiating re-handshake\n"); + if (matrixSslEncodeRehandshake(cp->ssl, NULL, +# ifdef USE_CLIENT_AUTH + certCb, +# else + NULL, +# endif /* USE_CLIENT_AUTH */ + SSL_OPTION_FULL_HANDSHAKE, NULL, 0) < 0) + { + printf("matrixSslEncodeRehandshake failed\n"); + exit(1); + } + g_numRehandshakes++; + } +#endif /* USE_REHANDSHAKING */ # ifdef ENABLE_FALSE_START /* OR this could be a Chrome browser using FALSE_START and the application data is already @@ -750,6 +788,7 @@ static void usage(void) " - '1' TLS 1.0\n" " - '2' TLS 1.1\n" " - '3' TLS 1.2 (default)\n" + "-V , - SSL/TLS version range to use, e.g. '-V 2,3'\n" "\n"); } @@ -799,7 +838,7 @@ static int32_t parse_cipher_list(char *cipherListString, static int32 process_cmd_options(int32 argc, char **argv) { int optionChar, str_len, version, numCiphers; - char *cipherListString; + char *cipherListString, *versionRangeStr; /* Start with all options zeroized. */ memset(g_keyfilePath, 0, MAX_KEYFILE_PATH); @@ -809,12 +848,12 @@ static int32 process_cmd_options(int32 argc, char **argv) memset(g_caFile, 0, MAX_KEYFILE_PATH); memset(g_password, 0, MAX_PASSWORD_LEN); - g_port = HTTPS_PORT; - g_version = 3; - g_disabledCiphers = 0; + g_port = HTTPS_PORT; + g_min_version = g_max_version = 3; + g_disabledCiphers = 0; opterr = 0; - while ((optionChar = getopt(argc, argv, "c:d:a:D:hk:p:P:v:x:")) != -1) + while ((optionChar = getopt(argc, argv, "c:d:a:D:hk:p:P:v:V:x:r:")) != -1) { switch (optionChar) { @@ -899,14 +938,44 @@ static int32 process_cmd_options(int32 argc, char **argv) g_port = atoi(optarg); break; + case 'r': +#ifdef USE_REHANDSHAKING + g_doSelfInitiatedRehandshakeTest = 1; + g_maxRehandshakes = atoi(optarg); +#else + printf("Need USE_REHANDSHAKING for re-handshake test\n"); + exit(EXIT_FAILURE); +#endif + break; + case 'v': + /* Single version. */ version = atoi(optarg); - if (version < 0 || version > 3) + if (!matrixSslTlsVersionRangeSupported(version, + version)) { printf("Invalid version: %d\n", version); return -1; } - g_version = version; + g_min_version = g_max_version = version; + break; + + case 'V': + /* Version range. */ + versionRangeStr = optarg; + if (strlen(versionRangeStr) != 3) + { + printf("Invalid version range string: %s\n", versionRangeStr); + return -1; + } + g_min_version = atoi(&versionRangeStr[0]); + g_max_version = atoi(&versionRangeStr[2]); + if (!matrixSslTlsVersionRangeSupported(g_min_version, + g_max_version)) + { + printf("Unsupported version range: %s\n", versionRangeStr); + return -1; + } break; } } diff --git a/common.mk b/common.mk index 8778b60..56ead70 100644 --- a/common.mk +++ b/common.mk @@ -9,9 +9,11 @@ COMMON_MK_PATH:=$(dir $(lastword $(MAKEFILE_LIST))) # Allow extra CFLAGS, CPPFLAGS and LDFLAGS to be used. +CFLAGS_DEBUGGABLE=$(DEBUGGABLE) +CPPFLAGS_DEBUGGABLE=$(DEBUGGABLE) LDFLAGS += $(EXTRA_LDFLAGS) $(LDFLAGS_MAKEFILES) -CFLAGS += $(CFLAGS_STANDARD) $(CFLAGS_PLATFORM) $(CFLAGS_ADDITIONAL) $(CFLAGS_WARNINGS) $(CFLAGS_CPU) $(CFLAGS_ASM) $(CFLAGS_PROFILE) $(CFLAGS_MAKEFILES) $(DEBUGGABLE) $(EXTRA_CFLAGS) -CPPFLAGS += $(CPPFLAGS_STANDARD) $(CPPFLAGS_PLATFORM) $(CPPFLAGS_ADDITIONAL) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_CPPPU) $(CPPFLAGS_ASM) $(CPPFLAGS_PROFILE) $(CPPFLAGS_MAKEFILES) $(DEBUGGABLE) $(EXTRA_CPPFLAGS) +CFLAGS += $(CFLAGS_STANDARD) $(CFLAGS_PLATFORM) $(CFLAGS_ADDITIONAL) $(CFLAGS_WARNINGS) $(CFLAGS_CPU) $(CFLAGS_ASM) $(CFLAGS_PROFILE) $(CFLAGS_MAKEFILES) $(CFLAGS_DEBUGGABLE) $(CFLAGS_EXTRA) $(EXTRA_CFLAGS) +CPPFLAGS += $(CPPFLAGS_STANDARD) $(CPPFLAGS_PLATFORM) $(CPPFLAGS_ADDITIONAL) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_CPU) $(CPPFLAGS_CPPPU) $(CPPFLAGS_ASM) $(CPPFLAGS_PROFILE) $(CPPFLAGS_MAKEFILES) $(CPPFLAGS_DEBUGGABLE) $(CPPFLAGS_EXTRA) $(EXTRA_CPPFLAGS) #------------------------------------------------------------------------------- ## Makefile variables that must be defined in this file @@ -65,13 +67,25 @@ CLEAN_ENV=LC_ALL=POSIX # i386-redhat-linux # x86_64-redhat-linux ifeq '$(CCARCH)' '' +CCARCH:=$(shell $(CLEAN_ENV) $(CC) $(CFLAGS_ARCHITECTURE_VARIANT) $(FLAGS_ARCHITECTURE_VARIANT) -print-multiarch) +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.) +$(error Unable to determine compiler architecture. +$(CC) $(CFLAGS_ARCHITECTURE_VARIANT) $(FLAGS_ARCHITECTURE_VARIANT) -print-multiarch or $(CC) -v or $(CC) -dumpmachine does not work. Please, provide CCARCH manually via an environment variable.) +endif +endif +endif +ifeq ($(origin CCARCH),file) +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(MAKECMDGOALS),clobber) +$(info Compiling target architecture: $(CCARCH)) +$(info If this is incorrect, provide the CCARCH variable manually to make.) +endif endif endif endif @@ -133,6 +147,12 @@ ifndef MATRIX_DEBUG endif CFLAGS+=$(OPT) $(C_STD) +ifdef MATRIX_SSL_TRACE + CFLAGS+=-DUSE_SSL_HANDSHAKE_MSG_TRACE + CFLAGS+=-DUSE_SSL_INFORMATIONAL_TRACE + CFLAGS+=-DUSE_DTLS_DEBUG_TRACE +endif + ifeq "$(COMMON_MK_NO_TARGETS)" "" default: $(BUILD) @@ -149,18 +169,22 @@ endif # 64 Bit Intel Target ifneq (,$(findstring x86_64-,$(CCARCH))) - CFLAGS+=-m64 + CFLAGS_ARCHITECTURE_VARIANT=-m64 STROPTS+=", 64-bit Intel RSA/ECC ASM" - # Enable AES-NI if the host supports it (assumes Host is Target) + # Provide flags for AES-NI if the host supports it (assumes Host is Target) ifneq (,$(findstring -linux,$(CCARCH))) ifeq ($(shell grep -o -m1 aes /proc/cpuinfo),aes) - CFLAGS+=-maes -mpclmul -msse4.1 + CFLAGS_ENABLE_AESNI=-maes -mpclmul -msse4.1 + CFLAGS_ENABLE_AES=-maes + CFLAGS+=$(CFLAGS_ENABLE_AES) STROPTS+=", AES-NI ASM" endif endif ifneq (,$(findstring apple,$(CCARCH))) ifeq ($(shell sysctl -n hw.optional.aes),1) - CFLAGS+=-maes -mpclmul -msse4.1 + CFLAGS_ENABLE_AESNI=-maes -mpclmul -msse4.1 + CFLAGS_ENABLE_AES=-maes + CFLAGS+=$(CFLAGS_ENABLE_AES) STROPTS+=", AES-NI ASM" endif endif @@ -168,13 +192,16 @@ endif # 32 Bit Intel Target ifneq (,$(findstring i586-,$(CCARCH))) - CFLAGS+=-m32 + CFLAGS_ARCHITECTURE_VARIANT=-m32 ifneq (,$(findstring edison,$(shell uname -n))) ifneq (,$(findstring -O3,$(OPT))) #Edison does not like -O3 OPT:=-O2 endif - CFLAGS+=-DEDISON -maes -mpclmul -msse4.1 + CFLAGS+=-DEDISON + CFLAGS_ENABLE_AESNI=-maes -mpclmul -msse4.1 + CFLAGS_ENABLE_AES=-maes + CFLAGS+=$(CFLAGS_ENABLE_AES) STROPTS+=", 32-bit Intel RSA/ECC ASM, AES-NI ASM, Intel Edison" else STROPTS+=", 32-bit Intel RSA/ECC ASM" @@ -183,7 +210,7 @@ endif # 32 Bit Intel Target Alternate ifneq (,$(findstring i686-,$(CCARCH))) - CFLAGS+=-m32 + CFLAGS_ARCHITECTURE_VARIANT=-m32 STROPTS+=", 32-bit Intel RSA/ECC ASM" endif ifneq (,$(findstring i386-,$(CCARCH))) diff --git a/configs/default/coreConfig.h b/configs/default/coreConfig.h index 81fa819..d8a568f 100644 --- a/configs/default/coreConfig.h +++ b/configs/default/coreConfig.h @@ -52,6 +52,19 @@ # define USE_CORE_ASSERT # endif +/** + When logging or tracing use psLog.h APIs. + + Generally, using psLog.h allows more control over logging, because + it is possible to filter log and tracing information more efficiently. + However, this feature comes with a footprint cost, so the feature can be + disabled by setting NO_PS_LOGF_COMMON or by commenting out USE_PS_LOGF_COMMON + below. + */ +#ifdef NO_PS_LOGF_COMMON +#define USE_PS_LOGF_COMMON +#endif /* NO_PS_LOGF_COMMON */ + /** If enabled, calls to the psError set of APIs will perform a platform abort on the exeutable to aid in debugging. diff --git a/configs/default/cryptoConfig.h b/configs/default/cryptoConfig.h index 7ec451c..c5ade0e 100644 --- a/configs/default/cryptoConfig.h +++ b/configs/default/cryptoConfig.h @@ -125,7 +125,7 @@ TLS clients and servers. These cipher suites are not allowed in FIPS mode of operation. */ -/* #define USE_CHACHA20_POLY1305 */ +/* #define USE_CHACHA20_POLY1305_IETF */ /** @security 3DES is still relatively secure, however is deprecated for TLS */ # define USE_3DES @@ -231,7 +231,20 @@ */ /* #define ALLOW_CRL_ISSUERS_WITHOUT_KEYUSAGE */ # endif -# define USE_OCSP/**< @pre USE_SHA1 */ +/** + Enable OCSP response and request handling. +*/ +/* #define USE_OCSP *//**< @pre USE_SHA1 */ +# ifdef USE_OCSP +# define USE_OCSP_RESPONSE +# define USE_OCSP_REQUEST +# elif defined(USE_X509) && defined(USE_SHA1) +/** + Enable parsing and writing of OCSP responses. This is enough + to support OCSP stapling. +*/ +# define USE_OCSP_RESPONSE /**< @pre USE_SHA1 */ +#endif /* USE_OCSP */ /******************************************************************************/ /** diff --git a/configs/default/matrixsslConfig.h b/configs/default/matrixsslConfig.h index 8ef6140..a4c0347 100644 --- a/configs/default/matrixsslConfig.h +++ b/configs/default/matrixsslConfig.h @@ -83,8 +83,7 @@ extern "C" { # 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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral ECC DH keys, RSA certificates */ @@ -95,8 +94,7 @@ extern "C" { # 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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral Diffie-Hellman ciphersuites, with RSA certificates */ @@ -209,6 +207,24 @@ extern "C" { # define USE_CLIENT_SIDE_SSL # define USE_SERVER_SIDE_SSL +/******************************************************************************/ +/** + Allow the server to parse SSL 2.0 ClientHello messages even when the + server does not actually support SSL 2.0. As per RFC 5246, E.2: + + "... even TLS servers that do not support SSL 2.0 MAY accept version + 2.0 CLIENT-HELLO messages." + + This option is for compatibility with clients that support + SSL 2.0 but are ready to negotiate a higher version such as TLS 1.0. + Note that enabling this option will only allow parsing of the SSL 2.0 + ClientHellos; it will not enable support for the SSL 2.0 protocol. + Only 32-byte challenges in the SSL 2.0 ClientHello are supported. +*/ +# ifdef USE_SERVER_SIDE_SSL +/* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ +# endif + /******************************************************************************/ /** Client certificate authentication @@ -229,7 +245,16 @@ extern "C" { */ /* #define USE_EXT_EXAMPLE_MODULE */ # endif -# endif + +/** + Enable loading of a new client certificate and private key + in response to a CertificateRequest message from a server. This feature + allows the client program to e.g. select a client certificate + whose issuer is included in the server's list of trusted CAs + that was received in the CertificateRequest message. +*/ +/* #define USE_EXT_CLIENT_CERT_KEY_LOADING */ +# endif /* USE_CLIENT_AUTH */ /** Enable if the server should send an empty CertificateRequest message if @@ -283,11 +308,11 @@ extern "C" { 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 + @pre USE_OCSP_RESPONSE must be enabled 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 +# ifdef USE_OCSP_RESPONSE # define USE_OCSP_MUST_STAPLE /**< @security NIST_SHALL */ # endif @@ -304,6 +329,21 @@ extern "C" { */ /* #define USE_REHANDSHAKING */ +/******************************************************************************//** + False Start support for Chrome and Firefox browsers. + @see https://tools.ietf.org/html/rfc7918 + + Some versions of Firefox browser and Chrome browser include support for + False Start. This flag will enable server side support on MatrixSSL + operating as server for client using false start feature. + + @note April 2012: Google has announced this feature will be removed in + version 20 of their browser due to industry compatibility issues. + However because there are other browsers using the feature, this feature + is often recommendable to enable for maximal browser compatibility. + */ +# define USE_SERVER_SIDE_FALSE_START_SUPPORT + /******************************************************************************/ /** If SERVER you may define the number of sessions to cache and how diff --git a/configs/noecc/coreConfig.h b/configs/noecc/coreConfig.h index 81fa819..d8a568f 100644 --- a/configs/noecc/coreConfig.h +++ b/configs/noecc/coreConfig.h @@ -52,6 +52,19 @@ # define USE_CORE_ASSERT # endif +/** + When logging or tracing use psLog.h APIs. + + Generally, using psLog.h allows more control over logging, because + it is possible to filter log and tracing information more efficiently. + However, this feature comes with a footprint cost, so the feature can be + disabled by setting NO_PS_LOGF_COMMON or by commenting out USE_PS_LOGF_COMMON + below. + */ +#ifdef NO_PS_LOGF_COMMON +#define USE_PS_LOGF_COMMON +#endif /* NO_PS_LOGF_COMMON */ + /** If enabled, calls to the psError set of APIs will perform a platform abort on the exeutable to aid in debugging. diff --git a/configs/noecc/cryptoConfig.h b/configs/noecc/cryptoConfig.h index 130c3ff..b49a44f 100644 --- a/configs/noecc/cryptoConfig.h +++ b/configs/noecc/cryptoConfig.h @@ -125,7 +125,7 @@ TLS clients and servers. These cipher suites are not allowed in FIPS mode of operation. */ -/* #define USE_CHACHA20_POLY1305 */ +/* #define USE_CHACHA20_POLY1305_IETF */ /** @security 3DES is still relatively secure, however is deprecated for TLS */ # define USE_3DES @@ -231,7 +231,20 @@ */ /* #define ALLOW_CRL_ISSUERS_WITHOUT_KEYUSAGE */ # endif -# define USE_OCSP/**< @pre USE_SHA1 */ +/** + Enable OCSP response and request handling. +*/ +/* #define USE_OCSP *//**< @pre USE_SHA1 */ +# ifdef USE_OCSP +# define USE_OCSP_RESPONSE +# define USE_OCSP_REQUEST +# elif defined(USE_X509) && defined(USE_SHA1) +/** + Enable parsing and writing of OCSP responses. This is enough + to support OCSP stapling. +*/ +# define USE_OCSP_RESPONSE /**< @pre USE_SHA1 */ +#endif /* USE_OCSP */ /******************************************************************************/ /** diff --git a/configs/noecc/matrixsslConfig.h b/configs/noecc/matrixsslConfig.h index bb9f2c7..2e018e7 100644 --- a/configs/noecc/matrixsslConfig.h +++ b/configs/noecc/matrixsslConfig.h @@ -83,8 +83,7 @@ extern "C" { /* #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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral ECC DH keys, RSA certificates */ @@ -95,8 +94,7 @@ extern "C" { /* #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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral Diffie-Hellman ciphersuites, with RSA certificates */ @@ -209,6 +207,24 @@ extern "C" { # define USE_CLIENT_SIDE_SSL # define USE_SERVER_SIDE_SSL +/******************************************************************************/ +/** + Allow the server to parse SSL 2.0 ClientHello messages even when the + server does not actually support SSL 2.0. As per RFC 5246, E.2: + + "... even TLS servers that do not support SSL 2.0 MAY accept version + 2.0 CLIENT-HELLO messages." + + This option is for compatibility with clients that support + SSL 2.0 but are ready to negotiate a higher version such as TLS 1.0. + Note that enabling this option will only allow parsing of the SSL 2.0 + ClientHellos; it will not enable support for the SSL 2.0 protocol. + Only 32-byte challenges in the SSL 2.0 ClientHello are supported. +*/ +# ifdef USE_SERVER_SIDE_SSL +/* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ +# endif + /******************************************************************************/ /** Client certificate authentication @@ -229,7 +245,16 @@ extern "C" { */ /* #define USE_EXT_EXAMPLE_MODULE */ # endif -# endif + +/** + Enable loading of a new client certificate and private key + in response to a CertificateRequest message from a server. This feature + allows the client program to e.g. select a client certificate + whose issuer is included in the server's list of trusted CAs + that was received in the CertificateRequest message. +*/ +/* #define USE_EXT_CLIENT_CERT_KEY_LOADING */ +# endif /* USE_CLIENT_AUTH */ /** Enable if the server should send an empty CertificateRequest message if @@ -283,11 +308,11 @@ extern "C" { 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 + @pre USE_OCSP_RESPONSE must be enabled 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 +# ifdef USE_OCSP_RESPONSE # define USE_OCSP_MUST_STAPLE /**< @security NIST_SHALL */ # endif @@ -304,6 +329,21 @@ extern "C" { */ /* #define USE_REHANDSHAKING */ +/******************************************************************************//** + False Start support for Chrome and Firefox browsers. + @see https://tools.ietf.org/html/rfc7918 + + Some versions of Firefox browser and Chrome browser include support for + False Start. This flag will enable server side support on MatrixSSL + operating as server for client using false start feature. + + @note April 2012: Google has announced this feature will be removed in + version 20 of their browser due to industry compatibility issues. + However because there are other browsers using the feature, this feature + is often recommendable to enable for maximal browser compatibility. + */ +# define USE_SERVER_SIDE_FALSE_START_SUPPORT + /******************************************************************************/ /** If SERVER you may define the number of sessions to cache and how diff --git a/configs/psk/coreConfig.h b/configs/psk/coreConfig.h index 6bb01cd..3a09ef6 100644 --- a/configs/psk/coreConfig.h +++ b/configs/psk/coreConfig.h @@ -52,6 +52,19 @@ # define USE_CORE_ASSERT # endif +/** + When logging or tracing use psLog.h APIs. + + Generally, using psLog.h allows more control over logging, because + it is possible to filter log and tracing information more efficiently. + However, this feature comes with a footprint cost, so the feature can be + disabled by setting NO_PS_LOGF_COMMON or by commenting out USE_PS_LOGF_COMMON + below. + */ +#ifdef NO_PS_LOGF_COMMON +#define USE_PS_LOGF_COMMON +#endif /* NO_PS_LOGF_COMMON */ + /** If enabled, calls to the psError set of APIs will perform a platform abort on the exeutable to aid in debugging. diff --git a/configs/psk/cryptoConfig.h b/configs/psk/cryptoConfig.h index ec332b3..4caf4cd 100644 --- a/configs/psk/cryptoConfig.h +++ b/configs/psk/cryptoConfig.h @@ -125,7 +125,7 @@ TLS clients and servers. These cipher suites are not allowed in FIPS mode of operation. */ -/* #define USE_CHACHA20_POLY1305 */ +/* #define USE_CHACHA20_POLY1305_IETF */ /** @security 3DES is still relatively secure, however is deprecated for TLS */ /* #define USE_3DES */ @@ -231,7 +231,20 @@ */ /* #define ALLOW_CRL_ISSUERS_WITHOUT_KEYUSAGE */ # endif +/** + Enable OCSP response and request handling. +*/ /* #define USE_OCSP *//**< @pre USE_SHA1 */ +# ifdef USE_OCSP +# define USE_OCSP_RESPONSE +# define USE_OCSP_REQUEST +# elif defined(USE_X509) && defined(USE_SHA1) +/** + Enable parsing and writing of OCSP responses. This is enough + to support OCSP stapling. +*/ +# define USE_OCSP_RESPONSE /**< @pre USE_SHA1 */ +#endif /* USE_OCSP */ /******************************************************************************/ /** diff --git a/configs/psk/matrixsslConfig.h b/configs/psk/matrixsslConfig.h index 8bc1755..d69f685 100644 --- a/configs/psk/matrixsslConfig.h +++ b/configs/psk/matrixsslConfig.h @@ -83,8 +83,7 @@ extern "C" { /* #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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral ECC DH keys, RSA certificates */ @@ -95,8 +94,7 @@ extern "C" { /* #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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral Diffie-Hellman ciphersuites, with RSA certificates */ @@ -209,6 +207,24 @@ extern "C" { # define USE_CLIENT_SIDE_SSL # define USE_SERVER_SIDE_SSL +/******************************************************************************/ +/** + Allow the server to parse SSL 2.0 ClientHello messages even when the + server does not actually support SSL 2.0. As per RFC 5246, E.2: + + "... even TLS servers that do not support SSL 2.0 MAY accept version + 2.0 CLIENT-HELLO messages." + + This option is for compatibility with clients that support + SSL 2.0 but are ready to negotiate a higher version such as TLS 1.0. + Note that enabling this option will only allow parsing of the SSL 2.0 + ClientHellos; it will not enable support for the SSL 2.0 protocol. + Only 32-byte challenges in the SSL 2.0 ClientHello are supported. +*/ +# ifdef USE_SERVER_SIDE_SSL +/* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ +# endif + /******************************************************************************/ /** Client certificate authentication @@ -229,7 +245,16 @@ extern "C" { */ /* #define USE_EXT_EXAMPLE_MODULE */ # endif -# endif + +/** + Enable loading of a new client certificate and private key + in response to a CertificateRequest message from a server. This feature + allows the client program to e.g. select a client certificate + whose issuer is included in the server's list of trusted CAs + that was received in the CertificateRequest message. +*/ +/* #define USE_EXT_CLIENT_CERT_KEY_LOADING */ +# endif /* USE_CLIENT_AUTH */ /** Enable if the server should send an empty CertificateRequest message if @@ -283,11 +308,11 @@ extern "C" { 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 + @pre USE_OCSP_RESPONSE must be enabled 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 +# ifdef USE_OCSP_RESPONSE # define USE_OCSP_MUST_STAPLE /**< @security NIST_SHALL */ # endif @@ -304,6 +329,21 @@ extern "C" { */ /* #define USE_REHANDSHAKING */ +/******************************************************************************//** + False Start support for Chrome and Firefox browsers. + @see https://tools.ietf.org/html/rfc7918 + + Some versions of Firefox browser and Chrome browser include support for + False Start. This flag will enable server side support on MatrixSSL + operating as server for client using false start feature. + + @note April 2012: Google has announced this feature will be removed in + version 20 of their browser due to industry compatibility issues. + However because there are other browsers using the feature, this feature + is often recommendable to enable for maximal browser compatibility. + */ +# define USE_SERVER_SIDE_FALSE_START_SUPPORT + /******************************************************************************/ /** If SERVER you may define the number of sessions to cache and how diff --git a/configs/rsaonly/coreConfig.h b/configs/rsaonly/coreConfig.h index 81fa819..d8a568f 100644 --- a/configs/rsaonly/coreConfig.h +++ b/configs/rsaonly/coreConfig.h @@ -52,6 +52,19 @@ # define USE_CORE_ASSERT # endif +/** + When logging or tracing use psLog.h APIs. + + Generally, using psLog.h allows more control over logging, because + it is possible to filter log and tracing information more efficiently. + However, this feature comes with a footprint cost, so the feature can be + disabled by setting NO_PS_LOGF_COMMON or by commenting out USE_PS_LOGF_COMMON + below. + */ +#ifdef NO_PS_LOGF_COMMON +#define USE_PS_LOGF_COMMON +#endif /* NO_PS_LOGF_COMMON */ + /** If enabled, calls to the psError set of APIs will perform a platform abort on the exeutable to aid in debugging. diff --git a/configs/rsaonly/cryptoConfig.h b/configs/rsaonly/cryptoConfig.h index 7943a94..16eaf03 100644 --- a/configs/rsaonly/cryptoConfig.h +++ b/configs/rsaonly/cryptoConfig.h @@ -125,7 +125,7 @@ TLS clients and servers. These cipher suites are not allowed in FIPS mode of operation. */ -/* #define USE_CHACHA20_POLY1305 */ +/* #define USE_CHACHA20_POLY1305_IETF */ /** @security 3DES is still relatively secure, however is deprecated for TLS */ # define USE_3DES @@ -231,7 +231,20 @@ */ /* #define ALLOW_CRL_ISSUERS_WITHOUT_KEYUSAGE */ # endif -# define USE_OCSP/**< @pre USE_SHA1 */ +/** + Enable OCSP response and request handling. +*/ +/* #define USE_OCSP *//**< @pre USE_SHA1 */ +# ifdef USE_OCSP +# define USE_OCSP_RESPONSE +# define USE_OCSP_REQUEST +# elif defined(USE_X509) && defined(USE_SHA1) +/** + Enable parsing and writing of OCSP responses. This is enough + to support OCSP stapling. +*/ +# define USE_OCSP_RESPONSE /**< @pre USE_SHA1 */ +#endif /* USE_OCSP */ /******************************************************************************/ /** diff --git a/configs/rsaonly/matrixsslConfig.h b/configs/rsaonly/matrixsslConfig.h index fd0ff94..8276e82 100644 --- a/configs/rsaonly/matrixsslConfig.h +++ b/configs/rsaonly/matrixsslConfig.h @@ -83,8 +83,7 @@ extern "C" { /* #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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral ECC DH keys, RSA certificates */ @@ -95,8 +94,7 @@ extern "C" { /* #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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral Diffie-Hellman ciphersuites, with RSA certificates */ @@ -209,6 +207,24 @@ extern "C" { # define USE_CLIENT_SIDE_SSL # define USE_SERVER_SIDE_SSL +/******************************************************************************/ +/** + Allow the server to parse SSL 2.0 ClientHello messages even when the + server does not actually support SSL 2.0. As per RFC 5246, E.2: + + "... even TLS servers that do not support SSL 2.0 MAY accept version + 2.0 CLIENT-HELLO messages." + + This option is for compatibility with clients that support + SSL 2.0 but are ready to negotiate a higher version such as TLS 1.0. + Note that enabling this option will only allow parsing of the SSL 2.0 + ClientHellos; it will not enable support for the SSL 2.0 protocol. + Only 32-byte challenges in the SSL 2.0 ClientHello are supported. +*/ +# ifdef USE_SERVER_SIDE_SSL +/* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ +# endif + /******************************************************************************/ /** Client certificate authentication @@ -229,7 +245,16 @@ extern "C" { */ /* #define USE_EXT_EXAMPLE_MODULE */ # endif -# endif + +/** + Enable loading of a new client certificate and private key + in response to a CertificateRequest message from a server. This feature + allows the client program to e.g. select a client certificate + whose issuer is included in the server's list of trusted CAs + that was received in the CertificateRequest message. +*/ +/* #define USE_EXT_CLIENT_CERT_KEY_LOADING */ +# endif /* USE_CLIENT_AUTH */ /** Enable if the server should send an empty CertificateRequest message if @@ -283,11 +308,11 @@ extern "C" { 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 + @pre USE_OCSP_RESPONSE must be enabled 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 +# ifdef USE_OCSP_RESPONSE # define USE_OCSP_MUST_STAPLE /**< @security NIST_SHALL */ # endif @@ -304,6 +329,21 @@ extern "C" { */ /* #define USE_REHANDSHAKING */ +/******************************************************************************//** + False Start support for Chrome and Firefox browsers. + @see https://tools.ietf.org/html/rfc7918 + + Some versions of Firefox browser and Chrome browser include support for + False Start. This flag will enable server side support on MatrixSSL + operating as server for client using false start feature. + + @note April 2012: Google has announced this feature will be removed in + version 20 of their browser due to industry compatibility issues. + However because there are other browsers using the feature, this feature + is often recommendable to enable for maximal browser compatibility. + */ +# define USE_SERVER_SIDE_FALSE_START_SUPPORT + /******************************************************************************/ /** If SERVER you may define the number of sessions to cache and how diff --git a/configs/tls/coreConfig.h b/configs/tls/coreConfig.h index 81fa819..d8a568f 100644 --- a/configs/tls/coreConfig.h +++ b/configs/tls/coreConfig.h @@ -52,6 +52,19 @@ # define USE_CORE_ASSERT # endif +/** + When logging or tracing use psLog.h APIs. + + Generally, using psLog.h allows more control over logging, because + it is possible to filter log and tracing information more efficiently. + However, this feature comes with a footprint cost, so the feature can be + disabled by setting NO_PS_LOGF_COMMON or by commenting out USE_PS_LOGF_COMMON + below. + */ +#ifdef NO_PS_LOGF_COMMON +#define USE_PS_LOGF_COMMON +#endif /* NO_PS_LOGF_COMMON */ + /** If enabled, calls to the psError set of APIs will perform a platform abort on the exeutable to aid in debugging. diff --git a/configs/tls/cryptoConfig.h b/configs/tls/cryptoConfig.h index 1e9e064..806bc79 100644 --- a/configs/tls/cryptoConfig.h +++ b/configs/tls/cryptoConfig.h @@ -125,7 +125,7 @@ TLS clients and servers. These cipher suites are not allowed in FIPS mode of operation. */ -/* #define USE_CHACHA20_POLY1305 */ +/* #define USE_CHACHA20_POLY1305_IETF */ /** @security 3DES is still relatively secure, however is deprecated for TLS */ # define USE_3DES @@ -231,7 +231,20 @@ */ /* #define ALLOW_CRL_ISSUERS_WITHOUT_KEYUSAGE */ # endif -# define USE_OCSP/**< @pre USE_SHA1 */ +/** + Enable OCSP response and request handling. +*/ +/* #define USE_OCSP *//**< @pre USE_SHA1 */ +# ifdef USE_OCSP +# define USE_OCSP_RESPONSE +# define USE_OCSP_REQUEST +# elif defined(USE_X509) && defined(USE_SHA1) +/** + Enable parsing and writing of OCSP responses. This is enough + to support OCSP stapling. +*/ +# define USE_OCSP_RESPONSE /**< @pre USE_SHA1 */ +#endif /* USE_OCSP */ /******************************************************************************/ /** diff --git a/configs/tls/matrixsslConfig.h b/configs/tls/matrixsslConfig.h index 8ef6140..a4c0347 100644 --- a/configs/tls/matrixsslConfig.h +++ b/configs/tls/matrixsslConfig.h @@ -83,8 +83,7 @@ extern "C" { # 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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral ECC DH keys, RSA certificates */ @@ -95,8 +94,7 @@ extern "C" { # 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 */ -/** CHACHA20-POLY1305 cipher suites according to old draft. - Do not enable except for compatibility with obsolete software. */ +/** CHACHA20-POLY1305 cipher suites according to RFC 7905. */ /* #define USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */ /** Ephemeral Diffie-Hellman ciphersuites, with RSA certificates */ @@ -209,6 +207,24 @@ extern "C" { # define USE_CLIENT_SIDE_SSL # define USE_SERVER_SIDE_SSL +/******************************************************************************/ +/** + Allow the server to parse SSL 2.0 ClientHello messages even when the + server does not actually support SSL 2.0. As per RFC 5246, E.2: + + "... even TLS servers that do not support SSL 2.0 MAY accept version + 2.0 CLIENT-HELLO messages." + + This option is for compatibility with clients that support + SSL 2.0 but are ready to negotiate a higher version such as TLS 1.0. + Note that enabling this option will only allow parsing of the SSL 2.0 + ClientHellos; it will not enable support for the SSL 2.0 protocol. + Only 32-byte challenges in the SSL 2.0 ClientHello are supported. +*/ +# ifdef USE_SERVER_SIDE_SSL +/* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ +# endif + /******************************************************************************/ /** Client certificate authentication @@ -229,7 +245,16 @@ extern "C" { */ /* #define USE_EXT_EXAMPLE_MODULE */ # endif -# endif + +/** + Enable loading of a new client certificate and private key + in response to a CertificateRequest message from a server. This feature + allows the client program to e.g. select a client certificate + whose issuer is included in the server's list of trusted CAs + that was received in the CertificateRequest message. +*/ +/* #define USE_EXT_CLIENT_CERT_KEY_LOADING */ +# endif /* USE_CLIENT_AUTH */ /** Enable if the server should send an empty CertificateRequest message if @@ -283,11 +308,11 @@ extern "C" { 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 + @pre USE_OCSP_RESPONSE must be enabled 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 +# ifdef USE_OCSP_RESPONSE # define USE_OCSP_MUST_STAPLE /**< @security NIST_SHALL */ # endif @@ -304,6 +329,21 @@ extern "C" { */ /* #define USE_REHANDSHAKING */ +/******************************************************************************//** + False Start support for Chrome and Firefox browsers. + @see https://tools.ietf.org/html/rfc7918 + + Some versions of Firefox browser and Chrome browser include support for + False Start. This flag will enable server side support on MatrixSSL + operating as server for client using false start feature. + + @note April 2012: Google has announced this feature will be removed in + version 20 of their browser due to industry compatibility issues. + However because there are other browsers using the feature, this feature + is often recommendable to enable for maximal browser compatibility. + */ +# define USE_SERVER_SIDE_FALSE_START_SUPPORT + /******************************************************************************/ /** If SERVER you may define the number of sessions to cache and how diff --git a/core/Makefile b/core/Makefile index f1db298..49cfb6f 100644 --- a/core/Makefile +++ b/core/Makefile @@ -12,24 +12,29 @@ SRC:=\ corelib.c \ psbuf.c \ psUtil.c \ - $(OSDEP)/osdep.c + $(OSDEP)/osdep.c \ + $(OSDEP)/psLog.c \ + $(OSDEP)/psPrnf.c ASM:=memset_s.s # Generated files STATIC:=libcore_s.a +CFLAGS+=$(CFLAGS_ARCHITECTURE_VARIANT) $(FLAGS_ARCHITECTURE_VARIANT) +LDFLAGS+=$(LDFLAGS_ARCHITECTURE_VARIANT) $(FLAGS_ARCHITECTURE_VARIANT) + all: compile compile: $(ASM) $(OBJS) $(STATIC) # Special rule to build memset_s function without optimization memset_s.o: memset_s.c - $(CC) -O0 -Wall -ffunction-sections -fdata-sections -o $@ $(CFLAGS_MEMSET_S) -c $< + $(CC) -O0 -Wall -ffunction-sections -fdata-sections -o $@ $(CFLAGS_MEMSET_S) $(CFLAGS_ARCHITECTURE_VARIANT) $(FLAGS_ARCHITECTURE_VARIANT) -c $< # Generate the (.s) assembly file to verify zero is being performed $(ASM): memset_s.c - $(CC) -O0 -g -fverbose-asm $(CFLAGS_MEMSET_S) -S $< + $(CC) -O0 -g -fverbose-asm $(CFLAGS_MEMSET_S) $(ASFLAGS_ARCHITECTURE_VARIANT) $(FLAGS_ARCHITECTURE_VARIANT) -S $< # Additional Dependencies $(OBJS): $(MATRIXSSL_ROOT)/common.mk Makefile *.h diff --git a/core/POSIX/osdep.c b/core/POSIX/osdep.c index a09056a..366363d 100644 --- a/core/POSIX/osdep.c +++ b/core/POSIX/osdep.c @@ -624,11 +624,12 @@ int32 psGetFileBufFp(psPool_t *pool, FILE *fp, unsigned char **buf, { struct stat f_stat; size_t tmp = 0; + int fno = fileno(fp); - if (fstat(fileno(fp), &f_stat) != 0) + if (fstat(fno, &f_stat) != 0) { fclose(fp); - psTraceStrCore("Unable to stat %s\n", (char *) fileName); + psTraceIntCore("Unable to stat fp %d\n", fno); return PS_PLATFORM_FAIL; } *buf = psMalloc(pool, (size_t) (f_stat.st_size + 1)); diff --git a/core/coreApi.h b/core/coreApi.h index ce98a17..35f7f69 100644 --- a/core/coreApi.h +++ b/core/coreApi.h @@ -48,6 +48,58 @@ extern "C" { # include "list.h" # include "psmalloc.h" +/******************************************************************************/ +/* + macros for function definitions. + */ +# ifndef PS_C99 +# if defined(__cplusplus) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L +# define PS_C99(X) +# else +/** C99 only code. + Produce output for compiler that is only processed if compiler is in C99 + mode or later. This macro can be used to use security enhancing constructs + in C99 without losing backwards compatibility with ANSI-C or C++. */ +# define PS_C99(X) X +# endif +# endif +#ifndef PS_AT_LEAST +/** Pointer needs to point at least x items. + Usage of this macro enhances interface with known restrictions on + intended amount of input elements. The macro is intended for compiler + guidance and documentation. + */ +#define PS_AT_LEAST(x) PS_C99(static) x +#endif /* PS_AT_LEAST */ +#ifndef PS_AT_LEAST_EXPR +/** Pointer needs to point at least x items. + Usage of this macro enhances interface with known restrictions on + intended amount of input elements. The macro is intended for compiler + guidance and documentation. + + The limit is expressed as expression of other inputs to the function. + + @note: Due to implementation, the value of expr needs to be at least 1. */ +#define PS_AT_LEAST_EXPR(x) PS_C99(static) 1 +#endif /* PS_AT_LEAST_EXPR */ +#ifndef PS_EXACTLY +/** Pointer needs to point exactly x items. + Usage of this macro enhances interface with known restrictions on + intended amount of input elements. The macro is intended for compiler + guidance and documentation. + */ +#define PS_EXACTLY(x) PS_C99(static) x +#endif /* PS_EXACTLY */ +#ifndef PS_EXACTLY_EXPR +/** Pointer needs to point exactly x items. + Usage of this macro enhances interface with known restrictions on + intended amount of input elements. The macro is intended for compiler + guidance and documentation. + + @note: Due to implementation, the value of expr needs to be at least 1. */ +#define PS_EXACTLY_EXPR(x) PS_C99(static) 1 +#endif /* PS_EXACTLY_EXPR */ + /******************************************************************************/ /* psCore return codes @@ -290,9 +342,14 @@ typedef enum PS_STRING_GENERAL_STRING = 27, PS_STRING_UNIVERSAL_STRING = 28, PS_STRING_CHARACTER_STRING = 29, - PS_STRING_BMP_STRING = 30, + PS_STRING_BMP_STRING = 30, /* This is BMP (Basic Multilingual Plane) + string, i.e. 2 byte characters only. + Use #PS_STRING_UTF16_STRING instead if + any UTF-16 encoding is allowed. */ PS_STRING_CHAR_STRING = 256, /* Input is represented as C string. */ PS_STRING_WCHAR_STRING = 257, /* Input is represented as wchar_t string. */ + PS_STRING_UTF16_STRING = 258, /* Input is represented as UTF-16 encoding. + */ } psStringType_t; /* Option for strictly checking input to UTF8 String. @@ -320,6 +377,40 @@ PSPUBLIC int32 psToUtf8String(psPool_t *pool, unsigned char **output, size_t *output_len, int opts); +/* + Helper function for usual string conversions. + The current version allows conversion of + PS_STRING_NUMERIC_STRING, PS_STRING_PRINTABLE_STRING, PS_STRING_BMP_STRING + to UTF-16 (BE). This function produces unsigned char (generic octet string) + output for compatibility with other functions although the output length + is always multiple of two. + The string will have terminating \0\0. + output_len will be written string length not counting terminating \0\0. + output_len can be provided as NULL. + */ +PSPUBLIC int32 psToUtf16String(psPool_t *pool, + const unsigned char *input, size_t input_len, + psStringType_t input_type, + unsigned char **output, size_t *output_len, + int opts); + +/* + Helper function for usual string conversions. + The current version allows conversion of + PS_STRING_NUMERIC_STRING, PS_STRING_PRINTABLE_STRING, PS_STRING_BMP_STRING + to UTF-32 (BE). This function produces unsigned char (generic octet string) + output for compatibility with other functions although the output length + is always multiple of four. + The string will have terminating \0\0\0\0. + output_len will be written string length not counting terminating \0\0\0\0. + output_len can be provided as NULL. + */ +PSPUBLIC int32 psToUtf32String(psPool_t *pool, + const unsigned char *input, size_t input_len, + psStringType_t input_type, + unsigned char **output, size_t *output_len, + int opts); + /******************************************************************************/ /* Statistics helpers diff --git a/core/corelib.c b/core/corelib.c index c23e1da..24fb9ab 100644 --- a/core/corelib.c +++ b/core/corelib.c @@ -176,7 +176,7 @@ void _psErrorStr(const char *msg, const char *val) /* copy 'len' bytes from 'b' to 's', converting all to printable characters */ -static void mem2str(char *s, const unsigned char *b, uint32 len) +void psMem2Str(char *s, const unsigned char *b, uint32 len) { for (; len > 0; len--) { @@ -216,7 +216,7 @@ void psTraceBytes(const char *tag, const unsigned char *p, int l) { if (i != 0) { - mem2str(s, p - 16, 16); + psMem2Str(s, p - 16, 16); _psTraceStr(" %s", s); } #ifdef _LP64 @@ -243,7 +243,7 @@ void psTraceBytes(const char *tag, const unsigned char *p, int l) { memset(s, 0x0, 16); i = l & 0xF; - mem2str(s, p - i, (unsigned int) i); + psMem2Str(s, p - i, (unsigned int) i); for (; i < 16; i++) { _psTrace(" "); @@ -820,18 +820,46 @@ PSPUBLIC int psBrokenDownTimeCmp(const psBrokenDownTime_t *t1, /* Helper function for String conversion. */ -PSPUBLIC int32 psToUtf8String(psPool_t *pool, +static int32 psToUtfXString(psPool_t *pool, const unsigned char *input, size_t input_len, psStringType_t input_type, unsigned char **output, size_t *output_len, - int opts) + int oclen, int opts) { int32 err; psParseBuf_t in; psDynBuf_t out; size_t ignored_size; int clen = 1; - + unsigned char bytes0[4] = { 0, 0, 0, 0 }; + const unsigned short *map = NULL; + const unsigned short map_t61[256] = + { + /* T.61 maps most of the ASCII as-is. */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 0, 0, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 0, 93, 0, 95, + 0, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 0, 124, + 0, 0, 127, + /* Control characters. */ + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, + /* Extended characters */ + 160, 161, 162, 163, 36, 165, 166, 167, 168, 0, 0, 171, 0, 0, 0, 0, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 0, 0, 187, 188, 189, 190, + 191, + 0, 0x300, 0x301, 0x302, 0x303, 0x304, 0x306, 0x307, 0x308, + 0, 0x30A, 0x327, 0x332, 0x30B, 0x328, 0x30C, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x2126, 0xC6, 0xD0, 0xAA, 0x126, 0, 0x132, 0x13F, 0x141, 0xD8, 0x152, + 0xBA, 0xDE, 0x166, 0x14A, 0x149, 0x138, 0xE6, 0x111, 0xF0, 0x127, + 0x131, 0x133, 0x140, 0x142, 0xF8, 0x153, 0xDF, 0xFE, 0x167, 0x14B, 0 + }; if ((opts & ~PS_STRING_DUAL_NIL) != 0) { return PS_UNSUPPORTED_FAIL; @@ -843,6 +871,15 @@ PSPUBLIC int32 psToUtf8String(psPool_t *pool, case PS_STRING_PRINTABLE_STRING: /* These are subsets of ASCII. */ break; + case PS_STRING_TELETEX_STRING: + /* Superset of ASCII. */ + map = map_t61; + break; + case PS_STRING_UTF8_STRING: + /* UTF-8 characters. */ + clen = 0; + break; + case PS_STRING_UTF16_STRING: case PS_STRING_BMP_STRING: /* UCS2 characters. */ clen = 2; @@ -865,20 +902,57 @@ PSPUBLIC int32 psToUtf8String(psPool_t *pool, /* Create dynamic buffer with initial size estimate being the same than input + termination character(s). */ - err = psDynBufInit(pool, &out, input_len + 2) ? PS_SUCCESS : PS_MEM_FAIL; + err = psDynBufInit(pool, &out, + ((input_len + 2) * oclen)) ? PS_SUCCESS : PS_MEM_FAIL; if (err != PS_SUCCESS) { return err; } - if (clen == 1) + if (clen == 0) + { + /* UTF-8: */ + while(psParseBufCanReadUtf8(&in)) + { + unsigned int chr = psParseBufReadUtf8(&in); + if (oclen == 1) + { + (void) psDynBufAppendUtf8(&out, chr); + } + else if (oclen == 2) + { + (void) psDynBufAppendUtf16(&out, chr); + } + else /* oclen == 4 */ + { + (void) psDynBufAppendUtf32(&out, chr); + } + } + } + else if (clen == 1) { while (psParseCanRead(&in, 1)) { - int8_t chr = (int8_t) *in.buf.start; - if (chr >= 1) + unsigned short chr = (unsigned short) *in.buf.start; + + if (map) { - (void) psDynBufAppendChar(&out, (char) chr); + chr = map[chr]; + } + if ((chr >= 1 && chr <= 127) || (map && chr >= 1)) + { + if (oclen == 1) + { + (void) psDynBufAppendUtf8(&out, chr); + } + else + { + if (oclen == 4) + { + (void) psDynBufAppendUtf16(&out, 0); + } + (void) psDynBufAppendUtf16(&out, chr); + } } else { @@ -900,8 +974,50 @@ PSPUBLIC int32 psToUtf8String(psPool_t *pool, chr |= a[1]; if (chr != 0 && (chr < 0xd800 || chr > 0xdfff)) { - /* ASCII */ - (void) psDynBufAppendUtf8(&out, chr); + /* ASCII or other page 0 characters. */ + if (oclen == 1) + { + (void) psDynBufAppendUtf8(&out, chr); + } + else if (oclen == 2) + { + (void) psDynBufAppendUtf16(&out, chr); + } + else /* oclen == 4 */ + { + (void) psDynBufAppendUtf32(&out, chr); + } + } + else if ((chr >= 0xd800 && chr <= 0xdbff) && + input_type == PS_STRING_UTF16_STRING && + psParseCanRead(&in, 4)) + { + /* surrogates. */ + unsigned char b[2]; + unsigned int c; + memcpy(b, in.buf.start + 2, 2); + + c = (chr & 0x3FF) << 10; + c |= ((b[0] & 0x3) << 8) | b[1]; + if (b[0] < 0xDC || b[0] > 0xDF) + { + /* Invalid code point third byte needs to be 0xDC..0xDF. */ + err = PS_LIMIT_FAIL; + } + if (oclen == 1) + { + (void) psDynBufAppendUtf8(&out, c + 0x010000); + } + else if (oclen == 2) + { + (void) psDynBufAppendUtf16(&out, c + 0x010000); + } + else /* oclen == 4 */ + { + (void) psDynBufAppendUtf32(&out, c + 0x010000); + } + psParseBufSkipBytes(&in, a, 2); + memcpy(a, b, 2); } else { @@ -917,17 +1033,17 @@ PSPUBLIC int32 psToUtf8String(psPool_t *pool, output_len = &ignored_size; } - /* Append terminating \0 or \0\0. */ - psDynBufAppendChar(&out, 0); + /* Append terminating \0 or \0\0. x oclen */ + psDynBufAppendOctets(&out, bytes0, oclen); if ((opts & PS_STRING_DUAL_NIL) != 0) { - psDynBufAppendChar(&out, 0); + psDynBufAppendOctets(&out, bytes0, oclen); } if (err == PS_SUCCESS) { *output = psDynBufDetach(&out, output_len); - *output_len -= (opts & PS_STRING_DUAL_NIL) ? 2 : 1; + *output_len -= (opts & PS_STRING_DUAL_NIL) ? 2 * oclen : oclen; if (*output == NULL) { return PS_MEM_FAIL; @@ -940,5 +1056,35 @@ PSPUBLIC int32 psToUtf8String(psPool_t *pool, return err; } +PSPUBLIC int32 psToUtf8String(psPool_t *pool, + const unsigned char *input, size_t input_len, + psStringType_t input_type, + unsigned char **output, size_t *output_len, + int opts) +{ + return psToUtfXString(pool, input, input_len, input_type, + output, output_len, 1, opts); +} + +PSPUBLIC int32 psToUtf16String(psPool_t *pool, + const unsigned char *input, size_t input_len, + psStringType_t input_type, + unsigned char **output, size_t *output_len, + int opts) +{ + return psToUtfXString(pool, input, input_len, input_type, + output, output_len, 2, opts); +} + +PSPUBLIC int32 psToUtf32String(psPool_t *pool, + const unsigned char *input, size_t input_len, + psStringType_t input_type, + unsigned char **output, size_t *output_len, + int opts) +{ + return psToUtfXString(pool, input, input_len, input_type, + output, output_len, 4, opts); +} + /******************************************************************************/ diff --git a/core/osdep.h b/core/osdep.h index f3873ef..ce45c1f 100644 --- a/core/osdep.h +++ b/core/osdep.h @@ -34,6 +34,7 @@ /* This file depends on osdependent type definitions for osdep-types.h */ #include "osdep-types.h" +#include "psLog.h" #ifndef _h_PS_PLATFORM # define _h_PS_PLATFORM @@ -108,57 +109,112 @@ PSPUBLIC void _psError(const char *msg); PSPUBLIC void _psErrorInt(const char *msg, int32 val); PSPUBLIC void _psErrorStr(const char *msg, const char *val); -/* Generic trace and debug macros. */ -# define psTrace(x) _psTrace(x) -# define psTraceInt(x, i) _psTraceInt(x, i) -# define psTraceStr(x, s) _psTraceStr(x, s) -# define psTracePtr(x, p) _psTracePtr(x, p) +PSPUBLIC void psMem2Str(char *s, const unsigned char *b, uint32 len); +# include "psLog.h" + +/* Generic trace and debug macros. */ +# ifdef USE_PS_LOGF_COMMON +# define psTrace(x) PS_LOGF_COMMON(Log_Trace, PS_UNKNOWN, PS_LOGF_FMT, \ + PS_LOGF_FILELINE, "%s", x) +# define psTraceInt(x, i) PS_LOGF_COMMON(Log_Trace, PS_UNKNOWN, PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, i) +# define psTraceStr(x, s) PS_LOGF_COMMON(Log_Trace, PS_UNKNOWN, PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, s) +# define psTracePtr(x, p) PS_LOGF_COMMON(Log_Trace, PS_UNKNOWN, PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, p) +# else +# define psTrace(x) _psTrace(x) +# define psTraceInt(x, i) _psTraceInt(x, i) +# define psTraceStr(x, s) _psTraceStr(x, s) +# define psTracePtr(x, p) _psTracePtr(x, p) +# endif /******************************************************************************/ /* Core trace */ -# ifndef USE_CORE_TRACE -# define psTraceCore(x) -# define psTraceStrCore(x, y) -# define psTraceIntCore(x, y) -# define psTracePtrCore(x, y) +# ifdef USE_PS_LOGF_COMMON +# define psTraceCore(x) PS_LOGF_COMMON(Log_Trace, PS_CORE, PS_LOGF_FMT, \ + PS_LOGF_FILELINE, "%s", x) +# define psTraceIntCore(x, i) PS_LOGF_COMMON(Log_Trace, PS_CORE, PS_LOGF_FMT,\ + PS_LOGF_FILELINE, x, i) +# define psTraceStrCore(x, s) PS_LOGF_COMMON(Log_Trace, PS_CORE, PS_LOGF_FMT,\ + PS_LOGF_FILELINE, x, s) +# define psTracePtrCore(x, p) PS_LOGF_COMMON(Log_Trace, PS_CORE, PS_LOGF_FMT,\ + PS_LOGF_FILELINE, x, p) # else -# define psTraceCore(x) _psTrace(x) -# define psTraceStrCore(x, y) _psTraceStr(x, y) -# define psTraceIntCore(x, y) _psTraceInt(x, y) -# define psTracePtrCore(x, y) _psTracePtr(x, y) -# endif /* USE_CORE_TRACE */ +# ifndef USE_CORE_TRACE +# define psTraceCore(x) +# define psTraceStrCore(x, y) +# define psTraceIntCore(x, y) +# define psTracePtrCore(x, y) +# else +# define psTraceCore(x) _psTrace(x) +# define psTraceStrCore(x, y) _psTraceStr(x, y) +# define psTraceIntCore(x, y) _psTraceInt(x, y) +# define psTracePtrCore(x, y) _psTracePtr(x, y) +# endif /* USE_CORE_TRACE */ +# endif /* USE_PS_LOGF_COMMON */ /******************************************************************************/ /* HALT_ON_PS_ERROR define at compile-time determines whether to halt on psAssert and psError calls */ -# ifdef USE_CORE_ASSERT -# define psAssert(C) if (C) {; } else \ +# ifdef USE_PS_LOGF_COMMON +# ifdef HALT_ON_PS_ERROR +# define PS_OSDEP_BREAK() osdepBreak() +# else +# define PS_OSDEP_BREAK() do { } while(0) +# endif +extern void osdepBreak(void); +# ifdef USE_CORE_ASSERT +# define psAssert(C) do { if (C) {; } else \ + { halAlert(); PS_LOGF_COMMON(Log_Trace, PS_CORE, PS_LOGF_FMT, PS_LOGF_FILELINE, "%s", #C); PS_OSDEP_BREAK(); } } while(0) +# else +# define psAssert(C) if (C) {; } else do { /* assert ignored. */ } while (0) +# endif +# else +# ifdef USE_CORE_ASSERT +# define psAssert(C) if (C) {; } else \ { halAlert(); _psTraceStr("psAssert %s", __FILE__); _psTraceInt(":%d ", __LINE__); \ _psError(#C); } -# else -# define psAssert(C) if (C) {; } else do { /* assert ignored. */ } while (0) +# else +# define psAssert(C) if (C) {; } else do { /* assert ignored. */ } while (0) +# endif # endif -# ifdef USE_CORE_ERROR -# define psError(a) \ +# ifdef USE_PS_LOGF_COMMON +# ifdef USE_CORE_ERROR +# define psError(a) \ + do { halAlert(); PS_LOGF_COMMON(Log_Trace, PS_CORE, PS_LOGF_FMT, PS_LOGF_FILELINE, "%s", a); PS_OSDEP_BREAK(); } while(0) +# define psErrorStr(a, s) \ + do { halAlert(); PS_LOGF_COMMON(Log_Trace, PS_CORE, PS_LOGF_FMT, PS_LOGF_FILELINE, a, s); PS_OSDEP_BREAK(); } while(0) +# define psErrorInt(a, i) \ + do { halAlert(); PS_LOGF_COMMON(Log_Trace, PS_CORE, PS_LOGF_FMT, PS_LOGF_FILELINE, a, i); PS_OSDEP_BREAK(); } while(0) +# else +# define psError(a) do { /* error ignored. */ } while (0) +# define psErrorStr(a, b) do { /* error ignored. */ } while (0) +# define psErrorInt(a, b) do { /* error ignored. */ } while (0) +# endif +# else +# ifdef USE_CORE_ERROR +# define psError(a) \ halAlert(); _psTraceStr("psError %s", __FILE__); _psTraceInt(":%d ", __LINE__); \ _psError(a); -# define psErrorStr(a, b) \ +# define psErrorStr(a, b) \ halAlert(); _psTraceStr("psError %s", __FILE__); _psTraceInt(":%d ", __LINE__); \ _psErrorStr(a, b) -# define psErrorInt(a, b) \ +# define psErrorInt(a, b) \ halAlert(); _psTraceStr("psError %s", __FILE__); _psTraceInt(":%d ", __LINE__); \ _psErrorInt(a, b) -# else -# define psError(a) do { /* error ignored. */ } while (0) -# define psErrorStr(a, b) do { /* error ignored. */ } while (0) -# define psErrorInt(a, b) do { /* error ignored. */ } while (0) +# else +# define psError(a) do { /* error ignored. */ } while (0) +# define psErrorStr(a, b) do { /* error ignored. */ } while (0) +# define psErrorInt(a, b) do { /* error ignored. */ } while (0) +# endif # endif /******************************************************************************/ diff --git a/core/psbuf.c b/core/psbuf.c index 36bb2f2..4173cdb 100644 --- a/core/psbuf.c +++ b/core/psbuf.c @@ -39,8 +39,8 @@ #include "coreApi.h" #include "osdep.h" -/* Omit debug printouts. */ -#define debugf(...) do { } while (0) +#include "psLog.h" /* SafeZone/Matrix common logging framework */ +#define debugf(x, ...) PS_LOGF_TRACE(CORE_PSBUF, x ,##__VA_ARGS__ ) /* This address is indicator for static allocations pool, and does not need to point to any valid pool. The pool cannot be NULL, because @@ -371,9 +371,11 @@ static void *psDynBufGrow(psDynBuf_t *db, size_t head_sz, size_t tail_sz) 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); + (int) (db->buf.buf - db->master->buf.start), + (psSizeL_t) db->buf.size, + db->buf.start - db->buf.buf, + db->buf.end - db->buf.start, + db->buf.buf + db->buf.size - db->buf.end); #ifdef PSBUF_DEBUG_WITH_MEMSET /* For debugging: */ @@ -440,7 +442,7 @@ void *psDynBufAppendUtf8(psDynBuf_t *db, int chr) unsigned int ch = (unsigned int) chr; /* Do not encode characters outside valid UTF-8 range. */ - if (ch > 0x1FFFF) + if (ch > 0x10FFFF) { db->err++; return NULL; @@ -489,6 +491,55 @@ void *psDynBufAppendUtf8(psDynBuf_t *db, int chr) return enc; } +void *psDynBufAppendUtf16(psDynBuf_t *db, int chr) +{ + unsigned int ch = (unsigned int) chr; + unsigned char cha[4]; + unsigned int chl = 2; + + if (ch > 0xFFFF) + { + /* Do not encode characters outside valid UTF-16 range. */ + if (ch > 0x10FFFF) + { + db->err++; + return NULL; + } + ch -= 0x10000; + chl = 4; + + /* Encode low surrogate. */ + cha[2] = 0xDC + (3 & (unsigned char) (ch >> 8)); + cha[3] = (unsigned char) (ch & 255); + + /* Start encoding high surrogate. */ + ch >>= 10; + ch += 0xD800; + } + + cha[0] = (unsigned char) (ch >> 8); + cha[1] = (unsigned char) (ch & 255); + return psDynBufAppendOctets(db, cha, chl); +} + +void *psDynBufAppendUtf32(psDynBuf_t *db, int chr) +{ + unsigned int ch = (unsigned int) chr; + unsigned char cha[4]; + + /* Do not encode characters outside valid UCS-4 range (31 bits). */ + if (ch > 0x7FFFFFFF) + { + db->err++; + return NULL; + } + + cha[0] = (unsigned char) (ch >> 24); + cha[1] = (unsigned char) (ch >> 16); + cha[2] = (unsigned char) (ch >> 8); + cha[3] = (unsigned char) (ch & 255); + return psDynBufAppendOctets(db, cha, 4); +} void psDynBufReservePrepend(psDynBuf_t *db, size_t sz) { @@ -837,7 +888,8 @@ size_t psParseBufTrySkipBytes(psParseBuf_t *pb, size_t skip_bytes = 0; if (psParseCanRead(pb, numbytes) && - memcmp(bytes, pb->buf.start, numbytes) == 0) + (bytes == NULL || + memcmp(bytes, pb->buf.start, numbytes) == 0)) { skip_bytes = numbytes; } @@ -1087,4 +1139,76 @@ void psParseBufCancel(psParseBuf_t *pb) pb->pool = NULL; } +static int psParseBufCanReadUtf8Bytes(const psParseBuf_t *pb) +{ + unsigned char chr0; + int bytes = 0; + + if (!psParseCanRead(pb, 1)) + { + return 0; + } + chr0 = (unsigned char) *(pb->buf.start); + bytes = chr0 <= 0x7F ? 1 : + chr0 <= 0xBF ? 0 : + chr0 <= 0xDF ? 2 : + chr0 <= 0xEF ? 3 : + chr0 <= 0xF7 ? 4 : 0; + + if (bytes) + { + return psParseCanRead(pb, bytes) ? bytes : 0; + } + return 0; +} + +int psParseBufCanReadUtf8(const psParseBuf_t *pb) +{ + return !!psParseBufCanReadUtf8Bytes(pb); +} + +unsigned int psParseBufReadUtf8(psParseBuf_t *pb) +{ + int bytes; + unsigned char a[4]; + + bytes = psParseBufCanReadUtf8Bytes(pb); + if (bytes == 0) + { + pb->err = 1; + return 0; + } + memcpy(a, pb->buf.start, bytes); + pb->buf.start += bytes; + + switch(bytes) + { + case 1: + return a[0]; + case 2: + if ((a[1] & 0700) != 0200) + { + break; + } + return ((a[0] & 0077) << 6) | (a[1] & 0077); + case 3: + if ((a[1] & 0700) != 0200 || (a[2] & 0700) != 0200) + { + break; + } + return ((a[0] & 0x0F) << 12) | ((a[1] & 0077) << 6) | (a[2] & 0077); + case 4: + if ((a[1] & 0700) != 0200 || (a[2] & 0700) != 0200 || + (a[3] & 0700) != 0200) + { + break; + } + return ((a[0] & 0007) << 18) | ((a[1] & 0077) << 12) | + ((a[2] & 0077) << 6) | (a[3] & 0077); + } + /* Unable to parse UTF-8 encoding. */ + pb->err = 1; + return 0; +} + /* end of file psbuf.c */ diff --git a/core/psbuf.h b/core/psbuf.h index f3ce92d..b766f5a 100644 --- a/core/psbuf.h +++ b/core/psbuf.h @@ -110,6 +110,8 @@ static __inline void *psDynBufAppendChar(psDynBuf_t *db, char ch) } void *psDynBufAppendUtf8(psDynBuf_t *db, int chr); +void *psDynBufAppendUtf16(psDynBuf_t *db, int chr); +void *psDynBufAppendUtf32(psDynBuf_t *db, int chr); static __inline void *psDynBufPrependChar(psDynBuf_t *db, char ch) { @@ -288,6 +290,12 @@ static __inline int psParseCanRead(const psParseBuf_t *pb, size_t nbytes) return bytes_readable >= nbytes; } +/* Check if there is sufficient data to parse left. */ +PSPUBLIC int psParseBufCanReadUtf8(const psParseBuf_t *pb); + +/* Check if there is sufficient data to parse left. */ +PSPUBLIC unsigned int psParseBufReadUtf8(psParseBuf_t *pb); + /* Get length of following ASN.1 tag (specify tag as unsigned char or 0 for ANY). diff --git a/core/psmalloc.h b/core/psmalloc.h index b79ccde..9b09e11 100644 --- a/core/psmalloc.h +++ b/core/psmalloc.h @@ -70,7 +70,10 @@ # define psFree(A, B) free(A) # define psFreeNoPool free +#ifndef PS_POOL_T_DEFINED +#define PS_POOL_T_DEFINED typedef int32 psPool_t; +#endif /* Functions without pool: Add N to the name, omit pool. */ # define psCallocN(B, C) psCalloc(MATRIX_NO_POOL, (B), (C)) diff --git a/core/psnet.h b/core/psnet.h index 1a71335..62ae65c 100644 --- a/core/psnet.h +++ b/core/psnet.h @@ -111,6 +111,7 @@ typedef struct psSocketFunctions struct addrinfo **res); void (*psFreeaddrinfo)(struct addrinfo *res); int (*psFd)(const psSocket_t *sock); + ssize_t (*psPeek)(psSocket_t *sock, void *buf, size_t len); } psSocketFunctions_t; /* @@ -188,6 +189,10 @@ PSPUBLIC int32 psSocketReadAppendBuf(psSocket_t *sock, psBuf_t *in, psSocketOptions_t opts); PSPUBLIC ssize_t psSocketReadData(psSocket_t *sock, void *data, size_t len, psSocketOptions_t opts); +PSPUBLIC int32 psSocketPeekAppendBuf(psSocket_t *sock, psBuf_t *in, + psSocketOptions_t opts); +PSPUBLIC ssize_t psSocketPeekData(psSocket_t *sock, void *data, + size_t len, psSocketOptions_t opts); PSPUBLIC int32 psSocketReadBufferSequence(psSocket_t *sock, void *response, size_t *responseLen, diff --git a/crypto/Makefile b/crypto/Makefile index 1dc6a86..aabc38d 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -45,6 +45,52 @@ SRC:=\ pubkey/ecc.c \ pubkey/pubkey.c \ pubkey/rsa.c + +SRC_CHACHA20POLY = \ + aead/chacha20poly1305ietf/sse2/poly1305_sse2.c \ + aead/chacha20poly1305ietf/donna/poly1305_donna.c \ + aead/chacha20poly1305ietf/dolbeau/chacha20_dolbeau-avx2.c \ + aead/chacha20poly1305ietf/dolbeau/chacha20_dolbeau-ssse3.c \ + aead/chacha20poly1305ietf/ref/chacha20_ref.c \ + aead/chacha20poly1305ietf/stream_chacha20.c \ + aead/chacha20poly1305ietf/onetimeauth_poly1305.c \ + aead/chacha20poly1305ietf/ps_chacha20poly1305ietf.c \ + aead/chacha20poly1305ietf/aead_chacha20poly1305.c \ + aead/chacha20poly1305ietf/utils.c \ + aead/chacha20poly1305ietf/verify.c \ + aead/chacha20poly1305ietf/runtime.c +SRC+=$(SRC_CHACHA20POLY) +CFLAGS_ADDITIONAL_CHACHA20POLY=-I`pwd`/aead/chacha20poly1305ietf -I`pwd` +ifdef MATRIX_DEBUG +OPT_CHACHA20POLY=-O2 -std=gnu99 -g +else +OPT_CHACHA20POLY=-O2 -std=gnu99 +endif +aead/chacha20poly1305ietf/ps_chacha20poly1305ietf.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/ps_chacha20poly1305ietf.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/sse2/poly1305_sse2.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/sse2/poly1305_sse2.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/donna/poly1305_donna.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/donna/poly1305_donna.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/dolbeau/chacha20_dolbeau-avx2.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/dolbeau/chacha20_dolbeau-avx2.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/dolbeau/chacha20_dolbeau-ssse3.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/dolbeau/chacha20_dolbeau-ssse3.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/ref/chacha20_ref.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/ref/chacha20_ref.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/stream_chacha20.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/stream_chacha20.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/onetimeauth_poly1305.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/onetimeauth_poly1305.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/aead_chacha20poly1305.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/aead_chacha20poly1305.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/utils.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/utils.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/verify.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/verify.o: OPT=$(OPT_CHACHA20POLY) +aead/chacha20poly1305ietf/runtime.o: CFLAGS_ADDITIONAL=$(CFLAGS_ADDITIONAL_CHACHA20POLY) +aead/chacha20poly1305ietf/runtime.o: OPT=$(OPT_CHACHA20POLY) + #ifdef USE_OPENSSL_CRYPTO ifdef USE_OPENSSL_CRYPTO SRC+=\ @@ -66,17 +112,25 @@ endif # These extra compilation definitions make those registers available for # these files to use. COMBA_MULTIPLIER_DEBUG=ON # Default on non-x86 platforms (debug build). +INTEL_32BIT=NO ifneq (,$(findstring i386-,$(CCARCH))) COMBA_MULTIPLIER_DEBUG=OFF +INTEL_32BIT=YES endif ifneq (,$(findstring i486-,$(CCARCH))) COMBA_MULTIPLIER_DEBUG=OFF +INTEL_32BIT=YES endif ifneq (,$(findstring i586-,$(CCARCH))) COMBA_MULTIPLIER_DEBUG=OFF +INTEL_32BIT=YES endif ifneq (,$(findstring i686-,$(CCARCH))) COMBA_MULTIPLIER_DEBUG=OFF +INTEL_32BIT=YES +endif +ifneq (,$(findstring x86_64-,$(CCARCH))) +INTEL_64BIT=YES endif ifeq '$(COMBA_MULTIPLIER_DEBUG)' 'OFF' CFLAGS_BASE:=$(CFLAGS) @@ -84,6 +138,26 @@ math/pstm_mul_comba.o: CFLAGS=$(CFLAGS_BASE) -fomit-frame-pointer math/pstm_sqr_comba.o: CFLAGS=$(CFLAGS_BASE) -fomit-frame-pointer endif +ifeq '$(INTEL_32BIT)' 'YES' +CFLAGS_ENABLE_SSE2=-msse2 +CFLAGS_ENABLE_AVX2=-mavx2 +CFLAGS_ENABLE_SSSE3=-mssse3 +endif +ifeq '$(INTEL_64BIT)' 'YES' +CFLAGS_ENABLE_SSE2=-msse2 +CFLAGS_ENABLE_AVX2=-mavx2 +CFLAGS_ENABLE_SSSE3=-mssse3 +endif + +# Additional flags for CHACHA20-POLY1305 (support of SSE/AVX) +aead/chacha20poly1305ietf/sse2/poly1305_sse2.o: CFLAGS_ADDITIONAL+= $(CFLAGS_ENABLE_SSE2) +aead/chacha20poly1305ietf/dolbeau/chacha20_dolbeau-avx2.o: CFLAGS_ADDITIONAL+= $(CFLAGS_ENABLE_AVX2) +aead/chacha20poly1305ietf/dolbeau/chacha20_dolbeau-ssse3.o: CFLAGS_ADDITIONAL+= $(CFLAGS_ENABLE_SSSE3) + +# Additional flags for AES-NI support. +# (note: only available on targets with AES-NI support detected.) +symmetric/aes_aesni.o: CFLAGS_ADDITIONAL+= $(CFLAGS_ENABLE_AESNI) + # Generated files STATIC:=libcrypt_s.a diff --git a/crypto/cryptoApi.h b/crypto/cryptoApi.h index 607c719..2adc706 100644 --- a/crypto/cryptoApi.h +++ b/crypto/cryptoApi.h @@ -178,8 +178,8 @@ typedef enum AES_CBC_DEC, AES_GCM_ENC, AES_GCM_DEC, - CHACHA20_POLY1305_ENC, - CHACHA20_POLY1305_DEC, + CHACHA20_POLY1305_IETF_ENC, + CHACHA20_POLY1305_IETF_DEC, ARC4, DES3, IDEA, @@ -270,29 +270,52 @@ PSPUBLIC void psAesClearGCM(psAesGcm_t *ctx); # endif /* USE_AES */ -# ifdef USE_CHACHA20_POLY1305 +# ifdef USE_CHACHA20_POLY1305_IETF /******************************************************************************/ -PSPUBLIC int32_t psChacha20Poly1305Init(psChacha20Poly1305_t *ctx, - const unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES], - uint8_t keylen); -PSPUBLIC void psChacha20Poly1305Ready(psChacha20Poly1305_t *ctx, - const unsigned char IV[crypto_aead_chacha20poly1305_NPUBBYTES + 4], - const unsigned char *aad, psSize_t aadLen); -PSPUBLIC void psChacha20Poly1305Encrypt(psChacha20Poly1305_t *ctx, - const unsigned char *pt, unsigned char *ct, uint32_t len); +PSPUBLIC psRes_t psChacha20Poly1305IetfInit( + psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], + const unsigned char Key_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_KEYBYTES)]); -PSPUBLIC int32_t psChacha20Poly1305Decrypt(psChacha20Poly1305_t *ctx, - const unsigned char *ct, uint32_t ctLen, - unsigned char *pt, uint32_t ptLen); +PSPUBLIC psResSize_t psChacha20Poly1305IetfEncryptDetached( + psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], + const unsigned char *Plaintext_p, + psSizeL_t PlaintextNBytes, + const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], + const unsigned char *Aad_p, + psSize_t AadNBytes, + unsigned char *Ciphertext_p, + unsigned char Mac_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_ABYTES)]); -PSPUBLIC void psChacha20Poly1305DecryptTagless(psChacha20Poly1305_t *ctx, - const unsigned char *ct, unsigned char *pt, - uint32_t len); +PSPUBLIC psResSize_t psChacha20Poly1305IetfDecryptDetached( + psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], + const unsigned char *Ciphertext_p, + psSizeL_t CiphertextNBytes, + const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], + const unsigned char *Aad_p, + psSizeL_t AadNBytes, + const unsigned char Mac_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_ABYTES)], + unsigned char *Plaintext_p); -PSPUBLIC void psChacha20Poly1305GetTag(psChacha20Poly1305_t * ctx, - uint8_t tagBytes, - unsigned char tag[crypto_aead_chacha20poly1305_ABYTES]); -PSPUBLIC void psChacha20Poly1305Clear(psChacha20Poly1305_t *ctx); +PSPUBLIC psResSize_t psChacha20Poly1305IetfEncrypt( + psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], + const unsigned char *Plaintext_p, + psSizeL_t PlaintextNBytes, + const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], + const unsigned char *Aad_p, + psSizeL_t AadNBytes, + unsigned char Ciphertext_p[PS_EXACTLY_EXPR(PlaintextNBytes + PS_CHACHA20POLY1305_IETF_ABYTES)]); + +PSPUBLIC psResSize_t psChacha20Poly1305IetfDecrypt( + psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], + const unsigned char CiphertextWithTag_p[PS_EXACTLY_EXPR(CiphertextNBytes)], + psSizeL_t CiphertextWithTagNBytes, + const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], + const unsigned char *Aad_p, + psSizeL_t AadNBytes, + unsigned char *Plaintext_p); + +PSPUBLIC void psChacha20Poly1305IetfClear( + psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)]); # endif # ifdef USE_3DES @@ -306,6 +329,10 @@ PSPUBLIC void psDes3Encrypt(psDes3_t *ctx, const unsigned char *pt, PSPUBLIC void psDes3Clear(psDes3_t *ctx); # endif +#ifndef PS_PARAMETER_UNUSED +# define PS_PARAMETER_UNUSED(x) do { (void) (x); } while (0) +#endif + /******************************************************************************/ /* Hash Digest Algorithms @@ -315,6 +342,7 @@ PSPUBLIC void psDes3Clear(psDes3_t *ctx); static __inline void psMd5PreInit(psMd5_t *md5) { /* Nothing to pre-initialize for native crypto. */ + PS_PARAMETER_UNUSED(md5); } PSPUBLIC int32_t psMd5Init(psMd5_t *md5); PSPUBLIC void psMd5Update(psMd5_t *md5, const unsigned char *buf, uint32_t len); @@ -328,6 +356,7 @@ PSPUBLIC void psMd5Final(psMd5_t * md, unsigned char hash[MD5_HASHLEN]); static __inline void psSha1PreInit(psSha1_t *sha1) { /* Nothing to pre-initialize for native crypto. */ + PS_PARAMETER_UNUSED(sha1); } PSPUBLIC int32_t psSha1Init(psSha1_t *sha1); PSPUBLIC void psSha1Update(psSha1_t *sha1, @@ -335,6 +364,8 @@ PSPUBLIC void psSha1Update(psSha1_t *sha1, PSPUBLIC void psSha1Final(psSha1_t * sha1, unsigned char hash[SHA1_HASHLEN]); static __inline void psSha1Sync(psSha1_t *ctx, int sync_all) { + PS_PARAMETER_UNUSED(ctx); + PS_PARAMETER_UNUSED(sync_all); } static __inline void psSha1Cpy(psSha1_t *d, const psSha1_t *s) { @@ -349,6 +380,7 @@ static __inline void psSha1Cpy(psSha1_t *d, const psSha1_t *s) static __inline void psMd5Sha1PreInit(psMd5Sha1_t *md) { /* Nothing to pre-initialize for native crypto. */ + PS_PARAMETER_UNUSED(md); } PSPUBLIC int32_t psMd5Sha1Init(psMd5Sha1_t *md); PSPUBLIC void psMd5Sha1Update(psMd5Sha1_t *md, @@ -357,6 +389,8 @@ PSPUBLIC void psMd5Sha1Final(psMd5Sha1_t * md, unsigned char hash[MD5SHA1_HASHLEN]); static __inline void psMd5Sha1Sync(psMd5Sha1_t *ctx, int sync_all) { + PS_PARAMETER_UNUSED(ctx); + PS_PARAMETER_UNUSED(sync_all); } static __inline void psMd5Sha1Cpy(psMd5Sha1_t *d, const psMd5Sha1_t *s) { @@ -371,6 +405,7 @@ static __inline void psMd5Sha1Cpy(psMd5Sha1_t *d, const psMd5Sha1_t *s) static __inline void psSha224PreInit(psSha256_t *sha224) { /* Nothing to pre-initialize for native crypto. */ + PS_PARAMETER_UNUSED(sha224); } PSPUBLIC void psSha224Init(psSha256_t *sha224); PSPUBLIC void psSha224Update(psSha256_t *sha224, @@ -379,6 +414,8 @@ PSPUBLIC void psSha224Final(psSha256_t * sha224, unsigned char hash[SHA224_HASHLEN]); static __inline void psSha224Sync(psSha256_t *md, int sync_all) { + PS_PARAMETER_UNUSED(md); + PS_PARAMETER_UNUSED(sync_all); } static __inline void psSha224Cpy(psSha256_t *d, const psSha256_t *s) { @@ -393,6 +430,7 @@ static __inline void psSha224Cpy(psSha256_t *d, const psSha256_t *s) static __inline void psSha256PreInit(psSha256_t *sha256) { /* Nothing to pre-initialize for native crypto. */ + PS_PARAMETER_UNUSED(sha256); } PSPUBLIC int32_t psSha256Init(psSha256_t *sha256); PSPUBLIC void psSha256Update(psSha256_t *sha256, @@ -401,6 +439,8 @@ PSPUBLIC void psSha256Final(psSha256_t * sha256, unsigned char hash[SHA256_HASHLEN]); static __inline void psSha256Sync(psSha256_t *md, int sync_all) { + PS_PARAMETER_UNUSED(md); + PS_PARAMETER_UNUSED(sync_all); } static __inline void psSha256Cpy(psSha256_t *d, const psSha256_t *s) { @@ -415,6 +455,7 @@ static __inline void psSha256Cpy(psSha256_t *d, const psSha256_t *s) static __inline void psSha384PreInit(psSha384_t *sha384) { /* Nothing to pre-initialize for native crypto. */ + PS_PARAMETER_UNUSED(sha384); } PSPUBLIC int32_t psSha384Init(psSha384_t *sha384); PSPUBLIC void psSha384Update(psSha384_t *sha384, @@ -423,6 +464,8 @@ PSPUBLIC void psSha384Final(psSha384_t * sha384, unsigned char hash[SHA384_HASHLEN]); static __inline void psSha384Sync(psSha384_t *md, int sync_all) { + PS_PARAMETER_UNUSED(md); + PS_PARAMETER_UNUSED(sync_all); } static __inline void psSha384Cpy(psSha384_t *d, const psSha384_t *s) { @@ -437,6 +480,7 @@ static __inline void psSha384Cpy(psSha384_t *d, const psSha384_t *s) static __inline void psSha512PreInit(psSha512_t *sha512) { /* Nothing to pre-initialize for native crypto. */ + PS_PARAMETER_UNUSED(sha512); } PSPUBLIC int32_t psSha512Init(psSha512_t *md); PSPUBLIC void psSha512Update(psSha512_t *md, @@ -445,6 +489,8 @@ PSPUBLIC void psSha512Final(psSha512_t * md, unsigned char hash[SHA512_HASHLEN]); static __inline void psSha512Sync(psSha512_t *md, int sync_all) { + PS_PARAMETER_UNUSED(md); + PS_PARAMETER_UNUSED(sync_all); } static __inline void psSha512Cpy(psSha512_t *d, const psSha512_t *s) { @@ -881,6 +927,7 @@ PSPUBLIC int32_t psMd4Final(psMd4_t *md, unsigned char *hash); static __inline void psMd2PreInit(psMd2_t *md2) { /* Nothing to pre-initialize for native crypto. */ + PS_PARAMETER_UNUSED(md2); } PSPUBLIC void psMd2Init(psMd2_t *md); PSPUBLIC int32_t psMd2Update(psMd2_t *md, const unsigned char *buf, diff --git a/crypto/cryptoCheck.h b/crypto/cryptoCheck.h index 8a66e02..ee99c45 100644 --- a/crypto/cryptoCheck.h +++ b/crypto/cryptoCheck.h @@ -105,12 +105,19 @@ # endif # endif -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE # ifndef USE_SHA1 # error "Enable USE_SHA1 in cryptoConfig.h for OCSP support" # endif # endif +# ifdef USE_OCSP_REQUEST +# ifndef USE_SHA1 +# error "Enable USE_SHA1 in cryptoConfig.h for OCSP support" +# endif +# error "Enable USE_CERT_GEN in cryptoConfig.h for USE_OCSP_REQUEST" +# endif + #endif /* _h_PS_CRYPTOCHECK */ /******************************************************************************/ diff --git a/crypto/cryptoImpl.h b/crypto/cryptoImpl.h index 17f2bfb..14dc249 100644 --- a/crypto/cryptoImpl.h +++ b/crypto/cryptoImpl.h @@ -36,8 +36,19 @@ # define _h_PS_CRYPTOIMPL # define PS_CRYPTO_IMPLEMENTATION 1 -# include "cryptoApi.h" -# include "../core/osdep.h" -# include "../core/psUtil.h" +# ifndef PS_LOGF_WITH_PRNF +# include "cryptoApi.h" +# include "../core/osdep.h" +# include "../core/psUtil.h" +# else +/* Note: The inclusion order of headers is very important when + PS_LOGF_WITH_PRNF is defined. */ +# include "../core/coreApi.h" +# include "../core/osdep.h" +# include "../core/psPrnf.h" +# include "../core/psLog.h" +# include "cryptoApi.h" +# include "cryptolib.h" +# endif #endif /* _h_PS_CRYPTOIMPL */ diff --git a/crypto/cryptolib.h b/crypto/cryptolib.h index e47fb94..6bb644c 100644 --- a/crypto/cryptolib.h +++ b/crypto/cryptolib.h @@ -85,17 +85,37 @@ /* Crypto trace */ -# ifndef USE_CRYPTO_TRACE -# define psTraceCrypto(x) -# define psTraceStrCrypto(x, y) -# define psTraceIntCrypto(x, y) -# define psTracePtrCrypto(x, y) +# ifdef USE_PS_LOGF_COMMON +# define psTraceCrypto(x) PS_LOGF_COMMON(Log_Trace, PS_CRYPTO, PS_LOGF_FMT, \ + PS_LOGF_FILELINE, "%s", x) +# define psTraceIntCrypto(x, i) PS_LOGF_COMMON(Log_Trace, PS_CRYPTO, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, i) +# define psTraceStrCrypto(x, s) PS_LOGF_COMMON(Log_Trace, PS_CRYPTO, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, s) +# define psTracePtrCrypto(x, p) PS_LOGF_COMMON(Log_Trace, PS_CRYPTO, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, p) +# define psTracefCrypto(x, ...) PS_LOGF_COMMON(Log_Trace, PS_CRYPTO, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, \ + __VA_ARGS__) # else -# define psTraceCrypto(x) _psTrace(x) -# define psTraceStrCrypto(x, y) _psTraceStr(x, y) -# define psTraceIntCrypto(x, y) _psTraceInt(x, y) -# define psTracePtrCrypto(x, y) _psTracePtr(x, y) -# endif /* USE_CRYPTO_TRACE */ +# ifndef USE_CRYPTO_TRACE +# define psTraceCrypto(x) +# define psTraceStrCrypto(x, y) +# define psTraceIntCrypto(x, y) +# define psTracePtrCrypto(x, y) +# define psTracefCrypto(x, y) +# else +# define psTraceCrypto(x) _psTrace(x) +# define psTraceStrCrypto(x, y) _psTraceStr(x, y) +# define psTraceIntCrypto(x, y) _psTraceInt(x, y) +# define psTracePtrCrypto(x, y) _psTracePtr(x, y) +# define psTracefCrypto(x, y) /* Only available via PS_LOGF_COMMON. */ +# endif /* USE_CRYPTO_TRACE */ +# endif /* PS_LOGF_COMMON */ /******************************************************************************/ /* @@ -399,7 +419,7 @@ extern int32_t psGetPrngLocked(unsigned char *bytes, psSize_t size, # define CRYPTO_FLAGS_ARC4 (1 << 3) # define CRYPTO_FLAGS_SEED (1 << 4) # define CRYPTO_FLAGS_IDEA (1 << 5) -# define CRYPTO_FLAGS_CHACHA (1 << 6) /* Short for CHACHA20_POLY2305 */ +# define CRYPTO_FLAGS_CHACHA (1 << 6) /* Short for CHACHA20_POLY1305_IETF */ # define CRYPTO_FLAGS_SHA1 (1 << 8) # define CRYPTO_FLAGS_SHA2 (1 << 9) diff --git a/crypto/keyformat/asn1.c b/crypto/keyformat/asn1.c index ce19d9a..54dd357 100644 --- a/crypto/keyformat/asn1.c +++ b/crypto/keyformat/asn1.c @@ -610,6 +610,13 @@ int32_t getAsnOID(const unsigned char **pp, uint32_t len, int32_t *oi, rc = PS_PARSE_FAIL; end = p + len; plen = end - p; + + if (len < 1) + { + psTraceCrypto("Malformed algorithmId 1\n"); + return rc; + } + if (*(p++) != ASN_OID || (rc = getAsnLength32(&p, (uint32_t) (end - p), &arcLen, 0)) < 0) { @@ -643,7 +650,8 @@ int32_t getAsnOID(const unsigned char **pp, uint32_t len, int32_t *oi, { plen -= (end - p); *paramLen = len - plen; - if (*p != ASN_NULL) + + if (*paramLen < 1 || *p != ASN_NULL) { *pp = p; /* paramLen tells whether params exist or completely missing (0) */ diff --git a/crypto/keyformat/asn1.h b/crypto/keyformat/asn1.h index 645430a..3709dfe 100644 --- a/crypto/keyformat/asn1.h +++ b/crypto/keyformat/asn1.h @@ -114,6 +114,15 @@ extern uint8_t asnParseOid(const unsigned char *der, psSize_t derlen, extern char *asnFormatOid(psPool_t *pool, const unsigned char *oid, size_t oidlen); +/* Format octet string representing ASN.1 in Der encoded format. */ +extern char *asnFormatDer(psPool_t *pool, + const unsigned char *Der_p, + size_t DerLen, + size_t MaxElements, + size_t MaxDepth, + size_t MaxElementOutput, + unsigned char Flags); + /******************************************************************************/ #endif /* _h_PS_ASN1 */ diff --git a/crypto/keyformat/asn1fmt.c b/crypto/keyformat/asn1fmt.c index b1b10b6..d68f0e1 100644 --- a/crypto/keyformat/asn1fmt.c +++ b/crypto/keyformat/asn1fmt.c @@ -32,14 +32,15 @@ */ /******************************************************************************/ -#if !defined USE_X509 && !defined USE_OCSP +#if !defined USE_X509 && !defined USE_OCSP_RESPONSE # include "../cryptoImpl.h" /* MatrixSSL API interface and configuration. */ #endif -#if (defined USE_X509 && defined USE_FULL_CERT_PARSE) || defined USE_OCSP +#if (defined USE_X509 && defined USE_FULL_CERT_PARSE) || defined USE_OCSP_RESPONSE # include /* for snprintf() */ # include /* for strlen() */ +#include "core/psPrnf.h" /* Constants used in OID formatting code. */ # define OID_STR_BUF_LEN (129 * 4) /* Temporary string length. */ @@ -336,5 +337,407 @@ char *asnFormatOid(psPool_t *pool, } # endif /* NO_ASN_FORMAT_OID */ +struct asnFormatTagInfo +{ + const char *str_short; + const char *str_long; + unsigned char constructed; + unsigned char omit; + unsigned char string8bit; +}; + +static struct asnFormatTagInfo asnFormatTagInfo[128] = +{ + { "END", "End-Of-Contents", 0, 0, 0 }, + { "BOOL", "BOOLEAN", 0, 1, 0 }, + { "INT", "INTEGER", 0, 1, 0 }, + { "BITS", "BIT STRING", 0, 0, 0 }, + { "OCTETS", "OCTET STRING", 0, 0, 0 }, + { "NULL", "NULL", 0, 0, 0 }, + { "OID", "OBJECT IDENTIFIER", 0, 1, 0 }, + { "Obj", "ObjectDescriptor", 0, 0, 0 }, + { "INST", "INSTANCE OF", 0, 0, 0 }, + { "REAL", "REAL", 0, 1, 0 }, + { "ENUM", "ENUMERATED", 0, 0, 0 }, + { "EMB", "EMBEDDED PDV", 0, 0, 0 }, + { "UTF8", "UTF8String", 0, 0, 1 }, + { "REL-OID", "RELATIVE-OID", 0, 0, 0 }, + { "Uni[14]", "Universal[14]", 0, 0, 0 }, + { "Uni[15]", "Universal[15]", 0, 0, 0 }, + { "SEQ", "SEQUENCE", 1, 0, 0 }, + { "SET", "SET", 1, 0, 0 }, + { "Num", "NumericString", 0, 0, 1 }, + { "Print", "PrintableString", 0, 1, 1 }, + { "T.61", "TeletexString", 0, 1, 1 }, + { "VID", "VideotexString", 0, 1, 1 }, + { "ASCII", "IA5String", 0, 0, 1 }, + { "UTCTime", "UTCTime", 0, 1, 1 }, + { "GenTime", "GeneralizedTime", 0, 1, 1 }, + { "Graphic", "GraphicString", 0, 0, 1 }, + { "Visible", "VisibleString", 0, 0, 1 }, + { "Gen", "GeneralString", 0, 0, 1 }, + { "UTF-32", "UniversalString", 0, 0, 0 }, + { "STR", "CHARACTER STRING", 0, 0, 1 }, + { "BMP", "BMP STRING", 0, 0, 1 }, + { "Uni[31]", "Universal[31]", 0, 0, 1 }, + { "App[0]", "Application[0]", 1, 0, 0 }, + { "App[1]", "Application[1]", 1, 0, 0 }, + { "App[2]", "Application[2]", 1, 0, 0 }, + { "App[3]", "Application[3]", 1, 0, 0 }, + { "App[4]", "Application[4]", 1, 0, 0 }, + { "App[5]", "Application[5]", 1, 0, 0 }, + { "App[6]", "Application[6]", 1, 0, 0 }, + { "App[7]", "Application[7]", 1, 0, 0 }, + { "App[8]", "Application[8]", 1, 0, 0 }, + { "App[9]", "Application[9]", 1, 0, 0 }, + { "App[10]", "Application[10]", 1, 0, 0 }, + { "App[11]", "Application[11]", 1, 0, 0 }, + { "App[12]", "Application[12]", 1, 0, 0 }, + { "App[13]", "Application[13]", 1, 0, 0 }, + { "App[14]", "Application[14]", 1, 0, 0 }, + { "App[15]", "Application[15]", 1, 0, 0 }, + { "App[16]", "Application[16]", 1, 0, 0 }, + { "App[17]", "Application[17]", 1, 0, 0 }, + { "App[18]", "Application[18]", 1, 0, 0 }, + { "App[19]", "Application[19]", 1, 0, 0 }, + { "App[20]", "Application[20]", 1, 0, 0 }, + { "App[21]", "Application[21]", 1, 0, 0 }, + { "App[22]", "Application[22]", 1, 0, 0 }, + { "App[23]", "Application[23]", 1, 0, 0 }, + { "App[24]", "Application[24]", 1, 0, 0 }, + { "App[25]", "Application[25]", 1, 0, 0 }, + { "App[26]", "Application[26]", 1, 0, 0 }, + { "App[27]", "Application[27]", 1, 0, 0 }, + { "App[28]", "Application[28]", 1, 0, 0 }, + { "App[29]", "Application[29]", 1, 0, 0 }, + { "App[30]", "Application[30]", 1, 0, 0 }, + { "App[31]", "Application[31]", 1, 0, 0 }, + { "Cont[0]", "Context-Specific[0]", 1, 0, 0 }, + { "Cont[1]", "Context-Specific[1]", 1, 0, 0 }, + { "Cont[2]", "Context-Specific[2]", 1, 0, 0 }, + { "Cont[3]", "Context-Specific[3]", 1, 0, 0 }, + { "Cont[4]", "Context-Specific[4]", 1, 0, 0 }, + { "Cont[5]", "Context-Specific[5]", 1, 0, 0 }, + { "Cont[6]", "Context-Specific[6]", 1, 0, 0 }, + { "Cont[7]", "Context-Specific[7]", 1, 0, 0 }, + { "Cont[8]", "Context-Specific[8]", 1, 0, 0 }, + { "Cont[9]", "Context-Specific[9]", 1, 0, 0 }, + { "Cont[10]", "Context-Specific[10]", 1, 0, 0 }, + { "Cont[11]", "Context-Specific[11]", 1, 0, 0 }, + { "Cont[12]", "Context-Specific[12]", 1, 0, 0 }, + { "Cont[13]", "Context-Specific[13]", 1, 0, 0 }, + { "Cont[14]", "Context-Specific[14]", 1, 0, 0 }, + { "Cont[15]", "Context-Specific[15]", 1, 0, 0 }, + { "Cont[16]", "Context-Specific[16]", 1, 0, 0 }, + { "Cont[17]", "Context-Specific[17]", 1, 0, 0 }, + { "Cont[18]", "Context-Specific[18]", 1, 0, 0 }, + { "Cont[19]", "Context-Specific[19]", 1, 0, 0 }, + { "Cont[20]", "Context-Specific[20]", 1, 0, 0 }, + { "Cont[21]", "Context-Specific[21]", 1, 0, 0 }, + { "Cont[22]", "Context-Specific[22]", 1, 0, 0 }, + { "Cont[23]", "Context-Specific[23]", 1, 0, 0 }, + { "Cont[24]", "Context-Specific[24]", 1, 0, 0 }, + { "Cont[25]", "Context-Specific[25]", 1, 0, 0 }, + { "Cont[26]", "Context-Specific[26]", 1, 0, 0 }, + { "Cont[27]", "Context-Specific[27]", 1, 0, 0 }, + { "Cont[28]", "Context-Specific[28]", 1, 0, 0 }, + { "Cont[29]", "Context-Specific[29]", 1, 0, 0 }, + { "Cont[30]", "Context-Specific[30]", 1, 0, 0 }, + { "Cont[31]", "Context-Specific[31]", 1, 0, 0 }, + { "Priv[0]", "Private[0]", 1, 0, 0 }, + { "Priv[1]", "Private[1]", 1, 0, 0 }, + { "Priv[2]", "Private[2]", 1, 0, 0 }, + { "Priv[3]", "Private[3]", 1, 0, 0 }, + { "Priv[4]", "Private[4]", 1, 0, 0 }, + { "Priv[5]", "Private[5]", 1, 0, 0 }, + { "Priv[6]", "Private[6]", 1, 0, 0 }, + { "Priv[7]", "Private[7]", 1, 0, 0 }, + { "Priv[8]", "Private[8]", 1, 0, 0 }, + { "Priv[9]", "Private[9]", 1, 0, 0 }, + { "Priv[10]", "Private[10]", 1, 0, 0 }, + { "Priv[11]", "Private[11]", 1, 0, 0 }, + { "Priv[12]", "Private[12]", 1, 0, 0 }, + { "Priv[13]", "Private[13]", 1, 0, 0 }, + { "Priv[14]", "Private[14]", 1, 0, 0 }, + { "Priv[15]", "Private[15]", 1, 0, 0 }, + { "Priv[16]", "Private[16]", 1, 0, 0 }, + { "Priv[17]", "Private[17]", 1, 0, 0 }, + { "Priv[18]", "Private[18]", 1, 0, 0 }, + { "Priv[19]", "Private[19]", 1, 0, 0 }, + { "Priv[20]", "Private[20]", 1, 0, 0 }, + { "Priv[21]", "Private[21]", 1, 0, 0 }, + { "Priv[22]", "Private[22]", 1, 0, 0 }, + { "Priv[23]", "Private[23]", 1, 0, 0 }, + { "Priv[24]", "Private[24]", 1, 0, 0 }, + { "Priv[25]", "Private[25]", 1, 0, 0 }, + { "Priv[26]", "Private[26]", 1, 0, 0 }, + { "Priv[27]", "Private[27]", 1, 0, 0 }, + { "Priv[28]", "Private[28]", 1, 0, 0 }, + { "Priv[29]", "Private[29]", 1, 0, 0 }, + { "Priv[30]", "Private[30]", 1, 0, 0 }, + { "Priv[31]", "Private[31]", 1, 0, 0 } +}; + +static unsigned char idx(unsigned char tag) +{ + unsigned char idx = (tag & 31) | ((tag & 192) >> 1); + return idx; +} + +const char *asnFormatTagId(unsigned char tag) +{ + return asnFormatTagInfo[idx(tag)].str_short; +} + +const char *asnFormatTagIdLong(unsigned char tag) +{ + return asnFormatTagInfo[idx(tag)].str_long; +} + +static char *internalStrdup(psPool_t *pool, const char *string) +{ + size_t len; + char *new_str; + + if (string == NULL) + { + return NULL; + } + len = strlen(string) + 1; + new_str = psMalloc(pool, len); + if (new_str) + { + memcpy(new_str, string, len); + } + return new_str; +} + + +char *asnFormatDer(psPool_t *pool, + const unsigned char *Der_p, + size_t DerLen, + size_t MaxElements, + size_t MaxDepth, + size_t MaxElementOutput, + unsigned char Flags) +{ + size_t i; + psParseBuf_t pb; + psParseBuf_t sub; + psDynBuf_t str; + size_t endlen; + size_t sz; + size_t MaxElementOutputD2; + + if (MaxElements == 0) + { + MaxElements = (size_t) -1; + } + + if (MaxDepth == 0) + { + MaxDepth = (size_t) -1; + } + + if (MaxElementOutput == 0) + { + MaxElementOutput = (size_t) -1; + } + MaxElementOutputD2 = MaxElementOutput / 2; + + if (DerLen < 1) + { + return internalStrdup(pool, "[length = 0]"); + } + + if (psParseBufFromStaticData(&pb, Der_p, DerLen) != PS_SUCCESS) + { + return internalStrdup(pool, "[ASN.1 Parser Failure]"); + } + psDynBufInit(pool, &str, 80); + for(i = 0; i < MaxElements; i++) + { + unsigned char tagid[1]; + const char *tagstr; + int has_content; + size_t content_len; + int printed; + int negative = 0; + const unsigned char *content; + const unsigned char *tagdata; + + if (!psParseCanRead(&pb, 1)) + { + break; /* All elements read. */ + } + + sz = 1; + (void) psParseBufCopyN(&pb, 1, tagid, &sz); + tagdata = psBufGetData(&pb.buf); + + if (sz != 1 || !psParseBufTryReadTagSub(&pb, &sub, tagid[0])) + { + psDynBufAppendStr(&str, "[unparseable data]"); + break; /* All elements read up-to error. */ + } + + if (i > 0) + { + psDynBufAppendStr(&str, ", "); + } + + tagstr = asnFormatTagId(tagid[0]); + has_content = psParseCanRead(&sub, 1); + content = psBufGetData(&sub.buf); + content_len = psBufGetDataSize(&sub.buf); + printed = 0; + + /* Formatting: tag specific. */ + switch (tagid[0]) + { + case 1: + if (content_len == 1 && content[0] == 0xff) + { + psDynBufAppendStrf(&str, "%s(true)", tagstr); + printed = 1; + } + + if (content_len == 1 && content[0] == 0x00) + { + psDynBufAppendStrf(&str, "%s(false)", tagstr); + printed = 1; + } + break; + case 2: + if (content_len > 0 && (content[0] & 0x80) != 0) + { + negative = 1; + } + /* FALL-THROUGH */ + case 4: + if (content_len > 0 && content_len <= MaxElementOutputD2) + { + /* This is a number or other sequence of hex. */ + PS_PRNF_CTX; + char *tmp_str = psAsprnf(pool, PSF, + PSA_HEX(content, content_len)); + if (tmp_str) + { + psDynBufAppendStrf(&str, "%s(%s0x%s)", + tagstr, negative ? "-" : "", tmp_str); + psFree(tmp_str, pool); + printed = 1; + } + } + break; + case 3: + if (content_len > 1 && content_len <= MaxElementOutputD2) + { + /* Print bit string as hex sequence. */ + PS_PRNF_CTX; + char *tmp_str = psAsprnf(pool, PSF, + PSA_HEX(content + 1, content_len - 1)); + if (tmp_str) + { + if (content[0] != 0) + { + psDynBufAppendStrf(&str, "%s(0x%s[padding=%u])", + tagstr, tmp_str, content[0]); + } + else + { + psDynBufAppendStrf(&str, "%s(0x%s)", + tagstr, tmp_str); + } + psFree(tmp_str, pool); + printed = 1; + } + } + break; + case 5: + /* NULL needs to be used without any content. + Omit "(empty)" in that case. */ + if (content_len == 0) + { + psDynBufAppendStr(&str, tagstr); + printed = 1; + } + break; + case 6: + if (content_len > 0 && content_len <= MaxElementOutputD2) + { + /* OID: Pass formatter also tag id and tag length. */ + size_t hlen = content - tagdata; + char *tmp_str = asnFormatOid(pool, tagdata, hlen + content_len); + if (tmp_str) + { + psDynBufAppendStrf(&str, "%s(%s)", tagstr, tmp_str); + psFree(tmp_str, pool); + printed = 1; + } + } + break; + default: + /* Constructed encodings perform recursion. */ + if ((tagid[0] & 32) == 32 && content_len > 0 && MaxDepth > 1) + { + char *tmp_str = asnFormatDer(pool, + content, + content_len, + 0, + MaxDepth - 1, + MaxElementOutput, + Flags); + if (tmp_str) + { + psDynBufAppendStrf(&str, "%s(%s)", tagstr, tmp_str); + psFree(tmp_str, pool); + printed = 1; + } + break; + } + + /* Generic handling for 8-bit strings. */ + if (asnFormatTagInfo[idx(tagid[0])].string8bit && + content_len <= MaxElementOutput) + { + /* This is 8bit string. */ + PS_PRNF_CTX; + char *tmp_str = psAsprnf(pool, PSF, + PSA_SSTR((const char *)content, + content_len)); + if (tmp_str) + { + psDynBufAppendStrf(&str, "%s(\"%s\")", tagstr, tmp_str); + psFree(tmp_str, pool); + printed = 1; + } + } + } + + /* Last resort: Indicate number of bytes. */ + if (!printed) + { + psDynBufAppendStrf(&str, "%s(%s)", + tagstr, has_content? "..." : "empty"); + } + (void)psParseBufFinish(&sub); + } + endlen = 0; + while(psParseCanRead(&pb, 1)) + { + psParseBufSkipBytes(&pb, NULL, 1); + endlen++; + } + if (endlen > 0) + { + psDynBufAppendStrf(&str, "[%llu unprocessed bytes]", + (unsigned long long) endlen); + } + (void)psParseBufFinish(&pb); + psDynBufAppendChar(&str, 0); /* Add terminating NUL character. */ + return psDynBufDetach(&str, &sz); +} + #endif /* compilation selector: full X.509 or OCSP enabled */ diff --git a/crypto/keyformat/x509.c b/crypto/keyformat/x509.c index 8083f55..e7cd9ae 100644 --- a/crypto/keyformat/x509.c +++ b/crypto/keyformat/x509.c @@ -159,7 +159,6 @@ static int32_t getTimeValidity(psPool_t *pool, const unsigned char **pp, static int32_t getImplicitBitString(psPool_t *pool, const unsigned char **pp, psSize_t len, int32_t impVal, unsigned char **bitString, psSize_t *bitLen); -static int32_t validateDateRange(psX509Cert_t *cert); static int32_t issuedBefore(rfc_e rfc, const psX509Cert_t *cert); # ifdef USE_RSA @@ -1025,7 +1024,7 @@ static int parse_single_cert(psPool_t *pool, const unsigned char **pp, goto out; } -# ifdef USE_OCSP +# if defined(USE_OCSP_RESPONSE) || defined(USE_OCSP_REQUEST) /* A sha1 hash of the public key is useful for OCSP */ memcpy(cert->sha1KeyHash, sha1KeyHash, SHA1_HASH_SIZE); # endif @@ -1487,6 +1486,26 @@ static void freeDomainComponentList(x509DomainComponent_t *domainComponent, } } +int32_t x509NewExtensions(x509v3extensions_t **extensions, psPool_t *pool) +{ + x509v3extensions_t *ext; + + ext = psMalloc(pool, sizeof(x509v3extensions_t)); + if (ext == NULL) + { + return PS_MEM_FAIL; + } + memset(ext, 0x0, sizeof(x509v3extensions_t)); + ext->pool = pool; + ext->bc.pathLenConstraint = -1; + ext->bc.cA = CA_UNDEFINED; + ext->refCount = 1; + + *extensions = ext; + + return PS_SUCCESS; +} + void x509FreeExtensions(x509v3extensions_t *extensions) { @@ -1503,6 +1522,13 @@ void x509FreeExtensions(x509v3extensions_t *extensions) { return; } + if (extensions->refCount > 1) + { + extensions->refCount--; + return; + } + extensions->refCount = 0; + if (extensions->san) { active = extensions->san; @@ -1510,6 +1536,10 @@ void x509FreeExtensions(x509v3extensions_t *extensions) { inc = active->next; psFree(active->data, extensions->pool); + if (active->oidLen > 0) + { + psFree(active->oid, extensions->pool); + } psFree(active, extensions->pool); active = inc; } @@ -1522,6 +1552,10 @@ void x509FreeExtensions(x509v3extensions_t *extensions) { inc = active->next; psFree(active->data, extensions->pool); + if (active->oidLen > 0) + { + psFree(active->oid, extensions->pool); + } psFree(active, extensions->pool); active = inc; } @@ -1634,9 +1668,15 @@ void x509FreeExtensions(x509v3extensions_t *extensions) { if (extensions->netscapeComment->comment) { - psFree(extensions->netscapeComment->comment, pool); + psFree(extensions->netscapeComment->comment, extensions->pool); } - psFree(extensions->netscapeComment, pool); + psFree(extensions->netscapeComment, extensions->pool); + } + + if (extensions->otherAttributes) + { + psDynBufUninit(extensions->otherAttributes); + psFree(extensions->otherAttributes, extensions->pool); } # endif /* USE_FULL_CERT_PARSE || USE_CERT_GEN */ } @@ -2492,10 +2532,19 @@ 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 - || activeName->oidLen > sizeof(activeName->oid)) + + if (*(p++) != ASN_OID) + { + psTraceCrypto("ASN parse error SAN otherName oid\n"); + return -1; + } + if (getAsnLength(&p, (int32) (extEnd - p), &activeName->oidLen) < 0) + { + psTraceCrypto("ASN parse error SAN otherName oid\n"); + return -1; + } + activeName->oid = psMalloc(pool, activeName->oidLen); + if ((uint32) (extEnd - p) < activeName->oidLen) { psTraceCrypto("ASN parse error SAN otherName oid\n"); @@ -4235,6 +4284,12 @@ int32_t getSerialNum(psPool_t *pool, const unsigned char **pp, psSize_t len, const unsigned char *p = *pp; psSize_t vlen; + if (len < 1) + { + psTraceCrypto("ASN getSerialNum failed\n"); + return PS_PARSE_FAIL; + } + if ((*p != (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) && (*p != ASN_INTEGER)) { @@ -4389,7 +4444,7 @@ static int32 issuedBefore(rfc_e rfc, const psX509Cert_t *cert) 0 on parse success (FAIL_DATE_FLAG could be set) PS_FAILURE on parse error */ -static int32 validateDateRange(psX509Cert_t *cert) +int32 validateDateRange(psX509Cert_t *cert) { int32 err; psBrokenDownTime_t timeNow; @@ -5577,13 +5632,23 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, if (sc->extensions.ak.keyLen != 0) { psTraceCrypto("Subject/Issuer key id mismatch\n"); +#ifdef DISABLE_AUTH_KEY_ID_CHECK + psTraceCrypto("Ignoring Subject/Issuer key id mismatch " \ + "due to #define DISABLE_AUTH_KEY_ID_CHECK\n"); +#else sc->authStatus = PS_CERT_AUTH_FAIL_AUTHKEY; +#endif /* DISABLE_AUTH_KEY_ID_CHECK */ } } else { psTraceCrypto("Subject/Issuer key id mismatch\n"); +#ifdef DISABLE_AUTH_KEY_ID_CHECK + psTraceCrypto("Ignoring Subject/Issuer key id mismatch " \ + "due to #define DISABLE_AUTH_KEY_ID_CHECK\n"); +#else sc->authStatus = PS_CERT_AUTH_FAIL_AUTHKEY; +#endif /* DISABLE_AUTH_KEY_ID_CHECK */ } } else @@ -5592,7 +5657,13 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, ic->extensions.sk.len) != 0) { psTraceCrypto("Subject/Issuer key id data mismatch\n"); +#ifdef DISABLE_AUTH_KEY_ID_CHECK + psTraceCrypto("Ignoring Subject/Issuer key id mismatch " \ + "due to #define DISABLE_AUTH_KEY_ID_CHECK\n"); +#else sc->authStatus = PS_CERT_AUTH_FAIL_AUTHKEY; +#endif /* DISABLE_AUTH_KEY_ID_CHECK */ + } } } @@ -5794,7 +5865,7 @@ static int32_t x509ConfirmSignature(const unsigned char *sigHash, /******************************************************************************/ # endif /* USE_CERT_PARSE */ -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE /******************************************************************************/ @@ -7213,7 +7284,7 @@ void psOcspResponseUninit(psOcspResponse_t *res) } -# endif /* USE_OCSP */ +# endif /* USE_OCSP_RESPONSE */ #endif /* USE_X509 */ /******************************************************************************/ diff --git a/crypto/keyformat/x509.h b/crypto/keyformat/x509.h index ae0092c..7a8175f 100644 --- a/crypto/keyformat/x509.h +++ b/crypto/keyformat/x509.h @@ -210,9 +210,10 @@ typedef struct psGeneralNameEntry psPool_t *pool; x509GeneralNameType_t id; unsigned char name[16]; - unsigned char oid[32]; /* SubjectAltName OtherName */ + unsigned char *oid; /* SubjectAltName OtherName */ unsigned char *data; psSize_t oidLen; + uint8_t oidHasTagLenPrefix; psSize_t dataLen; struct psGeneralNameEntry *next; } x509GeneralName_t; @@ -552,6 +553,9 @@ typedef struct unsigned char *crlNum; int32 crlNumLen; # endif /* USE_CRL */ + psDynBuf_t *otherAttributes; + int32_t refCount; + void *reserved[3]; /* Allow future extensions with binary compatibility. */ } x509v3extensions_t; # endif /* USE_CERT_PARSE */ @@ -646,9 +650,9 @@ typedef struct psCert # endif unsigned char sigHash[MAX_HASH_SIZE]; # endif /* USE_CERT_PARSE */ -# ifdef USE_OCSP +# if defined(USE_OCSP_RESPONSE) || defined(USE_OCSP_REQUEST) unsigned char sha1KeyHash[SHA1_HASH_SIZE]; -# endif +# endif /* USE_OCSP_RESPONSE || USE_OCSP_REQUEST */ # ifdef ENABLE_CA_CERT_HASH /** @note this is used only by MatrixSSL for Trusted CA Indication extension */ unsigned char sha1CertHash[SHA1_HASH_SIZE]; @@ -672,8 +676,11 @@ extern int32_t getSerialNum(psPool_t *pool, const unsigned char **pp, extern int32_t getExplicitExtensions(psPool_t *pool, const unsigned char **pp, psSize_t inlen, int32_t expVal, x509v3extensions_t *extensions, uint8_t known); +extern int32_t x509NewExtensions(x509v3extensions_t **extensions, + psPool_t *pool); extern void x509FreeExtensions(x509v3extensions_t *extensions); extern int32_t psX509ValidateGeneralName(const char *n); +extern int32_t validateDateRange(psX509Cert_t *cert); /** Get the number of organizationalUnits in a distinguished name (DN). */ extern int32_t psX509GetNumOrganizationalUnits(const x509DNattributes_t *DN); @@ -748,7 +755,7 @@ extern int32_t psX509GetOnelineDN(const x509DNattributes_t *DN, size_t *out_str_len); # endif /* USE_FULL_CERT_PARSE */ -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE # include # include @@ -943,6 +950,10 @@ extern int32_t psOcspRequestWriteOld(psPool_t *pool, psX509Cert_t *cert, /* Uninitialize OCSP response. */ void psOcspResponseUninit(psOcspResponse_t *res); +# endif /* USE_OCSP_RESPONSE */ + +# ifdef USE_OCSP_REQUEST + typedef struct { int32_t flags; @@ -1005,7 +1016,7 @@ extern void psOcspRequestWriteVersion( int version, psOcspRequestWriteInfo_t *info); -# endif +# endif /* USE_OCSP_REQUEST */ /******************************************************************************/ diff --git a/crypto/layer/layer.h b/crypto/layer/layer.h index 381d0c9..3fddd1a 100644 --- a/crypto/layer/layer.h +++ b/crypto/layer/layer.h @@ -66,10 +66,25 @@ # endif # ifdef USE_CHACHA20_POLY1305 -# ifndef USE_LIBSODIUM_CRYPTO -# error "libsodium required for chacha20_poly1305" -# endif -# endif +# ifndef USE_CHACHA20_POLY1305_IETF +# ifndef NO_CHACHA20_POLY1305_IETF + +/* Issue warning if old USE_CHACHA20_POLY1305 is used, and there is + nothing said about CHACHA20_POLY1305_IETF. + Old versions of MatrixSSL used USE_CHACHA20_POLY1305 to turn on/off + ChaCha20Poly1305 non-IETF/IETF. */ +# ifdef WIN32 +# pragma message("Define USE_CHACHA20_POLY1305_IETF instead of USE_CHACHA20_POLY1305.") +# else +# warning "Define USE_CHACHA20_POLY1305_IETF instead of USE_CHACHA20_POLY1305." +# endif + +/* Defining USE_CHACHA20_POLY1305_IETF for compatibility, unless + spefically forbidden using NO_CHACHA20_POLY1305_IETF. */ +# define USE_CHACHA20_POLY1305_IETF +# endif /* !NO_CHACHA20_POLY1305_IETF */ +# endif /* !USE_CHACHA20_POLY1305_IETF */ +# endif /* USE_CHACHA20_POLY1305 */ # ifdef USE_ARC4 # define USE_MATRIX_ARC4 @@ -146,14 +161,18 @@ # define USE_MATRIX_PRNG # endif +# ifdef USE_CHACHA20_POLY1305_IETF +# define USE_MATRIX_CHACHA20_POLY1305_IETF +# endif /* USE_CHACHA20_POLY1305_IETF */ + # ifdef USE_LIBSODIUM_CRYPTO /******************************************************************************/ /** Use libsodium cryptography primitives (link with libsodium.a). */ -# ifdef USE_CHACHA20_POLY1305 -/* #undef USE_MATRIX_CHACHA20_POLY1305 / * @note, not defined in matrix crypto * / */ -# define USE_LIBSODIUM_CHACHA20_POLY1305 +# ifdef USE_CHACHA20_POLY1305_IETF +# undef USE_MATRIX_CHACHA20_POLY1305_IETF /* @note, not defined in matrix crypto */ +# define USE_LIBSODIUM_CHACHA20_POLY1305_IETF # endif /* libsodium AES-GCM is not automatically enabled. diff --git a/crypto/layer/matrix.c b/crypto/layer/matrix.c index ea06515..c5d6882 100644 --- a/crypto/layer/matrix.c +++ b/crypto/layer/matrix.c @@ -75,12 +75,26 @@ int32_t psCryptoOpen(const char *config) return PS_SELFTEST_FAILED; } #endif /* USE_FLPS_BINDING */ +#ifdef USE_LIBSODIUM_CRYPTO + if (sodium_init() == -1) + { + return PS_FAILURE; + } +#endif /* USE_LIBSODIUM_CRYPTO */ +#ifdef USE_MATRIX_CHACHA20_POLY1305_IETF + /* Pick chacha20-poly1305 implementation. */ + { + psChacha20Poly1305Ietf_t tmp; + (void) psChacha20Poly1305IetfInit( + &tmp, + (const unsigned char *)g_config /* at least 32 bytes */); + } +#endif psOpenPrng(); #ifdef USE_CRL psCrlOpen(); #endif - /* Everything successful, store configuration. */ strncpy(g_config, PSCRYPTO_CONFIG, sizeof(g_config) - 1); diff --git a/crypto/math/pstm.c b/crypto/math/pstm.c index f630548..d957b4d 100644 --- a/crypto/math/pstm.c +++ b/crypto/math/pstm.c @@ -1582,7 +1582,7 @@ static uint64 psDiv128(uint128 *numerator, uint64 denominator) /* This version of division uses short & small function, but offers bit worse performance than some others. */ -int pstm_div(psPool_t *pool, const pstm_int *a, const pstm_int *b, +int32_t pstm_div(psPool_t *pool, const pstm_int *a, const pstm_int *b, pstm_int *c, pstm_int *d) { pstm_int ta, tb, tq, q; diff --git a/crypto/math/pstm.h b/crypto/math/pstm.h index 0e7ebfd..8d545e5 100644 --- a/crypto/math/pstm.h +++ b/crypto/math/pstm.h @@ -193,7 +193,7 @@ extern int32_t pstm_to_unsigned_bin(psPool_t *pool, const pstm_int *a, unsigned char *b); extern int32_t pstm_to_unsigned_bin_nr(psPool_t *pool, const pstm_int *a, unsigned char *b); -# ifdef USE_ECC +# if defined(USE_ECC) || defined(USE_CERT_GEN) extern int32_t pstm_read_radix(psPool_t *pool, pstm_int *a, const char *buf, psSize_t len, uint8_t radix); # endif diff --git a/crypto/math/pstm_montgomery_reduce.c b/crypto/math/pstm_montgomery_reduce.c index 71c4845..c2e73ab 100644 --- a/crypto/math/pstm_montgomery_reduce.c +++ b/crypto/math/pstm_montgomery_reduce.c @@ -205,6 +205,11 @@ /******************************************************************************/ # elif defined(PSTM_ARM) +# if defined __arm__ && defined __thumb__ && !defined __thumb2__ +# error "Platform not supported: Thumb1 mode on ARMv4-v6." +# error "Please, turn off thumb mode or enable thumb2." +# endif + # define MONT_START # define MONT_FINI # define LOOP_END diff --git a/crypto/math/pstm_mul_comba.c b/crypto/math/pstm_mul_comba.c index b9fbbcf..3b1a8da 100644 --- a/crypto/math/pstm_mul_comba.c +++ b/crypto/math/pstm_mul_comba.c @@ -121,6 +121,11 @@ /* ARM code */ /* #pragma message ("Using 32 bit ARM Assembly Optimizations") */ +# if defined __arm__ && defined __thumb__ && !defined __thumb2__ +# error "Platform not supported: Thumb1 mode on ARMv4-v6." +# error "Please, turn off thumb mode or enable thumb2." +# endif + # define COMBA_START # define COMBA_CLEAR \ diff --git a/crypto/math/pstm_sqr_comba.c b/crypto/math/pstm_sqr_comba.c index 0b02b25..a24fe46 100644 --- a/crypto/math/pstm_sqr_comba.c +++ b/crypto/math/pstm_sqr_comba.c @@ -187,6 +187,11 @@ /* ARM code */ /* #pragma message ("Using 32 bit ARM Assembly Optimizations") */ +# if defined __arm__ && defined __thumb__ && !defined __thumb2__ +# error "Platform not supported: Thumb1 mode on ARMv4-v6." +# error "Please, turn off thumb mode or enable thumb2." +# endif + # define COMBA_START # define CLEAR_CARRY \ diff --git a/crypto/math/pstmnt.c b/crypto/math/pstmnt.c index c5100e1..5f1e740 100644 --- a/crypto/math/pstmnt.c +++ b/crypto/math/pstmnt.c @@ -131,6 +131,11 @@ # endif /* PSTMNT_OMIT_ASSEMBLY_OPTIMIZATIONS */ # endif /* __arm__ */ +# if defined __arm__ && defined __thumb__ && !defined __thumb2__ +# error "Platform not supported: Thumb1 mode on ARMv4-v6." +# error "Please, turn off thumb mode or enable thumb2." +# endif + /* --- low-level mathematics operations --- */ # ifdef PSTMNT_USE_X86_ASSEMBLY @@ -854,7 +859,7 @@ pstmnt_square( } /* No square function, just use multiplier. */ - pstmnt_mult(a, a, r, n); + pstmnt_mult(a, a, r, sz); } # endif diff --git a/crypto/pubkey/ecc.c b/crypto/pubkey/ecc.c index febeeb8..78fb5e6 100644 --- a/crypto/pubkey/ecc.c +++ b/crypto/pubkey/ecc.c @@ -3098,7 +3098,6 @@ int32_t psEccDsaSign(psPool_t *pool, const psEccKey_t *privKey, int32_t err = PS_MEM_FAIL; psSize_t olen, rLen, sLen; uint32_t rflag, sflag, sanity; - unsigned char *negative; rflag = sflag = 0; @@ -3212,18 +3211,11 @@ int32_t psEccDsaSign(psPool_t *pool, const psEccKey_t *privKey, /* If r or s has the high bit set, the ASN.1 encoding should include a leading 0x0 byte to prevent it from being "negative". */ - negative = (unsigned char *) r.dp; - if (negative[rLen - 1] & 0x80) - { - rLen++; - rflag = 1; - } - negative = (unsigned char *) s.dp; - if (negative[sLen - 1] & 0x80) /* GOOD ONE */ - { - sLen++; - sflag = 1; - } + /* We check high bit by checking if number of bits is multiple of 8. */ + rflag = (pstm_count_bits(&r) & 7) == 0; + sflag = (pstm_count_bits(&s) & 7) == 0; + rLen += rflag; + sLen += sflag; olen = 6 + rLen + sLen; /* Handle lengths longer than 128.. but still only handling up to 256 */ @@ -3294,7 +3286,7 @@ int32_t psEccDsaSign(psPool_t *pool, const psEccKey_t *privKey, } if ((err = pstm_to_unsigned_bin(pool, &s, sig)) != PSTM_OKAY) { - goto error; + goto errnokey; } *siglen += sLen + 2; err = PS_SUCCESS; diff --git a/crypto/pubkey/pubkey.c b/crypto/pubkey/pubkey.c index 12ad0af..9a188f6 100644 --- a/crypto/pubkey/pubkey.c +++ b/crypto/pubkey/pubkey.c @@ -116,9 +116,131 @@ void psDeletePubKey(psPubKey_t **key) *key = NULL; } -# ifdef USE_PRIVATE_KEY_PARSING -# ifdef MATRIX_USE_FILE_SYSTEM -# if defined(USE_ECC) && defined(USE_RSA) +# if defined(USE_PRIVATE_KEY_PARSING) && defined(MATRIX_USE_FILE_SYSTEM) +# if defined(USE_ECC) || defined(USE_RSA) + +#ifdef USE_RSA +static psBool_t possiblyRSAKey(unsigned char *keyBuf, int32 keyBufLen) +{ + /* Guess if this can be RSA key based on length of encoding and content. + Even the smallest (obsolete 512-bit modulus) RSA private keys are > + 256 bytes. + */ + return (keyBufLen > 256 && keyBuf[0] == 0x30 && keyBuf[1] >= 0x82); +} +#endif /* USE_RSA */ + +/* + Helpers for trial and error private key parse + Return codes: + 1 RSA key + 2 ECC key + < 0 error + */ +static int32_t psTryParsePrivKeyMem(psPool_t *pool, + unsigned char *keyBuf, int32 keyBufLen, + const char *password, psPubKey_t *privkey) +{ +#ifdef USE_RSA + /* Examine data to ensure parses which could not succeed are not tried. */ + if (possiblyRSAKey(keyBuf, keyBufLen)) { + if (psRsaParsePkcs1PrivKey(pool, keyBuf, keyBufLen, &privkey->key.rsa) + >= PS_SUCCESS) + { + privkey->type = PS_RSA; + privkey->keysize = psRsaSize(&privkey->key.rsa); + privkey->pool = pool; + return 1; /* RSA */ + } + } +#endif /* USE_RSA */ + +#ifdef USE_ECC + if (psEccParsePrivKey(pool, keyBuf, keyBufLen, &privkey->key.ecc, NULL) + >= PS_SUCCESS) + { + privkey->type = PS_ECC; + privkey->keysize = psEccSize(&privkey->key.ecc); + privkey->pool = pool; + return 2; /* ECC */ + } +#endif /* USE_ECC */ + +#ifdef USE_PKCS8 + if (psPkcs8ParsePrivBin(pool, keyBuf, keyBufLen, + (char*)password, privkey) >= PS_SUCCESS) + { +# ifdef USE_RSA + if (privkey->type == PS_RSA) + { + return 1; /* RSA */ + } +# endif /* USE_RSA */ + +# ifdef USE_ECC + if (privkey->type == PS_ECC) + { + return 2; /* ECC */ + } +# endif /* USE_ECC */ + + return -1; /* Success, but keytype unknown? */ + } +#endif /* USE_PKCS8 */ + + return -1; /* Error */ +} + +static int32_t psTryParsePrivKeyFilePEM(psPool_t *pool, const char *keyfile, + const char *password, psPubKey_t *privkey) +{ +#ifdef USE_RSA + if (psPkcs1ParsePrivFile(pool, keyfile, password, &privkey->key.rsa) >= PS_SUCCESS) + { + privkey->type = PS_RSA; + privkey->keysize = psRsaSize(&privkey->key.rsa); + privkey->pool = pool; + return 1; /* RSA */ + } +#endif /* USE_RSA */ + +#ifdef USE_ECC + /* psEccParsePrivFile will also try psPkcs8ParsePrivBin. */ + if (psEccParsePrivFile(pool, keyfile, password, &privkey->key.ecc) >= PS_SUCCESS) + { + privkey->type = PS_ECC; + privkey->keysize = psEccSize(&privkey->key.ecc); + privkey->pool = pool; + return 2; /* ECC */ + } +#endif /* USE_ECC */ + + return -1; /* Error */ +} + +static int32_t psTryParsePubKeyFilePEM(psPool_t *pool, const char *keyfile, + const char *password, psPubKey_t *pubkey) +{ +#ifdef USE_RSA + /* PEM file. */ + if (psPkcs1ParsePubFile(pool, keyfile, &pubkey->key.rsa) >= PS_SUCCESS) + { + pubkey->type = PS_RSA; + pubkey->keysize = psRsaSize(&pubkey->key.rsa); + return 1; /* RSA */ + } +#endif /* USE_RSA */ + + PS_VARIABLE_SET_BUT_UNUSED(password); +#ifndef USE_RSA + PS_VARIABLE_SET_BUT_UNUSED(pool); + PS_VARIABLE_SET_BUT_UNUSED(keyfile); + PS_VARIABLE_SET_BUT_UNUSED(pubkey); +#endif /* !USE_RSA */ + + return -1; /* Error */ +} + /* Trial and error private key parse for when ECC or RSA is unknown. keyBuf must point to a buffer of length keyBufLen, containing @@ -133,77 +255,23 @@ int32_t psParseUnknownPrivKeyMem(psPool_t *pool, unsigned char *keyBuf, int32 keyBufLen, const char *password, psPubKey_t *privkey) { - psRsaKey_t *rsakey; - psEccKey_t *ecckey; - int32_t keytype = 1; - psBool_t notRsaKey; + int32_t keytype; if (keyBuf == NULL || keyBufLen <= 0) return PS_ARG_FAIL; privkey->keysize = 0; - rsakey = &privkey->key.rsa; - ecckey = &privkey->key.ecc; - /* Examine data to ensure parses which could not succeed are not tried. */ - - /* Guess if this can be RSA key based on length of encoding and content. - Even the smallest (obsolete 512-bit modulus) RSA private keys are > - 256 bytes. - */ - notRsaKey = keyBufLen < 257 || keyBuf[0] != 0x30 || keyBuf[1] < 0x82; + keytype = psTryParsePrivKeyMem(pool, keyBuf, keyBufLen, password, privkey); - /* A raw RSAPrivateKey? */ - if (notRsaKey != PS_FALSE || - psRsaParsePkcs1PrivKey(pool, keyBuf, keyBufLen, rsakey) - < PS_SUCCESS) + if (keytype < 0) { - /* A raw ECPrivateKey? */ - if (psEccParsePrivKey(pool, keyBuf, keyBufLen, ecckey, NULL) - < PS_SUCCESS) - { -# ifdef USE_PKCS8 - /* A PKCS #8 PrivateKeyInfo containing an ECPrivateKey? */ - if (psPkcs8ParsePrivBin(pool, keyBuf, keyBufLen, - (char*)password, privkey)) - { -# endif /* USE_PKCS8 */ - /* Nothing worked. */ - psTraceCrypto("Unable to parse private key. " \ - "Supported formats are RSAPrivateKey, " \ - "ECPrivateKey and PKCS #8.\n"); - return PS_FAILURE; -# 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; + psTraceCrypto("Unable to parse private key. " \ + "Supported formats are RSAPrivateKey, " \ + "ECPrivateKey and PKCS #8.\n"); + return PS_FAILURE; } -# ifdef USE_PKCS8 -parsed: -# endif /* USE_PKCS8 */ - if (keytype == 1) - { - privkey->type = PS_RSA; - privkey->keysize = psRsaSize(&privkey->key.rsa); - } - else - { - privkey->type = PS_ECC; - privkey->keysize = psEccSize(&privkey->key.ecc); - } - privkey->pool = pool; - return keytype; } @@ -220,35 +288,22 @@ int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer, const char *keyfile, const char *password, psPubKey_t *privkey) { - psRsaKey_t *rsakey; - psEccKey_t *ecckey; - int keytype = 1; + int keytype = -1; unsigned char *keyBuf; int32 keyBufLen; int32_t rc; privkey->keysize = 0; - rsakey = &privkey->key.rsa; - ecckey = &privkey->key.ecc; if (pemOrDer == 1) { - /* PEM file. */ - if (psPkcs1ParsePrivFile(pool, keyfile, password, rsakey) - < PS_SUCCESS) + /* PEM file */ + keytype = psTryParsePrivKeyFilePEM(pool, keyfile, password, privkey); + + if (keytype < 0) { - /* psEccParsePrivFile will also try psPkcs8ParsePrivBin. */ - if (psEccParsePrivFile(pool, keyfile, password, ecckey) - < PS_SUCCESS) - { - psTraceStrCrypto("Unable to parse private key file %s\n", - keyfile); - return PS_FAILURE; - } - keytype = 2; - } - else - { - keytype = 1; + psTraceStrCrypto("Unable to parse private key file %s\n", + keyfile); + return PS_FAILURE; } } else @@ -270,21 +325,8 @@ int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer, return -1; } keytype = rc; - goto out; /* psParseUnknownPrivKeyMem already set up everything. */ } - if (keytype == 1) - { - privkey->type = PS_RSA; - privkey->keysize = psRsaSize(&privkey->key.rsa); - } - else - { - privkey->type = PS_ECC; - privkey->keysize = psEccSize(&privkey->key.ecc); - } - privkey->pool = pool; -out: return keytype; } @@ -304,8 +346,7 @@ out: int32_t psParseUnknownPubKey(psPool_t *pool, int pemOrDer, char *keyfile, const char *password, psPubKey_t *pubkey) { - psRsaKey_t *rsakey; - int keytype = 1; + int keytype = -1; unsigned char *keyBuf; int32 keyBufLen; @@ -314,19 +355,16 @@ int32_t psParseUnknownPubKey(psPool_t *pool, int pemOrDer, char *keyfile, (void) password; /* password is for future extensions. */ pubkey->keysize = 0; - rsakey = &pubkey->key.rsa; if (pemOrDer == 1) { - /* PEM file. */ - if (psPkcs1ParsePubFile(pool, keyfile, rsakey) - < PS_SUCCESS) + /* PEM file */ + keytype = psTryParsePubKeyFilePEM(pool, keyfile, password, pubkey); + + if (keytype < 0) { + psTraceStrCrypto("Unable to parse public key file %s\n", keyfile); return PS_FAILURE; } - - pubkey->type = PS_RSA; - pubkey->keysize = psRsaSize(&pubkey->key.rsa); - return keytype; } else { @@ -339,13 +377,48 @@ int32_t psParseUnknownPubKey(psPool_t *pool, int pemOrDer, char *keyfile, /* Processing DER files not handled by current implementation of the function the input shall be in PEM format. */ psFree(keyBuf, pool); - return PS_FAILURE; } + + return keytype; } -# endif /* USE_ECC && USE_RSA */ -# endif /* MATRIX_USE_FILE_SYSTEM */ -# endif /* USE_PRIVATE_KEY_PARSING */ +# endif /* USE_ECC || USE_RSA */ +# else +int32_t psParseUnknownPrivKeyMem(psPool_t *pool, + unsigned char *keyBuf, int32 keyBufLen, + const char *password, psPubKey_t *privkey) +{ + PS_VARIABLE_SET_BUT_UNUSED(pool); + PS_VARIABLE_SET_BUT_UNUSED(keyBuf); + PS_VARIABLE_SET_BUT_UNUSED(keyBufLen); + PS_VARIABLE_SET_BUT_UNUSED(password); + PS_VARIABLE_SET_BUT_UNUSED(privkey); + return -1; /* Not implemented */ +} + +int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer, + const char *keyfile, const char *password, + psPubKey_t *privkey) +{ + PS_VARIABLE_SET_BUT_UNUSED(pool); + PS_VARIABLE_SET_BUT_UNUSED(pemOrDer); + PS_VARIABLE_SET_BUT_UNUSED(keyfile); + PS_VARIABLE_SET_BUT_UNUSED(password); + PS_VARIABLE_SET_BUT_UNUSED(privkey); + return -1; /* Not implemented */ +} + +int32_t psParseUnknownPubKey(psPool_t *pool, int pemOrDer, char *keyfile, + const char *password, psPubKey_t *pubkey) +{ + PS_VARIABLE_SET_BUT_UNUSED(pool); + PS_VARIABLE_SET_BUT_UNUSED(pemOrDer); + PS_VARIABLE_SET_BUT_UNUSED(keyfile); + PS_VARIABLE_SET_BUT_UNUSED(password); + PS_VARIABLE_SET_BUT_UNUSED(pubkey); + return -1; /* Not implemented */ +} +# endif /* USE_PRIVATE_KEY_PARSING && MATRIX_USE_FILE_SYSTEM */ int32_t psHashLenToSigAlg(psSize_t hash_len, uint8_t key_type) diff --git a/crypto/symmetric/aes_aesni.c b/crypto/symmetric/aes_aesni.c index 71d2b96..6e05694 100644 --- a/crypto/symmetric/aes_aesni.c +++ b/crypto/symmetric/aes_aesni.c @@ -781,7 +781,7 @@ static void galois_counter(psAesGcm_t *ctx, unsigned char *dst, /* Handle remainder */ if (partial_len != 0) { - unsigned int partial[16]; + unsigned char partial[16]; memset(partial, 0x00, 16); memcpy(partial, src + (n * 16), partial_len); diff --git a/crypto/symmetric/symmetric.h b/crypto/symmetric/symmetric.h index 8e99f16..d628753 100644 --- a/crypto/symmetric/symmetric.h +++ b/crypto/symmetric/symmetric.h @@ -52,7 +52,7 @@ # define SEED_BLOCKLEN 16 # define SEED_IVLEN SEED_BLOCKLEN # define SEED_KEYLEN 16 -# define CHACHA20POLY1305_IV_FIXED_LENGTH 12 +# define CHACHA20POLY1305_IETF_IV_FIXED_LENGTH 12 # define CHACHA20POLY1305_IETF /* Always use IETF mode */ # define MAX_IVLEN AES_IVLEN @@ -69,6 +69,10 @@ # endif # ifdef USE_LIBSODIUM_CRYPTO # include "symmetric_libsodium.h" +# include "../ps_chacha20poly1305ietf.h" +# endif +# ifdef USE_MATRIX_CHACHA20_POLY1305_IETF +# include "../ps_chacha20poly1305ietf.h" # endif /******************************************************************************/ @@ -81,8 +85,8 @@ typedef union # ifdef USE_AES_CBC psAesCbc_t aes; # endif -# ifdef USE_CHACHA20_POLY1305 - psChacha20Poly1305_t chacha20poly1305; +# ifdef USE_CHACHA20_POLY1305_IETF + psChacha20Poly1305Ietf_t chacha20poly1305ietf; # endif # ifdef USE_MATRIX_RC2 psRc2Cbc_t rc2; diff --git a/crypto/symmetric/symmetric_libsodium.c b/crypto/symmetric/symmetric_libsodium.c index 06fff4f..e030bb7 100644 --- a/crypto/symmetric/symmetric_libsodium.c +++ b/crypto/symmetric/symmetric_libsodium.c @@ -213,221 +213,240 @@ int32_t psAesDecryptGCM(psAesGcm_t *ctx, /******************************************************************************/ -#ifdef USE_LIBSODIUM_CHACHA20_POLY1305 +#ifdef USE_LIBSODIUM_CHACHA20_POLY1305_IETF /*********************************************************************************/ /* chacha20-poly1305 AEAD low-level implementation, based on libsodium library */ -/* Refer to the following spec: */ -/* https://tools.ietf.org/html/rfc7539 $2.8 AEAD Construction */ -/* */ -/* !!! Note that if CHACHA20POLY1305_IETF is defined than the nonce must be */ -/* 96bits, if CHACHA20POLY1305_IETF not defined the nonce must be 64bits */ +/* For details, see */ +/* https://tools.ietf.org/html/rfc7539 $2.8 AEAD Construction */ /*********************************************************************************/ -/** - Initialize an chacha20 poly1305 context. Put the provided key in the context - structure - @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... - @param key The algo's key - @param keylen The key's length - - @return PS_SUCCESS if success - PS_FAIL in case of key length problem - - */ -int32_t psChacha20Poly1305Init(psChacha20Poly1305_t *ctx, - const unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES], uint8_t keylen) +/* Initialize psChacha20Poly1305Ietf for use. */ +psRes_t psChacha20Poly1305IetfInit( + psChacha20Poly1305Ietf_t *ctx, + const unsigned char key[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_KEYBYTES)]) { - if (keylen != crypto_aead_chacha20poly1305_KEYBYTES) - { - psTraceCrypto("FAIL: libsodium-chacha20-poly1305 not supporting this key length"); - psAssert(0); - return PS_FAIL; - } - memset(ctx, 0x0, sizeof(psChacha20Poly1305_t)); /* Copy the key */ - memcpy(ctx->key, key, crypto_aead_chacha20poly1305_KEYBYTES); + memcpy(ctx->key, key, PS_CHACHA20POLY1305_IETF_KEYBYTES); return PS_SUCCESS; } /******************************************************************************/ -/** - Clear the provided context structure - @param ctx context structure +/* Clear the provided context structure */ -void psChacha20Poly1305Clear(psChacha20Poly1305_t *ctx) +void psChacha20Poly1305IetfClear(psChacha20Poly1305Ietf_t *ctx) { - memset_s(ctx, sizeof(psChacha20Poly1305_t), 0x0, sizeof(psChacha20Poly1305_t)); + memset_s(ctx, + sizeof(psChacha20Poly1305Ietf_t), + 0x0, + sizeof(psChacha20Poly1305Ietf_t)); } -/******************************************************************************/ -/** - Specifiy the IV and additional data to an chacha20 poly1305 context that was - created with psChacha20Poly1305Init. - - - @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... - @param IV pointer on the provided IV - (called nonce if referring to https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-03) - @param aad pointer on buffer holding additional data, as specified in - - */ -void psChacha20Poly1305Ready(psChacha20Poly1305_t *ctx, - const unsigned char *IV, - const unsigned char *aad, psSize_t aadLen) +psResSize_t psChacha20Poly1305IetfEncryptDetached( + psChacha20Poly1305Ietf_t *Context_p, + const unsigned char *Plaintext_p, + psSizeL_t PlaintextNBytes, + const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], + const unsigned char *Aad_p, + psSize_t AadNBytes, + unsigned char *Ciphertext_p, + unsigned char Mac_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_ABYTES)]) { - /* --- Set up context structure ---// */ + int ret; - /* Set up IV */ -# ifdef CHACHA20POLY1305_IETF - memset(ctx->IV, 0, crypto_aead_chacha20poly1305_IETF_NPUBBYTES); - memcpy(ctx->IV, IV, crypto_aead_chacha20poly1305_IETF_NPUBBYTES); -# else - memset(ctx->IV, 0, crypto_aead_chacha20poly1305_NPUBBYTES); - memcpy(ctx->IV, IV, crypto_aead_chacha20poly1305_NPUBBYTES); -# endif - - if (aadLen > sizeof(ctx->Aad)) + /* Check input is not too large for this API. */ + if (PlaintextNBytes > (psSizeL_t)PS_RES_SIZE_OK_MAX) { - psTraceCrypto("FAIL: size issue with libsodium-chacha20-poly1305 additionnal data"); - psAssert(0); + return PS_ARG_FAIL; } + + ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached( + Ciphertext_p, + Mac_p, + NULL, + (const unsigned char *)Plaintext_p, + (unsigned long long)PlaintextNBytes, + (const unsigned char *)Aad_p, + (unsigned long long)AadNBytes, + NULL, + (const unsigned char *)Iv_p, + (const unsigned char *)Context_p->key); - /* Set up additional data */ - memcpy(ctx->Aad, aad, aadLen); - ctx->AadLen = aadLen; -} - -/******************************************************************************/ -/* - Public chacha20 poly1305 encrypt function. - This will perform the encryption and compute the authentication tag at the - same time. In the output pointer (ct), only the encrypted text is present, the - tag should be fetched with psChacha20Poly1305GetTag - - @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... - @param pt pointer on the text to encrypt - @param ct pointer on encrypted text, output of this function - @param len length of the text to encrypt - */ -void psChacha20Poly1305Encrypt(psChacha20Poly1305_t *ctx, const unsigned char *pt, unsigned char *ct, uint32_t len) -{ - unsigned long long ciphertext_len; - unsigned char *resultEncryption; - - /* Allocate mem to store ciphertext and tag */ - resultEncryption = psMalloc(NULL, len + sizeof(ctx->Tag)); - - /* libsodium will put the cipher text and the tag in the result. */ - /* resultEncryption = cipherText || tag */ -# ifdef CHACHA20POLY1305_IETF - crypto_aead_chacha20poly1305_ietf_encrypt(resultEncryption, &ciphertext_len, - (const unsigned char *) pt, (unsigned long long) len, - (const unsigned char *) ctx->Aad, (unsigned long long) ctx->AadLen, - NULL, (const unsigned char *) ctx->IV, (const unsigned char *) ctx->key); -# else - crypto_aead_chacha20poly1305_encrypt(resultEncryption, &ciphertext_len, - (const unsigned char *) pt, (unsigned long long) len, - (const unsigned char *) ctx->Aad, (unsigned long long) ctx->AadLen, - NULL, (const unsigned char *) ctx->IV, (const unsigned char *) ctx->key); -# endif - - /* Copy the authentication tag in context to be able to retrieve it later */ - memcpy(ctx->Tag, (resultEncryption + len), sizeof(ctx->Tag)); - - /* Copy the ciphertext in destination */ - memcpy(ct, resultEncryption, len); - - psFree(resultEncryption, NULL); -} - -/************************************************************************************/ -/* - After encryption this function is used to retrieve the authentication tag - @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... - @param tagBytesLen length of tag to retrieve - @param tag the provided buffer to hold the AEAD' authentication tag - */ -void psChacha20Poly1305GetTag(psChacha20Poly1305_t *ctx, uint8_t tagBytesLen, unsigned char tag[crypto_aead_chacha20poly1305_ABYTES]) -{ - memcpy(tag, ctx->Tag, tagBytesLen); -} - -/************************************************************************************/ -/* - Just does the chacha20 poly1305 decrypt portion. Doesn't expect the tag to be - at the end of the ct. User will invoke psChacha20Poly1305GetTag seperately - !!! Currently not available with libsodium !!!!! - */ -void psChacha20Poly1305DecryptTagless(psChacha20Poly1305_t *ctx, - const unsigned char *ct, unsigned char *pt, - uint32_t len) -{ - /* Not possible with libsodium. */ - psAssert(0); -} - -/******************************************************************************/ -/* - Decrypt function using libsodium library. This function will perform - itself the tag comparaison. - So the provided cipherText must hold: cipher text || tag . - The provided length (ctLen) must reflect this. - - @param ctx Pointer on the cipher context structure. This structure holds the key, nonce & aad... - @param ct pointer on: (cipherText || AEAD-Tag) - @param ctLen length of data pointed by ct (so encrypted data + tag) - @param pt pointer on decrypted data - @param ptLen length of encrypted data - - @return length of decrypted data in case of success. - PS_ARG_FAIL in case of parameter problem - PS_AUTH_FAIL in case of problem during tag's authentication check or - during decryption operation - */ -int32_t psChacha20Poly1305Decrypt(psChacha20Poly1305_t *ctx, - const unsigned char *ct, uint32_t ctLen, - unsigned char *pt, uint32_t ptLen) -{ - unsigned long long decrypted_len; - - if ((ctLen - ptLen) != crypto_aead_chacha20poly1305_ABYTES) + if (ret == 0) + { + return (psResSize_t) PlaintextNBytes; + } + return PS_FAIL; +} + + +psResSize_t psChacha20Poly1305IetfDecryptDetached( + psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], + const unsigned char *Ciphertext_p, + psSizeL_t CiphertextNBytes, + const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], + const unsigned char *Aad_p, + psSizeL_t AadNBytes, + const unsigned char Mac_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_ABYTES)], + unsigned char *Plaintext_p) +{ + psSizeL_t plaintextNBytes = CiphertextNBytes; /* Plaintext length is the same than ciphertext length. */ + + /* Check input is not too large for this API. */ + if (plaintextNBytes > (psSizeL_t)(psResSize_t)PS_RES_SIZE_OK_MAX) { - psTraceCrypto("FAIL: Cipher text must include the tag\n"); return PS_ARG_FAIL; } -# ifdef CHACHA20POLY1305_IETF - if (crypto_aead_chacha20poly1305_ietf_decrypt(pt, &decrypted_len, NULL, - ct, (unsigned long long) ctLen, - (const unsigned char *) ctx->Aad, (unsigned long long) ctx->AadLen, - (const unsigned char *) ctx->IV, (const unsigned char *) ctx->key) != 0) - { - - psTraceCrypto("chacha20 poly1305 AEAD didn't authenticate\n"); - return PS_AUTH_FAIL; - } -# else - if (crypto_aead_chacha20poly1305_decrypt(pt, &decrypted_len, NULL, - ct, (unsigned long long) ctLen, - (const unsigned char *) ctx->Aad, (unsigned long long) ctx->AadLen, - (const unsigned char *) ctx->IV, - (const unsigned char *) ctx->key) != 0) + if (crypto_aead_chacha20poly1305_ietf_decrypt_detached( + Plaintext_p, + NULL, + Ciphertext_p, + (unsigned long long)CiphertextNBytes, + (const unsigned char *)Mac_p, + (const unsigned char *)Aad_p, + (unsigned long long)AadNBytes, + (const unsigned char *)Iv_p, + (const unsigned char *)Context_p->key) != 0) { psTraceCrypto("chacha20 poly1305 AEAD didn't authenticate\n"); return PS_AUTH_FAIL; } -# endif - if (decrypted_len != ptLen) - { - psTraceCrypto("Problem during chacha20 poly1305 AEAD decryption\n"); - return PS_AUTH_FAIL; - } - return decrypted_len; + return (psResSize_t)plaintextNBytes; } -/************************************************************************************/ +/******************************************************************************/ +/* + Chacha20 poly1305 Ietf encryption function (ciphertext + mac in one sequence.) + */ +psResSize_t psChacha20Poly1305IetfEncrypt( + psChacha20Poly1305Ietf_t *Context_p, + const unsigned char *Plaintext_p, + psSizeL_t PlaintextNBytes, + const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], + const unsigned char *Aad_p, + psSizeL_t AadNBytes, + unsigned char Ciphertext_p[PS_EXACTLY_EXPR(PlaintextLen + PS_CHACHA20POLY1305_IETF_ABYTES)]) +{ +#ifdef USE_PS_CRYPTO_AEAD_CHACHA20POLY1305_IETF_ENCRYPT + unsigned long long ciphertextNBytes = 0ULL; + psResSize_t ret; -#endif /* USE_LIBSODIUM_CHACHA20_POLY1305 */ + /* Check input is not too large for this API. */ + if ((PlaintextNBytes + PS_CHACHA20POLY1305_IETF_ABYTES) > + (psSizeL_t)PS_RES_SIZE_OK_MAX) + { + return PS_ARG_FAIL; + } + + ret = crypto_aead_chacha20poly1305_ietf_encrypt( + Ciphertext_p, + &ciphertextNBytes, + (const unsigned char *)Plaintext_p, + (unsigned long long)PlaintextNBytes, + (const unsigned char *)Aad_p, + (unsigned long long)AadNBytes, + NULL, + (const unsigned char *)Iv_p, + (const unsigned char *)Context_p->key); + if (ret == 0) + { + return (psResSize_t) ciphertextNBytes; + } + return PS_FAIL; +#else + psSizeL_t ciphertextNBytes = + PlaintextNBytes + PS_CHACHA20POLY1305_IETF_ABYTES; + psResSize_t ret; + + /* Check input is not too large for this API. */ + if (PlaintextNBytes > (psSizeL_t)PS_RES_SIZE_OK_MAX || + ciphertextNBytes > (psSizeL_t)PS_RES_SIZE_OK_MAX) + { + return PS_ARG_FAIL; + } + + ret = psChacha20Poly1305IetfEncryptDetached( + Context_p, + Plaintext_p, + PlaintextNBytes, + Iv_p, + Aad_p, + AadNBytes, + Ciphertext_p, + Ciphertext_p + PlaintextNBytes); + + if (ret >= 0) + { + ret += PS_CHACHA20POLY1305_IETF_ABYTES; + } + return ret; +#endif +} + +/******************************************************************************/ +/* + Decrypt data using chach20-poly1305 authenticated encryption function. + */ +psResSize_t psChacha20Poly1305IetfDecrypt( + psChacha20Poly1305Ietf_t Context_p[PS_EXACTLY(1)], + const unsigned char Ciphertext_p[PS_EXACTLY_EXPR(CiphertextNBytes)], + psSizeL_t CiphertextNBytes, + const unsigned char Iv_p[PS_EXACTLY(PS_CHACHA20POLY1305_IETF_NPUBBYTES)], + const unsigned char *Aad_p, + psSizeL_t AadNBytes, + unsigned char *Plaintext_p) +{ +#ifdef USE_PS_CRYPTO_AEAD_CHACHA20POLY1305_IETF_DECRYPT + /* Old path, which can be enabled by setting USE_PS_CRYPTO_AEAD_CHACHA20POLY1305_IETF_DECRYPT. */ + psSizeL_t plaintextNBytes = CiphertextNBytes - PS_CHACHA20POLY1305_IETF_ABYTES; + if (CiphertextNBytes < PS_CHACHA20POLY1305_IETF_ABYTES) + { + return PS_ARG_FAIL; + } + /* Check input is not too large for this API. */ + if (plaintextNBytes > (psSizeL_t)(psResSize_t)PS_RES_SIZE_OK_MAX) + { + return PS_ARG_FAIL; + } + + if (crypto_aead_chacha20poly1305_ietf_decrypt( + Plaintext_p, + NULL, + NULL, + Ciphertext_p, + (unsigned long long)CiphertextNBytes, + (const unsigned char *)Aad_p, + (unsigned long long)AadNBytes, + (const unsigned char *)Iv_p, + (const unsigned char *)Context_p->key) != 0) + { + psTraceCrypto("chacha20 poly1305 AEAD didn't authenticate\n"); + return PS_AUTH_FAIL; + } + + return (psResSize_t)plaintextNBytes; +#else + psSizeL_t plaintextNBytes; + + /* Ensure input is not too short. */ + if (CiphertextNBytes < PS_CHACHA20POLY1305_IETF_ABYTES) + { + return PS_ARG_FAIL; + } + + plaintextNBytes = CiphertextNBytes - PS_CHACHA20POLY1305_IETF_ABYTES; + return psChacha20Poly1305IetfDecryptDetached( + Context_p, + Ciphertext_p, + plaintextNBytes, + Iv_p, + Aad_p, + AadNBytes, + Ciphertext_p + plaintextNBytes, + Plaintext_p); +#endif +} +#endif /* USE_LIBSODIUM_CHACHA20_POLY1305_IETF */ diff --git a/crypto/symmetric/symmetric_libsodium.h b/crypto/symmetric/symmetric_libsodium.h index 94e73f9..63c23df 100644 --- a/crypto/symmetric/symmetric_libsodium.h +++ b/crypto/symmetric/symmetric_libsodium.h @@ -52,15 +52,16 @@ typedef struct __attribute__((aligned(16))) } psAesGcm_t; # endif -# ifdef USE_LIBSODIUM_CHACHA20_POLY1305 +# ifdef USE_LIBSODIUM_CHACHA20_POLY1305_IETF typedef struct { - unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES]; + unsigned char key[crypto_aead_chacha20poly1305_ietf_KEYBYTES]; unsigned char IV[crypto_aead_chacha20poly1305_IETF_NPUBBYTES]; - unsigned char Tag[crypto_aead_chacha20poly1305_ABYTES]; + unsigned char Tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; unsigned char Aad[16]; uint32_t AadLen; -} psChacha20Poly1305_t; +} psChacha20Poly1305Ietf_t; +# define PS_CHACHA20POLY1305IETF_DEFINED 1 # endif /******************************************************************************/ diff --git a/crypto/test/algorithmTest.c b/crypto/test/algorithmTest.c index 4a77c8f..c2a2c1c 100644 --- a/crypto/test/algorithmTest.c +++ b/crypto/test/algorithmTest.c @@ -1356,151 +1356,144 @@ L_CBC_TIMING: } #endif /* 0 */ -#ifdef USE_CHACHA20_POLY1305 +#ifdef USE_CHACHA20_POLY1305_IETF # define TEST_TEXT_MAXLEN 128 # define TEST_AAD_MAXLEN 32 -# ifdef USE_LIBSODIUM_CHACHA20_POLY1305 -# define TEST_TAG_LEN crypto_aead_chacha20poly1305_ABYTES -# define TEST_KEY_LEN crypto_aead_chacha20poly1305_KEYBYTES -# ifdef CHACHA20POLY1305_IETF -# define TEST_IV_LEN crypto_aead_chacha20poly1305_IETF_NPUBBYTES -# else -# define TEST_IV_LEN crypto_aead_chacha20poly1305_NPUBBYTES -# endif +# ifdef USE_LIBSODIUM_CHACHA20_POLY1305_IETF +# define TEST_TAG_LEN crypto_aead_chacha20poly1305_IETF_ABYTES +# define TEST_KEY_LEN crypto_aead_chacha20poly1305_IETF_KEYBYTES +# define TEST_IV_LEN crypto_aead_chacha20poly1305_IETF_NPUBBYTES # else # define TEST_TAG_LEN 16 # define TEST_KEY_LEN 32 # define TEST_IV_LEN 12 # endif -int32 psChacha20Poly1305Test(void) +int32 psChacha20Poly1305IetfTest(void) { int32 i; - psChacha20Poly1305_t eCtx, dCtx; + psChacha20Poly1305Ietf_t eCtx, dCtx; unsigned char ciphertext[TEST_TEXT_MAXLEN]; unsigned char plaintext[TEST_TEXT_MAXLEN]; + unsigned char plaintext2[TEST_TEXT_MAXLEN]; + unsigned char ciphertext_tag[TEST_TEXT_MAXLEN + TEST_TAG_LEN]; unsigned char tag[TEST_TAG_LEN]; + psResSize_t sz1; + psResSize_t sz2; static struct { int32 keylen, ptlen, aadlen; unsigned char key[TEST_KEY_LEN], iv[TEST_IV_LEN], pt[TEST_TEXT_MAXLEN], aad[TEST_AAD_MAXLEN], ct[TEST_TEXT_MAXLEN], tag[TEST_TAG_LEN]; } tests[] = { - -# ifdef CHACHA20POLY1305_IETF - { TEST_KEY_LEN, 114, 12, - { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }, + + { + TEST_KEY_LEN, 114, 12, + { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }, /* IV */ - { 0x07, 0x00, 0x00, 0x00, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }, + { + 0x07, 0x00, 0x00, 0x00, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }, /* pt */ - { 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, - 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, - 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, - 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, - 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, - 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, - 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, - 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, - 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, - 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, - 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, - 0x74, 0x2e }, + { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e }, /* aad */ - { 0x50, 0x51, 0x52, 0x53, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }, + { + 0x50, 0x51, 0x52, 0x53, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }, /* ct */ - { 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, - 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, - 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, - 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, - 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, - 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, - 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, - 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, - 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, - 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, - 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, - 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, - 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, - 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, - 0x61, 0x16 }, + { + 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, + 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, + 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, + 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, + 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, + 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, + 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, + 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, + 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, + 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, + 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, + 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, + 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, + 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, + 0x61, 0x16 }, /* tag */ - { 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, - 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 } }, + { + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, + 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 } }, - { TEST_KEY_LEN, 114, 0, - { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }, + { + TEST_KEY_LEN, 114, 0, + { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }, /* IV */ - { 0x07, 0x00, 0x00, 0x00, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }, + { + 0x07, 0x00, 0x00, 0x00, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }, /* pt */ - { 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, - 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, - 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, - 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, - 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, - 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, - 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, - 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, - 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, - 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, - 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, - 0x74, 0x2e }, + { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e }, /* aad */ - { "" }, + { + "" + }, /* ct */ - { 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, - 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, - 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, - 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, - 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, - 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, - 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, - 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, - 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, - 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, - 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, - 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, - 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, - 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, - 0x61, 0x16 }, + { + 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, + 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, + 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, + 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, + 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, + 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, + 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, + 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, + 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, + 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, + 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, + 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, + 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, + 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, + 0x61, 0x16 }, /* tag */ - { 0x6a, 0x23, 0xa4, 0x68, 0x1f, 0xd5, 0x94, 0x56, - 0xae, 0xa1, 0xd2, 0x9f, 0x82, 0x47, 0x72, 0x16 } } -# else - { TEST_KEY_LEN, 16, 13, - { 0x70, 0xd5, 0xbd, 0x03, 0xc6, 0x17, 0x68, 0xb2, - 0xd5, 0xce, 0xb4, 0xa4, 0x15, 0xc6, 0xf8, 0x40, - 0xf5, 0xd4, 0xbf, 0x5e, 0x63, 0x2b, 0xb6, 0xf3, - 0x73, 0xaf, 0xcd, 0xd7, 0xbb, 0xba, 0x85, 0xa7 }, - /* Nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* pt */ - { 0x14, 0x00, 0x00, 0x0c, - 0x9c, 0x49, 0x65, 0xfc, 0xeb, 0x2e, 0xfa, 0x01, 0xfc, 0xa1, 0x2a, 0xaf }, - /* aad */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x16, 0x03, 0x03, 0x00, 0x10 }, - /* ct */ - { 0x25, 0xd8, 0x3d, 0x53, 0xbd, 0x03, 0xdd, 0x69, - 0x5a, 0x44, 0x6f, 0xde, 0x0c, 0x3d, 0x87, 0x93 }, - /* tag */ - { 0x80, 0x53, 0x32, 0x2f, 0x5c, 0x27, 0x8f, 0x9d, - 0x78, 0xb5, 0x25, 0x3d, 0x5c, 0xc3, 0x8c, 0x9b } } -# endif + { + 0x6a, 0x23, 0xa4, 0x68, 0x1f, 0xd5, 0x94, 0x56, + 0xae, 0xa1, 0xd2, 0x9f, 0x82, 0x47, 0x72, 0x16 } } }; /* Test AEAD CHACHA20-POLY1305 */ @@ -1508,36 +1501,36 @@ int32 psChacha20Poly1305Test(void) for (i = 0; i < (int32) (sizeof(tests) / sizeof(tests[0])); i++) { _psTraceInt(" CHACHA20-POLY1305-%d " -# ifdef CHACHA20POLY1305_IETF "IETF " -# endif "known vector encrypt test... ", tests[i].keylen * 8); - psChacha20Poly1305Init(&eCtx, tests[i].key, tests[i].keylen); - psChacha20Poly1305Ready(&eCtx, tests[i].iv, tests[i].aad, tests[i].aadlen); - psChacha20Poly1305Encrypt(&eCtx, tests[i].pt, ciphertext, tests[i].ptlen); - psChacha20Poly1305GetTag(&eCtx, TEST_TAG_LEN, tag); + psChacha20Poly1305IetfInit(&eCtx, tests[i].key); + sz1 = psChacha20Poly1305IetfEncryptDetached(&eCtx, tests[i].pt, tests[i].ptlen, tests[i].iv, tests[i].aad, tests[i].aadlen, ciphertext, tag); - if ((memcmp(ciphertext, tests[i].ct, tests[i].ptlen) != 0) || - (memcmp(tag, tests[i].tag, TEST_TAG_LEN) != 0)) + sz2 = psChacha20Poly1305IetfEncrypt(&eCtx, tests[i].pt, tests[i].ptlen, tests[i].iv, tests[i].aad, tests[i].aadlen, ciphertext_tag); + + if (sz1 != tests[i].ptlen || + memcmp(ciphertext, tests[i].ct, tests[i].ptlen) != 0 || + memcmp(tag, tests[i].tag, TEST_TAG_LEN) != 0) { - printf("FAILED: memcmp mismatch\n"); + printf("FAILED: memcmp mismatch (psChacha20Poly1305IetfEncryptDetached)\n"); + } + else if (sz2 != tests[i].ptlen + TEST_TAG_LEN || + memcmp(ciphertext_tag, tests[i].ct, tests[i].ptlen) != 0 || + memcmp(ciphertext_tag + tests[i].ptlen, tests[i].tag, TEST_TAG_LEN) != 0) + { + printf("FAILED: memcmp mismatch (psChacha20Poly1305IetfEncrypt)\n"); } else { printf("PASSED\n"); } - psChacha20Poly1305Clear(&eCtx); - memset(tag, 0x0, TEST_TAG_LEN); - memset(ciphertext, 0x0, TEST_TEXT_MAXLEN); + psChacha20Poly1305IetfClear(&eCtx); _psTraceInt(" CHACHA20-POLY1305-%d " -# ifdef CHACHA20POLY1305_IETF "IETF " -# endif "known vector decrypt test... ", tests[i].keylen * 8); - psChacha20Poly1305Init(&dCtx, tests[i].key, tests[i].keylen); - psChacha20Poly1305Ready(&dCtx, tests[i].iv, tests[i].aad, tests[i].aadlen); + psChacha20Poly1305IetfInit(&dCtx, tests[i].key); /* Cipher text must include the tag */ unsigned char *cipherTextAuthData; @@ -1546,27 +1539,51 @@ int32 psChacha20Poly1305Test(void) memcpy(cipherTextAuthData, tests[i].ct, tests[i].ptlen); memcpy(cipherTextAuthData + tests[i].ptlen, tests[i].tag, TEST_TAG_LEN); - if (psChacha20Poly1305Decrypt(&dCtx, cipherTextAuthData, - tests[i].ptlen + TEST_TAG_LEN, plaintext, tests[i].ptlen) < 0) + sz1 = psChacha20Poly1305IetfDecrypt( + &dCtx, + cipherTextAuthData, + tests[i].ptlen + TEST_TAG_LEN, + tests[i].iv, + tests[i].aad, + tests[i].aadlen, + plaintext); + + sz2 = psChacha20Poly1305IetfDecryptDetached( + &dCtx, + ciphertext, + tests[i].ptlen, + tests[i].iv, + tests[i].aad, + tests[i].aadlen, + tests[i].tag, + plaintext2); + + if (sz1 != tests[i].ptlen) { - printf("FAILED: authentication failed\n"); + printf("FAILED: authentication failed (psChacha20Poly1305IetfDecrypt)\n"); } else if (memcmp(plaintext, tests[i].pt, tests[i].ptlen) != 0) { - printf("FAILED: data mismatch\n"); + printf("FAILED: data mismatch (psChacha20Poly1305IetfDecryptDetached)\n"); + } + else if (sz2 != (psResSize_t) tests[i].ptlen) + { + printf("FAILED: authentication failed (psChacha20Poly1305IetfDecryptDetached)\n"); + } + else if (memcmp(plaintext2, tests[i].pt, tests[i].ptlen) != 0) + { + printf("FAILED: data mismatch (psChacha20Poly1305IetfDecryptDetached)\n"); } else { printf("PASSED\n"); } psFree(cipherTextAuthData, NULL); - psChacha20Poly1305Clear(&dCtx); - memset(tag, 0x0, TEST_TAG_LEN); - memset(plaintext, 0x0, TEST_TEXT_MAXLEN); + psChacha20Poly1305IetfClear(&dCtx); } return PS_SUCCESS; } -#endif /* USE_CHACHA20_POLY1305 */ +#endif /* USE_CHACHA20_POLY1305_IETF */ /******************************************************************************/ #ifdef USE_DES @@ -5243,8 +5260,8 @@ static test_t tests[] = { { NULL, "AES" }, #endif -#ifdef USE_CHACHA20_POLY1305 - { psChacha20Poly1305Test, "***** CHACHA20_POLY1305 TESTS *****" }, +#ifdef USE_CHACHA20_POLY1305_IETF + { psChacha20Poly1305IetfTest, "***** CHACHA20_POLY1305 TESTS *****" }, #endif #ifdef USE_PKCS5 diff --git a/crypto/test/throughputTest.c b/crypto/test/throughputTest.c index 2e1d78c..7f09844 100644 --- a/crypto/test/throughputTest.c +++ b/crypto/test/throughputTest.c @@ -32,10 +32,13 @@ /******************************************************************************/ #include "crypto/cryptoImpl.h" +#include +#include #define DATABYTES_AMOUNT 100 * 1048576 /* # x 1MB (1024-byte variety) */ #define TINY_CHUNKS 16 +#define CHACHA20_TINY_CHUNKS 64 #define SMALL_CHUNKS 256 #define MEDIUM_CHUNKS 1024 #define LARGE_CHUNKS 4096 @@ -66,7 +69,8 @@ enum SHA256_ALG, SHA384_ALG, SHA512_ALG, - MD5_ALG + MD5_ALG, + CHACHA20POLY1305IETF_ALG }; #if defined(USE_HMAC_SHA1) || defined(USE_HMAC_SHA256) @@ -254,6 +258,38 @@ static void runTime(psCipherContext_t *ctx, psCipherGivContext_t *ctx_giv, } psGetTime(&end, NULL); break; +#endif +#ifdef USE_CHACHA20_POLY1305_IETF + case CHACHA20POLY1305IETF_ALG: + { + static unsigned char chacha20_iv[] = + { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f + }; + static unsigned char chacha20_aad[] = + { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, + }; + + psGetTime(&start, NULL); + while (bytesSent < bytesToSend) + { + psChacha20Poly1305IetfEncryptDetached( + &ctx->chacha20poly1305ietf, + dataChunk, + chunk, + chacha20_iv, + chacha20_aad, + sizeof chacha20_aad, + dataChunk, + chacha20_aad); + bytesSent += chunk; + } + psGetTime(&end, NULL); + break; + } #endif default: psFree(dataChunk, NULL); @@ -285,16 +321,16 @@ static int32 psAesTestCBC(void) psCipherContext_t eCtx; # if defined(USE_MATRIX_AES_CBC) && !defined(PS_AES_IMPROVE_PERF_INCREASE_CODESIZE) - _psTrace("##########\n#\n# "); - _psTrace("AES speeds can be improved by enabling\n# "); - _psTrace("PS_AES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); - _psTrace("#\n#\n#########\n"); + printf("##########\n#\n# "); + printf("AES speeds can be improved by enabling\n# "); + printf("PS_AES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + printf("#\n#\n#########\n"); # endif - _psTrace("***** AES-128 CBC *****\n"); + printf("***** AES-128 CBC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { - _psTraceInt("FAILED: returned %d\n", err); + printf("FAILED: returned %d\n", err); return err; } runTime(&eCtx, NULL, TINY_CHUNKS, AES_ENC_ALG); @@ -306,10 +342,10 @@ static int32 psAesTestCBC(void) runTime(&eCtx, NULL, HUGE_CHUNKS, AES_DEC_ALG); psAesClearCBC(&eCtx.aes); - _psTrace("***** AES-192 CBC *****\n"); + printf("***** AES-192 CBC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 24, PS_AES_ENCRYPT)) != PS_SUCCESS) { - _psTraceInt("FAILED: returned %d\n", err); + printf("FAILED: returned %d\n", err); return err; } runTime(&eCtx, NULL, TINY_CHUNKS, AES_ENC_ALG); @@ -321,10 +357,10 @@ static int32 psAesTestCBC(void) runTime(&eCtx, NULL, HUGE_CHUNKS, AES_DEC_ALG); psAesClearCBC(&eCtx.aes); - _psTrace("***** AES-256 CBC *****\n"); + printf("***** AES-256 CBC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { - _psTraceInt("FAILED: returned %d\n", err); + printf("FAILED: returned %d\n", err); return err; } runTime(&eCtx, NULL, TINY_CHUNKS, AES_ENC_ALG); @@ -347,17 +383,17 @@ static int32 psAesTestCBCHmac(void) psHmac_t hCtx; # if defined(USE_MATRIX_AES_CBC) && !defined(PS_AES_IMPROVE_PERF_INCREASE_CODESIZE) - _psTrace("##########\n#\n# "); - _psTrace("AES speeds can be improved by enabling\n# "); - _psTrace("PS_AES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); - _psTrace("#\n#\n#########\n"); + printf("##########\n#\n# "); + printf("AES speeds can be improved by enabling\n# "); + printf("PS_AES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + printf("#\n#\n#########\n"); # endif # ifdef USE_HMAC_SHA1 - _psTrace("***** AES-128 CBC + SHA1-HMAC *****\n"); + printf("***** AES-128 CBC + SHA1-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { - _psTraceInt("FAILED: returned %d\n", err); + printf("FAILED: returned %d\n", err); return err; } psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); @@ -372,10 +408,10 @@ static int32 psAesTestCBCHmac(void) runWithHmac(&eCtx, &hCtx, 0, HUGE_CHUNKS, AES_HMAC_ALG); psAesClearCBC(&eCtx.aes); - _psTrace("***** AES-256 CBC + SHA1-HMAC *****\n"); + printf("***** AES-256 CBC + SHA1-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { - _psTraceInt("FAILED: returned %d\n", err); + printf("FAILED: returned %d\n", err); return err; } psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); @@ -392,10 +428,10 @@ static int32 psAesTestCBCHmac(void) # endif # ifdef USE_HMAC_SHA256 - _psTrace("***** AES-128 CBC + SHA256-HMAC *****\n"); + printf("***** AES-128 CBC + SHA256-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { - _psTraceInt("FAILED: returned %d\n", err); + printf("FAILED: returned %d\n", err); return err; } psHmacSha256Init(&hCtx.u.sha256, key, 32); @@ -410,10 +446,10 @@ static int32 psAesTestCBCHmac(void) runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, HUGE_CHUNKS, AES_HMAC256_ALG); psAesClearCBC(&eCtx.aes); - _psTrace("***** AES-256 CBC + SHA256-HMAC *****\n"); + printf("***** AES-256 CBC + SHA256-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { - _psTraceInt("FAILED: returned %d\n", err); + printf("FAILED: returned %d\n", err); return err; } psHmacSha256Init(&hCtx.u.sha256, key, 32); @@ -446,10 +482,10 @@ int32 psAesTestGCM(void) memset(&eCtxGiv, 0, sizeof(eCtxGiv)); # ifndef USE_LIBSODIUM_AES_GCM - _psTrace("***** AES-GCM-128 *****\n"); + printf("***** AES-GCM-128 *****\n"); if ((err = psAesInitGCM(&eCtx.aesgcm, key, 16)) != PS_SUCCESS) { - _psTraceInt("FAILED: psAesInitGCM returned %d\n", err); + printf("FAILED: psAesInitGCM returned %d\n", err); return err; } psAesReadyGCM(&eCtx.aesgcm, iv, iv, 16); @@ -459,13 +495,13 @@ int32 psAesTestGCM(void) runTime(&eCtx, &eCtxGiv, LARGE_CHUNKS, AES_GCM_ALG); runTime(&eCtx, &eCtxGiv, HUGE_CHUNKS, AES_GCM_ALG); # else - _psTrace("***** Skipping AES-GCM-128 *****\n"); + printf("***** Skipping AES-GCM-128 *****\n"); # endif /* !USE_LIBSODIUM */ - _psTrace("***** AES-GCM-256 *****\n"); + printf("***** AES-GCM-256 *****\n"); if ((err = psAesInitGCM(&eCtx.aesgcm, key, 32)) != PS_SUCCESS) { - _psTraceInt("FAILED: psAesInitGCM returned %d\n", err); + printf("FAILED: psAesInitGCM returned %d\n", err); return err; } psAesReadyGCM(&eCtx.aesgcm, iv, iv, 16); @@ -496,10 +532,10 @@ int32 psDes3Test(void) psCipherContext_t eCtx; # if defined(USE_MATRIX_3DES) && !defined(PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE) - _psTrace("##########\n#\n# "); - _psTrace("3DES speeds can be improved by enabling\n# "); - _psTrace("PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); - _psTrace("#\n#\n#########\n"); + printf("##########\n#\n# "); + printf("3DES speeds can be improved by enabling\n# "); + printf("PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + printf("#\n#\n#########\n"); # endif psDes3Init(&eCtx.des3, iv, key); @@ -685,10 +721,10 @@ int32 psSha1Test(void) psDigestContext_t ctx; # if defined(USE_MATRIX_SHA1) && !defined(PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE) - _psTrace("##########\n#\n# "); - _psTrace("SHA-1 speeds can be improved by enabling\n# "); - _psTrace("PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); - _psTrace("#\n#\n#########\n"); + printf("##########\n#\n# "); + printf("SHA-1 speeds can be improved by enabling\n# "); + printf("PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + printf("#\n#\n#########\n"); # endif @@ -764,10 +800,10 @@ int32 psMd5Test(void) psDigestContext_t ctx; # if defined(USE_MATRIX_MD5) && !defined(PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE) - _psTrace("##########\n#\n# "); - _psTrace("MD5 speeds can be improved by enabling\n# "); - _psTrace("PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); - _psTrace("#\n#\n#########\n"); + printf("##########\n#\n# "); + printf("MD5 speeds can be improved by enabling\n# "); + printf("PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); + printf("#\n#\n#########\n"); # endif psMd5Init(&ctx.md5); @@ -800,6 +836,32 @@ int32 psMd2Test(void) #endif /* USE_MD2 */ /******************************************************************************/ +# ifdef USE_CHACHA20_POLY1305_IETF +static unsigned char chacha20_key[] = +{ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f +}; + +int32 psChacha20Poly1305IetfTest(void) +{ + psCipherContext_t cip; + psChacha20Poly1305Ietf_t *ctx = &(cip.chacha20poly1305ietf); + + psChacha20Poly1305IetfInit(ctx, chacha20_key); + /* Use sizes starting from CHACHA20 minimum block. */ + runTime(&cip, NULL, CHACHA20_TINY_CHUNKS, CHACHA20POLY1305IETF_ALG); + runTime(&cip, NULL, SMALL_CHUNKS, CHACHA20POLY1305IETF_ALG); + runTime(&cip, NULL, MEDIUM_CHUNKS, CHACHA20POLY1305IETF_ALG); + runTime(&cip, NULL, LARGE_CHUNKS, CHACHA20POLY1305IETF_ALG); + runTime(&cip, NULL, HUGE_CHUNKS, CHACHA20POLY1305IETF_ALG); + + return PS_SUCCESS; +} +# endif /* USE_CHACHA20_POLY1305_IETF */ + /******************************************************************************/ typedef struct @@ -902,7 +964,15 @@ static test_t tests[] = { #endif , "***** MD2 TESTS *****" }, +#ifdef USE_CHACHA20_POLY1305_IETF + { psChacha20Poly1305IetfTest +#else + { NULL +#endif + , "***** CHACHA20-POLY1305 *****" }, + { NULL, "" } + }; /******************************************************************************/ @@ -913,29 +983,71 @@ static test_t tests[] = { int main(int argc, char **argv) { int32 i; + int l; + if (argc > 1) + { + if (!strcmp(argv[1], "--list")) + { + printf("Tests:\n"); + for (i = 0; *tests[i].name; i++) + { + printf("%s\n", tests[i].name); + } + return 0; + } + for(l = 1; l < argc; l++) + { + for (i = 0; *tests[i].name; i++) + { + if (strstr(tests[i].name, argv[l])) + { + break; + } + } + if (!*tests[i].name) + { + fprintf(stderr, "Test not found: %s\n", argv[l]); + fprintf(stderr, "Usage: %s [--list | test...]\n", argv[0]); + exit(1); + } + } + } + if (psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS) { - _psTrace("Failed to initialize library: psCryptoOpen failed\n"); + printf("Failed to initialize library: psCryptoOpen failed\n"); return -1; } for (i = 0; *tests[i].name; i++) { + for(l = 1; argc > 1 && l < argc; l++) + { + if (strstr(tests[i].name, argv[l])) + { + break; + } + } + if (l == argc && argc > 1) + { + continue; + } + if (tests[i].fn) { - _psTraceStr("%s\n", tests[i].name); + printf("%s\n", tests[i].name); tests[i].fn(); } else { - _psTraceStr("%s: SKIPPED\n", tests[i].name); + printf("%s: SKIPPED\n", tests[i].name); } } psCryptoClose(); #ifdef WIN32 - _psTrace("Press any key to close"); + printf("Press any key to close"); getchar(); #endif diff --git a/doc/CHANGES_up_to_v3.9.0.html b/doc/CHANGES_up_to_v3.9.0.html index 81394ec..2327a13 100644 --- a/doc/CHANGES_up_to_v3.9.0.html +++ b/doc/CHANGES_up_to_v3.9.0.html @@ -346,7 +346,7 @@ matrixssl/matrixsslConfig.h

MatrixSSL now has support for ChaCha20-Poly1305 cipher suites compatible with RFC draft https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305. The supported cipher suites are defined for TLS 1.2 and can be enabled at compile time.

cryptoConfig.h
-
USE_CHACHA20_POLY1305 +
USE_CHACHA20_POLY1305_IETF
matrixsslConfig.h
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 diff --git a/doc/CHANGES_up_to_v3.9.0.md b/doc/CHANGES_up_to_v3.9.0.md index 9e10642..a58985f 100644 --- a/doc/CHANGES_up_to_v3.9.0.md +++ b/doc/CHANGES_up_to_v3.9.0.md @@ -533,7 +533,7 @@ MatrixSSL now has support for ChaCha20-Poly1305 cipher suites compatible with RF The supported cipher suites are defined for TLS 1.2 and can be enabled at compile time. _cryptoConfig.h_ -: `USE_CHACHA20_POLY1305` +: `USE_CHACHA20_POLY1305_IETF` _matrixsslConfig.h_ : `TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256` diff --git a/doc/CHANGES_up_to_v3.9.0.txt b/doc/CHANGES_up_to_v3.9.0.txt index 7482859..de3d007 100644 --- a/doc/CHANGES_up_to_v3.9.0.txt +++ b/doc/CHANGES_up_to_v3.9.0.txt @@ -707,7 +707,7 @@ supported cipher suites are defined for TLS 1.2 and can be enabled at compile time. _cryptoConfig.h_ - USE_CHACHA20_POLY1305 + USE_CHACHA20_POLY1305_IETF _matrixsslConfig.h_ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 diff --git a/doc/CHANGES_v3.9.html b/doc/CHANGES_v3.9.html index 9ab7dfe..92ef3b1 100644 --- a/doc/CHANGES_v3.9.html +++ b/doc/CHANGES_v3.9.html @@ -9,6 +9,63 @@

MatrixSSL 3.9 changelog

+

Changes between 3.9.3 and 3.9.5 [December 2017]

+

This version fixes several vulnerabilities in the CMS and TLS libraries, contains a large amount of bug fixes and some new features for the TLS and X.509 libraries.

+
    +
  • SSL/TLS

    +
      +
    • Fixed several out-of-bounds heap reads reported by researchers Simon Friedberger, Robert Merget and Juraj Somorovsky, working at the Ruhr-University Bochum. It was possible to trigger the out-of-bounds reads with maliciously crafted Certificate and ServerHello handshake messages.

    • +
    • Fixed vulnerabilities reported by Richard Clarke (@rsclarke). Truncated certificates could be created to cause out-of-bounds reads of size 1 in getAsnOID and getSerialNum.

    • +
    • Fixed an issue where the server did not keep the raw DER of the client cert during a rehandshake, even when the keep_peer_cert_der session option was set.

    • +
    • Fixed an issue that caused empty SNI to be sent in the ServerHello during renegotiation even when the last ClientHello did not contain it.

    • +
    • Fixed issues with handling of RSA-SHA-1 server and client certificates. One of the symptoms was a segfault that occurred when trying to use a server certificate signed with RSA-SHA-1.

    • +
    • Refactor supported_signature_algorithms checking and signature algorithm selection for CertificateVerify and ServerKeyExchange Including adding support for RSA-SHA-512 server certificates.

    • +
    • Added support for on-demand client certificate and client private key loading (USE_EXT_CLIENT_CERT_KEY_LOADING). MatrixSSL now provides an asynchronous mechanism that allows client-programs to load or change the client certificate on-demand, as a response to a CertificateRequest.

    • +
    • Added new option to matrixValidateCertsExt that can be used to (re-)perform certificate date validation in that function. By default, MatrixSSL checks the certificate date during parsing. The new option is useful for e.g. long-living processes that may outlast the certificate validity period.

    • +
    • Added support for SSLv2 Client Hello format used by some TLS clients. Only Client Hello message is supported, SSLv2 connections are not supported as it would have security implications. See RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 Appendix E.2 for details of TLS backwards compatibility with SSLv2.

    • +
    • Enabled TLS FALSE START support by default. This allows better interoperability with recent versions of Firefox browser and some versions of Chrome. (Controlled with USE_SERVER_SIDE_FALSE_START_SUPPORT.)

    • +
    • Fixed a compilation problem if USE_TLS_1_2 was not defined.

    • +
    • Fixed compilation issues when compiling without USE_SHA384.

    • +
    • Fixed compilation without USE_REHANDSHAKING.

    • +
    • Improved the example server and client applications.

    • +
    • Fixes to file paths client.c uses for RSA-3072 PEM files.

    • +
  • +
  • Crypto library

    +
      +
    • Fixed an out-of-bounds read in psAesUnwrap.

    • +
    • Fixed byte order issue in psEccDsaSign.

    • +
    • Fixed double-free when s parameter handling fails in MatrixCrypto's psEccDsaSign.

    • +
  • +
  • CMS library

    +
      +
    • Fixed a critical bug in the Authenticated-Enveloped-data stream parsing API (matrixCmsFinalParseAuthEnvData) that caused verification of the CBC MAC to be skipped.
    • +
  • +
  • X.509 library

    +
      +
    • The EC public key coordinates were encoded incorrectly into certificates when the leading 8 bits of a coordinate were all zero.

    • +
    • subjectKeyId got encoded always, even when no one actually computed the value.

    • +
    • Encoding of extensions was omitted when there was an issuerAltName but no subjectAltName given.

    • +
    • psWriteCertExt set the basicConstraints CA bit to TRUE even if the value was actually CA_UNDEFINED.

    • +
    • psX509SetCAIssuedCertExtensions used the extensions struct pointer from CSR when there were no extensions in the CA's config. This lead to a double-free.

    • +
    • The psWriteCertReqMem_BinConfig function was leaking memory.

    • +
    • Added new initialization function for the extensions struct.

    • +
    • Fix for otherName OID encoding in subjectAltName.

    • +
    • Added possibility to give the otherName OID as a dot-notation string.

    • +
    • Fixed otherName OIDs length restriction.

    • +
    • Added support for the PrintableString and IA5String ASN.1 types in psX509SetDNAttribute.

    • +
    • Improved the order in which Relative Distinguished Names are encoded into certificates and CSRs.

    • +
    • Support for setting and parsing certificate request with challenge password (psX509SetChallengePassword(), and psCertReqGetChallengePassword())

    • +
  • +
  • Networking and the MatrixSSL Net convenience layer

    +
      +
    • Fixed multirecord handling in matrixsslNet.

    • +
    • Fixed mishandled PS_EAGAIN from MatrixSSL in matrixsslNet.c.

    • +
    • Added "peek" to psnet.

    • +
    • Added feature to matrixsslNet that allows writing during read buffer contains some data.

    • +
    • Enlarged buffer used by matrixsslNet.c to avoid having the read input in multiple blocks.

    • +
    • Fixes to MatrixSslNet to work when it receives multiple application data records at once.

    • +
  • +

Changes between 3.9.2 and 3.9.3 [June 2017]

Fix serious buffer handling vulnerabilities along with other smaller bug fixes.

    diff --git a/doc/CHANGES_v3.9.md b/doc/CHANGES_v3.9.md index 8f61af6..e0334ac 100644 --- a/doc/CHANGES_v3.9.md +++ b/doc/CHANGES_v3.9.md @@ -1,5 +1,145 @@ # MatrixSSL 3.9 changelog +## Changes between 3.9.3 and 3.9.5 [December 2017] + +This version fixes several vulnerabilities in the CMS and TLS +libraries, contains a large amount of bug fixes and some new features +for the TLS and X.509 libraries. + +- SSL/TLS + + * Fixed several out-of-bounds heap reads reported by researchers + Simon Friedberger, Robert Merget and Juraj Somorovsky, working + at the Ruhr-University Bochum. It was possible to trigger the + out-of-bounds reads with maliciously crafted Certificate and + ServerHello handshake messages. + + * Fixed vulnerabilities reported by Richard Clarke + (@rsclarke). Truncated certificates could be created to cause + out-of-bounds reads of size 1 in getAsnOID and getSerialNum. + + * Fixed an issue where the server did not keep the raw DER of the + client cert during a rehandshake, even when the + keep_peer_cert_der session option was set. + + * Fixed an issue that caused empty SNI to be sent in the + ServerHello during renegotiation even when the last ClientHello + did not contain it. + + * Fixed issues with handling of RSA-SHA-1 server and client + certificates. One of the symptoms was a segfault that occurred + when trying to use a server certificate signed with RSA-SHA-1. + + * Refactor supported_signature_algorithms checking and signature + algorithm selection for CertificateVerify and ServerKeyExchange + Including adding support for RSA-SHA-512 server certificates. + + * Added support for on-demand client certificate and client + private key loading (USE_EXT_CLIENT_CERT_KEY_LOADING). MatrixSSL + now provides an asynchronous mechanism that allows + client-programs to load or change the client certificate + on-demand, as a response to a CertificateRequest. + + * Added new option to matrixValidateCertsExt that can be used to + (re-)perform certificate date validation in that function. By + default, MatrixSSL checks the certificate date during + parsing. The new option is useful for e.g. long-living processes + that may outlast the certificate validity period. + + * Added support for SSLv2 Client Hello format used by some TLS + clients. Only Client Hello message is supported, SSLv2 + connections are not supported as it would have security + implications. See RFC 5246: The Transport Layer Security (TLS) + Protocol Version 1.2 Appendix E.2 for details of TLS backwards + compatibility with SSLv2. + + * Enabled TLS FALSE START support by default. This allows better + interoperability with recent versions of Firefox browser and + some versions of Chrome. (Controlled with + USE_SERVER_SIDE_FALSE_START_SUPPORT.) + + * Fixed a compilation problem if USE_TLS_1_2 was not defined. + + * Fixed compilation issues when compiling without USE_SHA384. + + * Fixed compilation without USE_REHANDSHAKING. + + * Improved the example server and client applications. + + * Fixes to file paths client.c uses for RSA-3072 PEM files. + +- Crypto library + + * Fixed an out-of-bounds read in psAesUnwrap. + + * Fixed byte order issue in psEccDsaSign. + + * Fixed double-free when s parameter handling fails in + MatrixCrypto's psEccDsaSign. + +- CMS library + + * Fixed a critical bug in the Authenticated-Enveloped-data stream + parsing API (matrixCmsFinalParseAuthEnvData) that caused + verification of the CBC MAC to be skipped. + +- X.509 library + + * The EC public key coordinates were encoded incorrectly into + certificates when the leading 8 bits of a coordinate were all + zero. + + * subjectKeyId got encoded always, even when no one actually + computed the value. + + * Encoding of extensions was omitted when there was an + issuerAltName but no subjectAltName given. + + * psWriteCertExt set the basicConstraints CA bit to TRUE even if + the value was actually CA_UNDEFINED. + + * psX509SetCAIssuedCertExtensions used the extensions struct + pointer from CSR when there were no extensions in the CA's + config. This lead to a double-free. + + * The psWriteCertReqMem_BinConfig function was leaking memory. + + * Added new initialization function for the extensions struct. + + * Fix for otherName OID encoding in subjectAltName. + + * Added possibility to give the otherName OID as a dot-notation + string. + + * Fixed otherName OIDs length restriction. + + * Added support for the PrintableString and IA5String ASN.1 types + in psX509SetDNAttribute. + + * Improved the order in which Relative Distinguished Names are + encoded into certificates and CSRs. + + * Support for setting and parsing certificate request with + challenge password (psX509SetChallengePassword(), and + psCertReqGetChallengePassword()) + +- Networking and the MatrixSSL Net convenience layer + + * Fixed multirecord handling in matrixsslNet. + + * Fixed mishandled PS_EAGAIN from MatrixSSL in matrixsslNet.c. + + * Added "peek" to psnet. + + * Added feature to matrixsslNet that allows writing during read + buffer contains some data. + + * Enlarged buffer used by matrixsslNet.c to avoid having the read input + in multiple blocks. + + * Fixes to MatrixSslNet to work when it receives multiple application + data records at once. + ## Changes between 3.9.2 and 3.9.3 [June 2017] Fix serious buffer handling vulnerabilities along with other smaller bug fixes. diff --git a/doc/CHANGES_v3.9.txt b/doc/CHANGES_v3.9.txt index c3fdbe6..1d9a8b5 100644 --- a/doc/CHANGES_v3.9.txt +++ b/doc/CHANGES_v3.9.txt @@ -3,6 +3,147 @@ MATRIXSSL 3.9 CHANGELOG +Changes between 3.9.3 and 3.9.5 [December 2017] + +This version fixes several vulnerabilities in the CMS and TLS libraries, +contains a large amount of bug fixes and some new features for the TLS +and X.509 libraries. + +- SSL/TLS + + - Fixed several out-of-bounds heap reads reported by researchers + Simon Friedberger, Robert Merget and Juraj Somorovsky, working + at the Ruhr-University Bochum. It was possible to trigger the + out-of-bounds reads with maliciously crafted Certificate and + ServerHello handshake messages. + + - Fixed vulnerabilities reported by Richard Clarke (@rsclarke). + Truncated certificates could be created to cause out-of-bounds + reads of size 1 in getAsnOID and getSerialNum. + + - Fixed an issue where the server did not keep the raw DER of the + client cert during a rehandshake, even when the + keep_peer_cert_der session option was set. + + - Fixed an issue that caused empty SNI to be sent in the + ServerHello during renegotiation even when the last ClientHello + did not contain it. + + - Fixed issues with handling of RSA-SHA-1 server and + client certificates. One of the symptoms was a segfault that + occurred when trying to use a server certificate signed + with RSA-SHA-1. + + - Refactor supported_signature_algorithms checking and signature + algorithm selection for CertificateVerify and ServerKeyExchange + Including adding support for RSA-SHA-512 server certificates. + + - Added support for on-demand client certificate and client + private key loading (USE_EXT_CLIENT_CERT_KEY_LOADING). MatrixSSL + now provides an asynchronous mechanism that allows + client-programs to load or change the client certificate + on-demand, as a response to a CertificateRequest. + + - Added new option to matrixValidateCertsExt that can be used to + (re-)perform certificate date validation in that function. By + default, MatrixSSL checks the certificate date during parsing. + The new option is useful for e.g. long-living processes that may + outlast the certificate validity period. + + - Added support for SSLv2 Client Hello format used by some + TLS clients. Only Client Hello message is supported, SSLv2 + connections are not supported as it would have + security implications. See RFC 5246: The Transport Layer + Security (TLS) Protocol Version 1.2 Appendix E.2 for details of + TLS backwards compatibility with SSLv2. + + - Enabled TLS FALSE START support by default. This allows better + interoperability with recent versions of Firefox browser and + some versions of Chrome. (Controlled + with USE_SERVER_SIDE_FALSE_START_SUPPORT.) + + - Fixed a compilation problem if USE_TLS_1_2 was not defined. + + - Fixed compilation issues when compiling without USE_SHA384. + + - Fixed compilation without USE_REHANDSHAKING. + + - Improved the example server and client applications. + + - Fixes to file paths client.c uses for RSA-3072 PEM files. + +- Crypto library + + - Fixed an out-of-bounds read in psAesUnwrap. + + - Fixed byte order issue in psEccDsaSign. + + - Fixed double-free when s parameter handling fails in + MatrixCrypto's psEccDsaSign. + +- CMS library + + - Fixed a critical bug in the Authenticated-Enveloped-data stream + parsing API (matrixCmsFinalParseAuthEnvData) that caused + verification of the CBC MAC to be skipped. +- X.509 library + + - The EC public key coordinates were encoded incorrectly into + certificates when the leading 8 bits of a coordinate were + all zero. + + - subjectKeyId got encoded always, even when no one actually + computed the value. + + - Encoding of extensions was omitted when there was an + issuerAltName but no subjectAltName given. + + - psWriteCertExt set the basicConstraints CA bit to TRUE even if + the value was actually CA_UNDEFINED. + + - psX509SetCAIssuedCertExtensions used the extensions struct + pointer from CSR when there were no extensions in the + CA's config. This lead to a double-free. + + - The psWriteCertReqMem_BinConfig function was leaking memory. + + - Added new initialization function for the extensions struct. + + - Fix for otherName OID encoding in subjectAltName. + + - Added possibility to give the otherName OID as a + dot-notation string. + + - Fixed otherName OIDs length restriction. + + - Added support for the PrintableString and IA5String ASN.1 types + in psX509SetDNAttribute. + + - Improved the order in which Relative Distinguished Names are + encoded into certificates and CSRs. + + - Support for setting and parsing certificate request with + challenge password (psX509SetChallengePassword(), + and psCertReqGetChallengePassword()) + +- Networking and the MatrixSSL Net convenience layer + + - Fixed multirecord handling in matrixsslNet. + + - Fixed mishandled PS_EAGAIN from MatrixSSL in matrixsslNet.c. + + - Added "peek" to psnet. + + - Added feature to matrixsslNet that allows writing during read + buffer contains some data. + + - Enlarged buffer used by matrixsslNet.c to avoid having the read + input in multiple blocks. + + - Fixes to MatrixSslNet to work when it receives multiple + application data records at once. + + Changes between 3.9.2 and 3.9.3 [June 2017] Fix serious buffer handling vulnerabilities along with other smaller bug diff --git a/doc/matrixssl_dev_guide.md b/doc/matrixssl_dev_guide.md index 4fc258b..98194f1 100644 --- a/doc/matrixssl_dev_guide.md +++ b/doc/matrixssl_dev_guide.md @@ -1,4 +1,4 @@ -# Developer's Guide {#DevelopersGuide} +# @matrixssl Developer Guidance {#DevelopersGuide} **@matrixssl version @version** @@ -13,7 +13,7 @@ # OVERVIEW -This developer's guide is a general SSL/TLS overview and a @matrixssl specific integration reference for adding SSL security into an application. +This guidance is a general SSL/TLS overview and a @matrixssl specific integration reference for adding SSL security into an application. This document is primarily intended for the software developer performing @matrixssl integration into their custom application but is also a useful reference for anybody wishing to learn more about @matrixssl or the SSL/TLS protocol in general. @@ -149,7 +149,7 @@ The following TLS RFCs are implemented by @matrixssl. `TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256` * [draft-ietf-tls-falsestart](https://datatracker.ietf.org/doc/draft-ietf-tls-falsestart/) Transport Layer Security (TLS) False Start -: Supported. Disabled by default due to security concerns. See [False Start](#21-ssltls-version-security). +: Supported. Disabled by default due to security concerns -- see [False Start Weakness](https://en.wikipedia.org/wiki/Transport_Layer_Security#Version_rollback_attacks). ## Currently Unsupported RFCs @@ -249,7 +249,7 @@ SSL_DH_anon_WITH_RC4_128_MD5 ``` -# SECURITY CONSIDERATIONS +# SECURITY CONSIDERATIONS Prior to working directly with the @matrixssl library there are some critical SSL security concepts that application integrators should be familiar with. @@ -454,7 +454,8 @@ Example [Equifax GeoTrust](https://www.geotrust.com/resources/root-certificates/ Certificate chain sent to a @matrixssl client during SSL handshake Certificate message by remote server https://www.google.com. **C=US, O=GeoTrust Inc., CN=GeoTrust Global CA** - *Issuer*: C=US, O=Equifax, OU=Equifax Secure Certificate Authority [Valid, matches a loaded trusted root subject] + *Issuer*: C=US, O=Equifax, OU=Equifax Secure Certificate Authority + [Valid, matches a loaded trusted root subject] *Authority KeyId*: 48:E6:68:F9:2B:D2:B2:95... [Valid, matches the Issuer Subject KeyId] *Subject KeyId*: C0:7A:98:68:8D:89:FB:AB... *Basic Constraints*: critical CA:TRUE [Valid, this certificate can sign others] @@ -465,14 +466,16 @@ Certificate chain sent to a @matrixssl client during SSL handshake Certificate m *Authority KeyId*: C0:7A:98:68:8D:89:FB:AB... [Valid, matches the Issuer Subject KeyId] *Subject KeyId*: 4A:DD:06:16:1B:BC:F6:68... *Validity*: (Apr 5 15:15:55 2013 GMT to Apr 4 15:15:55 2015 GMT) [Valid] - *Basic Constraints*: critical CA:TRUE, pathlen:0 [Valid, this certificate can sign others and the signed certificate is not also a CA] + *Basic Constraints*: critical CA:TRUE, pathlen:0 + [Valid, this certificate can sign others and the signed certificate is not also a CA] *Key Usage*: critical Certificate Sign, CRL Sign [Valid, able to sign certificates] *Version*: 3 [Valid] >>>**C=US, ST=California, L=Mountain View, O=Google Inc, CN=*.google.com** *Issuer*: C=US, O=Google Inc, CN=Google Internet Authority G2 [Valid, matches parent subject] *X509v3 Basic Constraints*: critical CA:FALSE [Valid, this is a leaf cert] *Extended Key Usage*: TLS Web Server Authentication, TLS Web Client Authentication [Valid] - *X509v3 Subject Alternative Name*: DNS:*.google.com, DNS:*.android.com... [Valid, matches expected DNS name] + *X509v3 Subject Alternative Name*: DNS:*.google.com, DNS:*.android.com... + [Valid, matches expected DNS name] *Validity*: (Mar 12 09:53:40 2014 GMT to Jun 10 00:00:00 2014 GMT) [Valid] @@ -503,7 +506,7 @@ In _@matrixssl Commercial Edition_, Certificate Authority root and child certifi # APPLICATION INTEGRATION FLOW -@matrixssl is a C code library that provides a security layer for client and server applications allowing them to securely communicate with other SSL enabled peers. @matrixssl is transport agnostic and can just as easily integrate with an HTTP server as it could with a device communicating through a serial port. For simplicity, this developer's guide will assume a socket-based implementation for all its examples unless otherwise noted. +@matrixssl is a C code library that provides a security layer for client and server applications allowing them to securely communicate with other SSL enabled peers. @matrixssl is transport agnostic and can just as easily integrate with an HTTP server as it could with a device communicating through a serial port. For simplicity, this guidance will assume a socket-based implementation for all its examples unless otherwise noted. The term application in this document refers to the peer (client or server) application the @matrixssl library is being integrated into. @@ -512,7 +515,7 @@ This section will detail the specific points in the application life cycle where Refer to the @matrixssl API document to get familiar with the interface to the library and with the example code to see how they are used at implementation. Follow the guidelines below when using these APIs to integrate @matrixssl into an application. -## `ssl_t` Structure +## The ssl_t Structure The `ssl_t` structure holds the state and keys for each client or server connection as well as buffers for encoding and decoding SSL data. The buffers are dynamically managed internally to make the integration with existing non-secure software easier. SSL is a record based protocol, and the internal buffer management makes a better 'impedance match' with classic stream based protocols. For example, data may be read from a socket, but if a full SSL record has not been received, no data is available for the caller to process. This partial record is held within the `ssl_t` buffer. The @matrixssl API is also designed so there are no buffer copies, and the caller is able to read and write network data directly into the SSL buffers, providing a very low memory overhead per session. @@ -638,7 +641,7 @@ Example implementations of @matrixssl client and server applications integration # CONFIGURABLE FEATURES -@matrixssl contains a set of optional features that are configurable at compile time. This allows the user to remove unneeded functionality to reduce code size footprint and disable potentially insecure features. Each of these options are pre-processor defines that can be disabled by simply commenting out the #define in the header files or by using the -D compile flag during build. APIs with dependencies on optional features are highlighted in the Define Dependencies sub-section in the API documentation for that function. +@matrixssl contains a set of optional features that are configurable at compile time. This allows the user to remove unneeded functionality to reduce code size footprint and disable potentially insecure features. Each of these options are pre-processor defines that can be disabled by simply commenting out the \#define in the header files or by using the -D compile flag during build. APIs with dependencies on optional features are highlighted in the Define Dependencies sub-section in the API documentation for that function. *Not all configurable options are listed below. See comments directly in configuration header files for more fine-tuning.* @@ -674,7 +677,7 @@ Example implementations of @matrixssl client and server applications integration : Disabled by default. `REQUESTED_MAX_PLAINTEXT_RECORD_LEN` -: matrixsslConfig.h – Enable the “max_fragment_length” TLS extension defined in RFC 4366. Value of #define determines fragment length (server may reject) +: matrixsslConfig.h – Enable the “max_fragment_length” TLS extension defined in RFC 4366. Value of \#define determines fragment length (server may reject) `USE_CLIENT_AUTH` : matrixsslConfig.h - Enables two-way(mutual) authentication @@ -812,7 +815,7 @@ Optimizing assembly code for low level math operations is available for many com ## Debug Configuration -@matrixssl contains a set of optional debug features that are configurable at compile time. Each of these options are pre-processor defines that can be disabled by simply commenting out the `#define` in the specified header files. +@matrixssl contains a set of optional debug features that are configurable at compile time. Each of these options are pre-processor defines that can be disabled by simply commenting out the \#define in the specified header files. `HALT_ON_PS_ERROR` : coreConfig.h - Enables the osdepBreak platform function whenever a psError trace function is called. Helpful in debug environments. @@ -1102,9 +1105,11 @@ When creating the session resumption information (either the standard session ta **Servers**: Servers that wish to process ALPN extensions sent from a client must call the `matrixSslRegisterALPNCallback` function immediately after the session is created with `matrixSslNewServerSession`. The timing of the registration is important so that the callback can be associated with the proper session context before the first handshake message from the client is passed to `matrixSslReceivedData`. The server ALPN callback that is registered with `matrixSslRegisterALPNCallback` must have a prototype of: -```C + +```{.c} void ALPN_callback(void *ssl, short protoCount, char *proto[MAX_PROTO_EXT], int32_t protoLen[MAX_PROTO_EXT], int32_t *index) ``` + `ssl` : parameter is the session context and may be typecast to an `ssl_t * ` type if access is required. @@ -1126,7 +1131,8 @@ void ALPN_callback(void *ssl, short protoCount, char *proto[MAX_PROTO_EXT], int3 To generate the ALPN extension, the API `matrixSslCreateALPNext` is used in conjunction with the `matrixSslNewHelloExtension` or `matrixSslLoadHelloExtension` framework. The `matrixSslCreateALPNext` API accepts an array of `unsigned char * ` string values (array length of `MAX_PROTO_EXT`) along with a companion array that hold the string lengths for the protocol list. The function will format the protocols into the specified ALPN extension format and return that to the caller in the output parameters. Once the extension has been created the client must load the extension using the `matrixSslLoadHelloExtension` API (`matrixSslNewHelloExtension` must have been called as well). Finally, the extension must be passed to `matrixSslNewClientSession` in the extensions parameter. Here is what the ALPN extension creation and session start might look like: -```C + +```{.c} tlsExtension_t * extension; unsigned char *alpn[MAX_PROTO_EXT]; int32_t alpnLen[MAX_PROTO_EXT]; @@ -1150,6 +1156,7 @@ matrixSslNewClientSession(&ssl, keys, sid, g_cipher, g_ciphers, certCb, g_ip, ex matrixSslDeleteHelloExtension(extension); ``` + To receive the server reply to the ALPN extension the client must register an extension callback routine using the `extCb` parameter when calling `matrixSslNewClientSession`. The callback will be invoked with the ALPN extension ID of `EXT_ALPN` (16) with a format of a single byte length followed by the protocol string value the server has agreed to. See the example in `apps/ssl/client.c` for full implementation details. @@ -1250,14 +1257,13 @@ When a client sends the `status_request` extension the server will look to see i ### Configuring OCSP Feature for Use The OCSP functionality depends on definitions in `cryptoConfig.h`. Full read/write functionality and server features requires following defines: -``` {.c} -#define USE_X509 -#define USE_CERT_PARSE -#define USE_FULL_CERT_PARSE -#define USE_CRL -#define USE_OCSP -#define USE_OCSP_MUST_STAPLE -``` + + #define USE_X509 + #define USE_CERT_PARSE + #define USE_FULL_CERT_PARSE + #define USE_CRL + #define USE_OCSP + #define USE_OCSP_MUST_STAPLE The standard configurations like `default` on *@matrixssl* FIPS and Commercial releases have already neccessary features enabled. @@ -1277,15 +1283,16 @@ The most of functionality of `ocsp.c` program is found in `OCSPRequestAndRespons In @matrixssl, function `matrixSslWriteOCSPRequestExt()` is used to create OCSP requests. The function is invoked as follows: -``` {.c} -if (matrixSslWriteOCSPRequestExt(NULL, - subject, - issuer, - &request, - &requestLen, - &info) != PS_SUCCESS) { - /* Error handling */ - return PS_FAILURE; + +```{.c} + if (matrixSslWriteOCSPRequestExt(NULL, + subject, + issuer, + &request, + &requestLen, + &info) != PS_SUCCESS) { + /* Error handling */ + return PS_FAILURE; } ``` @@ -1302,21 +1309,15 @@ is no longer needed. ##### Providing name for requestor (requestorName) -The @matrixssl allows providing name for OCSP requestor. The name is represented -using X.509 GeneralName. matrixSslWriteOCSPRequestInfoSetRequestorId() function -is provided to help encoding the OCSP requestor name in suitable format for -OCSP request. Note: This option is relatively rarely used and some OCSP -Responders will reject requests with RequestorName. +The @matrixssl allows providing name for OCSP requestor. The name is represented using X.509 GeneralName. matrixSslWriteOCSPRequestInfoSetRequestorId() function is provided to help encoding the OCSP requestor name in suitable format for OCSP request. Note: This option is relatively rarely used and some OCSP Responders will reject requests with RequestorName. ##### Providing list of requests (requestList) If `matrixSslWriteOCSPRequestInfo_t` flag `MATRIXSSL_WRITE_OCSP_REQUEST_FLAG_CERT_LIST` is specified, -then OCSP request is made concerning a list of certificates linked -(via `subject->next`). This is a convenient way to allow for less network -traffic when working with the certificates from the same issuer. -Note: Some OCSP responders only support single request, and will reject requests -concerning multiple certificates. +then OCSP request is made concerning a list of certificates linked (via `subject->next`). This is a convenient way to allow for less network traffic when working with the certificates from the same issuer. + +Note: Some OCSP responders only support single request, and will reject requests concerning multiple certificates. #### Interacting with OCSP server @@ -1326,6 +1327,7 @@ The most OCSP servers use **HTTP** protocol. *@matrixssl* provides `psUrlInterac You can see `getOCSPResponse()` function in `ocsp.c` for a concrete example on how to interact with the server. To use HTTP protocol, it is necessary to know the correct URL. The URL is in practice commonly specified in AuthorityInfoAccess extensions of X.509 certificate. The following function will extract authority information from X.509 certificate. + ```{.c} static char *getAuthorityInfoOCSP_URI(const psX509Cert_t *subject) { @@ -1369,6 +1371,7 @@ The functions support both OCSP responses just retrieved as response to a constr To validate OCSP response, an issuer certificate is used. Many organizations use the same certificates to sign OCSP responses than are used to validate certificates themselves. In this case, the issuer certificate has been obtained and validated already as part of X.509 certificate validation. In case, OCSP responses have been signed with other keys designated for that purpose, then they shall be validated just like any other X.509 intermediate certificate, e.g. using `psX509ParseCert()` and `psX509AuthenticateCert()`. The certificate of keys intended to be used for OCSP may have been marked for that purpose. This can be checked e.g. with the following code: + ```{.c} bool gotEKU_OCSP = false; bool gotKU_OCSP = false; @@ -1380,6 +1383,7 @@ if ((ext->ekuFlags & EXT_KEY_USAGE_OCSP_SIGNING) > 0) if ((ext->keyUsageFlags & KEY_USAGE_DIGITAL_SIGNATURE) > 0) gotKY_OCSP = true; ``` + Only if both key usage and extended key usage flags are found in the certificate, the key can be considered to be marked for OCSP usage. However, many of the keys used for OCSP do not have this purpose marked in their certificate, and the most important validity check for OCSP signers remains ensuring that they have been signed by (one of) the CA root(s). @@ -1401,8 +1405,7 @@ If OCSP response is found to be no longer valid or there is another issue in tim The purpose of OCSP is to check if a certificate is revoked. `validateOCSPResponse_ex()` function is (finally) provided for this purpose. The function supports many different arguments. The options are used to pass in optional arguments. -``` -{.c} +```{.c} opts.knownFlag = &known; opts.revocationFlag = &revocated; opts.nonceMatch = &nonceOk; @@ -1454,7 +1457,8 @@ Implementations that wish to capture counts of SSL events can tap into the `MATR - Failed resumed handshake count -- Number of application data bytes received +- Number of +- application data bytes received - Number of application data bytes sent @@ -1482,7 +1486,7 @@ EAP-FAST requires a _Protected Access Credential (PAC)_ to be provisioned betwe The _PAC_ is exchanged between the peers by the client sending the [Stateless Session Ticket Resumption](#61-stateless-session-ticket-resumption) specification: the `CLIENT_HELLO SessionTicket Extension`. However, a _PAC_ explicitly cannot be received by a client in the corresponding `NewSessionTicket` handshake message from the server, and must be provisioned out-of-band. Unfortunately this requires alteration of the standard TLS state machine logic. -```C +```{.c} sslSessionId_t *sid; ssl_t *ssl; ... diff --git a/matrixssl/cipherSuite.c b/matrixssl/cipherSuite.c index 0842f8e..89a2004 100644 --- a/matrixssl/cipherSuite.c +++ b/matrixssl/cipherSuite.c @@ -348,48 +348,40 @@ int32 csAesDecrypt(void *ssl, unsigned char *ct, /******************************************************************************/ -/* #define DEBUG_CHACHA20_POLY1305_CIPHER_SUITE */ -#ifdef USE_CHACHA20_POLY1305_CIPHER_SUITE -int32 csChacha20Poly1305Init(sslSec_t *sec, int32 type, uint32 keysize) +/* #define DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE */ +#ifdef USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE +int32 csChacha20Poly1305IetfInit(sslSec_t *sec, int32 type, uint32 keysize) { - int32 err; + psRes_t err; + + psAssert(keysize == PS_CHACHA20POLY1305_IETF_KEYBYTES); if (type == INIT_ENCRYPT_CIPHER) { -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE - psTraceInfo("Entering csChacha20Poly1305Init encrypt\n"); +# ifdef DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305IetfInit encrypt\n"); psTraceBytes("sec->writeKey", sec->writeKey, keysize); # endif - memset(&sec->encryptCtx.chacha20poly1305, 0, sizeof(psChacha20Poly1305_t)); - if ((err = psChacha20Poly1305Init(&sec->encryptCtx.chacha20poly1305, sec->writeKey, - keysize)) < 0) - { - return err; - } + err = psChacha20Poly1305IetfInit(&sec->encryptCtx.chacha20poly1305ietf, sec->writeKey); } else { -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE - psTraceInfo("Entering csChacha20Poly1305Init decrypt\n"); +# ifdef DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305IetfInit decrypt\n"); psTraceBytes("sec->readKey", sec->readKey, keysize); # endif - memset(&sec->decryptCtx.chacha20poly1305, 0, sizeof(psChacha20Poly1305_t)); - if ((err = psChacha20Poly1305Init(&sec->decryptCtx.chacha20poly1305, sec->readKey, - keysize)) < 0) - { - return err; - } + err = psChacha20Poly1305IetfInit(&sec->decryptCtx.chacha20poly1305ietf, sec->readKey); } - return 0; + return err; } -int32 csChacha20Poly1305Encrypt(void *ssl, unsigned char *pt, +int32 csChacha20Poly1305IetfEncrypt(void *ssl, unsigned char *pt, unsigned char *ct, uint32 len) { ssl_t *lssl = ssl; - psChacha20Poly1305_t *ctx; + psChacha20Poly1305Ietf_t *ctx; unsigned char nonce[TLS_AEAD_NONCE_MAXLEN]; - unsigned char aad[TLS_CHACHA20_POLY1305_AAD_LEN]; + unsigned char aad[TLS_CHACHA20_POLY1305_IETF_AAD_LEN]; int32 i, ptLen; if (len == 0) @@ -400,44 +392,32 @@ int32 csChacha20Poly1305Encrypt(void *ssl, unsigned char *pt, { return PS_LIMIT_FAIL; } - ptLen = len - TLS_CHACHA20_POLY1305_TAG_LEN; - ctx = &lssl->sec.encryptCtx.chacha20poly1305; + ptLen = len - TLS_CHACHA20_POLY1305_IETF_TAG_LEN; + ctx = &lssl->sec.encryptCtx.chacha20poly1305ietf; memset(nonce, 0, TLS_AEAD_NONCE_MAXLEN); - memset(aad, 0, TLS_CHACHA20_POLY1305_AAD_LEN); + memset(aad, 0, TLS_CHACHA20_POLY1305_IETF_AAD_LEN); -# ifdef CHACHA20POLY1305_IETF -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE - psTraceInfo("Entering csChacha20Poly1305Encrypt IETF\n"); +# ifdef DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305IetfEncrypt IETF\n"); # endif - if (sizeof(lssl->sec.writeIV) < CHACHA20POLY1305_IV_FIXED_LENGTH) + if (sizeof(lssl->sec.writeIV) < CHACHA20POLY1305_IETF_IV_FIXED_LENGTH) { return PS_LIMIT_FAIL; } - if (sizeof(nonce) < CHACHA20POLY1305_IV_FIXED_LENGTH) + if (sizeof(nonce) < CHACHA20POLY1305_IETF_IV_FIXED_LENGTH) { return PS_LIMIT_FAIL; } /* The nonce is built according to: https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305 */ - memcpy(nonce + (CHACHA20POLY1305_IV_FIXED_LENGTH - TLS_AEAD_SEQNB_LEN), lssl->sec.seq, TLS_AEAD_SEQNB_LEN); + memcpy(nonce + (CHACHA20POLY1305_IETF_IV_FIXED_LENGTH - TLS_AEAD_SEQNB_LEN), lssl->sec.seq, TLS_AEAD_SEQNB_LEN); - for (i = 0; i < CHACHA20POLY1305_IV_FIXED_LENGTH; i++) + for (i = 0; i < CHACHA20POLY1305_IETF_IV_FIXED_LENGTH; i++) { nonce[i] ^= lssl->sec.writeIV[i]; } -# else -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE - psTraceInfo("Entering csChacha20Poly1305Encrypt\n"); -# endif - -/* - The nonce is just the sequence number, as explained in - https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-5 AEAD construction - */ - memcpy(nonce, lssl->sec.seq, TLS_AEAD_SEQNB_LEN); -# endif /* --- Fill Additional data ---// */ memcpy(aad, lssl->sec.seq, TLS_AEAD_SEQNB_LEN); i = TLS_AEAD_SEQNB_LEN; @@ -448,20 +428,25 @@ int32 csChacha20Poly1305Encrypt(void *ssl, unsigned char *pt, aad[i++] = ptLen >> 8 & 0xFF; aad[i++] = ptLen & 0xFF; -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE - psTraceBytes("nonce", nonce, CHACHA20POLY1305_IV_FIXED_LENGTH); - psTraceBytes("aad", aad, TLS_CHACHA20_POLY1305_AAD_LEN); +# ifdef DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE + psTraceBytes("nonce", nonce, CHACHA20POLY1305_IETF_IV_FIXED_LENGTH); + psTraceBytes("aad", aad, TLS_CHACHA20_POLY1305_IETF_AAD_LEN); psTraceBytes("pt", pt, ptLen); # endif /* Perform encryption and authentication tag computation */ - psChacha20Poly1305Ready(ctx, nonce, aad, TLS_CHACHA20_POLY1305_AAD_LEN); - psChacha20Poly1305Encrypt(ctx, pt, ct, ptLen); - psChacha20Poly1305GetTag(ctx, TLS_CHACHA20_POLY1305_TAG_LEN, ct + ptLen); + (void)psChacha20Poly1305IetfEncrypt( + ctx, + pt, + ptLen, + nonce, + aad, + TLS_CHACHA20_POLY1305_IETF_AAD_LEN, + ct); -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE +# ifdef DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE psTraceBytes("ct", ct, ptLen); - psTraceBytes("tag", ct + ptLen, TLS_CHACHA20_POLY1305_TAG_LEN); + psTraceBytes("tag", ct + ptLen, TLS_CHACHA20_POLY1305_IETF_TAG_LEN); # endif /* Normally HMAC would increment the sequence */ @@ -476,63 +461,56 @@ int32 csChacha20Poly1305Encrypt(void *ssl, unsigned char *pt, return len; } -int32 csChacha20Poly1305Decrypt(void *ssl, unsigned char *ct, +int32 csChacha20Poly1305IetfDecrypt(void *ssl, unsigned char *ct, unsigned char *pt, uint32 len) { ssl_t *lssl = ssl; - psChacha20Poly1305_t *ctx; + psChacha20Poly1305Ietf_t *ctx; int32 i, ctLen, bytes; unsigned char nonce[TLS_AEAD_NONCE_MAXLEN]; - unsigned char aad[TLS_CHACHA20_POLY1305_AAD_LEN]; + unsigned char aad[TLS_CHACHA20_POLY1305_IETF_AAD_LEN]; - ctx = &lssl->sec.decryptCtx.chacha20poly1305; + ctx = &lssl->sec.decryptCtx.chacha20poly1305ietf; memset(nonce, 0, TLS_AEAD_NONCE_MAXLEN); - memset(aad, 0, TLS_CHACHA20_POLY1305_AAD_LEN); + memset(aad, 0, TLS_CHACHA20_POLY1305_IETF_AAD_LEN); -# ifdef CHACHA20POLY1305_IETF /* Check https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-06 */ -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE - psTraceInfo("Entering csChacha20Poly1305Decrypt IETF\n"); +# ifdef DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE + psTraceInfo("Entering csChacha20Poly1305IetfDecrypt IETF\n"); # endif - if (sizeof(lssl->sec.readIV) < CHACHA20POLY1305_IV_FIXED_LENGTH) + if (sizeof(lssl->sec.readIV) < CHACHA20POLY1305_IETF_IV_FIXED_LENGTH) { return PS_LIMIT_FAIL; } - if (sizeof(nonce) < CHACHA20POLY1305_IV_FIXED_LENGTH) + if (sizeof(nonce) < CHACHA20POLY1305_IETF_IV_FIXED_LENGTH) { return PS_LIMIT_FAIL; } /* The nonce is built according to: https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305 */ - memcpy(nonce + (CHACHA20POLY1305_IV_FIXED_LENGTH - TLS_AEAD_SEQNB_LEN), lssl->sec.remSeq, TLS_AEAD_SEQNB_LEN); + memcpy(nonce + (CHACHA20POLY1305_IETF_IV_FIXED_LENGTH - TLS_AEAD_SEQNB_LEN), lssl->sec.remSeq, TLS_AEAD_SEQNB_LEN); - for (i = 0; i < CHACHA20POLY1305_IV_FIXED_LENGTH; i++) + for (i = 0; i < CHACHA20POLY1305_IETF_IV_FIXED_LENGTH; i++) { nonce[i] ^= lssl->sec.readIV[i]; } -# else -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE - psTraceInfo("Entering csChacha20Poly1305Decrypt\n"); -# endif - memcpy(nonce, lssl->sec.remSeq, TLS_AEAD_SEQNB_LEN); -# endif /* --- Fill Additional data ---// */ memcpy(aad, lssl->sec.remSeq, TLS_AEAD_SEQNB_LEN); i = TLS_AEAD_SEQNB_LEN; /* Update length of encrypted data: we have to remove tag's length */ - if (len < TLS_CHACHA20_POLY1305_TAG_LEN) + if (len < TLS_CHACHA20_POLY1305_IETF_TAG_LEN) { return PS_LIMIT_FAIL; } - ctLen = len - TLS_CHACHA20_POLY1305_TAG_LEN; + ctLen = len - TLS_CHACHA20_POLY1305_IETF_TAG_LEN; aad[i++] = lssl->rec.type; aad[i++] = lssl->majVer; @@ -540,19 +518,17 @@ int32 csChacha20Poly1305Decrypt(void *ssl, unsigned char *ct, aad[i++] = ctLen >> 8 & 0xFF; aad[i++] = ctLen & 0xFF; -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE - psTraceBytes("nonce", nonce, CHACHA20POLY1305_IV_FIXED_LENGTH); - psTraceBytes("aad", aad, TLS_CHACHA20_POLY1305_AAD_LEN); +# ifdef DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE + psTraceBytes("nonce", nonce, CHACHA20POLY1305_IETF_IV_FIXED_LENGTH); + psTraceBytes("aad", aad, TLS_CHACHA20_POLY1305_IETF_AAD_LEN); psTraceBytes("ct", ct, ctLen); - psTraceBytes("tag", ct + ctLen, TLS_CHACHA20_POLY1305_TAG_LEN); + psTraceBytes("tag", ct + ctLen, TLS_CHACHA20_POLY1305_IETF_TAG_LEN); # endif /* --- Check authentication tag and decrypt data ---// */ - psChacha20Poly1305Ready(ctx, nonce, aad, TLS_CHACHA20_POLY1305_AAD_LEN); - - if ((bytes = psChacha20Poly1305Decrypt(ctx, ct, len, pt, ctLen)) < 0) + if ((bytes = psChacha20Poly1305IetfDecrypt(ctx, ct, len, nonce, aad, TLS_CHACHA20_POLY1305_IETF_AAD_LEN, pt)) < 0) { -# ifdef DEBUG_CHACHA20_POLY1305_CIPHER_SUITE +# ifdef DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE psTraceInfo("Decrypt NOK\n"); # endif return -1; @@ -569,7 +545,7 @@ int32 csChacha20Poly1305Decrypt(void *ssl, unsigned char *ct, return bytes; } -#endif /* USE_CHACHA20_POLY1305_CIPHER_SUITE */ +#endif /* USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE */ /******************************************************************************/ @@ -917,11 +893,11 @@ const static sslCipherSpec_t supportedCiphers[] = { CRYPTO_FLAGS_CHACHA | CRYPTO_FLAGS_SHA2, 0, /* macSize */ 32, /* keySize */ - CHACHA20POLY1305_IV_FIXED_LENGTH, /* ivSize */ + CHACHA20POLY1305_IETF_IV_FIXED_LENGTH, /* ivSize */ 0, /* blocksize */ - csChacha20Poly1305Init, - csChacha20Poly1305Encrypt, - csChacha20Poly1305Decrypt, + csChacha20Poly1305IetfInit, + csChacha20Poly1305IetfEncrypt, + csChacha20Poly1305IetfDecrypt, NULL, NULL }, #endif /* USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */ @@ -932,11 +908,11 @@ const static sslCipherSpec_t supportedCiphers[] = { CRYPTO_FLAGS_CHACHA | CRYPTO_FLAGS_SHA2, 0, /* macSize */ 32, /* keySize */ - CHACHA20POLY1305_IV_FIXED_LENGTH, /* ivSize */ + CHACHA20POLY1305_IETF_IV_FIXED_LENGTH, /* ivSize */ 0, /* blocksize */ - csChacha20Poly1305Init, - csChacha20Poly1305Encrypt, - csChacha20Poly1305Decrypt, + csChacha20Poly1305IetfInit, + csChacha20Poly1305IetfEncrypt, + csChacha20Poly1305IetfDecrypt, NULL, NULL }, #endif /* USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */ @@ -1972,59 +1948,11 @@ static int32_t validateKeyForExtensions(ssl_t *ssl, const sslCipherSpec_t *spec, } # endif /* USE_DHE_CIPHER_SUITE */ - /* Now look for the specific pubkey/hash combo is supported */ - switch (crt->sigAlgorithm) + if (!peerSupportsSigAlg(crt->sigAlgorithm, + ssl->hashSigAlg)) { -# ifdef USE_RSA_CIPHER_SUITE - case OID_SHA256_RSA_SIG: - if (!(ssl->hashSigAlg & HASH_SIG_SHA256_RSA_MASK)) - { - return PS_UNSUPPORTED_FAIL; - } - break; -# ifdef USE_SHA1 - case OID_SHA1_RSA_SIG: - if (!(ssl->hashSigAlg & HASH_SIG_SHA1_RSA_MASK)) - { - return PS_UNSUPPORTED_FAIL; - } - break; -# endif -# ifdef USE_SHA384 - case OID_SHA384_RSA_SIG: - if (!(ssl->hashSigAlg & HASH_SIG_SHA384_RSA_MASK)) - { - return PS_UNSUPPORTED_FAIL; - } - break; -# endif -# endif /* USE_RSA_CIPHER_SUITE */ -# ifdef USE_ECC_CIPHER_SUITE - case OID_SHA256_ECDSA_SIG: - if (!(ssl->hashSigAlg & HASH_SIG_SHA256_ECDSA_MASK)) - { - return PS_UNSUPPORTED_FAIL; - } - break; -# ifdef USE_SHA1 - case OID_SHA1_ECDSA_SIG: - if (!(ssl->hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK)) - { - return PS_UNSUPPORTED_FAIL; - } - break; -# endif -# ifdef USE_SHA384 - case OID_SHA384_ECDSA_SIG: - if (!(ssl->hashSigAlg & HASH_SIG_SHA384_ECDSA_MASK)) - { - return PS_UNSUPPORTED_FAIL; - } - break; -# endif -# endif /* USE_ECC */ - default: - psTraceInfo("Don't share ANY sig/hash algorithms with peer\n"); + psTraceInfo("Peer doesn't support all sig/hash algorithm " \ + "pairs in our certificate chain.\n"); return PS_UNSUPPORTED_FAIL; } @@ -2121,7 +2049,14 @@ int32_t haveKeyMaterial(const ssl_t *ssl, int32 cipherType, short reallyTest) return PS_SUCCESS; } # endif - +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + if (!(ssl->flags & SSL_FLAGS_SERVER) && reallyTest == 0) + { + /* When using on-demand client cert and key loading, we may not + have loaded any key or cert material yet. */ + return PS_SUCCESS; + } +# endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ # ifndef USE_ONLY_PSK_CIPHER_SUITE /* To start, capture all the cipherTypes where servers must have an diff --git a/matrixssl/dtls.c b/matrixssl/dtls.c index c4ce062..c6a9a88 100644 --- a/matrixssl/dtls.c +++ b/matrixssl/dtls.c @@ -552,7 +552,7 @@ int32 dtlsEncryptFragRecord(ssl_t *ssl, flightEncode_t *msg, if (ssl->encrypt(ssl, encryptStart, encryptStart, (int32) (*c - encryptStart)) < 0) { - psTraceStrInfo("Error encrypting message for write\n", NULL); + psTraceInfo("Error encrypting message for write\n"); return PS_FAILURE; } diff --git a/matrixssl/extDecode.c b/matrixssl/extDecode.c index fd04b55..0f3f05e 100644 --- a/matrixssl/extDecode.c +++ b/matrixssl/extDecode.c @@ -70,6 +70,7 @@ int32 parseClientHelloExtensions(ssl_t *ssl, unsigned char **cp, unsigned short /* Clear extFlags in case of rehandshakes */ ssl->extFlags.truncated_hmac = 0; ssl->extFlags.sni = 0; + ssl->extFlags.sni_in_last_client_hello = 0; ssl->extFlags.session_id = 0; ssl->extFlags.session_ticket = 0; ssl->extFlags.extended_master_secret = 0; @@ -233,9 +234,9 @@ static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext # ifdef USE_ECC_CIPHER_SUITE unsigned short dataLen, curveId; uint32 ecFlags; -# elif defined USE_OCSP +# elif defined USE_OCSP_RESPONSE unsigned short dataLen; -# endif /* USE_ECC_CIPHER_SUITE || USE_OCSP */ +# endif /* USE_ECC_CIPHER_SUITE || USE_OCSP_RESPONSE */ # ifdef USE_TLS_1_2 unsigned short tmpLen; # endif @@ -351,6 +352,7 @@ static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext } memcpy(ssl->expectedName, c, i); ssl->expectedName[i] = '\0'; + ssl->extFlags.sni_in_last_client_hello = 1; break; # ifdef USE_ALPN @@ -419,6 +421,7 @@ static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; return MATRIXSSL_ERROR; } + ssl->secureRenegotiationInProgress = PS_TRUE; } else { @@ -627,7 +630,7 @@ static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext break; # endif /* USE_ECC_CIPHER_SUITE */ -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE case EXT_STATUS_REQUEST: /* Validation of minimum size and status_type of 1 (ocsp) */ if (extLen < 5 || *c != 0x1) @@ -642,7 +645,7 @@ static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext dataLen += *c; c++; extLen--; if (dataLen + 2 > extLen) { - psTraceIntInfo("Bad cert_status_request extension: \n", extType); + psTraceIntInfo("Bad cert_status_request extension: %d\n", extType); ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; return MATRIXSSL_ERROR; } @@ -652,7 +655,7 @@ static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext dataLen += *c; c++; extLen--; if (dataLen > extLen) { - psTraceIntInfo("Bad cert_status_request extension: \n", extType); + psTraceIntInfo("Bad cert_status_request extension: %d\n", extType); ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; return MATRIXSSL_ERROR; } @@ -671,7 +674,7 @@ static int ClientHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext } break; -# endif +# endif /* USE_OCSP_RESPONSE */ /**************************************************************************/ @@ -1168,6 +1171,7 @@ static int ServerHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext psTraceInfo("Srv had bad peer renegotiationInfo\n"); return MATRIXSSL_ERROR; } + ssl->secureRenegotiationInProgress = PS_TRUE; } else { diff --git a/matrixssl/hsDecode.c b/matrixssl/hsDecode.c index 0545339..e6b8e18 100644 --- a/matrixssl/hsDecode.c +++ b/matrixssl/hsDecode.c @@ -80,6 +80,9 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) ssl->reqMajVer = *c; c++; ssl->reqMinVer = *c; c++; + psTracePrintProtocolVersion("Parsed ClientHello.client_version", + ssl->reqMajVer, ssl->reqMinVer, 1); + # 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) */ @@ -145,8 +148,12 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) if (compareMin >= TLS_MIN_VER) { # ifndef DISABLE_TLS_1_0 - ssl->minVer = TLS_MIN_VER; - ssl->flags |= SSL_FLAGS_TLS; + /* Allow TLS 1.0, unless specifically disabled. */ + if (!ssl->disable_tls_1_0) + { + ssl->minVer = TLS_MIN_VER; + ssl->flags |= SSL_FLAGS_TLS; + } # endif # ifdef USE_TLS_1_1 /* TLS_1_1 */ if (compareMin >= TLS_1_1_MIN_VER) @@ -157,11 +164,19 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) # endif } # ifdef USE_TLS_1_2 - if (compareMin == TLS_1_2_MIN_VER) +# ifdef USE_TLS_1_2_TOGGLE + /* Prefer TLS 1.2, unless specifically disabled. */ + if (!ssl->disable_tls_1_2) { - ssl->minVer = TLS_1_2_MIN_VER; - ssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS; +# endif /* USE_TLS_1_2_TOGGLE */ + if (compareMin == TLS_1_2_MIN_VER) + { + ssl->minVer = TLS_1_2_MIN_VER; + ssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS; + } +# ifdef USE_TLS_1_2_TOGGLE } +# endif /* USE_TLS_1_2_TOGGLE */ # ifdef USE_DTLS if (ssl->flags & SSL_FLAGS_DTLS) { @@ -206,11 +221,19 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) } ssl->minVer = DTLS_MIN_VER; # ifdef USE_TLS_1_2 - if (compareMin == DTLS_1_2_MIN_VER) +# ifdef USE_TLS_1_2_TOGGLE + /* Prefer TLS 1.2, unless specifically disabled. */ + if (!ssl->disable_tls_1_2) { - ssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS; - ssl->minVer = DTLS_1_2_MIN_VER; +# endif /* USE_TLS_1_2_TOGGLE */ + if (compareMin == DTLS_1_2_MIN_VER) + { + ssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS; + ssl->minVer = DTLS_1_2_MIN_VER; + } +# ifdef USE_TLS_1_2_TOGGLE } +# endif /* USE_TLS_1_2_TOGGLE */ # ifdef USE_DTLS if (ssl->flags & SSL_FLAGS_DTLS) { @@ -504,9 +527,88 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) } else { +#if defined(USE_INTERCEPTOR) || defined(ALLOW_SSLV2_CLIENT_HELLO_PARSE) + /* Parse a SSLv2 ClientHello message. The same information is + conveyed but the order and format is different. + First get the cipher suite length, session id length and challenge + (client random) length - all two byte values, network byte order */ + uint32_t challengeLen; + psTraceInfo("Parsing SSLv2 ClientHello\n"); + if (end - c < 6) + { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Can't parse hello message\n"); + return MATRIXSSL_ERROR; + } + suiteLen = *c << 8; c++; + suiteLen += *c; c++; + if (suiteLen == 0 || suiteLen % 3 != 0) + { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Can't parse hello message\n"); + return MATRIXSSL_ERROR; + } + ssl->sessionIdLen = *c << 8; c++; + ssl->sessionIdLen += *c; c++; + /* A resumed session would use a SSLv3 ClientHello, not SSLv2. */ + if (ssl->sessionIdLen != 0) + { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("Bad resumption request\n"); + return MATRIXSSL_ERROR; + } + challengeLen = *c << 8; c++; + challengeLen += *c; c++; +#ifdef ALLOW_SSLV2_CLIENT_HELLO_PARSE + if (challengeLen != 32) /* Allow only 32-bit, as per RFC 2246, E.2. */ +#else + if (challengeLen < 16 || challengeLen > 32) +#endif + { + psTraceInfo("Bad challenge length\n"); + ssl->err = SSL_ALERT_DECODE_ERROR; + return MATRIXSSL_ERROR; + } + /* Validate the three lengths that were just sent to us, don't + want any buffer overflows while parsing the remaining data */ + if ((uint32) (end - c) != suiteLen + ssl->sessionIdLen + + challengeLen) + { + ssl->err = SSL_ALERT_DECODE_ERROR; + psTraceInfo("Malformed SSLv2 clientHello\n"); + return MATRIXSSL_ERROR; + } + /* Parse the cipher suite list similar to the SSLv3 method, except + each suite is 3 bytes, instead of two bytes. We define the suite + as an integer value, so either method works for lookup. + We don't support session resumption from V2 handshakes, so don't + need to worry about matching resumed cipher suite. */ + suiteStart = c; + while (c < (suiteStart + suiteLen)) + { + cipher = *c << 16; c++; + cipher += *c << 8; c++; + cipher += *c; c++; + /* NOT CHOOSING SUITE HERE ANY LONGER*/ + } + /* We don't allow session IDs for v2 ClientHellos */ + if (ssl->sessionIdLen > 0) + { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceInfo("SSLv2 sessions not allowed\n"); + return MATRIXSSL_ERROR; + } + /* The client random (between 16 and 32 bytes) fills the least + significant bytes in the (always) 32 byte SSLv3 client random */ + memset(ssl->sec.clientRandom, 0x0, SSL_HS_RANDOM_SIZE); + memcpy(ssl->sec.clientRandom + (SSL_HS_RANDOM_SIZE - challengeLen), + c, challengeLen); + c += challengeLen; +# else ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; psTraceInfo("SSLV2 CLIENT_HELLO not supported.\n"); return MATRIXSSL_ERROR; +# endif } /* ClientHello should be the only one in the record. */ @@ -1360,6 +1462,8 @@ int32 parseCertificateVerify(ssl_t *ssl, } hashSigAlg = HASH_SIG_MASK(c[0], c[1]); + psTracePrintSigAlgs(hashSigAlg, "Peer CertificateVerify\n"); + /* The server-sent algorithms has to be one of the ones we sent in our ClientHello extension */ if (!(ssl->hashSigAlg & hashSigAlg)) @@ -1588,6 +1692,9 @@ int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp, } ssl->reqMajVer = *c; c++; ssl->reqMinVer = *c; c++; + psTracePrintProtocolVersion("Parsed ServerHello.server_version", + ssl->reqMajVer, ssl->reqMinVer, 1); + if (ssl->reqMajVer != ssl->majVer) { ssl->err = SSL_ALERT_PROTOCOL_VERSION; @@ -1663,9 +1770,18 @@ int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp, psTraceInfo("Server wants to talk TLS1.0 but it's disabled\n"); return MATRIXSSL_ERROR; # else - ssl->reqMinVer = ssl->minVer; - ssl->minVer = TLS_MIN_VER; - ssl->flags &= ~SSL_FLAGS_TLS_1_1; + if (ssl->disable_tls_1_0) + { + ssl->err = SSL_ALERT_PROTOCOL_VERSION; + psTraceInfo("Server wants to talk TLS1.0 but it's disabled\n"); + return MATRIXSSL_ERROR; + } + else + { + ssl->reqMinVer = ssl->minVer; + ssl->minVer = TLS_MIN_VER; + ssl->flags &= ~SSL_FLAGS_TLS_1_1; + } # endif } else @@ -1876,7 +1992,7 @@ PROTOCOL_DETERMINED: next handshake message or if it is extension data */ if (c != end && ((int32) hsLen > (c - extData))) { - rc = parseServerHelloExtensions(ssl, hsLen, extData, &c, c - end); + rc = parseServerHelloExtensions(ssl, hsLen, extData, &c, end - c); if (rc < 0) { /* Alerts will already have been set inside */ @@ -2635,7 +2751,7 @@ int32 parseServerKeyExchange(ssl_t *ssl, return PS_SUCCESS; } -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE int32 parseCertificateStatus(ssl_t *ssl, int32 hsLen, unsigned char **cp, unsigned char *end) { @@ -2722,7 +2838,7 @@ int32 parseCertificateStatus(ssl_t *ssl, int32 hsLen, unsigned char **cp, ssl->decState = SSL_HS_CERTIFICATE_STATUS; return PS_SUCCESS; } -# endif /* USE_OCSP */ +# endif /* USE_OCSP_RESPONSE */ /******************************************************************************/ @@ -2822,9 +2938,6 @@ int32 parseCertificateRequest(ssl_t *ssl, int32 hsLen, unsigned char **cp, uint32 certLen; # ifdef USE_TLS_1_2 uint32 sigAlgMatch; -# ifdef USE_CLIENT_AUTH - uint32 hashSigAlg; -# endif # endif unsigned char *c; @@ -2872,37 +2985,29 @@ int32 parseCertificateRequest(ssl_t *ssl, int32 hsLen, unsigned char **cp, return MATRIXSSL_ERROR; } # ifdef USE_CLIENT_AUTH - /* Going to adhere to this supported_signature_algorithm to - be compliant with the spec. This is now the first line - of testing about what certificates the server will accept. - If any of our certs do not use a signature algorithm - that the server supports we will flag that here which will - ultimately result in an empty CERTIFICATE message and - no CERTIFICATE_VERIFY message. We're going to convert - MD5 to use SHA1 instead though. - - Start by building a bitmap of supported algs */ - hashSigAlg = 0; + /* Parse supported_signature_algorithms list. */ + ssl->serverSigAlgs = 0; while (certChainLen >= 2) { i = HASH_SIG_MASK(c[0], c[1]); - /* Our own ssl->hashSigAlg is the list we support. So choose - from those only */ - if (ssl->hashSigAlg & i) - { - hashSigAlg |= i; - } + ssl->serverSigAlgs |= i; c += 2; certChainLen -= 2; } - /* RFC: The end-entity certificate provided by the client MUST - contain a key that is compatible with certificate_types. - If the key is a signature key, it MUST be usable with some - hash/signature algorithm pair in supported_signature_algorithms. + psTracePrintSigAlgs(ssl->serverSigAlgs, "Peer CertificateRequest"); - So not only do we have to check the signature algorithm, we - have to check the pub key type as well. */ - sigAlgMatch = 1; /* de-flag if we hit unsupported one */ + /* + RFC 5246, section 7.4.4: + "Any certificates provided by the client MUST be signed using a + hash/signature algorithm pair found in + supported_signature_algorithms." + + Check our certificate chain and set sigAlgMatch to 0 if we + find a cert whose sigAlg is not supported by the server. + sigAlgMatch==0 will result in us sending an empty Certificate + message later, as required by RFC 5246. + */ + sigAlgMatch = 1; if (ssl->keys == NULL || ssl->keys->cert == NULL) { sigAlgMatch = 0; @@ -2912,100 +3017,11 @@ int32 parseCertificateRequest(ssl_t *ssl, int32 hsLen, unsigned char **cp, cert = ssl->keys->cert; while (cert) { - if (cert->pubKeyAlgorithm == OID_RSA_KEY_ALG) + if (!peerSupportsSigAlg(cert->sigAlgorithm, + ssl->serverSigAlgs)) { - if (!(hashSigAlg & HASH_SIG_SHA1_RSA_MASK) && -# ifdef USE_SHA384 - !(hashSigAlg & HASH_SIG_SHA384_RSA_MASK) && -# endif - !(hashSigAlg & HASH_SIG_SHA256_RSA_MASK) && - !(hashSigAlg & HASH_SIG_MD5_RSA_MASK)) - { - sigAlgMatch = 0; - } + sigAlgMatch = 0; } - if (cert->sigAlgorithm == OID_SHA1_RSA_SIG || - cert->sigAlgorithm == OID_MD5_RSA_SIG) - { - if (!(hashSigAlg & HASH_SIG_SHA1_RSA_MASK)) - { - sigAlgMatch = 0; - } - } - if (cert->sigAlgorithm == OID_SHA256_RSA_SIG) - { - if (!(hashSigAlg & HASH_SIG_SHA256_RSA_MASK)) - { - sigAlgMatch = 0; - } - } -# ifdef USE_SHA384 - if (cert->sigAlgorithm == OID_SHA384_RSA_SIG) - { - if (!(hashSigAlg & HASH_SIG_SHA384_RSA_MASK)) - { - sigAlgMatch = 0; - } - } -# endif -# ifdef USE_SHA512 - if (cert->sigAlgorithm == OID_SHA512_RSA_SIG) - { - if (!(hashSigAlg & HASH_SIG_SHA512_RSA_MASK)) - { - sigAlgMatch = 0; - } - } -# endif -# ifdef USE_ECC - if (cert->pubKeyAlgorithm == OID_ECDSA_KEY_ALG) - { - if (!(hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK) && -# ifdef USE_SHA384 - !(hashSigAlg & HASH_SIG_SHA384_ECDSA_MASK) && -# endif -# ifdef USE_SHA512 - !(hashSigAlg & HASH_SIG_SHA512_ECDSA_MASK) && -# endif - !(hashSigAlg & HASH_SIG_SHA256_ECDSA_MASK) && - !(hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK)) - { - sigAlgMatch = 0; - } - } - if (cert->sigAlgorithm == OID_SHA1_ECDSA_SIG) - { - if (!(hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK)) - { - sigAlgMatch = 0; - } - } - if (cert->sigAlgorithm == OID_SHA256_ECDSA_SIG) - { - if (!(hashSigAlg & HASH_SIG_SHA256_ECDSA_MASK)) - { - sigAlgMatch = 0; - } - } -# ifdef USE_SHA384 - if (cert->sigAlgorithm == OID_SHA384_ECDSA_SIG) - { - if (!(hashSigAlg & HASH_SIG_SHA384_ECDSA_MASK)) - { - sigAlgMatch = 0; - } - } -# endif -# ifdef USE_SHA512 - if (cert->sigAlgorithm == OID_SHA512_ECDSA_SIG) - { - if (!(hashSigAlg & HASH_SIG_SHA512_ECDSA_MASK)) - { - sigAlgMatch = 0; - } - } -# endif -# endif /* USE_ECC */ cert = cert->next; } } @@ -3177,13 +3193,19 @@ int32 parseFinished(ssl_t *ssl, int32 hsLen, } else { +#ifdef ENABLE_SECURE_REHANDSHAKES + /* We're the server and we are doing a resumed (i.e. abbreviated) + handshake. The Finished message we just parsed was the final + handshake message. */ + ssl->secureRenegotiationInProgress = PS_FALSE; +#endif #ifdef USE_SSL_INFORMATIONAL_TRACE /* Server side resumed completion */ matrixSslPrintHSDetails(ssl); #endif } } - else + else /* We are the client. */ { #ifdef USE_STATELESS_SESSION_TICKETS /* Now that FINISHED is verified, we can mark the ticket as @@ -3199,6 +3221,12 @@ int32 parseFinished(ssl_t *ssl, int32 hsLen, } else { +#ifdef ENABLE_SECURE_REHANDSHAKES + /* We are the client and were doing a full handshake. + The Finished message we just parsed was the final + handshake message. */ + ssl->secureRenegotiationInProgress = PS_FALSE; +#endif #ifdef USE_SSL_INFORMATIONAL_TRACE /* Client side standard completion */ matrixSslPrintHSDetails(ssl); @@ -3314,7 +3342,7 @@ int32 parseCertificate(ssl_t *ssl, unsigned char **cp, unsigned char *end) certChainLen = *c << 16; c++; certChainLen |= *c << 8; c++; certChainLen |= *c; c++; - if (certChainLen == 0) + if (certChainLen < 3) { # ifdef SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG if (ssl->flags & SSL_FLAGS_SERVER) @@ -3660,7 +3688,7 @@ STRAIGHT_TO_USER_CALLBACK: } else if (rc < 0) { - psTraceIntInfo("User certificate callback had an internal error\n", rc); + psTraceIntInfo("User certificate callback had an internal error (rc=%d)\n", rc); ssl->err = SSL_ALERT_INTERNAL_ERROR; return MATRIXSSL_ERROR; } @@ -3690,7 +3718,7 @@ STRAIGHT_TO_USER_CALLBACK: ssl->hsState = SSL_HS_SERVER_KEY_EXCHANGE; } # endif /* USE_DHE_CIPHER_SUITE */ -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE /* State management for OCSP use. Testing if we received a status_request from the server to set next expected state */ if (ssl->extFlags.status_request || ssl->extFlags.status_request_v2) @@ -3703,7 +3731,7 @@ STRAIGHT_TO_USER_CALLBACK: sent a "status_request" extension in the server hello message */ ssl->hsState = SSL_HS_CERTIFICATE_STATUS; } -# endif +# endif /* USE_OCSP_RESPONSE */ } *cp = c; ssl->decState = SSL_HS_CERTIFICATE; diff --git a/matrixssl/matrixssl.c b/matrixssl/matrixssl.c index ed2e3e0..d700907 100644 --- a/matrixssl/matrixssl.c +++ b/matrixssl/matrixssl.c @@ -664,6 +664,7 @@ static int32 matrixSslLoadKeyMaterial(sslKeys_t *keys, const char *certFile, if (keys->cert->authFailFlags) { psAssert(keys->cert->authFailFlags == PS_CERT_AUTH_FAIL_DATE_FLAG); + psTraceStrInfo("Certificate out-of-date: %s\n", (char *)certFile); # ifdef POSIX /* TODO - implement date check on WIN32, etc. */ psX509FreeCert(keys->cert); keys->cert = NULL; @@ -776,6 +777,7 @@ static int32 matrixSslLoadKeyMaterial(sslKeys_t *keys, const char *certFile, /* This should be the only no err, FailFlags case currently */ psAssert(keys->CAcerts->authFailFlags == PS_CERT_AUTH_FAIL_DATE_FLAG); + psTraceStrInfo("Certificate out-of-date: %s\n", (char *)CAfile); # ifdef POSIX /* TODO - implement date check on WIN32, etc. */ psX509FreeCert(keys->CAcerts); keys->CAcerts = NULL; @@ -1078,23 +1080,26 @@ static int32 matrixSslLoadKeyMaterialMem(sslKeys_t *keys, ca_load_failed: #endif /* ALLOW_CA_BUNDLE_PARTIAL_PARSE */ -# if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) if (err < 0) { +# if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) psClearPubKey(&keys->privKey); psX509FreeCert(keys->cert); + keys->cert = NULL; +# endif +# if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) psX509FreeCert(keys->CAcerts); - keys->cert = keys->CAcerts = NULL; + keys->CAcerts = NULL; +# endif return err; } -# endif return PS_SUCCESS; } #endif /* USE_RSA || USE_ECC */ -#if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +#if defined(USE_OCSP_RESPONSE) && defined(USE_SERVER_SIDE_SSL) int32_t matrixSslLoadOCSPResponse(sslKeys_t *keys, const unsigned char *OCSPResponseBuf, psSize_t OCSPResponseBufLen) { @@ -1123,7 +1128,7 @@ int32_t matrixSslLoadOCSPResponse(sslKeys_t *keys, memcpy(keys->OCSPResponseBuf, OCSPResponseBuf, OCSPResponseBufLen); return PS_SUCCESS; } -#endif /* USE_OCSP && USE_SERVER_SIDE_SSL */ +#endif /* USE_OCSP_RESPONSE && USE_SERVER_SIDE_SSL */ /******************************************************************************/ /* @@ -1209,7 +1214,7 @@ void matrixSslDeleteKeys(sslKeys_t *keys) /* Remainder of structure is cleared below */ #endif -#if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +#if defined(USE_OCSP_RESPONSE) && defined(USE_SERVER_SIDE_SSL) if (keys->OCSPResponseBuf != NULL) { psFree(keys->OCSPResponseBuf, keys->pool); @@ -1335,6 +1340,161 @@ int32 matrixSslLoadDhParamsMem(sslKeys_t *keys, const unsigned char *dhBin, } #endif /* REQUIRE_DH_PARAMS */ +psBool_t matrixSslTlsVersionRangeSupported(int32_t low, + int32_t high) +{ + if (low < MIN_ENABLED_TLS_VER) + { + psTraceIntInfo("Minimum of version range not supported " \ + "by config: %d\n", low); + return PS_FALSE; + } + if (high > MAX_ENABLED_TLS_VER) + { + psTraceIntInfo("Maximum of version range not supported " \ + "by config: %d\n", high); + return PS_FALSE; + } + if (low > high) + { + psTraceInfo("Invalid version range: low > high\n"); + return PS_FALSE; + } + + return PS_TRUE; +} + +#ifdef USE_CLIENT_SIDE_SSL +static +int32 tlsVerToVersionFlag(int32_t ver) +{ + switch (ver) + { + case tls_v_1_2: + return SSL_FLAGS_TLS_1_2; + case tls_v_1_1: + return SSL_FLAGS_TLS_1_1; + case tls_v_1_0: + return SSL_FLAGS_TLS_1_0; + } + + return 0; +} + +int32_t matrixSslSessOptsSetClientTlsVersionRange(sslSessOpts_t *options, + int32_t low, int32_t high) +{ + if (options == NULL) + { + return PS_ARG_FAIL; + } + if (!matrixSslTlsVersionRangeSupported(low, high)) + { + psTraceInfo("Please enable more versions in matrixsslConfig.h.\n"); + return PS_ARG_FAIL; + } + if (low < tls_v_1_0) + { + psTraceInfo("matrixSslSessOptsSetClientTlsVersionRange only " \ + "supports TLS 1.0 to TLS 1.2. SSL 3.0 is not supported\n"); + return PS_ARG_FAIL; + } + + if (low == high) + { + /* Single version. */ + options->clientRejectVersionDowngrade = 1; + } + else + { + if (low > tls_v_1_0) + { + /* Range: TLS 1.1 - TLS 1.2. */ +# ifdef USE_TLS_1_0_TOGGLE + options->disableTls1_0 = PS_TRUE; +# else + psTraceInfo("Need USE_TLS_1_0_TOGGLE for this version range\n"); + return PS_UNSUPPORTED_FAIL; +# endif /* USE_TLS_1_0_TOGGLE */ + } + } + + /* Always put the highest version we support to ClientHello.client_version, + as recommended by the RFC. */ + options->versionFlag = tlsVerToVersionFlag(high); + + return PS_SUCCESS; +} +#endif /* USE_CLIENT_SIDE_SSL */ + +#ifdef USE_SERVER_SIDE_SSL +int32_t matrixSslSessOptsSetServerTlsVersionRange(sslSessOpts_t *options, + int32_t low, int32_t high) +{ + if (options == NULL) + { + return PS_ARG_FAIL; + } + if (!matrixSslTlsVersionRangeSupported(low, high)) + { + psTraceInfo("Please enable more versions in matrixsslConfig.h.\n"); + return PS_ARG_FAIL; + } + if (low < tls_v_1_0) + { + psTraceInfo("matrixSslSessOptsSetServerTlsVersionRange only " \ + "supports TLS 1.0 to TLS 1.2. SSL 3.0 is not supported\n"); + return PS_ARG_FAIL; + } + + if (low == high) + { + /* Single version. */ + if (low == tls_v_1_2) + { + options->versionFlag = SSL_FLAGS_TLS_1_2; + } + else if (low == tls_v_1_1) + { + options->versionFlag = SSL_FLAGS_TLS_1_1; + } + else if (low == tls_v_1_0) + { + options->versionFlag = SSL_FLAGS_TLS_1_0; + } + else + { + return PS_ARG_FAIL; + } + } + else + { + /* Version range. */ + options->versionFlag = 0; + if (low > tls_v_1_0) + { +# ifdef USE_TLS_1_0_TOGGLE + options->disableTls1_0 = PS_TRUE; +# else + psTraceInfo("Need USE_TLS_1_0_TOGGLE for this version range\n"); + return PS_UNSUPPORTED_FAIL; +# endif /* USE_TLS_1_0_TOGGLE */ + } + if (high < tls_v_1_2) + { +# ifdef USE_TLS_1_2_TOGGLE + options->serverDisableTls1_2 = PS_TRUE; +# else + psTraceInfo("Need USE_TLS_1_2_TOGGLE for this version range\n"); + return PS_UNSUPPORTED_FAIL; +# endif /* USE_TLS_1_2_TOGGLE */ + } + } + + return PS_SUCCESS; +} +#endif /* USE_SERVER_SIDE_SSL */ + /******************************************************************************/ /* New SSL protocol context @@ -2058,199 +2218,174 @@ void matrixSslPrintHSDetails(ssl_t *ssl) if (ssl->hsState == SSL_HS_DONE) { psTraceInfo("\n"); - if (ssl->minVer == SSL3_MIN_VER) - { - psTraceInfo("SSL 3.0 "); - } - else if (ssl->minVer == TLS_MIN_VER) - { - psTraceInfo("TLS 1.0 "); - } - else if (ssl->minVer == TLS_1_1_MIN_VER) - { - psTraceInfo("TLS 1.1 "); - } - else if (ssl->minVer == TLS_1_2_MIN_VER) - { - psTraceInfo("TLS 1.2 "); - } -# ifdef USE_DTLS - else if (ssl->minVer == DTLS_1_2_MIN_VER) - { - psTraceInfo("DTLS 1.2 "); - } - else if (ssl->minVer == DTLS_MIN_VER) - { - psTraceInfo("DTLS 1.0 "); - } -# endif - psTraceInfo("connection established: "); + psTracePrintProtocolVersion(NULL, ssl->majVer, ssl->minVer, 0); + _psTrace(" connection established: "); switch (ssl->cipher->ident) { case SSL_RSA_WITH_NULL_MD5: - psTraceInfo("SSL_RSA_WITH_NULL_MD5\n"); + _psTrace("SSL_RSA_WITH_NULL_MD5\n"); break; case SSL_RSA_WITH_NULL_SHA: - psTraceInfo("SSL_RSA_WITH_NULL_SHA\n"); + _psTrace("SSL_RSA_WITH_NULL_SHA\n"); break; case SSL_RSA_WITH_RC4_128_MD5: - psTraceInfo("SSL_RSA_WITH_RC4_128_MD5\n"); + _psTrace("SSL_RSA_WITH_RC4_128_MD5\n"); break; case SSL_RSA_WITH_RC4_128_SHA: - psTraceInfo("SSL_RSA_WITH_RC4_128_SHA\n"); + _psTrace("SSL_RSA_WITH_RC4_128_SHA\n"); break; case SSL_RSA_WITH_3DES_EDE_CBC_SHA: - psTraceInfo("SSL_RSA_WITH_3DES_EDE_CBC_SHA\n"); + _psTrace("SSL_RSA_WITH_3DES_EDE_CBC_SHA\n"); break; case TLS_RSA_WITH_AES_128_CBC_SHA: - psTraceInfo("TLS_RSA_WITH_AES_128_CBC_SHA\n"); + _psTrace("TLS_RSA_WITH_AES_128_CBC_SHA\n"); break; case TLS_RSA_WITH_AES_256_CBC_SHA: - psTraceInfo("TLS_RSA_WITH_AES_256_CBC_SHA\n"); + _psTrace("TLS_RSA_WITH_AES_256_CBC_SHA\n"); break; case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - psTraceInfo("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA\n"); + _psTrace("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA\n"); break; case SSL_DH_anon_WITH_RC4_128_MD5: - psTraceInfo("SSL_DH_anon_WITH_RC4_128_MD5\n"); + _psTrace("SSL_DH_anon_WITH_RC4_128_MD5\n"); break; case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - psTraceInfo("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA\n"); + _psTrace("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA\n"); break; case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - psTraceInfo("TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n"); + _psTrace("TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n"); break; case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - psTraceInfo("TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n"); + _psTrace("TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n"); break; case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - psTraceInfo("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\n"); + _psTrace("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\n"); break; case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - psTraceInfo("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\n"); + _psTrace("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\n"); break; case TLS_DH_anon_WITH_AES_128_CBC_SHA: - psTraceInfo("TLS_DH_anon_WITH_AES_128_CBC_SHA\n"); + _psTrace("TLS_DH_anon_WITH_AES_128_CBC_SHA\n"); break; case TLS_DH_anon_WITH_AES_256_CBC_SHA: - psTraceInfo("TLS_DH_anon_WITH_AES_256_CBC_SHA\n"); + _psTrace("TLS_DH_anon_WITH_AES_256_CBC_SHA\n"); break; case TLS_RSA_WITH_AES_128_CBC_SHA256: - psTraceInfo("TLS_RSA_WITH_AES_128_CBC_SHA256\n"); + _psTrace("TLS_RSA_WITH_AES_128_CBC_SHA256\n"); break; case TLS_RSA_WITH_AES_256_CBC_SHA256: - psTraceInfo("TLS_RSA_WITH_AES_256_CBC_SHA256\n"); + _psTrace("TLS_RSA_WITH_AES_256_CBC_SHA256\n"); break; case TLS_RSA_WITH_SEED_CBC_SHA: - psTraceInfo("TLS_RSA_WITH_SEED_CBC_SHA\n"); + _psTrace("TLS_RSA_WITH_SEED_CBC_SHA\n"); break; case TLS_RSA_WITH_IDEA_CBC_SHA: - psTraceInfo("TLS_RSA_WITH_IDEA_CBC_SHA\n"); + _psTrace("TLS_RSA_WITH_IDEA_CBC_SHA\n"); break; case TLS_PSK_WITH_AES_128_CBC_SHA: - psTraceInfo("TLS_PSK_WITH_AES_128_CBC_SHA\n"); + _psTrace("TLS_PSK_WITH_AES_128_CBC_SHA\n"); break; case TLS_PSK_WITH_AES_128_CBC_SHA256: - psTraceInfo("TLS_PSK_WITH_AES_128_CBC_SHA256\n"); + _psTrace("TLS_PSK_WITH_AES_128_CBC_SHA256\n"); break; case TLS_PSK_WITH_AES_256_CBC_SHA384: - psTraceInfo("TLS_PSK_WITH_AES_256_CBC_SHA384\n"); + _psTrace("TLS_PSK_WITH_AES_256_CBC_SHA384\n"); break; case TLS_PSK_WITH_AES_256_CBC_SHA: - psTraceInfo("TLS_PSK_WITH_AES_256_CBC_SHA\n"); + _psTrace("TLS_PSK_WITH_AES_256_CBC_SHA\n"); break; case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - psTraceInfo("TLS_DHE_PSK_WITH_AES_128_CBC_SHA\n"); + _psTrace("TLS_DHE_PSK_WITH_AES_128_CBC_SHA\n"); break; case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - psTraceInfo("TLS_DHE_PSK_WITH_AES_256_CBC_SHA\n"); + _psTrace("TLS_DHE_PSK_WITH_AES_256_CBC_SHA\n"); break; case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA\n"); + _psTrace("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA\n"); break; case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA\n"); + _psTrace("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA\n"); break; case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA\n"); + _psTrace("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA\n"); break; case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA\n"); + _psTrace("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA\n"); break; case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - psTraceInfo("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n"); + _psTrace("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n"); break; case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - psTraceInfo("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA\n"); + _psTrace("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA\n"); break; case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - psTraceInfo("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\n"); + _psTrace("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\n"); break; case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - psTraceInfo("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384\n"); + _psTrace("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384\n"); break; case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - psTraceInfo("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\n"); + _psTrace("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\n"); break; case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - psTraceInfo("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n"); + _psTrace("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n"); break; case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - psTraceInfo("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n"); + _psTrace("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n"); break; case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - psTraceInfo("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA\n"); + _psTrace("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA\n"); break; case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - psTraceInfo("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256\n"); + _psTrace("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256\n"); break; case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - psTraceInfo("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384\n"); + _psTrace("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384\n"); break; case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - psTraceInfo("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256\n"); + _psTrace("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256\n"); break; case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - psTraceInfo("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384\n"); + _psTrace("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384\n"); break; case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - psTraceInfo("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA\n"); + _psTrace("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA\n"); break; case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\n"); + _psTrace("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\n"); break; case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384\n"); + _psTrace("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384\n"); break; case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256\n"); + _psTrace("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256\n"); break; case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384\n"); + _psTrace("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384\n"); break; case TLS_RSA_WITH_AES_128_GCM_SHA256: - psTraceInfo("TLS_RSA_WITH_AES_128_GCM_SHA256\n"); + _psTrace("TLS_RSA_WITH_AES_128_GCM_SHA256\n"); break; case TLS_RSA_WITH_AES_256_GCM_SHA384: - psTraceInfo("TLS_RSA_WITH_AES_256_GCM_SHA384\n"); + _psTrace("TLS_RSA_WITH_AES_256_GCM_SHA384\n"); break; case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n"); + _psTrace("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n"); break; case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - psTraceInfo("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\n"); + _psTrace("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\n"); break; case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256\n"); + _psTrace("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256\n"); break; case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - psTraceInfo("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384\n"); + _psTrace("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384\n"); break; case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - psTraceInfo("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\n"); + _psTrace("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\n"); break; case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - psTraceInfo("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\n"); + _psTrace("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\n"); break; default: psTraceIntInfo("!!!! DEFINE ME %d !!!!\n", ssl->cipher->ident); @@ -2269,6 +2404,49 @@ int32_t matrixSslHandshakeIsComplete(const ssl_t *ssl) return (ssl->hsState == SSL_HS_DONE) ? PS_TRUE : PS_FALSE; } +# ifdef ENABLE_SECURE_REHANDSHAKES +/** + Return PS_TRUE when a secure renegotiation is in progress. + return PS_FALSE otherwise. + + Return PS_TRUE when we have written a non-empty renegotiation_info + extension into our ClientHello or ServerHello. This can happen + only when empty renegotiation_infos or the + TLS_EMPTY_RENEGOTIATION_INFO_SCSV ciphersuites were exchanged + during the initial handshake, indicating that both sides support + secure renegotiation. + + The situation where we, as the client, have parsed HelloRequest, + but have not sent our renegotiating ClientHello yet, should not + happen, because matrixSslDecode will call matrixSslEncodeClientHello + directly after parsing a HelloRequest. Thus, it should not be + possible that this function will be called between HelloRequest + parsing and ClientHello sending (in which case it would incorrectly + return PS_FALSE). + +#ifdef TODO + Check the reset logic for ssl->secureRenegotiationInProgress. + Currently we set it to PS_FALSE after sending or receiving the + final handshake message. +#endif + + @return PS_TRUE when a secure renegotiation is in progress. + @return PS_FALSE when no secure renegotiation is in progress. +*/ +psBool_t matrixSslRehandshaking(const ssl_t *ssl) +{ + if (ssl->flags & SSL_FLAGS_ERROR) + { + /* Fatal alerts mean the handshake is over. */ + return PS_FALSE; + } + else + { + return ssl->secureRenegotiationInProgress; + } +} +# endif /* ENABLE_SECURE_REHANDSHAKES */ + #if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH) /******************************************************************************/ /* @@ -3213,6 +3391,20 @@ int32 matrixServerSetKeysSNI(ssl_t *ssl, char *host, int32 hostLen) */ void sslResetContext(ssl_t *ssl) { +#ifdef USE_X509 + int32_t bFlagsToKeep = 0; + + /* Most bFlags are cleared below. However, some options we wish + to retain for the rehandshake. */ + if (ssl->bFlags & BFLAG_KEEP_PEER_CERTS) + { + bFlagsToKeep |= BFLAG_KEEP_PEER_CERTS; + } + if (ssl->bFlags & BFLAG_KEEP_PEER_CERT_DER) + { + bFlagsToKeep |= BFLAG_KEEP_PEER_CERT_DER; + } +#endif #ifdef USE_CLIENT_SIDE_SSL if (!(ssl->flags & SSL_FLAGS_SERVER)) { @@ -3259,6 +3451,10 @@ void sslResetContext(ssl_t *ssl) } #endif ssl->bFlags = 0; /* Reset buffer control */ + +#ifdef USE_X509 + ssl->bFlags |= bFlagsToKeep; +#endif } #ifdef USE_CERT_VALIDATE @@ -3427,6 +3623,28 @@ int32 matrixValidateCertsExt(psPool_t *pool, psX509Cert_t *subjectCerts, } *foundIssuer = NULL; + + if (opts->flags & VCERTS_FLAG_REVALIDATE_DATES) + { + sc = subjectCerts; + while(sc) + { + rc = validateDateRange(sc); + if (rc < 0) + { + psTraceCrypto("Could not parse certificate date\n"); + return PS_PARSE_FAIL; + } + if (sc->authFailFlags & PS_CERT_AUTH_FAIL_DATE_FLAG) + { + psTraceCrypto("Certificate date validation failed\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_EXTENSION; + return PS_CERT_AUTH_FAIL_EXTENSION; + } + sc = sc->next; + } + } + /* Case #1 is no issuing cert. Going to want to check that the final subject cert presented is a SelfSigned CA @@ -3530,6 +3748,23 @@ int32 matrixValidateCertsExt(psPool_t *pool, psX509Cert_t *subjectCerts, } } + if (opts->flags & VCERTS_FLAG_REVALIDATE_DATES) + { + /* Re-validate the date of the issuer cert also. */ + rc = validateDateRange(ic); + if (rc < 0) + { + psTraceCrypto("Could not parse certificate date\n"); + return PS_PARSE_FAIL; + } + if (ic->authFailFlags & PS_CERT_AUTH_FAIL_DATE_FLAG) + { + psTraceCrypto("Issuer cert out of date\n"); + sc->authStatus = PS_CERT_AUTH_FAIL_EXTENSION; + return PS_CERT_AUTH_FAIL_EXTENSION; + } + } + /* Validate extensions of leaf certificate */ ext = &subjectCerts->extensions; diff --git a/matrixssl/matrixsslApi.c b/matrixssl/matrixsslApi.c index dc1bab7..1a8c83d 100644 --- a/matrixssl/matrixsslApi.c +++ b/matrixssl/matrixsslApi.c @@ -327,6 +327,86 @@ int32_t matrixSslGetEapFastSKS(const ssl_t *ssl, } # endif /* USE_EAP_FAST */ +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING +int32_t matrixSslNeedClientCert(ssl_t *ssl) +{ + if (ssl->extClientCertKeyStateFlags == + EXT_CLIENT_CERT_KEY_STATE_WAIT_FOR_CERT_KEY_UPDATE) + { + return PS_TRUE; + } + else + { + return PS_FALSE; + } +} +int32_t matrixSslNeedClientPrivKey(ssl_t *ssl) +{ + if (ssl->extClientCertKeyStateFlags == + EXT_CLIENT_CERT_KEY_STATE_WAIT_FOR_CERT_KEY_UPDATE) + { +# ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING + /* + Not going to need priv key loading when we are signing + the CertificateVerify message externally - we won't need + direct access to the priv key in that case. + */ + if (matrixSslNeedCvSignature(ssl)) + { + return PS_FALSE; + } +# endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */ + return PS_TRUE; + } + else + { + return PS_FALSE; + } +} +int32_t matrixSslClientCertUpdated(ssl_t *ssl) +{ + if (ssl->extClientCertKeyStateFlags != + EXT_CLIENT_CERT_KEY_STATE_WAIT_FOR_CERT_KEY_UPDATE) + { + psTraceInfo("Error: wrong state for client cert update\n"); + return PS_FALSE; + } + else + { + ssl->extClientCertKeyStateFlags = + EXT_CLIENT_CERT_KEY_STATE_GOT_CERT_KEY_UPDATE; + /* + We will assume the client has loaded a cert that is + compatible with the server's expectations. + By-pass MatrixSSL checks. + */ + /**/ + if (ssl->keys && ssl->keys->cert) + { + ssl->sec.certMatch = 1; + } + + return PS_TRUE; + } +} + +int32_t matrixSslClientPrivKeyUpdated(ssl_t *ssl) +{ + if (ssl->extClientCertKeyStateFlags != + EXT_CLIENT_CERT_KEY_STATE_WAIT_FOR_CERT_KEY_UPDATE) + { + psTraceInfo("Error: wrong state for client key update\n"); + return PS_FALSE; + } + else + { + ssl->extClientCertKeyStateFlags = + EXT_CLIENT_CERT_KEY_STATE_GOT_CERT_KEY_UPDATE; + return PS_TRUE; + } +} +# endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ + # ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING int32_t matrixSslNeedCvSignature(ssl_t *ssl) { @@ -525,6 +605,7 @@ int32 matrixSslNewServerSession(ssl_t **ssl, const sslKeys_t *keys, sslSessOpts_t *options) { ssl_t *lssl; + int32 providedVersionFlag; if (!ssl) { @@ -535,6 +616,8 @@ int32 matrixSslNewServerSession(ssl_t **ssl, const sslKeys_t *keys, return PS_ARG_FAIL; } + providedVersionFlag = options->versionFlag; + /* Add SERVER_FLAGS to versionFlag member of options */ options->versionFlag |= SSL_FLAGS_SERVER; *ssl = NULL; @@ -562,6 +645,29 @@ int32 matrixSslNewServerSession(ssl_t **ssl, const sslKeys_t *keys, } # endif /* USE_CLIENT_AUTH */ + /* + Server-specific options that can be used to restrict the + supported protocol version range. These are only applicable + when the library user did not set any specific version to + versionFlag. + */ +# if defined(USE_TLS_1_2_TOGGLE) || defined(USE_TLS_1_0_TOGGLE) + if (providedVersionFlag == 0) + { +# ifdef USE_TLS_1_2_TOGGLE + if (options->serverDisableTls1_2) + { + lssl->disable_tls_1_2 = PS_TRUE; + } +# endif +# ifdef USE_TLS_1_0_TOGGLE + if (options->disableTls1_0) + { + lssl->disable_tls_1_0 = PS_TRUE; + } +# endif + } +# endif /* USE_TLS_1_2_TOGGLE || USE_TLS_1_0_TOGGLE */ /* For the server, ssl->expectedName can only be populated with the server name parsed from the Server Name Indication @@ -1188,6 +1294,13 @@ DECODE_MORE: decodeRet = matrixSslDecode(ssl, &buf, &len, size, &start, &reqLen, &decodeErr, &alertLevel, &alertDesc); +#if defined(USE_HARDWARE_CRYPTO_RECORD) || defined(USE_HARDWARE_CRYPTO_PKA) || defined(USE_EXT_CLIENT_CERT_KEY_LOADING) + if (decodeRet == PS_PENDING || decodeRet == PS_EAGAIN) + { + return decodeRet; + } +HW_ASYNC_RESUME: +#endif /* Convenience for the cases that expect buf to have moved - calculate the number of encoded bytes that were decoded diff --git a/matrixssl/matrixsslApi.h b/matrixssl/matrixsslApi.h index 28c672f..b18d01f 100644 --- a/matrixssl/matrixsslApi.h +++ b/matrixssl/matrixsslApi.h @@ -128,7 +128,7 @@ PSPUBLIC int32 matrixSslLoadPkcs12(sslKeys_t *keys, const unsigned char *importPass, int32 ipasslen, const unsigned char *macPass, int32 mpasslen, int32 flags); -# if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +# if defined(USE_OCSP_RESPONSE) && defined(USE_SERVER_SIDE_SSL) PSPUBLIC int32_t matrixSslLoadOCSPResponse(sslKeys_t *keys, const unsigned char *OCSPResponseBuf, psSize_t OCSPResponseBufLen); @@ -157,6 +157,9 @@ PSPUBLIC int32 matrixSslProcessedData(ssl_t *ssl, PSPUBLIC int32 matrixSslEncodeClosureAlert(ssl_t *ssl); PSPUBLIC void matrixSslDeleteSession(ssl_t *ssl); +PSPUBLIC psBool_t matrixSslTlsVersionRangeSupported(int32_t low, + int32_t high); + /******************************************************************************/ /* Advanced feature public APIS @@ -192,6 +195,8 @@ PSPUBLIC int32 matrixSslLoadHelloExtension(tlsExtension_t *extension, PSPUBLIC void matrixSslDeleteHelloExtension(tlsExtension_t *extension); PSPUBLIC int32 matrixSslCreateSNIext(psPool_t *pool, unsigned char *host, int32 hostLen, unsigned char **extOut, int32 *extLen); +PSPUBLIC int32_t matrixSslSessOptsSetClientTlsVersionRange(sslSessOpts_t *options, + int32_t low, int32_t high); # ifdef USE_ALPN PSPUBLIC int32 matrixSslCreateALPNext(psPool_t *pool, int32 protoCount, unsigned char *proto[], int32 protoLen[], @@ -311,6 +316,33 @@ PSPUBLIC int32_t matrixSslGetPubKeySize(ssl_t *ssl); */ PSPUBLIC int32_t matrixSslSetCvSignature(ssl_t *ssl, const unsigned char *sig, const size_t sig_len); # endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */ + +#ifdef USE_EXT_CLIENT_CERT_KEY_LOADING +/* + Note: these flags, stored in ssl->extClientCertKeyStateFlags, + define the state of the "external client cert loading + feature". These are mutually exclusive, except + for GOT_CERTIFICATE_REQUEST and GOT_SERVER_HELLO_DONE. + This is because we try to prepare for the case where + these HS messages are decoded in different calls to + matrixSslReceivedData. +*/ +#define EXT_CLIENT_CERT_KEY_STATE_INIT 0 +#define EXT_CLIENT_CERT_KEY_STATE_GOT_CERTIFICATE_REQUEST 1 +#define EXT_CLIENT_CERT_KEY_STATE_GOT_SERVER_HELLO_DONE 2 +#define EXT_CLIENT_CERT_KEY_STATE_WAIT_FOR_CERT_KEY_UPDATE 4 +#define EXT_CLIENT_CERT_KEY_STATE_GOT_CERT_KEY_UPDATE 8 + +/** Returns PS_TRUE when the client program should load a new client cert. */ +PSPUBLIC int32_t matrixSslNeedClientCert(ssl_t *ssl); + +/** Returns PS_TRUE when the client program should load a new priv key. */ +PSPUBLIC int32_t matrixSslNeedClientPrivKey(ssl_t *ssl); + +/** Client program should call these after updating ssl->keys. */ +PSPUBLIC int32_t matrixSslClientCertUpdated(ssl_t *ssl); +PSPUBLIC int32_t matrixSslClientPrivKeyUpdated(ssl_t *ssl); +#endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ # endif /* USE_CLIENT_SIDE_SSL */ /******************************************************************************/ @@ -326,6 +358,8 @@ PSPUBLIC int32_t matrixSslNewServer(ssl_t **ssl, sslSessOpts_t *options); PSPUBLIC int32 matrixSslSetCipherSuiteEnabledStatus(ssl_t *ssl, psCipher16_t cipherId, uint32 status); +PSPUBLIC int32_t matrixSslSessOptsSetServerTlsVersionRange(sslSessOpts_t *options, + int32_t low, int32_t high); PSPUBLIC void matrixSslRegisterSNICallback(ssl_t *ssl, void (*sni_cb)(void *ssl, char *hostname, int32 hostnameLen, sslKeys_t **newKeys)); diff --git a/matrixssl/matrixsslCheck.h b/matrixssl/matrixsslCheck.h index 386a47d..05c19c9 100644 --- a/matrixssl/matrixsslCheck.h +++ b/matrixssl/matrixsslCheck.h @@ -66,6 +66,29 @@ extern "C" { # endif # endif +/* + Convenience macros for finding out minimum and maximum enabled TLS version. +*/ +# if defined(USE_TLS_1_2) && !defined(DISABLE_TLS_1_2) +# define MAX_ENABLED_TLS_VER TLS_1_2_MIN_VER +# elif defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1) +# define MAX_ENABLED_TLS_VER TLS_1_1_MIN_VER +# elif defined(USE_TLS) && !defined(DISABLE_TLS_1_0) +# define MAX_ENABLED_TLS_VER TLS_MIN_VER +# elif !defined(DISABLE_SSLV3) +# define MAX_ENABLED_TLS_VER SSL3_MIN_VER +# endif + +# if !defined(DISABLE_SSLV3) +# define MIN_ENABLED_TLS_VER SSL3_MIN_VER +# elif defined(USE_TLS) && !defined(DISABLE_TLS_1_0) +# define MIN_ENABLED_TLS_VER TLS_MIN_VER +# elif defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1) +# define MIN_ENABLED_TLS_VER TLS_1_1_MIN_VER +# elif defined(USE_TLS_1_2) && !defined(DISABLE_TLS_1_2) +# define MIN_ENABLED_TLS_VER TLS_1_2_MIN_VER +# endif + # ifdef USE_SHARED_SESSION_CACHE # ifndef POSIX # error "USE_SHARED_SESSION_CACHE only implemented for POSIX platforms." @@ -244,8 +267,8 @@ extern "C" { # endif # ifdef USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -# ifndef USE_CHACHA20_POLY1305 -# error "Enable USE_CHACHA20_POLY1305 in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" +# ifndef USE_CHACHA20_POLY1305_IETF +# error "Enable USE_CHACHA20_POLY1305_IETF in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" # endif # ifndef USE_ECC # error "Enable USE_ECC in cryptoConfig.h for USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" @@ -253,15 +276,15 @@ extern "C" { # define USE_DHE_CIPHER_SUITE # define USE_ECDSA_CIPHER_SUITE # define USE_ECC_CIPHER_SUITE -# define USE_CHACHA20_POLY1305_CIPHER_SUITE +# define USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE # endif # ifdef USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 # ifndef USE_RSA # error "Enable USE_RSA in cryptoConfig.h for USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" # endif -# ifndef USE_CHACHA20_POLY1305 -# error "Enable USE_CHACHA20_POLY1305 in cryptoConfig.h for USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" +# ifndef USE_CHACHA20_POLY1305_IETF +# error "Enable USE_CHACHA20_POLY1305_IETF in cryptoConfig.h for USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" # endif # ifndef USE_ECC # error "Enable USE_ECC in cryptoConfig.h for USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" @@ -269,7 +292,7 @@ extern "C" { # define USE_DHE_CIPHER_SUITE # define USE_RSA_CIPHER_SUITE # define USE_ECC_CIPHER_SUITE -# define USE_CHACHA20_POLY1305_CIPHER_SUITE +# define USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE # endif # ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 diff --git a/matrixssl/matrixsslNet.c b/matrixssl/matrixsslNet.c index 66fe0fc..abfd3e6 100644 --- a/matrixssl/matrixsslNet.c +++ b/matrixssl/matrixsslNet.c @@ -22,17 +22,30 @@ # include # include # include +# include "core/psUtil.h" + +# ifndef MATRIXSSL_INTERACT_READBUF_SIZE +# define MATRIXSSL_INTERACT_READBUF_SIZE (1024 * 18) +# endif # ifndef MATRIXSSL_INTERACT_MAX_TRANSFER # define MATRIXSSL_INTERACT_MAX_TRANSFER 64000 # endif # ifdef USE_MATRIX_NET_DEBUG +# include # define MATRIXSSL_NET_DEBUGF(...) printf(__VA_ARGS__) # else # define MATRIXSSL_NET_DEBUGF(...) do {} while (0) # endif +/* Defines for constants of TLS record format. + These are needed when readahead mode is turned off. */ +#define MSI_TLS_REC_LEN 5 /* Record length of TLS. + 1 * type, 2 * version, 2 * content length. */ +#define MSI_TLS_REC_CONTENT_LEN_HIGH 3 /* Offset from beginning. */ +#define MSI_TLS_REC_CONTENT_LEN_LOW 4 /* Offset from beginning. */ +#define MSI_TLS_MAX_CONTENT_LEN (16384 + 2048) /* See RFC 5246. */ void matrixSslInteractBegin(matrixSslInteract_t *i, ssl_t *ssl, psSocket_t *sock) @@ -45,6 +58,153 @@ void matrixSslInteractBegin(matrixSslInteract_t *i, ssl_t *ssl, i->handshake_complete = PS_FALSE; } +/* Adjust amount to read according to record header size or + record size if in no read-ahead mode. */ +static +int32 +matrixSslInteractBeforeSocketRead(matrixSslInteract_t *i, int32 len) +{ + if (!i->no_readahead) + { + /* No adjustment appropriate, just read input as much as possible. */ + return len; + } + else + { + /* Adjust amount of input to read to hold either record header or + record content. */ + + if (i->rechdrlen < MSI_TLS_REC_LEN) + { + /* Reading record header: read at the most missing part of + 5 header bytes, less if read buffer is too small + (should not happen). */ + i->hdrread = 1; + return PS_MIN(len, MSI_TLS_REC_LEN - i->rechdrlen); + } + + if (i->recleft > 0) + { + /* Constrain amount of bytes to process according to the record + length left. */ + return PS_MIN(i->recleft, len); + } + } + + /* Fallback: The rechdrlen or recleft is not set properly. + We fallback to process the input just as if readahead was not set. + Then core of MatrixSSL will decide how to deal with the packet. + */ + return len; +} + +/* Process result of socket read. */ +static +void +matrixSslInteractAfterSocketRead(matrixSslInteract_t *i, + const unsigned char *buf, int32 transferred) +{ + i->recvretry = 0; /* Typically: do not retry after receive. */ + + if (transferred <= 0) + { + return; /* No data available. */ + } + + if (i->no_readahead) + { + if (i->hdrread) + { + /* The request was for reading record header. + Process record header. */ + i->hdrread = 0; + + /* Keep a copy of the record header inside matrixsslNet. + We use this private copy to determine record length. */ + memcpy(i->rechdr + i->rechdrlen, buf, transferred); + i->rechdrlen += transferred; + + if (i->rechdrlen == MSI_TLS_REC_LEN) + { + int32 reclen; + + /* Interpret record length (the record type and the TLS version + are ignored here.) */ + reclen = i->rechdr[MSI_TLS_REC_CONTENT_LEN_HIGH] << 8; + reclen |= i->rechdr[MSI_TLS_REC_CONTENT_LEN_LOW]; + + /* Check we do not read beyond TLS maximal encrypted record + length. */ + if (reclen <= MSI_TLS_MAX_CONTENT_LEN && reclen != 0) + { + /* We have received record header that is of a valid + size. We constrain amount of data to transfer + with the next transfer to the record size. */ + if (i->recleft == 0) + { + i->recleft = reclen; + i->recvretry = 1; /* After providing the record + header bytes to matrixssl, + continue with the read for record + content. */ + MATRIXSSL_NET_DEBUGF( + "Parsed record header: need to read %u " + "bytes of record content.\n", + (unsigned) reclen); + return; + } + } + } + else + { + /* Full record header not received yet. */ + } + } + + if (i->no_readahead && i->recleft) + { + psAssert(transferred <= i->recleft); + i->recleft -= (uint32_t) transferred; + if (i->recleft == 0) + { + /* Entire record received => + Coming up next: read a record header again. + Set length of record header read to 0. */ + i->rechdrlen = 0; + } + } + } +} + +/* Check if we should retry receive. */ +static +psBool_t +matrixSslInteractSocketReadRetry(matrixSslInteract_t *i, int32 rc) +{ + if (i->recvretry) + { + /* We have performed partial read for record header, and + we should retry the reading in case MatrixSSL agrees + there is a partial record. */ + if (rc == MATRIXSSL_REQUEST_RECV) + { + /* We have read a record header and passed it to MatrixSSL. + MatrixSSL returned that it needs to receive more bytes. + In this case we will read the record itself, + without returning MATRIXSSL_REQUEST_RECV. + */ + + i->recvretry = 0; /* Mark we do not do retry again. */ + MATRIXSSL_NET_DEBUGF("Record header read. Repeating " + "receive for record content (%d bytes)" + "\n", + (int) i->recleft); + return true; + } + } + return false; /* Common case: no read retry. */ +} + static int32 matrixSslInteractGotData(matrixSslInteract_t *i, int32 rc) { /* Cook the received data from behalf of caller. @@ -78,12 +238,14 @@ static int32 matrixSslInteractGotData(matrixSslInteract_t *i, int32 rc) } static -int32 matrixSslInteractInt(matrixSslInteract_t *i, - int can_send, int can_receive) +int32 matrixSslInteractInt3(matrixSslInteract_t *i, + int can_send, int can_receive, + int can_receive_local) { ssize_t transferred; unsigned char *buf; int32 rc; + uint32_t transferlen; # ifdef USE_MATRIX_NET_DEBUG int block = 1; @@ -95,8 +257,9 @@ int32 matrixSslInteractInt(matrixSslInteract_t *i, uint32_t len = i->receive_len; buf = i->receive_buf - len; + again_zero_app_data: rc = matrixSslProcessedData(i->ssl, &buf, &len); - if (buf != NULL || len != 0) + if (buf != NULL && len != 0) { MATRIXSSL_NET_DEBUGF("processed some data, but pending processing:\n" "rc=%d buf=%p len=%u\n", @@ -107,26 +270,45 @@ int32 matrixSslInteractInt(matrixSslInteract_t *i, i->receive_buf = buf; i->receive_len = len; i->receive_len_left = len; - return matrixSslInteractGotData(i, rc); + rc = matrixSslInteractGotData(i, rc); + if (i->send_close_notify == false) + { + return rc; + } } else { return PS_FAILURE; } } + if (rc == MATRIXSSL_APP_DATA && len == 0) + { + MATRIXSSL_NET_DEBUGF("ignored zero length APP data\n"); + goto again_zero_app_data; + } /* Mark buffer as processed. */ i->receive_buf = NULL; i->receive_len = 0; i->receive_len_left = 0; MATRIXSSL_NET_DEBUGF("Acked processed data, got: rc=%d\n", rc); - return rc; + if (i->send_close_notify == false && rc != MATRIXSSL_REQUEST_RECV) + { + return rc; + } } - else if (can_receive && i->receive_buf && i->receive_len_left > 0) + else if (can_receive_local && i->receive_buf && i->receive_len_left > 0) { MATRIXSSL_NET_DEBUGF("Signal more data ready for reading.\n"); /* Maybe there is remaining application data? */ rc = MATRIXSSL_APP_DATA; - return rc; + if (matrixSslHandshakeIsComplete(i->ssl)) + { + i->handshake_complete = PS_TRUE; + } + if (i->send_close_notify == false) + { + return rc; + } } if (can_send && i->send_len_left == 0) @@ -153,12 +335,21 @@ int32 matrixSslInteractInt(matrixSslInteract_t *i, i->sock, buf, len < MATRIXSSL_INTERACT_MAX_TRANSFER ? len : MATRIXSSL_INTERACT_MAX_TRANSFER, 0); + if (transferred == PS_EAGAIN) + { + return MATRIXSSL_REQUEST_SEND; + } if (transferred < 0) { return PS_PLATFORM_FAIL; } MATRIXSSL_NET_DEBUGF("Sent%s: %d bytes\n", block ? " cont" : "", (int) transferred); + if (i->send_close_notify) + { + MATRIXSSL_NET_DEBUGF("Successfully sent close_notify\n"); + i->send_close_notify = PS_FALSE; + } i->send_buf += transferred; i->send_len_left -= transferred; if (i->send_len_left > 0) @@ -170,6 +361,33 @@ int32 matrixSslInteractInt(matrixSslInteract_t *i, rc == MATRIXSSL_HANDSHAKE_COMPLETE || rc == MATRIXSSL_REQUEST_SEND) { + if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) + { +#ifdef ENABLE_FALSE_START + /* If false start is enabled, there may be + some data from client received during + handshake. Query for such data. */ + unsigned char *buf = NULL; + uint32_t len = 0; + i->handshake_complete = PS_TRUE; + rc = matrixSslReceivedData(i->ssl, 0, &buf, &len); + while(rc == MATRIXSSL_APP_DATA && len == 0) + { + MATRIXSSL_NET_DEBUGF("Ignored zero length false start data record"); + rc = matrixSslProcessedData(i->ssl, &buf, &len); + } + if (rc == MATRIXSSL_APP_DATA && len > 0) + { + MATRIXSSL_NET_DEBUGF("Received false start data (%u bytes)", + (unsigned) len); + i->receive_buf = buf; + i->receive_len = len; + i->receive_len_left = len; + return MATRIXSSL_HANDSHAKE_COMPLETE; + } +#endif /* ENABLE_FALSE_START */ + return MATRIXSSL_HANDSHAKE_COMPLETE; + } return rc; } } @@ -180,12 +398,34 @@ int32 matrixSslInteractInt(matrixSslInteract_t *i, if (can_receive) { int32 len; + + receive_repeat: +# ifdef MATRIXSSL_INTERACT_READBUF_SIZE + /* Use MatrixsslNet's read buffer size. */ + len = matrixSslGetReadbufOfSize(i->ssl, + MATRIXSSL_INTERACT_READBUF_SIZE, + &buf); +# else + /* Use standard buffer size (usually SSL_DEFAULT_IN_BUF_SIZE). */ len = matrixSslGetReadbuf(i->ssl, &buf); +#endif if (len <= 0) { return PS_PLATFORM_FAIL; } - transferred = (int32) psSocketReadData(i->sock, buf, len, 0); + + /* Read from socket, either up-to full read buffer, or + record header or record content size if in no_readahead mode. */ + transferlen = matrixSslInteractBeforeSocketRead(i, len); + MATRIXSSL_NET_DEBUGF("Reading input from socket, up-to %u bytes%s\n", + (unsigned) transferlen, + i->hdrread ? + " (the record header)" : + (i->recleft > 0 ? + " (the remaining part of a record)" : "")); + transferred = (int32) psSocketReadData(i->sock, buf, transferlen, 0); + matrixSslInteractAfterSocketRead(i, buf, transferred); + if (transferred >= 0) { MATRIXSSL_NET_DEBUGF("Received from peer %d bytes\n", @@ -196,6 +436,15 @@ int32 matrixSslInteractInt(matrixSslInteract_t *i, rc = matrixSslReceivedData(i->ssl, (int32) transferred, &buf, (uint32 *) &len); + + /* Check if there are more read operations to perform. */ + if (matrixSslInteractSocketReadRetry(i, rc)) + { + /* Clear transferred variable because we have handled + all bytes this far. */ + transferred = 0; + goto receive_repeat; + } if (rc == MATRIXSSL_APP_DATA || rc == MATRIXSSL_RECEIVED_ALERT) { @@ -208,6 +457,15 @@ int32 matrixSslInteractInt(matrixSslInteract_t *i, { return PS_PLATFORM_FAIL; /* Unsupported. */ } +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + if (rc == PS_PENDING && matrixSslNeedClientCert(i->ssl)) + { + i->num_last_read_transferred = transferred; + MATRIXSSL_NET_DEBUGF("Client cert needed in response to " \ + "CertificateRequest. Returning PS_PENDING\n"); + return PS_PENDING; + } +# endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ } else if (transferred == 0) { @@ -215,7 +473,15 @@ int32 matrixSslInteractInt(matrixSslInteract_t *i, MATRIXSSL_NET_DEBUGF("Connection cut off.\n"); return MATRIXSSL_NET_DISCONNECTED; } - else if (rc < 0) + else if (transferred == PS_EAGAIN) + { + return PS_SUCCESS; /* This operation ok, but more data needed. */ + } + else if (transferred == PS_MEM_FAIL) + { + return PS_MEM_FAIL; + } + else if (transferred < 0) { return PS_PLATFORM_FAIL; } @@ -223,11 +489,43 @@ int32 matrixSslInteractInt(matrixSslInteract_t *i, return rc; } +static +psBool_t handshake_is_complete(matrixSslInteract_t *i) +{ +#ifdef ENABLE_SECURE_REHANDSHAKES + if (matrixSslRehandshaking(i->ssl)) + { + return PS_FALSE; + } +#endif + return i->handshake_complete; +} + int32 matrixSslInteract(matrixSslInteract_t *i, int can_send, int can_receive) { - int32 rc = matrixSslInteractInt(i, can_send, can_receive); + int32 rc = matrixSslInteractInt3(i, can_send, can_receive, can_receive); - if (rc == PS_SUCCESS && i->handshake_complete == PS_FALSE) + if (rc == PS_SUCCESS && !handshake_is_complete(i)) + { + /* If handshaking, guide the caller to wait reading. */ + rc = MATRIXSSL_REQUEST_RECV; + } + else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) + { + i->handshake_complete = PS_TRUE; + } + i->prev_rc = rc; + return rc; +} + +int32 matrixSslInteract3(matrixSslInteract_t *i, + int can_send_net, int can_receive_net, + int can_receive_local) +{ + int32 rc = matrixSslInteractInt3(i, can_send_net, can_receive_net, + can_receive_local); + + if (rc == PS_SUCCESS && !handshake_is_complete(i)) { /* If handshaking, guide the caller to wait reading. */ rc = MATRIXSSL_REQUEST_RECV; @@ -245,7 +543,7 @@ int32 matrixSslInteractHandshake(matrixSslInteract_t *i, { int32 rc = PS_SUCCESS; - while (i->handshake_complete == PS_FALSE && rc == PS_SUCCESS) + while (rc == PS_SUCCESS && !handshake_is_complete(i)) { rc = matrixSslInteract(i, can_send, can_receive); if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) @@ -264,6 +562,7 @@ int32 matrixSslInteractRead(matrixSslInteract_t *i, unsigned char *target, size_t max_length) { + size_t total_read = 0; size_t real = matrixSslInteractReadLeft(i); if (real > max_length) @@ -277,16 +576,21 @@ int32 matrixSslInteractRead(matrixSslInteract_t *i, memcpy(target, i->receive_buf, real); i->receive_buf += real; i->receive_len_left -= real; + total_read = real; + if (i->receive_buf && i->receive_len_left == 0) { - MATRIXSSL_NET_DEBUGF("All app data read. Will ack soon.\n"); + MATRIXSSL_NET_DEBUGF("Read single record (last_part_len=%d).\n", + (int) total_read); } else if (i->receive_buf) { - MATRIXSSL_NET_DEBUGF("Remaining application data: %d bytes\n", - (int) i->receive_len_left); + MATRIXSSL_NET_DEBUGF("Remaining application data: %d bytes " + "(this_part_len=%d)\n", + (int) i->receive_len_left, + (int) total_read); } - return real; + return total_read; } int32 matrixSslInteractPeek(matrixSslInteract_t *i, unsigned char *target, @@ -307,42 +611,53 @@ int32 matrixSslInteractPeek(matrixSslInteract_t *i, } int32 matrixSslInteractWrite(matrixSslInteract_t *i, const unsigned char *target, - size_t length) + size_t in_len) { unsigned char *buf; + int32 bytesToEncrypt; int32 rc; - int32 rc2; - int32 len; + int32 out_len; - rc = matrixSslGetWritebuf(i->ssl, &buf, length); + rc = matrixSslGetWritebuf(i->ssl, &buf, in_len); if (rc <= 0) { return rc; } - if (rc > length) + bytesToEncrypt = rc; + if (bytesToEncrypt > in_len) { - rc = length; + bytesToEncrypt = in_len; } - memcpy(buf, target, rc); - length -= (size_t) rc; - rc2 = matrixSslEncodeWritebuf(i->ssl, rc); - if (rc2 < 0) + memcpy(buf, target, bytesToEncrypt); + + /* Encrypt. */ + rc = matrixSslEncodeWritebuf(i->ssl, bytesToEncrypt); + if (rc < 0) { - MATRIXSSL_NET_DEBUGF("couldn't encode data %d\n", rc2); - return rc2; + MATRIXSSL_NET_DEBUGF("couldn't encode data %d\n", rc); + return rc; } + if (i->send_len_left == 0) { - len = matrixSslGetOutdata(i->ssl, &buf); - if (len > 0) + /* Encode into TLS records. */ + out_len = matrixSslGetOutdata(i->ssl, &buf); + if (out_len > 0) { - MATRIXSSL_NET_DEBUGF("To be sent: %d bytes (for %d bytes)\n", - (int) len, (int) length); + MATRIXSSL_NET_DEBUGF("matrixSslInteractWrite: " \ + "%d plaintext bytes (from a total of %zu) " \ + "encoded into %d bytes\n", + bytesToEncrypt, in_len, out_len); i->send_buf = buf; - i->send_len_left = i->send_len = len; + i->send_len_left = i->send_len = out_len; } - rc = len; + rc = out_len; } + + /* Store how many plaintext bytes we were able to encrypt + and encode. Caller can use this to measure progress. */ + i->last_encoded_pt_bytes = bytesToEncrypt; + return rc; } @@ -370,11 +685,13 @@ int32 matrixSslInteractSendCloseNotify(matrixSslInteract_t *i) ssl_t *ssl; int32 rc; + MATRIXSSL_NET_DEBUGF("Sending connection closure alert.\n"); ssl = i->ssl; rc = matrixSslEncodeClosureAlert(ssl); if (rc >= 0) { - rc = matrixSslInteract(i, PS_TRUE, PS_FALSE); + i->send_close_notify = PS_TRUE; + rc = matrixSslInteract3(i, PS_TRUE, PS_FALSE, PS_TRUE); if (rc < 0) { return rc; @@ -474,6 +791,15 @@ int32 matrixSslInteractBeginAccept(matrixSslInteract_t *msi_p, } # endif /* USE_SERVER_SIDE_SSL */ +void matrixSslInteractSetReadahead(matrixSslInteract_t *i, + psBool_t readahead_on) +{ + if (i) + { + i->no_readahead = !readahead_on; + } +} + #endif /* USE_PS_NETWORKING */ /* end of file matrixsslNet.c */ diff --git a/matrixssl/matrixsslNet.h b/matrixssl/matrixsslNet.h index 94ab310..68996b2 100644 --- a/matrixssl/matrixsslNet.h +++ b/matrixssl/matrixsslNet.h @@ -36,13 +36,32 @@ typedef struct matrixSslInteract size_t receive_len_left; unsigned char ch2[2]; int32 prev_rc; + int32 last_encoded_pt_bytes; psBool_t handshake_complete; + psBool_t send_close_notify; + /* State variables for processing input as TLS records. */ + psBool_t no_readahead; /* read all input (false) or TLS records (true). */ + unsigned int recleft; /* bytes left in record. */ + unsigned char rechdr[5]; /* The latest received record header. */ + unsigned char rechdrlen; /* The length of the latest received + record header. */ + unsigned char hdrread; /* Reading record header bytes. */ + unsigned char recvretry; /* Should retry receive, with record content. */ +#ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + /* Need this for the extra call to matrixSslReceivedData, + to be performed after new client cert and key have been + loaded. */ + size_t num_last_read_transferred; +#endif } matrixSslInteract_t; /* Lower-level API for interacting with MatrixSSL API. */ void matrixSslInteractBegin(matrixSslInteract_t *i, ssl_t *ssl, psSocket_t *sock); int32 matrixSslInteract(matrixSslInteract_t *i, int can_send, int can_receive); +int32 matrixSslInteract3(matrixSslInteract_t *i, + int can_send_net, int can_receive_net, + int can_receive_local); int32 matrixSslInteractHandshake(matrixSslInteract_t *i, int can_send, int can_receive); size_t matrixSslInteractReadLeft(matrixSslInteract_t *i); @@ -59,6 +78,9 @@ void matrixSslInteractClose(matrixSslInteract_t *i); void matrixSslInteractCloseErr(matrixSslInteract_t *i, int32 status); int32 matrixSslInteractSendCloseNotify(matrixSslInteract_t *i); int32 matrixSslInteractReceiveCloseNotify(matrixSslInteract_t *i); +void matrixSslInteractSetReadahead(matrixSslInteract_t *i, + psBool_t readahead_on); + # ifdef USE_CLIENT_SIDE_SSL int32 matrixSslInteractBeginConnected(matrixSslInteract_t *msi_p, const char *hostname, const char *port, diff --git a/matrixssl/matrixsslSocket.c b/matrixssl/matrixsslSocket.c index 6a1f4fc..7635689 100644 --- a/matrixssl/matrixsslSocket.c +++ b/matrixssl/matrixsslSocket.c @@ -47,13 +47,13 @@ static const psCipher16_t cipherlist_default[] = { 47 }; # define logMessage(l, t, ...) do { printf(#l " " #t ": " __VA_ARGS__); printf("\n"); } while (0) /* Log_Verbose, TAG, "Wrote %d bytes", transferred */ +# ifdef USE_CLIENT_SIDE_SSL /* The MatrixSSL certificate validation callback. */ static int32 ssl_cert_auth_default(ssl_t *ssl, psX509Cert_t *cert, int32 alert) { return MATRIXSSL_SUCCESS; } -# ifdef USE_CLIENT_SIDE_SSL static int32 extensionCb(ssl_t *ssl, uint16_t extType, uint8_t extLen, void *e) { if (extType == EXT_SNI) diff --git a/matrixssl/matrixssllib.h b/matrixssl/matrixssllib.h index f98504b..a1b57eb 100644 --- a/matrixssl/matrixssllib.h +++ b/matrixssl/matrixssllib.h @@ -70,17 +70,21 @@ extern "C" { /* #define USE_SSL_RSA_WITH_NULL_MD5 / **< @security OFF * / */ /** - False Start support for Chrome browser. - @see http://tools.ietf.org/html/draft-bmoeller-tls-falsestart-00 + False Start support for Chrome and Firefox browsers. + @see https://tools.ietf.org/html/rfc7918 + + Some versions of Firefox browser and Chrome browser include support for + False Start. This flag will enable server side support on MatrixSSL + operating as server for client using false start feature. @note April 2012: Google has announced this feature will be removed in version 20 of their browser due to industry compatibility issues. - - @note November 2017: An official IETF draft is in process for this - functionality to become standardized. - @see https://datatracker.ietf.org/doc/draft-ietf-tls-falsestart/ + However because there are other browsers using the feature, this feature + is often recommendable to enable for maximal browser compatibility. */ -/* #define ENABLE_FALSE_START / **< @security OFF * / */ +#ifdef USE_SERVER_SIDE_FALSE_START_SUPPORT +#define ENABLE_FALSE_START +#endif /* USE_SERRVER_SIDE_FALSE_START_SUPPORT */ /** zlib compression support. @@ -210,6 +214,13 @@ extern "C" { # define DISABLE_SSLV3 /**< DO NOT DISABLE, undef below if required @security NIST_SHALL_NOT */ +# ifndef NO_TLS_1_2_TOGGLE +# define USE_TLS_1_2_TOGGLE /**< Allow disabling TLS 1.2 dynamically. */ +# endif + # ifndef NO_TLS_1_0_TOGGLE +# define USE_TLS_1_0_TOGGLE /**< Allow disabling TLS 1.0 dynamically. */ +# endif + # if defined USE_TLS_1_2_AND_ABOVE # define DISABLE_TLS_1_1 # define DISABLE_TLS_1_0 @@ -236,7 +247,7 @@ extern "C" { # include "zlib.h" # endif -# if defined(USE_AES_GCM) || defined(USE_AES_CCM) || defined(USE_CHACHA20_POLY1305) +# if defined(USE_AES_GCM) || defined(USE_AES_CCM) || defined(USE_CHACHA20_POLY1305_IETF) # define USE_AEAD_CIPHER # endif @@ -274,7 +285,7 @@ extern "C" { # define SSL_MAX_PLAINTEXT_LEN 0x4000 /* 16KB */ # define SSL_MAX_RECORD_LEN SSL_MAX_PLAINTEXT_LEN + 2048 # define SSL_MAX_BUF_SIZE SSL_MAX_RECORD_LEN + 0x5 -# define SSL_MAX_DISABLED_CIPHERS 8 +# define SSL_MAX_DISABLED_CIPHERS 32 /* Maximum buffer sizes for static SSL array types */ @@ -308,18 +319,18 @@ extern "C" { # define DTLS_HEADER_ADD_LEN 8 # endif -# define TLS_CHACHA20_POLY1305_AAD_LEN 13 +# define TLS_CHACHA20_POLY1305_IETF_AAD_LEN 13 # define TLS_GCM_AAD_LEN 13 # define TLS_AEAD_SEQNB_LEN 8 # define TLS_GCM_TAG_LEN 16 -# define TLS_CHACHA20_POLY1305_TAG_LEN 16 +# define TLS_CHACHA20_POLY1305_IETF_TAG_LEN 16 # define TLS_CCM_TAG_LEN 16 # define TLS_CCM8_TAG_LEN 8 # define TLS_AEAD_NONCE_MAXLEN 12/* Maximum length for an AEAD's nonce */ # define TLS_EXPLICIT_NONCE_LEN 8 -# define TLS_CHACHA20_POLY1305_NONCE_LEN 0 +# define TLS_CHACHA20_POLY1305_IETF_NONCE_LEN 0 # define AEAD_NONCE_LEN(SSL) ((SSL->flags & SSL_FLAGS_NONCE_W) ? TLS_EXPLICIT_NONCE_LEN : 0) # define AEAD_TAG_LEN(SSL) ((SSL->cipher->flags & CRYPTO_FLAGS_CCM8) ? 8 : 16) @@ -429,6 +440,13 @@ extern "C" { # define BFLAG_KEEP_PEER_CERTS (1 << 3) /* Keep peer cert chain. */ # define BFLAG_KEEP_PEER_CERT_DER (1 << 4) /* Keep raw DER of peer certs. */ +enum PACKED +{ + tls_v_1_0 = 1, + tls_v_1_1 = 2, + tls_v_1_2 = 3 +}; + /* Number of bytes server must send before creating a re-handshake credit */ @@ -640,15 +658,9 @@ static __inline uint16_t HASH_SIG_MASK(uint8_t hash, uint8_t sig) # define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /* 49200 */ # define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */ # define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */ -# ifdef CHACHA20POLY1305_IETF /* Defined in https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305 */ # define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /* 52392 */ # define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /* 52393 */ -# else -/* Defined in https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305 */ -# define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCC13 /* 52243 */ -# define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCC14 /* 52244 */ -# endif /* Supported HELLO extensions @@ -723,37 +735,110 @@ typedef struct char *hsHeader; } dtlsFragHdr_t; -# ifndef USE_DTLS_DEBUG_TRACE -# define psTraceDtls(x) -# define psTraceIntDtls(x, y) -# define psTraceStrDtls(x, y) +# include "../core/psLog.h" +# ifdef PS_LOGF_COMMON +# define psTraceDtls(x) PS_LOGF_COMMON(Log_Trace, PS_DTLS, PS_LOGF_FMT, \ + PS_LOGF_FILELINE, "%s", x) +# define psTraceIntDtls(x, i) PS_LOGF_COMMON(Log_Trace, PS_DTLS, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, i) +# define psTraceStrDtls(x, s) PS_LOGF_COMMON(Log_Trace, PS_DTLS, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, s) +# define psTracePtrDtls(x, p) PS_LOGF_COMMON(Log_Trace, PS_DTLS, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, p) +# define psTracefDtls(x, ...) PS_LOGF_COMMON(Log_Trace, PS_DTLS, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, __VA_ARGS__) # else -# define psTraceDtls(x) _psTrace(x) -# define psTraceIntDtls(x, y) _psTraceInt(x, y) -# define psTraceStrDtls(x, y) _psTraceStr(x, y) -# endif /* USE_DTLS_DEBUG_TRACE */ +# ifndef USE_DTLS_DEBUG_TRACE +# define psTraceDtls(x) +# define psTraceIntDtls(x, y) +# define psTraceStrDtls(x, y) +# else +# define psTraceDtls(x) _psTrace(x) +# define psTraceIntDtls(x, y) _psTraceInt(x, y) +# define psTraceStrDtls(x, y) _psTraceStr(x, y) +# endif /* USE_DTLS_DEBUG_TRACE */ +# endif /* PS_LOGF_COMMON */ # endif /* USE_DTLS */ - -# ifndef USE_SSL_HANDSHAKE_MSG_TRACE -# define psTraceHs(x) -# define psTraceStrHs(x, y) +# ifdef PS_LOGF_COMMON +# define psTraceHs(x) PS_LOGF_COMMON(Log_Trace, PS_MATRIXSSL_HS, PS_LOGF_FMT, \ + PS_LOGF_FILELINE, "%s", x) +# define psTraceStrHs(x, s) PS_LOGF_COMMON(Log_Trace, PS_MATRIXSSL_HS, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, s) # else -# define psTraceHs(x) _psTrace(x) -# define psTraceStrHs(x, y) _psTraceStr(x, y) -# endif /* USE_SSL_HANDSHAKE_MSG_TRACE */ +# ifndef USE_SSL_HANDSHAKE_MSG_TRACE +# define psTraceHs(x) +# define psTraceStrHs(x, y) +# else +# define psTraceHs(x) _psTrace(x) +# define psTraceStrHs(x, y) _psTraceStr(x, y) +# endif /* USE_SSL_HANDSHAKE_MSG_TRACE */ +# endif /* PS_LOGF_COMMON */ -# ifndef USE_SSL_INFORMATIONAL_TRACE -# define psTraceInfo(x) -# define psTraceStrInfo(x, y) -# define psTraceIntInfo(x, y) +# ifdef PS_LOGF_COMMON +# define psTraceInfo(x) PS_LOGF_COMMON(Log_Info, PS_MATRIXSSL, PS_LOGF_FMT, \ + PS_LOGF_FILELINE, "%s", x) +# define psTraceIntInfo(x, i) PS_LOGF_COMMON(Log_Info, PS_MATRIXSSL, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, i) +# define psTraceStrInfo(x, s) PS_LOGF_COMMON(Log_Info, PS_MATRIXSSL, \ + PS_LOGF_FMT, \ + PS_LOGF_FILELINE, x, s) # else -# define psTraceInfo(x) _psTrace(x) -# define psTraceStrInfo(x, y) _psTraceStr(x, y) -# define psTraceIntInfo(x, y) _psTraceInt(x, y) +# ifndef USE_SSL_INFORMATIONAL_TRACE +# define psTraceInfo(x) +# define psTraceStrInfo(x, y) +# define psTraceIntInfo(x, y) +# else +# define psTraceInfo(x) _psTrace(x) +# define psTraceStrInfo(x, y) _psTraceStr(x, y) +# define psTraceIntInfo(x, y) _psTraceInt(x, y) +# endif /* USE_SSL_INFORMATIONAL_TRACE */ +# endif /* PS_LOGF_COMMON */ + +# ifdef USE_SSL_INFORMATIONAL_TRACE +void psPrintSigAlgs(uint16_t sigAlgs, const char *where); +void psPrintProtocolVersion(const char *where, + unsigned char majVer, + unsigned char minVer, + psBool_t addNewline); +# define psTracePrintSigAlgs(sigAlgs, where) \ + psPrintSigAlgs(sigAlgs, where) +# define psTracePrintProtocolVersion(where, majVer, minVer, addNewline) \ + psPrintProtocolVersion(where, majVer, minVer, addNewline) +# else +# define psTracePrintSigAlgs(sigAlgs, where) +# define psTracePrintProtocolVersion(where, majVer, minVer, addNewline) # endif /* USE_SSL_INFORMATIONAL_TRACE */ +# if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) +psBool_t weSupportSigAlg(int32_t sigAlg, + int32_t pubKeyAlgorithm); +psBool_t peerSupportsSigAlg(int32_t sigAlg, + uint16_t peerSigAlgs); +psBool_t canUseSigAlg(int32_t sigAlg, + int32_t pubKeyAlgorithm, + uint16_t peerSigAlgs); +int32_t upgradeSigAlg(int32_t sigAlg, int32_t pubKeyAlgorithm); +int32_t chooseSigAlgInt(int32_t certSigAlg, + psSize_t keySize, + int32_t pubKeyAlgorithm, + uint16_t peerSigAlgs); +int32_t chooseSigAlg(psX509Cert_t *cert, + psPubKey_t *privKey, + uint16_t peerSigAlgs); +int32_t getSignatureAndHashAlgorithmEncoding(uint16_t sigAlgOid, + unsigned char *b1, + unsigned char *b2, + uint16_t *hashSize); +# endif + /******************************************************************************/ struct ssl; @@ -804,7 +889,7 @@ typedef struct } matrixValidateCertsOptions_t; /* flags for matrixValidateCertsOptions_t: */ -/* +/** Validate the expectedName argument against a subset of the GeneralName rules for DNS, Email and IP types _before_ trying to find for expectedName in the cert. Note that this is only @@ -813,7 +898,7 @@ typedef struct */ # define VCERTS_FLAG_VALIDATE_EXPECTED_GENERAL_NAME 0x01 -/* +/** Skip the expectedName matching. This is useful e.g. when matrixValidateCerts is called by the TLS server to validate a client certificate. The client name is usually not known @@ -821,6 +906,23 @@ typedef struct */ # define VCERTS_FLAG_SKIP_EXPECTED_NAME_VALIDATION 0x02 +/** + Enable matrixValidateCertsExt to perform an independent validation + of the certificate date ranges. Dates of the subject cert chain + and the found issuer cert are validated against the current + system time. + + By default, MatrixSSL only checks the certificate date validity + during certificate parsing, setting the PS_CERT_AUTH_FAIL_DATE_FLAG + flag in cert->authFailFlags when date validation fails. This flag + will be noticed by matrixValidateCertsExt (but only for subject + certs, not the found issuer cert). In some applications, the delay + between parsing and the actual chain validation can be long. In such + situations, it is useful to re-perform the date validation + in matrixValidateCertsExt. +*/ +# define VCERTS_FLAG_REVALIDATE_DATES 0x04 + /* mFlags for matrixValidateCertsOptions_t: */ /** If expectedName is a hostname, always attempt to match it @@ -923,7 +1025,7 @@ typedef struct psSessionTicketKeys_t *sessTickets; sslSessTicketCb_t ticket_cb; # endif -# if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +# if defined(USE_OCSP_RESPONSE) && defined(USE_SERVER_SIDE_SSL) unsigned char *OCSPResponseBuf; psSize_t OCSPResponseBufLen; # endif @@ -944,7 +1046,7 @@ typedef struct short extendedMasterSecret; /* On by default. -1 to disable */ short trustedCAindication; /* Client: 1 to use */ short fallbackScsv; /* Client: 1 to use */ -# ifdef USE_OCSP +# if defined(USE_OCSP_RESPONSE) || defined(USE_OCSP_REQUEST) short OCSPstapling; /* Client: 1 to send status_request */ # endif # ifdef USE_ECC @@ -961,6 +1063,10 @@ typedef struct ClientHello. Effectively, this ensures that only the version in versionFlag can be negotiated. */ #endif /* USE_CLIENT_SIDE_SSL */ + psBool_t disableTls1_0; +#ifdef USE_SERVER_SIDE_SSL + psBool_t serverDisableTls1_2; +#endif /* USE_SERVER_SIDE_SSL */ void *userPtr; /* Initial value of ssl->userPtr during NewSession */ void *memAllocPtr; /* Will be passed to psOpenPool for each call related to this session */ @@ -987,10 +1093,10 @@ typedef int32_t (*sslExtCb_t)(struct ssl *ssl, uint16_t extType, uint8_t extLen, void *e); typedef int32_t (*sslCertCb_t)(struct ssl *ssl, psX509Cert_t *cert, int32_t alert); -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE typedef int32_t (*ocspCb_t)(struct ssl *ssl, psOcspResponse_t *response, psX509Cert_t *cert, int32_t status); -# endif +# endif /* USE_OCSP_RESPONSE */ /******************************************************************************/ /* @@ -1257,6 +1363,9 @@ struct ssl int32_t extCvSigAlg; unsigned char *extCvOrigFlightEnd; # endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */ +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + uint32_t extClientCertKeyStateFlags; /* Flags: EXT_CLIENT_CERT_KEY_* */ +# endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ flightEncode_t *flightEncode; unsigned char *delayHsHash; unsigned char *seqDelay; /* tmp until flightEncode_t is built */ @@ -1284,7 +1393,16 @@ struct ssl char *alpn; /* proto user has agreed to use */ int32 alpnLen; # endif /* USE_ALPN */ +# ifdef USE_TLS_1_2_TOGGLE + psBool_t disable_tls_1_2; /* Allow to disable TLS 1.2 dynamically. + (Servers only). */ +# endif /* USE_TLS_1_2_TOGGLE */ # endif /* USE_SERVER_SIDE_SSL */ + +# ifdef USE_TLS_1_0_TOGGLE + psBool_t disable_tls_1_0; /* Allow to disable TLS 1.0 dynamically. */ +# endif /* USE_TLS_1_0_TOGGLE */ + # ifdef USE_CLIENT_SIDE_SSL /* Just to handle corner case of app data tacked on HELLO_REQUEST */ int32 anonBk; @@ -1361,6 +1479,7 @@ struct ssl uint32 myVerifyDataLen; uint32 peerVerifyDataLen; int32 secureRenegotiationFlag; + psBool_t secureRenegotiationInProgress; # endif /* ENABLE_SECURE_REHANDSHAKES */ # ifdef SSL_REHANDSHAKES_ENABLED int32 rehandshakeCount; /* Make this an internal define of 1 */ @@ -1377,7 +1496,10 @@ struct ssl # endif # ifdef USE_TLS_1_2 uint16_t hashSigAlg; -# endif +# if defined(USE_CLIENT_AUTH) && defined(USE_CLIENT_SIDE_SSL) + uint16_t serverSigAlgs; +# endif /* USE_CLIENT_AUTH && USE_CLIENT_SIDE_SSL */ +# endif /* USE_TLS_1_2 */ # ifdef USE_DTLS # ifdef USE_SERVER_SIDE_SSL @@ -1475,6 +1597,8 @@ struct ssl uint32 status_request : 1; /* received EXT_STATUS_REQUEST */ uint32 status_request_v2 : 1; /* received EXT_STATUS_REQUEST_V2 */ uint32 require_extended_master_secret : 1; /* peer may require */ + /* For renegotiations. */ + uint32 sni_in_last_client_hello : 1; # ifdef USE_EAP_FAST uint32 eap_fast_master_secret : 1; /* Using eap_fast key derivation */ # endif @@ -1516,6 +1640,7 @@ extern int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys, sslSessionId_t *session, sslSessOpts_t *options); extern void matrixSslSetSessionOption(ssl_t *ssl, int32 option, void *arg); extern int32_t matrixSslHandshakeIsComplete(const ssl_t *ssl); +extern psBool_t matrixSslRehandshaking(const ssl_t *ssl); /* This used to be prefixed with 'matrix' */ extern int32 sslEncodeClosureAlert(ssl_t *ssl, sslBuf_t *out, @@ -1594,10 +1719,10 @@ extern int32 parseServerHelloDone(ssl_t *ssl, int32 hsLen, unsigned char **cp, extern int32 parseServerKeyExchange(ssl_t * ssl, unsigned char hsMsgHash[SHA512_HASH_SIZE], unsigned char **cp, unsigned char *end); -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE extern int32 parseCertificateStatus(ssl_t *ssl, int32 hsLen, unsigned char **cp, unsigned char *end); -# endif +# endif /* USE_OCSP_RESPONSE */ # ifndef USE_ONLY_PSK_CIPHER_SUITE extern int32 parseCertificateRequest(ssl_t *ssl, int32 hsLen, unsigned char **cp, unsigned char *end); diff --git a/matrixssl/sslDecode.c b/matrixssl/sslDecode.c index bb90083..443d237 100644 --- a/matrixssl/sslDecode.c +++ b/matrixssl/sslDecode.c @@ -148,6 +148,18 @@ int32 matrixSslDecode(ssl_t *ssl, unsigned char **buf, uint32 *len, p = pend = mac = ctStart = NULL; padLen = 0; +#ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + if (ssl->extClientCertKeyStateFlags == + EXT_CLIENT_CERT_KEY_STATE_GOT_CERT_KEY_UPDATE) + { + /* Client program has loaded new client cert and keys based on + the server's CertificateRequest message. We have already parsed + the server's last flight entirely. Now skip directly to writing + the response. Reset extClientCertKey state. */ + ssl->extClientCertKeyStateFlags = EXT_CLIENT_CERT_KEY_STATE_INIT; + goto encodeResponse; + } +#endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ # ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING if (ssl->hwflags & SSL_HWFLAGS_PENDING_PKA_W || ssl->hwflags & SSL_HWFLAGS_PENDING_FLIGHT_W) @@ -291,11 +303,19 @@ decodeMore: } else { +#if defined(USE_INTERCEPTOR) || defined(ALLOW_SSLV2_CLIENT_HELLO_PARSE) + ssl->rec.type = SSL_RECORD_TYPE_HANDSHAKE; + ssl->rec.majVer = 2; + ssl->rec.minVer = 0; + ssl->rec.len = (*c & 0x7f) << 8; c++; + ssl->rec.len += *c; c++; +#else /* OpenSSL 0.9.8 will send a SSLv2 CLIENT_HELLO. Use the -no_ssl2 option when running a 0.9.8 client to prevent this */ ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; psTraceInfo("SSLv2 records not supported\n"); goto encodeResponse; +#endif } /* Validate the various record headers. The type must be valid, @@ -1192,15 +1212,13 @@ ADVANCE_TO_APP_DATA: special record type in the specs). This will just be set between CCS parse and FINISHED parse */ ssl->parsedCCS = 1; + /* + Expect epoch to increment after successful CCS parse + */ + incrTwoByte(ssl, ssl->expectedEpoch, 0); } -/* - Expect epoch to increment after successful CCS parse - */ - incrTwoByte(ssl, ssl->expectedEpoch, 0); #endif /* USE_DTLS */ - *remaining = *len - (c - origbuf); - *buf = c; /* If we're expecting finished, then this is the right place to get this record. It is really part of the handshake but it has its @@ -1307,6 +1325,8 @@ ADVANCE_TO_APP_DATA: #endif } ssl->decState = SSL_HS_CCC; + *remaining = *len - (c - origbuf); + *buf = c; return MATRIXSSL_SUCCESS; case SSL_RECORD_TYPE_ALERT: @@ -1398,7 +1418,19 @@ ADVANCE_TO_APP_DATA: *remaining = *len - (c - origbuf); *buf = c; return MATRIXSSL_SUCCESS; - +#ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + case PS_PENDING: + if (matrixSslNeedClientCert(ssl)) + { + /* + Do not create the response flight just yet. Instead, + return to the client application to give it a chance + to load a new client cert and key if desired. + */ + psTraceInfo("matrixSslDecode returning PS_PENDING\n"); + return PS_PENDING; + } +#endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ #ifdef USE_DTLS case DTLS_RETRANSMIT: /* The idea here is to only return retransmit if @@ -2041,7 +2073,7 @@ parseHandshake: #endif /* USE_STATELESS_SESSION_TICKETS */ -#ifdef USE_OCSP +#ifdef USE_OCSP_RESPONSE /* Another possible mismatch is server didn't send the optional CERTIFICATE_STATUS message. Unfortunate this was not specified to be strictly handled in the status_request extensions */ @@ -2075,7 +2107,7 @@ parseHandshake: } # endif /* USE_OCSP_MUST_STAPLE */ } -#endif /* USE_OCSP */ +#endif /* USE_OCSP_RESPONSE */ #ifdef USE_PSK_CIPHER_SUITE /* @@ -2520,6 +2552,11 @@ SKIP_HSHEADER_PARSE: writing of CLIENT_HELLO will properly move the state along itself */ ssl->decState = SSL_HS_HELLO_REQUEST; rc = SSL_PROCESS_DATA; +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + /* Reinitialize the state of the on-demand client cert and key loading + feature for the re-handshake. */ + ssl->extClientCertKeyStateFlags = EXT_CLIENT_CERT_KEY_STATE_INIT; +# endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ break; /******************************************************************************/ @@ -2555,7 +2592,7 @@ SKIP_HSHEADER_PARSE: #ifdef USE_CLIENT_SIDE_SSL /******************************************************************************/ -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE case SSL_HS_CERTIFICATE_STATUS: psTraceHs(">>> Client parsing CERTIFICATE_STATUS message\n"); rc = parseCertificateStatus(ssl, hsLen, &c, end); @@ -2564,7 +2601,7 @@ SKIP_HSHEADER_PARSE: return rc; } break; -# endif /* USE_OCSP */ +# endif /* USE_OCSP_RESPONSE */ /******************************************************************************/ @@ -2666,6 +2703,12 @@ SKIP_HSHEADER_PARSE: { return rc; } +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + /* Note: we must have parsed both CertificateRequest and ServerHelloDone + before proceeding to new client cert and key loading state. */ + ssl->extClientCertKeyStateFlags |= + EXT_CLIENT_CERT_KEY_STATE_GOT_SERVER_HELLO_DONE; +# endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ break; @@ -2680,6 +2723,13 @@ SKIP_HSHEADER_PARSE: { return rc; } +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + /* Note: we must have parsed both CertificateRequest and ServerHelloDone + before proceeding to new client cert and key loading state. */ + ssl->extClientCertKeyStateFlags |= + EXT_CLIENT_CERT_KEY_STATE_GOT_CERTIFICATE_REQUEST; +# endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ + break; # endif /* !USE_ONLY_PSK_CIPHER_SUITE */ #endif /* USE_CLIENT_SIDE_SSL */ @@ -2804,6 +2854,21 @@ SKIP_HSHEADER_PARSE: { goto parseHandshake; } + +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + if ((ssl->extClientCertKeyStateFlags & + EXT_CLIENT_CERT_KEY_STATE_GOT_CERTIFICATE_REQUEST) && + (ssl->extClientCertKeyStateFlags & + EXT_CLIENT_CERT_KEY_STATE_GOT_SERVER_HELLO_DONE)) + { + psTraceInfo("Received CertificateRequest flight\n"); + psTraceInfo("Now returning PS_PENDING to get client cert and key\n"); + ssl->extClientCertKeyStateFlags = + EXT_CLIENT_CERT_KEY_STATE_WAIT_FOR_CERT_KEY_UPDATE; + return PS_PENDING; + } +# endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */ + return rc; } diff --git a/matrixssl/sslEncode.c b/matrixssl/sslEncode.c index 582fe58..935a29d 100644 --- a/matrixssl/sslEncode.c +++ b/matrixssl/sslEncode.c @@ -38,7 +38,7 @@ # ifndef USE_ONLY_PSK_CIPHER_SUITE static int32 writeCertificate(ssl_t *ssl, sslBuf_t *out, int32 notEmpty); -# if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +# if defined(USE_OCSP_RESPONSE) && defined(USE_SERVER_SIDE_SSL) static int32 writeCertificateStatus(ssl_t *ssl, sslBuf_t *out); # endif # endif @@ -1665,7 +1665,7 @@ int32 sslEncodeResponse(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen) messageSize += 4; /* 2 type, 2 length, 0 value */ } -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE /* If we are sending the OCSP status_request extension, we are also sending the CERTIFICATE_STATUS handshake message */ if (ssl->extFlags.status_request) @@ -1680,7 +1680,7 @@ int32 sslEncodeResponse(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen) ssl->keys->OCSPResponseBufLen; messageSize += secureWriteAdditions(ssl, 1); } -# endif +# endif /* USE_OCSP_RESPONSE */ # ifdef USE_STATELESS_SESSION_TICKETS if (ssl->sid && @@ -1760,12 +1760,12 @@ int32 sslEncodeResponse(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen) { rc = writeCertificate(ssl, out, 1); } -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE if (rc == MATRIXSSL_SUCCESS) { rc = writeCertificateStatus(ssl, out); } -# endif +# endif /* USE_OCSP_RESPONSE */ } # endif /* !USE_ONLY_PSK_CIPHER_SUITE */ if (rc == MATRIXSSL_SUCCESS) @@ -1806,12 +1806,12 @@ int32 sslEncodeResponse(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen) { rc = writeCertificate(ssl, out, 1); } -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE if (rc == MATRIXSSL_SUCCESS) { rc = writeCertificateStatus(ssl, out); } -# endif +# endif /* USE_OCSP_RESPONSE */ # endif /* !USE_ONLY_PSK_CIPHER_SUITE */ # ifdef USE_PSK_CIPHER_SUITE } @@ -2575,9 +2575,14 @@ static int32 encryptFlight(ssl_t *ssl, unsigned char **end) incrTwoByte(ssl, ssl->epoch, 1); zeroSixByte(ssl->rsn); } +#ifdef psTracefDtls + psTracefDtls("Flight Encode: RSN %d, MSN %d, Epoch %d\n", + ssl->rsn[5], ssl->msn, ssl->epoch[1]); +#else psTraceIntDtls("RSN %d, ", ssl->rsn[5]); psTraceIntDtls("MSN %d, ", ssl->msn); psTraceIntDtls("Epoch %d\n", ssl->epoch[1]); +#endif *msg->seqDelay = ssl->epoch[0]; msg->seqDelay++; *msg->seqDelay = ssl->epoch[1]; msg->seqDelay++; *msg->seqDelay = ssl->rsn[0]; msg->seqDelay++; @@ -3609,7 +3614,7 @@ static int32 encryptRecord(ssl_t *ssl, int32 type, int32 hsMsgType, { psTraceIntInfo("Error encrypting 1: %d\n", rc); psTraceIntInfo("messageSize is %d\n", messageSize); - psTraceIntInfo("pointer diff %d\n", *c - out->end); + psTraceIntInfo("pointer diff %d\n", (int) (*c - out->end)); psTraceIntInfo("cipher suite %d\n", ssl->cipher->ident); return MATRIXSSL_ERROR; } @@ -3793,7 +3798,12 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) } # endif - if (ssl->extFlags.sni) + /* + Second condition is for renegotiations. Otherwise we would + send an empty SNI extension as a response during renegotation, + even when the latest ClientHello did not actually contain SNI. + */ + if (ssl->extFlags.sni && ssl->extFlags.sni_in_last_client_hello) { if (extLen == 0) { @@ -3801,7 +3811,7 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) } extLen += 4; } -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE if (ssl->extFlags.status_request) { if (extLen == 0) @@ -3810,7 +3820,7 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) } extLen += 4; } -# endif +# endif /* USE_OCSP_RESPONSE */ # ifdef USE_ALPN if (ssl->alpnLen) @@ -3890,6 +3900,9 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) *c = ssl->majVer; c++; *c = ssl->minVer; c++; + psTracePrintProtocolVersion("Encoded ServerHello.server_version", + ssl->majVer, ssl->minVer, 1); + /* The next 32 bytes are the server's random value, to be combined with the client random and premaster for key generation later @@ -3986,14 +3999,15 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) } # endif - if (ssl->extFlags.sni) + /* For the second condition, see comment above. */ + if (ssl->extFlags.sni && ssl->extFlags.sni_in_last_client_hello) { *c = (EXT_SNI & 0xFF00) >> 8; c++; *c = EXT_SNI & 0xFF; c++; *c = 0; c++; *c = 0; c++; } -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE if (ssl->extFlags.status_request) { *c = (EXT_STATUS_REQUEST & 0xFF00) >> 8; c++; @@ -4001,7 +4015,7 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) *c = 0; c++; *c = 0; c++; } -# endif +# endif /* USE_OCSP_RESPONSE */ # ifdef USE_ALPN if (ssl->alpnLen) @@ -4045,6 +4059,7 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) c += ssl->peerVerifyDataLen; memcpy(c, ssl->myVerifyData, ssl->myVerifyDataLen); c += ssl->myVerifyDataLen; + ssl->secureRenegotiationInProgress = PS_TRUE; } } # endif /* ENABLE_SECURE_REHANDSHAKES */ @@ -4475,9 +4490,12 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, */ if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA) { + int32 skeSigAlg = 0; /* If this stays 0, we will use MD5-SHA-1. */ + + psTracePrintSigAlgs(ssl->hashSigAlg, "Peer ClientHello"); # ifndef USE_ONLY_PSK_CIPHER_SUITE /* Saved aside for pkaAfter_t */ - if ((hsMsgHash = psMalloc(ssl->hsPool, SHA384_HASH_SIZE)) == NULL) + if ((hsMsgHash = psMalloc(ssl->hsPool, SHA512_HASH_SIZE)) == NULL) { return PS_MEM_FAIL; } @@ -4485,59 +4503,10 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, # ifdef USE_TLS_1_2 if (ssl->flags & SSL_FLAGS_TLS_1_2) { - /* Using the algorithm from the certificate */ - if (ssl->keys->cert->sigAlgorithm == OID_SHA256_RSA_SIG) - { - hashSize = SHA256_HASH_SIZE; - psSha256PreInit(&digestCtx.sha256); - psSha256Init(&digestCtx.sha256); - psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); - psSha256Update(&digestCtx.sha256, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psSha256Update(&digestCtx.sha256, sigStart, - (uint32) (c - sigStart)); - psSha256Final(&digestCtx.sha256, hsMsgHash); - *c++ = 0x4; - *c++ = 0x1; -# ifdef USE_SHA384 - } - else if (ssl->keys->cert->sigAlgorithm == OID_SHA384_RSA_SIG) - { - hashSize = SHA384_HASH_SIZE; - psSha384PreInit(&digestCtx.sha384); - psSha384Init(&digestCtx.sha384); - psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); - psSha384Update(&digestCtx.sha384, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psSha384Update(&digestCtx.sha384, sigStart, - (uint32) (c - sigStart)); - psSha384Final(&digestCtx.sha384, hsMsgHash); - *c++ = 0x5; - *c++ = 0x1; -# endif /* USE_SHA384 */ - /* If MD5, just send a SHA1. Don't want to contribute to any - longevity of MD5 */ -# ifdef USE_SHA1 - } - else if (ssl->keys->cert->sigAlgorithm == OID_SHA1_RSA_SIG || - ssl->keys->cert->sigAlgorithm == OID_MD5_RSA_SIG) - { - hashSize = SHA1_HASH_SIZE; - psSha1PreInit(&digestCtx.sha1); - psSha1Init(&digestCtx.sha1); - psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psSha1Update(&digestCtx.sha1, sigStart, (uint32) (c - sigStart)); - psSha1Final(&digestCtx.sha1, hsMsgHash); - *c++ = 0x2; - *c++ = 0x1; -# endif - } - else + skeSigAlg = chooseSigAlg(ssl->keys->cert, + &ssl->keys->privKey, + ssl->hashSigAlg); + if (skeSigAlg == PS_UNSUPPORTED_FAIL) { psTraceIntInfo("Unavailable sigAlgorithm for SKE write: %d\n", ssl->keys->cert->sigAlgorithm); @@ -4545,43 +4514,94 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen, return PS_UNSUPPORTED_FAIL; } } - else +# endif /* USE_TLS_1_2 */ + + switch(skeSigAlg) { -# ifdef USE_MD5SHA1 +# ifdef USE_MD5SHA1 + case 0: hashSize = MD5SHA1_HASHLEN; psMd5Sha1PreInit(&digestCtx.md5sha1); psMd5Sha1Init(&digestCtx.md5sha1); psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); + SSL_HS_RANDOM_SIZE); psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psMd5Sha1Update(&digestCtx.md5sha1, sigStart, (uint32) (c - sigStart)); + SSL_HS_RANDOM_SIZE); + psMd5Sha1Update(&digestCtx.md5sha1, sigStart, + (uint32) (c - sigStart)); psMd5Sha1Final(&digestCtx.md5sha1, hsMsgHash); -# else + break; +# endif /* USE_MD5SHA1 */ +# ifdef USE_SHA1 + case OID_SHA1_RSA_SIG: + hashSize = SHA1_HASH_SIZE; + psSha1PreInit(&digestCtx.sha1); + psSha1Init(&digestCtx.sha1); + psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha1Update(&digestCtx.sha1, sigStart, + (uint32) (c - sigStart)); + psSha1Final(&digestCtx.sha1, hsMsgHash); + *c++ = 0x2; + *c++ = 0x1; + break; +# endif /* USE_SHA1 */ +# ifdef USE_SHA256 + case OID_SHA256_RSA_SIG: + hashSize = SHA256_HASH_SIZE; + psSha256PreInit(&digestCtx.sha256); + psSha256Init(&digestCtx.sha256); + psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha256Update(&digestCtx.sha256, sigStart, + (uint32) (c - sigStart)); + psSha256Final(&digestCtx.sha256, hsMsgHash); + *c++ = 0x4; + *c++ = 0x1; + break; +# endif /* USE_SHA256 */ +# ifdef USE_SHA384 + case OID_SHA384_RSA_SIG: + hashSize = SHA384_HASH_SIZE; + psSha384PreInit(&digestCtx.sha384); + psSha384Init(&digestCtx.sha384); + psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha384Update(&digestCtx.sha384, sigStart, + (uint32) (c - sigStart)); + psSha384Final(&digestCtx.sha384, hsMsgHash); + *c++ = 0x5; + *c++ = 0x1; + break; +# endif /* USE_SHA384 */ +# ifdef USE_SHA512 + case OID_SHA512_RSA_SIG: + hashSize = SHA512_HASH_SIZE; + psSha512PreInit(&digestCtx.sha512); + psSha512Init(&digestCtx.sha512); + psSha512Update(&digestCtx.sha512, ssl->sec.clientRandom, + SSL_HS_RANDOM_SIZE); + psSha512Update(&digestCtx.sha512, ssl->sec.serverRandom, + SSL_HS_RANDOM_SIZE); + psSha512Update(&digestCtx.sha512, sigStart, + (uint32) (c - sigStart)); + psSha512Final(&digestCtx.sha512, hsMsgHash); + *c++ = 0x6; + *c++ = 0x1; + break; +# endif /* USE_SHA512 */ + default: psTraceIntInfo("Unavailable sigAlgorithm for SKE write: %d\n", - ssl->keys->cert->sigAlgorithm); + skeSigAlg); psFree(hsMsgHash, ssl->hsPool); return PS_UNSUPPORTED_FAIL; -# endif /* USE_MD5SHA1 */ } -# else /* USE_TLS_1_2 */ -# ifdef USE_MD5SHA1 - hashSize = MD5SHA1_HASHLEN; - psMd5Sha1PreInit(&digestCtx.md5sha1); - psMd5Sha1Init(&digestCtx.md5sha1); - psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.clientRandom, - SSL_HS_RANDOM_SIZE); - psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.serverRandom, - SSL_HS_RANDOM_SIZE); - psMd5Sha1Update(&digestCtx.md5sha1, sigStart, (uint32) (c - sigStart)); - psMd5Sha1Final(&digestCtx.md5sha1, hsMsgHash); -# else - psTraceIntInfo("Unavailable sigAlgorithm for SKE write: %d\n", - ssl->keys->cert->sigAlgorithm); - psFree(hsMsgHash, ssl->hsPool); - return PS_UNSUPPORTED_FAIL; -# endif /* USE_MD5SHA1 */ -# endif /* USE_TLS_1_2 */ *c = (ssl->keys->privKey.keysize & 0xFF00) >> 8; c++; *c = ssl->keys->privKey.keysize & 0xFF; c++; @@ -5080,7 +5100,7 @@ static int32 writeMultiRecordCertificate(ssl_t *ssl, sslBuf_t *out, # endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ -# if defined(USE_OCSP) && defined(USE_SERVER_SIDE_SSL) +# if defined(USE_OCSP_RESPONSE) && defined(USE_SERVER_SIDE_SSL) static int32 writeCertificateStatus(ssl_t *ssl, sslBuf_t *out) { unsigned char *c, *end, *encryptStart; @@ -5424,6 +5444,25 @@ static int32 writeFinished(ssl_t *ssl, sslBuf_t *out) } # endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */ # endif /* !USE_ONLY_PSK_CIPHER_SUITE */ + +# ifdef ENABLE_SECURE_REHANDSHAKES + /* Check if this was the last message in the handshake, + indicating that the handshake is over. */ + if (ssl->flags & SSL_FLAGS_SERVER) + { + if (!(ssl->flags & SSL_FLAGS_RESUMED)) + { + ssl->secureRenegotiationInProgress = PS_FALSE; + } + } + else /* We're the client. */ + { + if (ssl->flags & SSL_FLAGS_RESUMED) + { + ssl->secureRenegotiationInProgress = PS_FALSE; + } + } +# endif return MATRIXSSL_SUCCESS; } @@ -5815,7 +5854,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, } # endif -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE if (options && options->OCSPstapling == 1) { if (extLen == 0) @@ -5825,7 +5864,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, /* Currently only supporting an empty status_request extension */ extLen += 9; } -# endif +# endif /* USE_OCSP_RESPONSE */ # ifdef USE_TLS_1_2 /* @@ -5903,6 +5942,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, /* On the client side, the value is set to the algorithms offered */ ssl->hashSigAlg = sigHashFlags; + psTracePrintSigAlgs(ssl->hashSigAlg, "Our ClientHello"); # endif /* USE_TLS_1_2 */ /* Add any user-provided extensions */ @@ -6002,6 +6042,9 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, *c = ssl->majVer; c++; *c = ssl->minVer; c++; + psTracePrintProtocolVersion("Encoded ClientHello.client_version", + ssl->majVer, ssl->minVer, 1); + /* The next 32 bytes are the server's random value, to be combined with the client random and premaster for key generation later @@ -6194,6 +6237,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, *c = ssl->myVerifyDataLen & 0xFF; c++; memcpy(c, ssl->myVerifyData, ssl->myVerifyDataLen); c += ssl->myVerifyDataLen; + ssl->secureRenegotiationInProgress = PS_TRUE; } # endif /* ENABLE_SECURE_REHANDSHAKES */ @@ -6263,7 +6307,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, } # endif /* USE_STATELESS_SESSION_TICKETS */ -# ifdef USE_OCSP +# ifdef USE_OCSP_RESPONSE if (options->OCSPstapling) { ssl->extFlags.req_status_request = 1; @@ -6277,7 +6321,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, *c = 0x00; c++; *c = 0x00; c++; } -# endif +# endif /* USE_OCSP_RESPONSE */ # ifdef USE_TRUSTED_CA_INDICATION if (options->trustedCAindication) @@ -7247,7 +7291,7 @@ static int nowDoCvPkaInnerRSA(ssl_t *ssl, pkaAfter_t *pka, using_tls_1_2 = 0; /* TLS 1.2 defined but not used. */ } # else /* ! USE_TLS_1_2 */ - use_tls_1_2 = 0; /* TLS 1.2 not defined and thus not used. */ + using_tls_1_2 = 0; /* TLS 1.2 not defined and thus not used. */ # endif /* USE_TLS_1_2 */ psAssert(using_tls_1_2 == 0 || using_tls_1_2 == 1); @@ -7304,7 +7348,10 @@ static int nowDoCvPkaInnerRSA(ssl_t *ssl, pkaAfter_t *pka, out: clearPkaAfter(ssl); - return PS_SUCCESS; + if (rc >= 0) + return PS_SUCCESS; + else + return rc; } # endif /* USE_RSA */ @@ -7324,8 +7371,8 @@ static int32 nowDoCvPka(ssl_t *ssl, psBuf_t *out) if (ssl->retransmit) { /* This call is not gated on pkaAfter.type so we test for - retransmits manaully. The retransmit will have already been - written in writeCertifiateVerify if true */ + retransmits manually. The retransmit will have already been + written in writeCertificateVerify if true */ return PS_SUCCESS; } } @@ -7388,6 +7435,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out) int32_t rc; pkaAfter_t *pkaAfter; void *pkiData = ssl->userPtr; + int32_t sigAlg; psTraceHs("<<< Client creating CERTIFICATE_VERIFY message\n"); c = out->end; @@ -7470,67 +7518,47 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out) Correct to be looking at the child-most cert here because that is the one associated with the private key. */ +# ifdef USE_TLS_1_2 + if (ssl->flags & SSL_FLAGS_TLS_1_2) + { + /* + Pick the hash algorithm to use with the public key. + Use the signature algorithm used in our certificate as + the basis for the selection, because we have checked + in parseCertificateRequest that the server supports that. + */ + sigAlg = chooseSigAlg(ssl->keys->cert, + &ssl->keys->privKey, + ssl->serverSigAlgs); + if (sigAlg <= 0) + { + psTraceInfo("Need more hash support for certVerify\n"); + return MATRIXSSL_ERROR; + } + } + else + { + hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; + } +# else /* USE_TLS_1_2 */ + hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; +# endif /* USE_TLS_1_2 */ + # ifdef USE_ECC if (ssl->keys->cert->pubKeyAlgorithm == OID_ECDSA_KEY_ALG) { - hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; # ifdef USE_TLS_1_2 if (ssl->flags & SSL_FLAGS_TLS_1_2) { - /* RFC: "The hash and signature algorithms used in the - signature MUST be one of those present in the - supported_signature_algorithms field of the - CertificateRequest message. In addition, the hash and - signature algorithms MUST be compatible with the key in the - client's end-entity certificate." + unsigned char b1, b2; - We've done the above tests in the parse of the - CertificateRequest message and wouldn't be here if our - certs didn't match the sigAlgs. However, we do have - to test for both sig algorithm types here to find the - hash strength because the sig alg might not match the - pubkey alg. This was also already confirmed in - CertRequest parse so wouldn't be here if not allowed */ - if ((ssl->keys->cert->sigAlgorithm == OID_SHA1_ECDSA_SIG) || - (ssl->keys->cert->sigAlgorithm == OID_SHA1_RSA_SIG)) + if (getSignatureAndHashAlgorithmEncoding(sigAlg, + &b1, &b2, &hashSize) < 0) { - *c = 0x2; c++; /* SHA1 */ - *c = 0x3; c++; /* ECDSA */ - hashSize = SHA1_HASH_SIZE; - } - else if ((ssl->keys->cert->sigAlgorithm == - OID_SHA256_ECDSA_SIG) || (ssl->keys->cert->sigAlgorithm - == OID_SHA256_RSA_SIG)) - { - *c = 0x4; c++; /* SHA256 */ - *c = 0x3; c++; /* ECDSA */ - hashSize = SHA256_HASH_SIZE; -# ifdef USE_SHA384 - } - else if ((ssl->keys->cert->sigAlgorithm == - OID_SHA384_ECDSA_SIG) || (ssl->keys->cert->sigAlgorithm - == OID_SHA384_RSA_SIG)) - { - *c = 0x5; c++; /* SHA384 */ - *c = 0x3; c++; /* ECDSA */ - hashSize = SHA384_HASH_SIZE; -# endif -# ifdef USE_SHA512 - } - else if ((ssl->keys->cert->sigAlgorithm == - OID_SHA512_ECDSA_SIG) || (ssl->keys->cert->sigAlgorithm - == OID_SHA512_RSA_SIG)) - { - *c = 0x6; c++; /* SHA512 */ - *c = 0x3; c++; /* ECDSA */ - hashSize = SHA512_HASH_SIZE; -# endif - } - else - { - psTraceInfo("Need more hash support for certVerify\n"); return MATRIXSSL_ERROR; } + *c = b1; c++; + *c = b2; c++; } # endif /* USE_TLS_1_2 */ @@ -7566,7 +7594,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out) pkaAfter->user = rc; c += rc; # ifdef USE_DTLS - } + } # endif } else @@ -7574,59 +7602,25 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out) # endif /* USE_ECC */ # ifdef USE_RSA - hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE; # ifdef USE_TLS_1_2 if (ssl->flags & SSL_FLAGS_TLS_1_2) { - /* RFC: "The hash and signature algorithms used in the - signature MUST be one of those present in the - supported_signature_algorithms field of the - CertificateRequest message. In addition, the hash and - signature algorithms MUST be compatible with the key in the - client's end-entity certificate. + unsigned char b1, b2; - We've done the above tests in the parse of the - CertificateRequest message and wouldn't be here if our - certs didn't match the sigAlgs. However, we do have - to test for both sig algorithm types here to find the - hash strength because the sig alg might not match the - pubkey alg. This was also already confirmed in - CertRequest parse so wouldn't be here if not allowed */ - if (ssl->keys->cert->sigAlgorithm == OID_SHA1_RSA_SIG || - ssl->keys->cert->sigAlgorithm == OID_MD5_RSA_SIG || - ssl->keys->cert->sigAlgorithm == OID_SHA1_ECDSA_SIG) + if (ssl->keys->cert->sigAlgorithm != OID_RSASSA_PSS) { - *c = 0x2; c++; /* SHA1 */ - *c = 0x1; c++; /* RSA */ - hashSize = SHA1_HASH_SIZE; + if (getSignatureAndHashAlgorithmEncoding(sigAlg, + &b1, &b2, &hashSize) < 0) + { + psTraceInfo("Need additional hash support for certVerify\n"); + return MATRIXSSL_ERROR; + } + *c = b1; c++; + *c = b2; c++; } - else if (ssl->keys->cert->sigAlgorithm == OID_SHA256_RSA_SIG || - ssl->keys->cert->sigAlgorithm == OID_SHA256_ECDSA_SIG) - { - *c = 0x4; c++; /* SHA256 */ - *c = 0x1; c++; /* RSA */ - /* Normal handshake hash uses SHA256 and has been done above */ - hashSize = SHA256_HASH_SIZE; -# ifdef USE_SHA384 - } - else if (ssl->keys->cert->sigAlgorithm == OID_SHA384_RSA_SIG || - ssl->keys->cert->sigAlgorithm == OID_SHA384_ECDSA_SIG) - { - *c = 0x5; c++; /* SHA384 */ - *c = 0x1; c++; /* RSA */ - hashSize = SHA384_HASH_SIZE; -# endif /* USE_SHA384 */ -# ifdef USE_SHA512 - } - else if (ssl->keys->cert->sigAlgorithm == OID_SHA512_RSA_SIG || - ssl->keys->cert->sigAlgorithm == OID_SHA512_ECDSA_SIG) - { - *c = 0x6; c++; /* SHA512 */ - *c = 0x1; c++; /* RSA */ - hashSize = SHA512_HASH_SIZE; -# endif /* USE_SHA512 */ # ifdef USE_PKCS1_PSS - } + /* Special handling for OID_RSASSA_PSS, since it is not yet + supported by the sigAlg functions. */ else if (ssl->keys->cert->sigAlgorithm == OID_RSASSA_PSS) { if (ssl->keys->cert->pssHash == PKCS1_SHA1_ID || @@ -7660,8 +7654,8 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out) return MATRIXSSL_ERROR; } *c = 0x1; c++; /* RSA */ -# endif } +# endif /* USE_PKCS1_PSS */ else { psTraceInfo("Need additional hash support for certVerify\n"); diff --git a/matrixssl/test/sslTest.c b/matrixssl/test/sslTest.c index 261c6e8..ca6abc6 100644 --- a/matrixssl/test/sslTest.c +++ b/matrixssl/test/sslTest.c @@ -841,7 +841,8 @@ L_NEXT_ECC: # ifdef REQUIRE_DH_PARAMS L_NEXT_DH: - if (spec->type == CS_DHE_RSA || spec->type == CS_DHE_PSK) + if (spec->type == CS_DHE_RSA || spec->type == CS_DHE_PSK + || spec->type == CS_DH_ANON) { switch (DH_SIZE) { diff --git a/matrixssl/tls.c b/matrixssl/tls.c index d204f49..4b8145b 100644 --- a/matrixssl/tls.c +++ b/matrixssl/tls.c @@ -422,7 +422,9 @@ int32_t tlsHMACSha1(ssl_t *ssl, int32 mode, unsigned char type, tmp[4] = len & 0xFF; # ifdef USE_HMAC_TLS # ifdef USE_HMAC_TLS_LUCKY13_COUNTERMEASURE - alt_len = mode == HMAC_CREATE ? len : ssl->rec.len; + /* Lucky13 counter measure is only used when receiving record. + Decrement 4 bytes of header from amount of ssl->rec to process. */ + alt_len = mode == HMAC_CREATE || ssl->rec.len < len + 4? len : ssl->rec.len - 4; # else alt_len = len; # endif @@ -520,7 +522,9 @@ int32_t tlsHMACSha2(ssl_t *ssl, int32 mode, unsigned char type, # ifdef USE_HMAC_TLS # ifdef USE_HMAC_TLS_LUCKY13_COUNTERMEASURE - alt_len = mode == HMAC_CREATE ? len : ssl->rec.len; + /* Lucky13 counter measure is only used when receiving record. + Decrement 4 bytes of header from amount of ssl->rec to process. */ + alt_len = mode == HMAC_CREATE || ssl->rec.len < len + 4? len : ssl->rec.len - 4; # else alt_len = len; # endif @@ -985,5 +989,741 @@ int32 matrixSslLoadHelloExtension(tlsExtension_t *ext, } #endif /* USE_CLIENT_SIDE_SSL */ +#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) +#ifndef USE_ONLY_PSK_CIPHER_SUITE +/** + Return PS_TRUE if sigAlg is in peerSigAlgs, PS_FALSE otherwise. + + peerSigAlgs should be the a set of masks we created after + parsing the peer's supported_signature_algorithms list + in ClientHello or CertificateRequest. +*/ +psBool_t peerSupportsSigAlg(int32_t sigAlg, + uint16_t peerSigAlgs) +{ + uint16_t yes; + + if (sigAlg == OID_MD5_RSA_SIG) + { + yes = ((peerSigAlgs & HASH_SIG_MD5_RSA_MASK) != 0); + } + else if (sigAlg == OID_SHA1_RSA_SIG) + { + yes = ((peerSigAlgs & HASH_SIG_SHA1_RSA_MASK) != 0); + } + else if (sigAlg == OID_SHA256_RSA_SIG) + { + yes = ((peerSigAlgs & HASH_SIG_SHA256_RSA_MASK) != 0); + } + else if (sigAlg == OID_SHA384_RSA_SIG) + { + yes = ((peerSigAlgs & HASH_SIG_SHA384_RSA_MASK) != 0); + } + else if (sigAlg == OID_SHA512_RSA_SIG) + { + yes = ((peerSigAlgs & HASH_SIG_SHA512_RSA_MASK) != 0); + } + else if (sigAlg == OID_SHA1_ECDSA_SIG) + { + yes = ((peerSigAlgs & HASH_SIG_SHA1_ECDSA_MASK) != 0); + } + else if (sigAlg == OID_SHA256_ECDSA_SIG) + { + yes = ((peerSigAlgs & HASH_SIG_SHA256_ECDSA_MASK) != 0); + } + else if (sigAlg == OID_SHA384_ECDSA_SIG) + { + yes = ((peerSigAlgs & HASH_SIG_SHA384_ECDSA_MASK) != 0); + } + else if (sigAlg == OID_SHA512_ECDSA_SIG) + { + yes = ((peerSigAlgs & HASH_SIG_SHA512_ECDSA_MASK) != 0); + } + else + { + return PS_FALSE; /* Unknown/unsupported sig alg. */ + } + + if (yes) + { + return PS_TRUE; + } + else + { + return PS_FALSE; + } +} + +/** + Return PS_TRUE when we support sigAlg for signature generation, + PS_FALSE otherwise. + + Compile-time switches as well as FIPS or non-FIPS mode is taken + into account. + + @param[in] sigAlg The signature algorithm whose support is to + be checked. + @param[in] pubKeyAlgorithm The public key algorithm of our + private/public key pair (OID_RSA_KEY_ALG or OID_ECDSA_KEY_ALG.) +*/ +psBool_t weSupportSigAlg(int32_t sigAlg, + int32_t pubKeyAlgorithm) +{ + uint16_t we_support = 0; + uint16_t is_non_fips = 0; /* 1 if not allowed in FIPS mode for + signature generation. */ + + PS_VARIABLE_SET_BUT_UNUSED(is_non_fips); + +#ifndef USE_RSA + if (pubKeyAlgorithm == OID_RSA_KEY_ALG) + { + return PS_FALSE; + } +#endif +#ifndef USE_ECC + if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG) + { + return PS_FALSE; + } +#endif + + if (pubKeyAlgorithm == OID_RSA_KEY_ALG) + { + if (sigAlg == OID_MD2_RSA_SIG || sigAlg == OID_MD5_RSA_SIG) + { + /* No support for generating RSA-MD2 or RSA-MD5 signatures. */ + is_non_fips = 1; + we_support = 0; + } + else if (sigAlg == OID_SHA1_RSA_SIG) + { + is_non_fips = 1; +#ifdef USE_SHA1 + we_support = 1; +#endif + } + else if (sigAlg == OID_SHA256_RSA_SIG) + { +#ifdef USE_SHA256 + we_support = 1; +#endif + } + else if (sigAlg == OID_SHA384_RSA_SIG) + { +#ifdef USE_SHA384 + we_support = 1; +#endif + } + else if (sigAlg == OID_SHA512_RSA_SIG) + { +#ifdef USE_SHA512 + we_support = 1; +#endif + } + else + { + /* Our key does not support this algorithm. */ + return PS_FALSE; + } + } + else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG) + { + if (sigAlg == OID_SHA1_ECDSA_SIG) + { +#ifdef USE_SHA1 + we_support = 1; +#endif + } + else if (sigAlg == OID_SHA256_ECDSA_SIG) + { +#ifdef USE_SHA256 + we_support = 1; +#endif + } + else if (sigAlg == OID_SHA384_ECDSA_SIG) + { +#ifdef USE_SHA384 + we_support = 1; +#endif + } + else if (sigAlg == OID_SHA512_ECDSA_SIG) + { +#ifdef USE_SHA512 + we_support = 1; +#endif + } + else + { + /* Our key does not support this algorithm. */ + return PS_FALSE; + } + } + else + { + return PS_FALSE; /* Unsupported public key alg, e.g. DSA. */ + } + + /* The basic capability is there. Now do some further checks + if needed. */ + + if (we_support) + { + return PS_TRUE; + } + else + { + return PS_FALSE; + } +} + +/** Return PS_TRUE when: + - We support sigAlg for signature generation. + - sigAlg is in peerSigAlgs. + + @param[in] sigAlg The signature algorithm whose support to check. + @param[in] pubKeyAlgorithm The public key algorithm of our key. + @param[in] peerSigAlgs The masks of the sigAlgs supported by the + peer. This should be the one parsed from the peer's + supported_signature_algorithms list in CertificateVerify or + CertificateRequest. In this case, sigAlg \in peerSigAlgs + means that the peer supports sigAlg for signature verification. +*/ +psBool_t canUseSigAlg(int32_t sigAlg, + int32_t pubKeyAlgorithm, + uint16_t peerSigAlgs) +{ + return (weSupportSigAlg(sigAlg, pubKeyAlgorithm) && + peerSupportsSigAlg(sigAlg, peerSigAlgs)); +} + +/** + Upgrade to a more secure signature algorithm. If the algorithm + is already the strongest possible for the key type (i.e. + RSA-SHA-512 or ECDSA-SHA-512) change to the most popular + one (i.e. RSA-SHA-256 or ECDSA-SHA-256). +*/ +int32_t upgradeSigAlg(int32_t sigAlg, int32_t pubKeyAlgorithm) +{ + /* + RSA: + MD2 -> SHA256 + MD5 -> SHA256 + SHA1 -> SHA256 + SHA256 -> SHA384 + SHA384 -> SHA512 + SHA512 -> SHA256 + */ + if (pubKeyAlgorithm == OID_RSA_KEY_ALG) + { + if (sigAlg == OID_MD2_RSA_SIG || + sigAlg == OID_MD5_RSA_SIG || + sigAlg == OID_SHA1_RSA_SIG) + { + return OID_SHA256_RSA_SIG; + } + else if (sigAlg == OID_SHA256_RSA_SIG) + { + return OID_SHA384_RSA_SIG; + } + else if (sigAlg == OID_SHA384_RSA_SIG) + { + return OID_SHA512_RSA_SIG; + } + else if (sigAlg == OID_SHA512_RSA_SIG) + { + return OID_SHA256_RSA_SIG; + } + else + { + return PS_UNSUPPORTED_FAIL; + } + } + /* + ECDSA: + SHA1 -> SHA256 + SHA256 -> SHA384 + SHA384 -> SHA512 + SHA512 -> SHA256 + */ + else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG) + { + if (sigAlg == OID_SHA1_ECDSA_SIG) + { + return OID_SHA256_ECDSA_SIG; + } + else if (sigAlg == OID_SHA256_ECDSA_SIG) + { + return OID_SHA384_ECDSA_SIG; + } + else if (sigAlg == OID_SHA384_ECDSA_SIG) + { + return OID_SHA512_ECDSA_SIG; + } + else if (sigAlg == OID_SHA512_ECDSA_SIG) + { + return OID_SHA256_ECDSA_SIG; + } + else + { + return PS_UNSUPPORTED_FAIL; + } + } + else + { + return PS_UNSUPPORTED_FAIL; + } +} + +static +psSize_t sigAlgToHashLen(int32_t sigAlg) +{ + switch(sigAlg) + { + case OID_MD2_RSA_SIG: + case OID_MD5_RSA_SIG: + return MD5_HASH_SIZE; + case OID_SHA1_RSA_SIG: + case OID_SHA1_ECDSA_SIG: + return SHA1_HASH_SIZE; + case OID_SHA256_RSA_SIG: + case OID_SHA256_ECDSA_SIG: + return SHA256_HASH_SIZE; + case OID_SHA384_RSA_SIG: + case OID_SHA384_ECDSA_SIG: + return SHA384_HASH_SIZE; + case OID_SHA512_RSA_SIG: + case OID_SHA512_ECDSA_SIG: + return SHA512_HASH_SIZE; + default: + return PS_UNSUPPORTED_FAIL; + } +} + +/** Return PS_TRUE if sigAlg is deemed insecure. + Return PS_FALSE otherwise. +*/ +static +int32_t isInsecureSigAlg(int32_t sigAlg) +{ + if (sigAlg == OID_MD2_RSA_SIG + || sigAlg == OID_MD5_RSA_SIG + || sigAlg == OID_SHA1_RSA_SIG + || sigAlg == OID_SHA1_ECDSA_SIG) + { + return 1; + } + else + { + return 0; + } +} + +/* Return PS_TRUE when sigAlg,modulusNBytes is an invalid + hash and modulus size combination. Return PS_FALSE + otherwise. */ +static +int32_t isInvalidModulusHashSizeCombination(int32_t sigAlg, + psSize_t modulusNBytes) +{ + psSize_t hashLen = sigAlgToHashLen(sigAlg); + + /* Check the PKCS #1.5 restriction that there should be room + for at least 8 padding bytes before RSA encryption. + (11 = 8 pad bytes + 00 + BT + 00). */ + if (modulusNBytes < (hashLen + 11)) + { + return PS_TRUE; + } + + return PS_FALSE; +} + +static +int32_t sigAlgRsaToEcdsa(int32_t sigAlg) +{ + if (sigAlg == OID_SHA1_RSA_SIG) + { + return OID_SHA1_ECDSA_SIG; + } + if (sigAlg == OID_SHA256_RSA_SIG) + { + return OID_SHA256_ECDSA_SIG; + } + if (sigAlg == OID_SHA384_RSA_SIG) + { + return OID_SHA384_ECDSA_SIG; + } + if (sigAlg == OID_SHA512_RSA_SIG) + { + return OID_SHA512_ECDSA_SIG; + } + else + { + return OID_SHA256_ECDSA_SIG; + } +} + +static +int32_t ecdsaToRsa(int32_t sigAlg) +{ + if (sigAlg == OID_SHA1_ECDSA_SIG) + { + return OID_SHA1_RSA_SIG; + } + if (sigAlg == OID_SHA256_ECDSA_SIG) + { + return OID_SHA256_RSA_SIG; + } + if (sigAlg == OID_SHA384_ECDSA_SIG) + { + return OID_SHA384_RSA_SIG; + } + if (sigAlg == OID_SHA512_ECDSA_SIG) + { + return OID_SHA512_RSA_SIG; + } + else + { + return OID_SHA256_RSA_SIG; + } +} + +/** + Determine signature algorithm to use in the CertificateVerify or + ServerKeyExchange handshake messages in TLS 1.2. + + TODO: add support for RSASSA-PSS. + + This function should only be called when using TLS 1.2. + + @param[in] certSigAlg The signature algorithm with which our + certificate was signed. + @param[in] keySize The size of our private key in bytes. For RSA, + this is modulus; for ECDSA, this is the curve size. + @param[in] pubKeyAlgorithm The public key algorithm to use for + authentication. This should the same algorithm our public/private key + pair is meant for. Must be either OID_RSA_KEY_ALG or + OID_ECDSA_KEY_ALG. + @param[in] peerSigAlg The list of signature algorithm masks + the peer supports (e.g. HASH_SIG_SHA*_RSA_MASK). This should + be the list created during parsing of the ClientHello or + CertificateRequest message. + @return The signature algorithm to use. +*/ +int32_t chooseSigAlgInt(int32_t certSigAlg, + psSize_t keySize, + int32_t pubKeyAlgorithm, + uint16_t peerSigAlgs) +{ + int32 a = certSigAlg; + +#ifndef USE_RSA + if (pubKeyAlgorithm == OID_RSA_KEY_ALG) + { + return PS_UNSUPPORTED_FAIL; + } +#endif +#ifndef USE_ECC + if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG) + { + return PS_UNSUPPORTED_FAIL; + } +#endif + + /* + We are going to use certSigAlg as the basis of our choice. + This is because the SSL layer must ensure anyway that the peer + supports this algorithm. + */ + if (pubKeyAlgorithm == OID_RSA_KEY_ALG) + { + if (certSigAlg == OID_SHA1_ECDSA_SIG || + certSigAlg == OID_SHA256_ECDSA_SIG || + certSigAlg == OID_SHA384_ECDSA_SIG || + certSigAlg == OID_SHA512_ECDSA_SIG) + { + /* Pubkey is RSA, but cert is signed with ECDSA. + Convert certSigAlg to corresponding RSA alg. */ + a = ecdsaToRsa(certSigAlg); + } + + /* + For RSA signatures, RFC 5746 allows to pick any hash algorithm, + as long as it is supported by the peer, i.e. included in the + peer's signature_algorithms list. + + We use this opportunity to switch from the insecure MD5 and + SHA-1 to SHA-256, if possible. We don't want to contribute + to the longevity of obsolete hash algorithms. + */ + if (isInsecureSigAlg(a)) + { + /* Try to upgrade. */ + a = upgradeSigAlg(a, OID_RSA_KEY_ALG); + if (!canUseSigAlg(a, OID_RSA_KEY_ALG, peerSigAlgs)) + { + /* Stil not supported. Try the next alternative. */ + a = upgradeSigAlg(a, OID_RSA_KEY_ALG); + if (!canUseSigAlg(a, OID_RSA_KEY_ALG, peerSigAlgs)) + { + /* Unable to upgrade insecure alg. Have to use the server + cert sig alg. */ + a = certSigAlg; + } + } + } + /* Not allowing e.g. RSA-SHA-512 with a 512-bit modulus. */ + if (isInvalidModulusHashSizeCombination(a, keySize)) + { + /* Try "next best" hash algorithm. */ + a = upgradeSigAlg(a, OID_RSA_KEY_ALG); + if (isInvalidModulusHashSizeCombination(a, keySize)) + { + return PS_UNSUPPORTED_FAIL; + } + } + } + else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG) + { + if (certSigAlg != OID_SHA1_ECDSA_SIG && + certSigAlg != OID_SHA256_ECDSA_SIG && + certSigAlg != OID_SHA384_ECDSA_SIG && + certSigAlg != OID_SHA512_ECDSA_SIG) + { + /* Pubkey is ECDSA, but cert is signed with RSA. + Convert to corresponding ECDSA alg. */ + a = sigAlgRsaToEcdsa(certSigAlg); + } + } + else + { + return PS_UNSUPPORTED_FAIL; /* Unknown/unsupported pub key alg. */ + } + + /* Validate our choice. */ + if (canUseSigAlg(a, pubKeyAlgorithm, peerSigAlgs)) + { + psTraceIntInfo("Chose sigAlg %d\n", a); + return a; + } + else + { + return PS_UNSUPPORTED_FAIL; + } +} + +int32_t chooseSigAlg(psX509Cert_t *cert, + psPubKey_t *privKey, + uint16_t peerSigAlgs) +{ + int32 pubKeyAlg; + +# ifdef USE_CERT_PARSE + pubKeyAlg = cert->pubKeyAlgorithm; +# else + if (privKey->type == PS_RSA) + { + pubKeyAlg = OID_RSA_KEY_ALG; + } + else if (privKey->type == PS_ECC) + { + pubKeyAlg = OID_ECDSA_KEY_ALG; + } + else + { + return PS_UNSUPPORTED_FAIL; + } +# endif /* USE_CERT_PARSE */ + + return chooseSigAlgInt(cert->sigAlgorithm, + privKey->keysize, + pubKeyAlg, + peerSigAlgs); +} + +/* Return the TLS 1.2 SignatureAndHashAlgorithm encoding for the + given algorithm OID. */ +int32_t getSignatureAndHashAlgorithmEncoding(uint16_t sigAlgOid, + unsigned char *octet1, + unsigned char *octet2, + uint16_t *hashSize) +{ + unsigned char b1, b2; + uint16_t hLen = 0; + + psAssert(octet1 != NULL && octet2 != NULL && hashSize != NULL); + + switch(sigAlgOid) + { +#ifdef USE_SHA1 + case OID_SHA1_ECDSA_SIG: + b1 = 0x2; /* SHA-1 */ + b2 = 0x3; /* ECDSA */ + hLen = SHA1_HASH_SIZE; + break; + case OID_SHA1_RSA_SIG: + b1 = 0x2; /* SHA-1 */ + b2 = 0x1; /* RSA */ + hLen = SHA1_HASH_SIZE; + break; +#endif +#ifdef USE_SHA256 + case OID_SHA256_ECDSA_SIG: + b1 = 0x4; /* SHA-256 */ + b2 = 0x3; /* ECDSA */ + hLen = SHA256_HASH_SIZE; + break; + case OID_SHA256_RSA_SIG: + b1 = 0x4; /* SHA-256 */ + b2 = 0x1; /* RSA */ + hLen = SHA256_HASH_SIZE; + break; +#endif +#ifdef USE_SHA384 + case OID_SHA384_ECDSA_SIG: + b1 = 0x5; /* SHA-384 */ + b2 = 0x3; /* ECDSA */ + hLen = SHA384_HASH_SIZE; + break; + case OID_SHA384_RSA_SIG: + b1 = 0x5; /* SHA-384 */ + b2 = 0x1; /* RSA */ + hLen = SHA384_HASH_SIZE; + break; +#endif +#ifdef USE_SHA512 + case OID_SHA512_ECDSA_SIG: + b1 = 0x6; /* SHA-512 */ + b2 = 0x3; /* ECDSA */ + hLen = SHA512_HASH_SIZE; + break; + case OID_SHA512_RSA_SIG: + b1 = 0x6; /* SHA-512 */ + b2 = 0x1; /* RSA */ + hLen = SHA512_HASH_SIZE; + break; +#endif + default: + return PS_UNSUPPORTED_FAIL; + } + + *octet1 = b1; + *octet2 = b2; + *hashSize = hLen; + + return PS_SUCCESS; +} +#endif /* ! USE_ONLY_PSK_CIPHER_SUITE */ +#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ + +# ifdef USE_SSL_INFORMATIONAL_TRACE +void psPrintSigAlgs(uint16_t sigAlgs, const char *where) +{ + if (where) + { + psTraceStrInfo("Signature algorithms in %s:\n", where); + } + + if (sigAlgs & HASH_SIG_MD5_RSA_MASK) + { + _psTrace("RSA-MD5"); + } + if (sigAlgs & HASH_SIG_SHA1_RSA_MASK) + { + _psTrace(" RSA-SHA1"); + } + if (sigAlgs & HASH_SIG_SHA256_RSA_MASK) + { + _psTrace(" RSA-SHA256"); + } + if (sigAlgs & HASH_SIG_SHA384_RSA_MASK) + { + _psTrace(" RSA-SHA384"); + } + if (sigAlgs & HASH_SIG_SHA512_RSA_MASK) + { + _psTrace(" RSA-SHA512"); + } + if (sigAlgs & HASH_SIG_SHA1_ECDSA_MASK) + { + _psTrace(" ECDSA-SHA1"); + } + if (sigAlgs & HASH_SIG_SHA256_ECDSA_MASK) + { + _psTrace(" ECDSA-SHA256"); + } + if (sigAlgs & HASH_SIG_SHA384_ECDSA_MASK) + { + _psTrace(" ECDSA-SHA384"); + } + if (sigAlgs & HASH_SIG_SHA512_ECDSA_MASK) + { + _psTrace(" ECDSA-SHA512"); + } + _psTrace("\n"); +} + +void psPrintProtocolVersion(const char *where, + unsigned char majVer, + unsigned char minVer, + psBool_t addNewline) +{ + if (where) + { + psTraceStrInfo("%s : ", where); + } + if (majVer == TLS_MAJ_VER) + { + if (minVer == TLS_1_2_MIN_VER) + { + _psTrace("TLS 1.2"); + } + else if (minVer == TLS_1_1_MIN_VER) + { + _psTrace("TLS 1.1"); + } + else if (minVer == TLS_1_0_MIN_VER) + { + _psTrace("TLS 1.0"); + } + else if (minVer == SSL3_MIN_VER) + { + _psTrace("SSL 3.0"); + } + else + { + _psTrace("Unsupported protocol version"); + } + } +# ifdef USE_DTLS + else if (majVer == DTLS_MAJ_VER) + { + if (minVer == DTLS_1_2_MIN_VER) + { + _psTrace("DTLS 1.2"); + } + else if (minVer == DTLS_MIN_VER) + { + _psTrace("DTLS 1.0"); + } + else + { + _psTrace("Unsupported protocol version"); + } + } +# endif /* USE_DTLS */ + else + { + _psTrace("Unsupported protocol version"); + } + if (addNewline) + { + _psTrace("\n"); + } +} + +# endif /* USE_SSL_INFORMATIONAL_TRACE */ + /******************************************************************************/ diff --git a/matrixssl/version.h b/matrixssl/version.h index 202d604..d176f85 100644 --- a/matrixssl/version.h +++ b/matrixssl/version.h @@ -8,10 +8,10 @@ extern "C" { #endif -#define MATRIXSSL_VERSION "3.9.3-OPEN" +#define MATRIXSSL_VERSION "3.9.5-OPEN" #define MATRIXSSL_VERSION_MAJOR 3 #define MATRIXSSL_VERSION_MINOR 9 -#define MATRIXSSL_VERSION_PATCH 3 +#define MATRIXSSL_VERSION_PATCH 5 #define MATRIXSSL_VERSION_CODE "OPEN" #ifdef __cplusplus diff --git a/testkeys/EC/192_EC.h b/testkeys/EC/192_EC.h index 6052fc1..7694bbc 100644 --- a/testkeys/EC/192_EC.h +++ b/testkeys/EC/192_EC.h @@ -1,6 +1,6 @@ /** * @file 192_EC.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC192[] = { diff --git a/testkeys/EC/192_EC_CA.h b/testkeys/EC/192_EC_CA.h index 9bce202..ebaf6b9 100644 --- a/testkeys/EC/192_EC_CA.h +++ b/testkeys/EC/192_EC_CA.h @@ -1,6 +1,6 @@ /** * @file 192_EC_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC192CA[] = { diff --git a/testkeys/EC/224_EC.h b/testkeys/EC/224_EC.h index 827af4d..9e6946a 100644 --- a/testkeys/EC/224_EC.h +++ b/testkeys/EC/224_EC.h @@ -1,6 +1,6 @@ /** * @file 224_EC.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC224[] = { diff --git a/testkeys/EC/224_EC_CA.h b/testkeys/EC/224_EC_CA.h index 8067cd8..eb379af 100644 --- a/testkeys/EC/224_EC_CA.h +++ b/testkeys/EC/224_EC_CA.h @@ -1,6 +1,6 @@ /** * @file 224_EC_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC224CA[] = { diff --git a/testkeys/EC/256_EC.h b/testkeys/EC/256_EC.h index 6a0ee8a..1b3dfc9 100644 --- a/testkeys/EC/256_EC.h +++ b/testkeys/EC/256_EC.h @@ -1,6 +1,6 @@ /** * @file 256_EC.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC256[] = { diff --git a/testkeys/EC/256_EC_CA.h b/testkeys/EC/256_EC_CA.h index 8f20066..f946ad7 100644 --- a/testkeys/EC/256_EC_CA.h +++ b/testkeys/EC/256_EC_CA.h @@ -1,6 +1,6 @@ /** * @file 256_EC_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC256CA[] = { diff --git a/testkeys/EC/384_EC.h b/testkeys/EC/384_EC.h index 0a0ff99..a8c7283 100644 --- a/testkeys/EC/384_EC.h +++ b/testkeys/EC/384_EC.h @@ -1,6 +1,6 @@ /** * @file 384_EC.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC384[] = { diff --git a/testkeys/EC/384_EC_CA.h b/testkeys/EC/384_EC_CA.h index c7abe20..d92f793 100644 --- a/testkeys/EC/384_EC_CA.h +++ b/testkeys/EC/384_EC_CA.h @@ -1,6 +1,6 @@ /** * @file 384_EC_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC384CA[] = { diff --git a/testkeys/EC/521_EC.h b/testkeys/EC/521_EC.h index 7909f5c..0907ef7 100644 --- a/testkeys/EC/521_EC.h +++ b/testkeys/EC/521_EC.h @@ -1,6 +1,6 @@ /** * @file 521_EC.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC521[] = { diff --git a/testkeys/EC/521_EC_CA.h b/testkeys/EC/521_EC_CA.h index 0d215d4..6897a46 100644 --- a/testkeys/EC/521_EC_CA.h +++ b/testkeys/EC/521_EC_CA.h @@ -1,6 +1,6 @@ /** * @file 521_EC_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char EC521CA[] = { diff --git a/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.h b/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.h index c8bacac..13c0df7 100644 --- a/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.h +++ b/testkeys/ECDH_RSA/1024_ECDH-RSA_CA.h @@ -1,6 +1,6 @@ /** * @file 1024_ECDH-RSA_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char ECDHRSA1024CA[] = { diff --git a/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.h b/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.h index 9c522cd..0b904cc 100644 --- a/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.h +++ b/testkeys/ECDH_RSA/2048_ECDH-RSA_CA.h @@ -1,6 +1,6 @@ /** * @file 2048_ECDH-RSA_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char ECDHRSA2048CA[] = { diff --git a/testkeys/ECDH_RSA/256_ECDH-RSA.h b/testkeys/ECDH_RSA/256_ECDH-RSA.h index 4d3d341..650bb4c 100644 --- a/testkeys/ECDH_RSA/256_ECDH-RSA.h +++ b/testkeys/ECDH_RSA/256_ECDH-RSA.h @@ -1,6 +1,6 @@ /** * @file 256_ECDH-RSA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char ECDHRSA256[] = { diff --git a/testkeys/ECDH_RSA/521_ECDH-RSA.h b/testkeys/ECDH_RSA/521_ECDH-RSA.h index fa1e6aa..4058c09 100644 --- a/testkeys/ECDH_RSA/521_ECDH-RSA.h +++ b/testkeys/ECDH_RSA/521_ECDH-RSA.h @@ -1,6 +1,6 @@ /** * @file 521_ECDH-RSA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char ECDHRSA521[] = { diff --git a/testkeys/RSA/1024_RSA.h b/testkeys/RSA/1024_RSA.h index 7652bc8..2bdf29e 100644 --- a/testkeys/RSA/1024_RSA.h +++ b/testkeys/RSA/1024_RSA.h @@ -1,6 +1,6 @@ /** * @file 1024_RSA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char RSA1024[] = { diff --git a/testkeys/RSA/1024_RSA_CA.h b/testkeys/RSA/1024_RSA_CA.h index dd56f36..2fe9076 100644 --- a/testkeys/RSA/1024_RSA_CA.h +++ b/testkeys/RSA/1024_RSA_CA.h @@ -1,6 +1,6 @@ /** * @file 1024_RSA_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char RSA1024CA[] = { diff --git a/testkeys/RSA/2048_RSA.h b/testkeys/RSA/2048_RSA.h index 9e0e765..cb51431 100644 --- a/testkeys/RSA/2048_RSA.h +++ b/testkeys/RSA/2048_RSA.h @@ -1,6 +1,6 @@ /** * @file 2048_RSA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char RSA2048[] = { diff --git a/testkeys/RSA/2048_RSA_CA.h b/testkeys/RSA/2048_RSA_CA.h index f9f81e4..3d47f63 100644 --- a/testkeys/RSA/2048_RSA_CA.h +++ b/testkeys/RSA/2048_RSA_CA.h @@ -1,6 +1,6 @@ /** * @file 2048_RSA_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char RSA2048CA[] = { diff --git a/testkeys/RSA/3072_RSA.h b/testkeys/RSA/3072_RSA.h index 57d2962..f42d142 100644 --- a/testkeys/RSA/3072_RSA.h +++ b/testkeys/RSA/3072_RSA.h @@ -1,6 +1,6 @@ /** * @file 3072_RSA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char RSA3072[] = { diff --git a/testkeys/RSA/3072_RSA_CA.h b/testkeys/RSA/3072_RSA_CA.h index 5062367..2491761 100644 --- a/testkeys/RSA/3072_RSA_CA.h +++ b/testkeys/RSA/3072_RSA_CA.h @@ -1,6 +1,6 @@ /** * @file 3072_RSA_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char RSA3072CA[] = { diff --git a/testkeys/RSA/4096_RSA.h b/testkeys/RSA/4096_RSA.h index bd86700..3221960 100644 --- a/testkeys/RSA/4096_RSA.h +++ b/testkeys/RSA/4096_RSA.h @@ -1,6 +1,6 @@ /** * @file 4096_RSA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char RSA4096[] = { diff --git a/testkeys/RSA/4096_RSA_CA.h b/testkeys/RSA/4096_RSA_CA.h index 830764a..4641c3d 100644 --- a/testkeys/RSA/4096_RSA_CA.h +++ b/testkeys/RSA/4096_RSA_CA.h @@ -1,6 +1,6 @@ /** * @file 4096_RSA_CA.h - * + * @version :%h%d$ * Binary file for including certificate to MatrixSSL. */ static const unsigned char RSA4096CA[] = { diff --git a/testkeys/RSA/ALL_RSA_CAS.h b/testkeys/RSA/ALL_RSA_CAS.h index 446694d..3c33cdf 100644 --- a/testkeys/RSA/ALL_RSA_CAS.h +++ b/testkeys/RSA/ALL_RSA_CAS.h @@ -73,7 +73,7 @@ const static unsigned char RSACAS[] = { 0x16, 0x98, 0x93, 0x7c, 0xf0, 0x42, 0x24, 0xf6, 0x7c, 0xa7, 0x94, 0x89, 0xe6, 0x70, 0x0e, 0x60, 0x30, 0xe8, 0x7a, 0x57, 0x30, 0x82, 0x04, 0x69, 0x30, 0x82, 0x03, 0x51, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, - 0xd0, 0xdd, 0x75, 0x52, 0xf7, 0xfa, 0xf9, 0xfe, 0x30, 0x0d, 0x06, 0x09, + 0xf3, 0x16, 0x51, 0xf5, 0x47, 0x28, 0x6f, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xbf, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x49, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, @@ -91,9 +91,9 @@ const static unsigned char RSACAS[] = { 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x74, 0x65, 0x73, 0x74, 0x40, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x36, 0x31, - 0x37, 0x30, 0x37, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, 0x33, - 0x31, 0x36, 0x31, 0x37, 0x30, 0x37, 0x33, 0x33, 0x5a, 0x30, 0x81, 0xbf, + 0x73, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x37, 0x30, + 0x39, 0x33, 0x31, 0x33, 0x31, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, 0x33, + 0x31, 0x37, 0x30, 0x39, 0x33, 0x31, 0x33, 0x31, 0x5a, 0x30, 0x81, 0xbf, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x49, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x07, 0x46, 0x69, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, @@ -142,31 +142,31 @@ const static unsigned char RSACAS[] = { 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x7b, 0x38, 0x71, 0xc2, 0xa1, 0xe1, 0xbc, 0x86, 0x55, 0xd9, 0x29, 0xbe, 0x2e, 0x2e, 0x5c, 0x55, 0x1d, 0xbe, 0xe8, 0x22, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x00, - 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x52, 0xaf, 0xc0, - 0x53, 0x3a, 0xf1, 0xa5, 0x22, 0xab, 0xf7, 0x00, 0xaf, 0xcd, 0x08, 0x5e, - 0x21, 0x85, 0xa8, 0x6b, 0x94, 0xd7, 0x53, 0x3b, 0x62, 0x1a, 0x89, 0xab, - 0x6e, 0x8f, 0x32, 0xfa, 0xb2, 0x66, 0x9d, 0xdb, 0xbe, 0xaf, 0x29, 0x79, - 0x6a, 0x2c, 0xa6, 0x1a, 0x0d, 0xf0, 0x55, 0x34, 0xd6, 0xea, 0x2c, 0xa6, - 0x49, 0xaf, 0x14, 0x74, 0x33, 0x28, 0x82, 0xee, 0xec, 0xdb, 0x42, 0x17, - 0x29, 0x0b, 0xf7, 0x0b, 0xda, 0x2a, 0x35, 0x62, 0x2f, 0x6f, 0xa2, 0x87, - 0x71, 0xa9, 0xb2, 0x7a, 0x50, 0x57, 0xb9, 0x23, 0x1c, 0x0a, 0x01, 0x46, - 0xe3, 0x43, 0x91, 0xa9, 0x92, 0xbb, 0xa3, 0xbf, 0xd6, 0xa9, 0x42, 0x04, - 0x4f, 0xb7, 0xa1, 0x9f, 0x66, 0xc7, 0x07, 0x49, 0xb8, 0xc6, 0x55, 0xfc, - 0x63, 0x4d, 0x22, 0xc0, 0xea, 0x94, 0xee, 0x54, 0x23, 0x61, 0x26, 0x0c, - 0xeb, 0xea, 0x33, 0xa4, 0xa4, 0xab, 0x94, 0xe1, 0x10, 0x5c, 0x9d, 0x5e, - 0x6b, 0x80, 0xa6, 0x18, 0x32, 0x59, 0x2d, 0x4e, 0x55, 0xc0, 0x74, 0x98, - 0x7b, 0x8a, 0x11, 0x16, 0x8d, 0x26, 0xd7, 0xb2, 0x8c, 0x2f, 0xc5, 0x39, - 0xb9, 0x7e, 0x4d, 0xe4, 0xc2, 0x08, 0xf8, 0x30, 0xff, 0x3f, 0xee, 0x58, - 0x8a, 0x5a, 0x71, 0xa6, 0xf2, 0xcf, 0x71, 0x8d, 0x8f, 0xff, 0x42, 0xf5, - 0x5a, 0x62, 0x6d, 0x41, 0x09, 0x78, 0xab, 0xda, 0xed, 0x2b, 0x06, 0x32, - 0x34, 0x81, 0x71, 0x01, 0xf5, 0x55, 0x46, 0x37, 0x32, 0x73, 0x3b, 0x53, - 0xe4, 0xd6, 0x11, 0xeb, 0x8d, 0x75, 0xf6, 0x20, 0xd7, 0x4e, 0xaf, 0x34, - 0xaf, 0x6b, 0x45, 0xe6, 0xd9, 0x54, 0x30, 0xcf, 0xea, 0xfc, 0xa3, 0x95, - 0xf1, 0x41, 0x63, 0x3c, 0x04, 0x7c, 0xa1, 0x0b, 0x21, 0x16, 0x5b, 0xf8, - 0xdd, 0x30, 0x42, 0xb3, 0x0d, 0xba, 0x75, 0xe3, 0x3b, 0xc8, 0x28, 0x8a, - 0x93, 0x30, 0x82, 0x05, 0x69, 0x30, 0x82, 0x03, 0xd1, 0xa0, 0x03, 0x02, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, + 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x28, 0x3d, 0xbe, + 0xba, 0x1e, 0xe1, 0xea, 0xc0, 0x47, 0x4d, 0x11, 0xef, 0x10, 0x4f, 0x96, + 0x2e, 0x85, 0x9a, 0x7b, 0xba, 0xc8, 0xbd, 0x5a, 0xdc, 0x6a, 0x26, 0x8c, + 0x0f, 0x87, 0x50, 0x4c, 0x04, 0x0b, 0x0b, 0xe9, 0xe4, 0x14, 0xa7, 0xf5, + 0x20, 0x15, 0x5c, 0x6d, 0x8f, 0xbd, 0x4d, 0xcc, 0xdf, 0x76, 0xc3, 0x18, + 0xc4, 0xf9, 0x20, 0xef, 0x20, 0x40, 0x5f, 0x6e, 0xab, 0xa7, 0xfc, 0x9c, + 0xc6, 0x51, 0x7d, 0x26, 0xee, 0x12, 0xb4, 0xac, 0x35, 0xda, 0x23, 0xdf, + 0x42, 0x03, 0x52, 0xc2, 0x84, 0xa7, 0x85, 0x13, 0x24, 0x24, 0xc2, 0x56, + 0x3e, 0xaf, 0x2a, 0xfe, 0x7f, 0x8d, 0xd9, 0x6c, 0xff, 0x75, 0x91, 0x0a, + 0xd2, 0x62, 0x3f, 0x4f, 0x22, 0x61, 0xfb, 0x98, 0x69, 0xd8, 0x37, 0xa4, + 0xf0, 0xde, 0x4b, 0x25, 0x05, 0x49, 0x9e, 0xeb, 0x33, 0x2c, 0x00, 0xca, + 0x3a, 0x4d, 0xb2, 0x97, 0xb2, 0xef, 0xc3, 0x50, 0xdd, 0xce, 0xdb, 0x7a, + 0x03, 0xa1, 0xa3, 0x9a, 0x40, 0x01, 0x06, 0xf3, 0xf8, 0x53, 0xc4, 0x92, + 0xc3, 0x2c, 0xb1, 0xc4, 0x7c, 0xed, 0x27, 0x84, 0x2a, 0x06, 0xef, 0xd8, + 0x63, 0x7b, 0x50, 0xbf, 0xe8, 0xaf, 0x6d, 0x0d, 0x0d, 0x97, 0x09, 0xf9, + 0x5e, 0x8d, 0xc7, 0xed, 0x4f, 0x3c, 0x38, 0x29, 0xdc, 0x96, 0xa7, 0x6d, + 0xfd, 0x6c, 0xa8, 0x37, 0x57, 0x47, 0x6e, 0x2d, 0x62, 0x5d, 0xa1, 0x5e, + 0x21, 0xab, 0x81, 0xec, 0xd6, 0xa1, 0xe1, 0x72, 0x51, 0x76, 0x67, 0xd9, + 0x32, 0xe0, 0x86, 0x23, 0xc0, 0x3d, 0xf2, 0x73, 0xb9, 0x5c, 0x99, 0x7c, + 0x59, 0x84, 0x78, 0x4d, 0xd7, 0x27, 0x69, 0x48, 0xcb, 0xf9, 0x9b, 0xac, + 0x5b, 0x81, 0x13, 0xd5, 0x93, 0x52, 0x2b, 0xa2, 0x2e, 0xde, 0x97, 0x36, + 0x50, 0x4f, 0x07, 0xc3, 0xba, 0xe1, 0x11, 0xbd, 0x98, 0xbb, 0x2f, 0xce, + 0x48, 0x30, 0x82, 0x05, 0x69, 0x30, 0x82, 0x03, 0xd1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xa6, 0xff, 0xcc, 0x19, 0x5b, 0xdf, 0xdd, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xbf, 0x31, 0x0b, 0x30, 0x09, 0x06, diff --git a/testkeys/RSA/ALL_RSA_CAS.pem b/testkeys/RSA/ALL_RSA_CAS.pem index 1e35d54..a610da5 100644 --- a/testkeys/RSA/ALL_RSA_CAS.pem +++ b/testkeys/RSA/ALL_RSA_CAS.pem @@ -20,12 +20,12 @@ AV50HdCjlLfLrAsmxrUJZdO5rKgCpbEgP07CppNadVS3fLieFpiTfPBCJPZ8p5SJ 5nAOYDDoelc= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEaTCCA1GgAwIBAgIJANDddVL3+vn+MA0GCSqGSIb3DQEBCwUAMIG/MQswCQYD +MIIEaTCCA1GgAwIBAgIJAPMWUfVHKG8DMA0GCSqGSIb3DQEBCwUAMIG/MQswCQYD VQQGEwJGSTEQMA4GA1UECAwHRmlubGFuZDERMA8GA1UEBwwISGVsc2lua2kxIjAg BgNVBAoMGUlOU0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3Qx NTAzBgNVBAMMLFNhbXBsZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0 aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJ0ZXN0QGVtYWlsLmFkZHJlc3MwHhcNMTcw -MzE2MTcwNzMzWhcNMjcwMzE2MTcwNzMzWjCBvzELMAkGA1UEBhMCRkkxEDAOBgNV +MzE3MDkzMTMxWhcNMjcwMzE3MDkzMTMxWjCBvzELMAkGA1UEBhMCRkkxEDAOBgNV BAgMB0ZpbmxhbmQxETAPBgNVBAcMCEhlbHNpbmtpMSIwIAYDVQQKDBlJTlNJREUg U2VjdXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTUwMwYDVQQDDCxTYW1w bGUgTWF0cml4IFJTQS0yMDQ4IENlcnRpZmljYXRlIEF1dGhvcml0eTEhMB8GCSqG @@ -37,13 +37,13 @@ LpaPv0RgdvQU5nEZ8vqsLcWDLGamoyiFUz+tVCCHssCLecjZsiRznbtfZkfHHrKH WNdaalZr2rpRef8hB805UbX0tpmtSfp+fG58tXCGB7ovsRTec3IOny3dh5sD4l/J 8Pbj9l+dGb/D5DSWI+BSBqyh+s6KEIViV2P8ewIDAQABo2YwZDASBgNVHRMBAf8E CDAGAQH/AgEAMB0GA1UdDgQWBBR7OHHCoeG8hlXZKb4uLlxVHb7oIjAfBgNVHSME -GDAWgBR7OHHCoeG8hlXZKb4uLlxVHb7oIjAOBgNVHQ8BAf8EBAMCAAQwDQYJKoZI -hvcNAQELBQADggEBAFKvwFM68aUiq/cAr80IXiGFqGuU11M7YhqJq26PMvqyZp3b -vq8peWosphoN8FU01uospkmvFHQzKILu7NtCFykL9wvaKjViL2+ih3GpsnpQV7kj -HAoBRuNDkamSu6O/1qlCBE+3oZ9mxwdJuMZV/GNNIsDqlO5UI2EmDOvqM6Skq5Th -EFydXmuAphgyWS1OVcB0mHuKERaNJteyjC/FObl+TeTCCPgw/z/uWIpacabyz3GN -j/9C9VpibUEJeKva7SsGMjSBcQH1VUY3MnM7U+TWEeuNdfYg106vNK9rRebZVDDP -6vyjlfFBYzwEfKELIRZb+N0wQrMNunXjO8goipM= +GDAWgBR7OHHCoeG8hlXZKb4uLlxVHb7oIjAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQELBQADggEBACg9vroe4erAR00R7xBPli6Fmnu6yL1a3GomjA+HUEwECwvp +5BSn9SAVXG2PvU3M33bDGMT5IO8gQF9uq6f8nMZRfSbuErSsNdoj30IDUsKEp4UT +JCTCVj6vKv5/jdls/3WRCtJiP08iYfuYadg3pPDeSyUFSZ7rMywAyjpNspey78NQ +3c7begOho5pAAQbz+FPEksMsscR87SeEKgbv2GN7UL/or20NDZcJ+V6Nx+1PPDgp +3Janbf1sqDdXR24tYl2hXiGrgezWoeFyUXZn2TLghiPAPfJzuVyZfFmEeE3XJ2lI +y/mbrFuBE9WTUiuiLt6XNlBPB8O64RG9mLsvzkg= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFaTCCA9GgAwIBAgIJAKb/zBlb390tMA0GCSqGSIb3DQEBCwUAMIG/MQswCQYD diff --git a/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.h b/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.h index ca9c5f5..34f9a51 100644 --- a/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.h +++ b/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.h @@ -1,6 +1,6 @@ const static unsigned char RSACAS[] = { 0x30, 0x82, 0x04, 0x69, 0x30, 0x82, 0x03, 0x51, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x09, 0x00, 0xd0, 0xdd, 0x75, 0x52, 0xf7, 0xfa, 0xf9, 0xfe, + 0x02, 0x02, 0x09, 0x00, 0xf3, 0x16, 0x51, 0xf5, 0x47, 0x28, 0x6f, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xbf, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x49, 0x31, 0x10, 0x30, 0x0e, 0x06, @@ -19,8 +19,8 @@ const static unsigned char RSACAS[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x74, 0x65, 0x73, 0x74, 0x40, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, - 0x33, 0x31, 0x36, 0x31, 0x37, 0x30, 0x37, 0x33, 0x33, 0x5a, 0x17, 0x0d, - 0x32, 0x37, 0x30, 0x33, 0x31, 0x36, 0x31, 0x37, 0x30, 0x37, 0x33, 0x33, + 0x33, 0x31, 0x37, 0x30, 0x39, 0x33, 0x31, 0x33, 0x31, 0x5a, 0x17, 0x0d, + 0x32, 0x37, 0x30, 0x33, 0x31, 0x37, 0x30, 0x39, 0x33, 0x31, 0x33, 0x31, 0x5a, 0x30, 0x81, 0xbf, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x49, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x07, 0x46, 0x69, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x31, @@ -70,30 +70,30 @@ const static unsigned char RSACAS[] = { 0x18, 0x30, 0x16, 0x80, 0x14, 0x7b, 0x38, 0x71, 0xc2, 0xa1, 0xe1, 0xbc, 0x86, 0x55, 0xd9, 0x29, 0xbe, 0x2e, 0x2e, 0x5c, 0x55, 0x1d, 0xbe, 0xe8, 0x22, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, - 0x04, 0x03, 0x02, 0x00, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, - 0x00, 0x52, 0xaf, 0xc0, 0x53, 0x3a, 0xf1, 0xa5, 0x22, 0xab, 0xf7, 0x00, - 0xaf, 0xcd, 0x08, 0x5e, 0x21, 0x85, 0xa8, 0x6b, 0x94, 0xd7, 0x53, 0x3b, - 0x62, 0x1a, 0x89, 0xab, 0x6e, 0x8f, 0x32, 0xfa, 0xb2, 0x66, 0x9d, 0xdb, - 0xbe, 0xaf, 0x29, 0x79, 0x6a, 0x2c, 0xa6, 0x1a, 0x0d, 0xf0, 0x55, 0x34, - 0xd6, 0xea, 0x2c, 0xa6, 0x49, 0xaf, 0x14, 0x74, 0x33, 0x28, 0x82, 0xee, - 0xec, 0xdb, 0x42, 0x17, 0x29, 0x0b, 0xf7, 0x0b, 0xda, 0x2a, 0x35, 0x62, - 0x2f, 0x6f, 0xa2, 0x87, 0x71, 0xa9, 0xb2, 0x7a, 0x50, 0x57, 0xb9, 0x23, - 0x1c, 0x0a, 0x01, 0x46, 0xe3, 0x43, 0x91, 0xa9, 0x92, 0xbb, 0xa3, 0xbf, - 0xd6, 0xa9, 0x42, 0x04, 0x4f, 0xb7, 0xa1, 0x9f, 0x66, 0xc7, 0x07, 0x49, - 0xb8, 0xc6, 0x55, 0xfc, 0x63, 0x4d, 0x22, 0xc0, 0xea, 0x94, 0xee, 0x54, - 0x23, 0x61, 0x26, 0x0c, 0xeb, 0xea, 0x33, 0xa4, 0xa4, 0xab, 0x94, 0xe1, - 0x10, 0x5c, 0x9d, 0x5e, 0x6b, 0x80, 0xa6, 0x18, 0x32, 0x59, 0x2d, 0x4e, - 0x55, 0xc0, 0x74, 0x98, 0x7b, 0x8a, 0x11, 0x16, 0x8d, 0x26, 0xd7, 0xb2, - 0x8c, 0x2f, 0xc5, 0x39, 0xb9, 0x7e, 0x4d, 0xe4, 0xc2, 0x08, 0xf8, 0x30, - 0xff, 0x3f, 0xee, 0x58, 0x8a, 0x5a, 0x71, 0xa6, 0xf2, 0xcf, 0x71, 0x8d, - 0x8f, 0xff, 0x42, 0xf5, 0x5a, 0x62, 0x6d, 0x41, 0x09, 0x78, 0xab, 0xda, - 0xed, 0x2b, 0x06, 0x32, 0x34, 0x81, 0x71, 0x01, 0xf5, 0x55, 0x46, 0x37, - 0x32, 0x73, 0x3b, 0x53, 0xe4, 0xd6, 0x11, 0xeb, 0x8d, 0x75, 0xf6, 0x20, - 0xd7, 0x4e, 0xaf, 0x34, 0xaf, 0x6b, 0x45, 0xe6, 0xd9, 0x54, 0x30, 0xcf, - 0xea, 0xfc, 0xa3, 0x95, 0xf1, 0x41, 0x63, 0x3c, 0x04, 0x7c, 0xa1, 0x0b, - 0x21, 0x16, 0x5b, 0xf8, 0xdd, 0x30, 0x42, 0xb3, 0x0d, 0xba, 0x75, 0xe3, - 0x3b, 0xc8, 0x28, 0x8a, 0x93, 0x30, 0x82, 0x05, 0x69, 0x30, 0x82, 0x03, + 0x00, 0x28, 0x3d, 0xbe, 0xba, 0x1e, 0xe1, 0xea, 0xc0, 0x47, 0x4d, 0x11, + 0xef, 0x10, 0x4f, 0x96, 0x2e, 0x85, 0x9a, 0x7b, 0xba, 0xc8, 0xbd, 0x5a, + 0xdc, 0x6a, 0x26, 0x8c, 0x0f, 0x87, 0x50, 0x4c, 0x04, 0x0b, 0x0b, 0xe9, + 0xe4, 0x14, 0xa7, 0xf5, 0x20, 0x15, 0x5c, 0x6d, 0x8f, 0xbd, 0x4d, 0xcc, + 0xdf, 0x76, 0xc3, 0x18, 0xc4, 0xf9, 0x20, 0xef, 0x20, 0x40, 0x5f, 0x6e, + 0xab, 0xa7, 0xfc, 0x9c, 0xc6, 0x51, 0x7d, 0x26, 0xee, 0x12, 0xb4, 0xac, + 0x35, 0xda, 0x23, 0xdf, 0x42, 0x03, 0x52, 0xc2, 0x84, 0xa7, 0x85, 0x13, + 0x24, 0x24, 0xc2, 0x56, 0x3e, 0xaf, 0x2a, 0xfe, 0x7f, 0x8d, 0xd9, 0x6c, + 0xff, 0x75, 0x91, 0x0a, 0xd2, 0x62, 0x3f, 0x4f, 0x22, 0x61, 0xfb, 0x98, + 0x69, 0xd8, 0x37, 0xa4, 0xf0, 0xde, 0x4b, 0x25, 0x05, 0x49, 0x9e, 0xeb, + 0x33, 0x2c, 0x00, 0xca, 0x3a, 0x4d, 0xb2, 0x97, 0xb2, 0xef, 0xc3, 0x50, + 0xdd, 0xce, 0xdb, 0x7a, 0x03, 0xa1, 0xa3, 0x9a, 0x40, 0x01, 0x06, 0xf3, + 0xf8, 0x53, 0xc4, 0x92, 0xc3, 0x2c, 0xb1, 0xc4, 0x7c, 0xed, 0x27, 0x84, + 0x2a, 0x06, 0xef, 0xd8, 0x63, 0x7b, 0x50, 0xbf, 0xe8, 0xaf, 0x6d, 0x0d, + 0x0d, 0x97, 0x09, 0xf9, 0x5e, 0x8d, 0xc7, 0xed, 0x4f, 0x3c, 0x38, 0x29, + 0xdc, 0x96, 0xa7, 0x6d, 0xfd, 0x6c, 0xa8, 0x37, 0x57, 0x47, 0x6e, 0x2d, + 0x62, 0x5d, 0xa1, 0x5e, 0x21, 0xab, 0x81, 0xec, 0xd6, 0xa1, 0xe1, 0x72, + 0x51, 0x76, 0x67, 0xd9, 0x32, 0xe0, 0x86, 0x23, 0xc0, 0x3d, 0xf2, 0x73, + 0xb9, 0x5c, 0x99, 0x7c, 0x59, 0x84, 0x78, 0x4d, 0xd7, 0x27, 0x69, 0x48, + 0xcb, 0xf9, 0x9b, 0xac, 0x5b, 0x81, 0x13, 0xd5, 0x93, 0x52, 0x2b, 0xa2, + 0x2e, 0xde, 0x97, 0x36, 0x50, 0x4f, 0x07, 0xc3, 0xba, 0xe1, 0x11, 0xbd, + 0x98, 0xbb, 0x2f, 0xce, 0x48, 0x30, 0x82, 0x05, 0x69, 0x30, 0x82, 0x03, 0xd1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xa6, 0xff, 0xcc, 0x19, 0x5b, 0xdf, 0xdd, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xbf, 0x31, diff --git a/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.pem b/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.pem index a93441b..063f8a2 100644 --- a/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.pem +++ b/testkeys/RSA/ALL_RSA_CAS_EXCEPT_1024.pem @@ -1,10 +1,10 @@ -----BEGIN CERTIFICATE----- -MIIEaTCCA1GgAwIBAgIJANDddVL3+vn+MA0GCSqGSIb3DQEBCwUAMIG/MQswCQYD +MIIEaTCCA1GgAwIBAgIJAPMWUfVHKG8DMA0GCSqGSIb3DQEBCwUAMIG/MQswCQYD VQQGEwJGSTEQMA4GA1UECAwHRmlubGFuZDERMA8GA1UEBwwISGVsc2lua2kxIjAg BgNVBAoMGUlOU0lERSBTZWN1cmUgQ29ycG9yYXRpb24xDTALBgNVBAsMBFRlc3Qx NTAzBgNVBAMMLFNhbXBsZSBNYXRyaXggUlNBLTIwNDggQ2VydGlmaWNhdGUgQXV0 aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJ0ZXN0QGVtYWlsLmFkZHJlc3MwHhcNMTcw -MzE2MTcwNzMzWhcNMjcwMzE2MTcwNzMzWjCBvzELMAkGA1UEBhMCRkkxEDAOBgNV +MzE3MDkzMTMxWhcNMjcwMzE3MDkzMTMxWjCBvzELMAkGA1UEBhMCRkkxEDAOBgNV BAgMB0ZpbmxhbmQxETAPBgNVBAcMCEhlbHNpbmtpMSIwIAYDVQQKDBlJTlNJREUg U2VjdXJlIENvcnBvcmF0aW9uMQ0wCwYDVQQLDARUZXN0MTUwMwYDVQQDDCxTYW1w bGUgTWF0cml4IFJTQS0yMDQ4IENlcnRpZmljYXRlIEF1dGhvcml0eTEhMB8GCSqG @@ -16,13 +16,13 @@ LpaPv0RgdvQU5nEZ8vqsLcWDLGamoyiFUz+tVCCHssCLecjZsiRznbtfZkfHHrKH WNdaalZr2rpRef8hB805UbX0tpmtSfp+fG58tXCGB7ovsRTec3IOny3dh5sD4l/J 8Pbj9l+dGb/D5DSWI+BSBqyh+s6KEIViV2P8ewIDAQABo2YwZDASBgNVHRMBAf8E CDAGAQH/AgEAMB0GA1UdDgQWBBR7OHHCoeG8hlXZKb4uLlxVHb7oIjAfBgNVHSME -GDAWgBR7OHHCoeG8hlXZKb4uLlxVHb7oIjAOBgNVHQ8BAf8EBAMCAAQwDQYJKoZI -hvcNAQELBQADggEBAFKvwFM68aUiq/cAr80IXiGFqGuU11M7YhqJq26PMvqyZp3b -vq8peWosphoN8FU01uospkmvFHQzKILu7NtCFykL9wvaKjViL2+ih3GpsnpQV7kj -HAoBRuNDkamSu6O/1qlCBE+3oZ9mxwdJuMZV/GNNIsDqlO5UI2EmDOvqM6Skq5Th -EFydXmuAphgyWS1OVcB0mHuKERaNJteyjC/FObl+TeTCCPgw/z/uWIpacabyz3GN -j/9C9VpibUEJeKva7SsGMjSBcQH1VUY3MnM7U+TWEeuNdfYg106vNK9rRebZVDDP -6vyjlfFBYzwEfKELIRZb+N0wQrMNunXjO8goipM= +GDAWgBR7OHHCoeG8hlXZKb4uLlxVHb7oIjAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQELBQADggEBACg9vroe4erAR00R7xBPli6Fmnu6yL1a3GomjA+HUEwECwvp +5BSn9SAVXG2PvU3M33bDGMT5IO8gQF9uq6f8nMZRfSbuErSsNdoj30IDUsKEp4UT +JCTCVj6vKv5/jdls/3WRCtJiP08iYfuYadg3pPDeSyUFSZ7rMywAyjpNspey78NQ +3c7begOho5pAAQbz+FPEksMsscR87SeEKgbv2GN7UL/or20NDZcJ+V6Nx+1PPDgp +3Janbf1sqDdXR24tYl2hXiGrgezWoeFyUXZn2TLghiPAPfJzuVyZfFmEeE3XJ2lI +y/mbrFuBE9WTUiuiLt6XNlBPB8O64RG9mLsvzkg= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFaTCCA9GgAwIBAgIJAKb/zBlb390tMA0GCSqGSIb3DQEBCwUAMIG/MQswCQYD