diff --git a/apps/ssl/Makefile b/apps/ssl/Makefile index 69fb580..fcd498b 100644 --- a/apps/ssl/Makefile +++ b/apps/ssl/Makefile @@ -3,7 +3,7 @@ # 'make' builds debug (Default). # 'make gold' builds optimized. # -# Copyright (c) 2013-2016 INSIDE Secure Corporation. All Rights Reserved. +# Copyright (c) 2013-2019 INSIDE Secure Corporation. All Rights Reserved. # MATRIXSSL_ROOT:=../.. @@ -21,8 +21,10 @@ SIMPLE_CLIENT_EXE:=simpleClient$(E) SIMPLE_SERVER_SRC:=simpleServer.c SIMPLE_SERVER_EXE:=simpleServer$(E) -IA_CLIENT_SRC:=interactiveClient.c +IA_CLIENT_SRC:=interactiveClient.c interactiveCommon.c IA_CLIENT_EXE:=interactiveClient$(E) +IA_SERVER_SRC:=interactiveServer.c interactiveCommon.c +IA_SERVER_EXE:=interactiveServer$(E) SRC+=$(SIMPLE_CLIENT_SRC) EXE+=$(SIMPLE_CLIENT_EXE) @@ -30,6 +32,8 @@ SRC+=$(SIMPLE_SERVER_SRC) EXE+=$(SIMPLE_SERVER_EXE) SRC+=$(IA_CLIENT_SRC) EXE+=$(IA_CLIENT_EXE) +SRC+=$(IA_SERVER_SRC) +EXE+=$(IA_SERVER_EXE) #The Mac OS X Xcode project has a target name of 'server' or 'client' ifneq (,$(TARGET_NAME)) @@ -91,6 +95,9 @@ $(IA_CLIENT_EXE): $(IA_CLIENT_SRC:.c=.o) $(STATIC) $(SIMPLE_SERVER_EXE): $(SIMPLE_SERVER_SRC:.c=.o) $(STATIC) $(CC) -o $@ $^ $(LDFLAGS) $(CFLAGS) +$(IA_SERVER_EXE): $(IA_SERVER_SRC:.c=.o) $(STATIC) + $(CC) -o $@ $^ $(LDFLAGS) $(CFLAGS) + $(NET_EXE): $(NET_SRC:.c=.o) $(STATIC) $(CC) -o $@ $^ $(LDFLAGS) $(CFLAGS) diff --git a/apps/ssl/client.c b/apps/ssl/client.c index 0464247..13f2e47 100644 --- a/apps/ssl/client.c +++ b/apps/ssl/client.c @@ -35,6 +35,12 @@ # define _POSIX_C_SOURCE 200112L #endif +#ifdef __APPLE__ +# ifndef _DARWIN_C_SOURCE +# define _DARWIN_C_SOURCE +# endif +#endif + #ifndef NEED_PS_TIME_CONCRETE # define NEED_PS_TIME_CONCRETE #endif @@ -104,9 +110,6 @@ static unsigned char g_httpRequestHdr[] = "GET %s HTTP/1.0\r\n" "Content-Length: 0\r\n" "\r\n"; -static const char g_strver[][8] = -{ "SSL 3.0", "TLS 1.0", "TLS 1.1", "TLS 1.2", "TLS 1.3" }; - static psList_t *g_groupList; static psSize_t g_num_key_shares; static psList_t *g_sigAlgsList; @@ -130,6 +133,8 @@ static int g_trace; static int g_keepalive; static int g_req_ocsp_stapling; static int g_disable_peer_authentication; +static int g_use_session_tickets; +static int g_handshake_until_ticket; static uint32_t g_bytes_requested; static uint8_t g_send_closure_alert; @@ -197,6 +202,43 @@ static void addTimeDiff(int64 *t, psTime_t t1, psTime_t t2); compatibility. */ extern int32_t psVerToFlag(psProtocolVersion_t ver); +static +int32_t print_connection_extra_details(ssl_t *ssl) +{ + int32_t rc = PS_SUCCESS; + +# ifdef ENABLE_MASTER_SECRET_EXPORT + { + unsigned char *masterSecret = NULL; + psSizeL_t hsMasterSecretLen = 0; + matrixSslGetMasterSecret( + ssl, + &masterSecret, + &hsMasterSecretLen); + psTraceBytes("Master secret", + masterSecret, hsMasterSecretLen); + } +# endif /* ENABLE_MASTER_SECRET_EXPORT */ +# ifdef USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS + { + unsigned char bindings[36]; + psSizeL_t bindingsLen = sizeof(bindings); + + rc = matrixSslGetTlsUniqueChannelBindings( + ssl, + bindings, + &bindingsLen); + if (rc < 0) + { + goto out; + } + psTraceBytes("tls-unique", bindings, bindingsLen); + } +out: +# endif + return rc; +} + /******************************************************************************/ /* Make a secure HTTP request to a defined IP and port @@ -261,6 +303,13 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid, } # endif +# ifdef USE_STATELESS_SESSION_TICKETS + if (g_use_session_tickets) + { + options.ticketResumption = PS_TRUE; + } +# endif + # ifdef USE_DH rc = matrixSslSessOptsSetMinDhBits(&options, g_min_dh_p_size); if (rc != PS_SUCCESS) @@ -487,19 +536,7 @@ WRITE_MORE: if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { Printf("TLS handshake complete.\n"); -# ifdef ENABLE_MASTER_SECRET_EXPORT - { - unsigned char *masterSecret = NULL; - psSizeL_t hsMasterSecretLen = 0; - matrixSslGetMasterSecret( - ssl, - &masterSecret, - &hsMasterSecretLen); - psTraceBytes("Master secret", - masterSecret, hsMasterSecretLen); - } -# endif /* ENABLE_MASTER_SECRET_EXPORT */ - + (void)print_connection_extra_details(ssl); if ((matrixSslGetNegotiatedVersion(ssl) & v_tls_1_3_any) && sid != NULL && g_resumed > 0) { @@ -666,19 +703,7 @@ PROCESS_MORE: goto WRITE_MORE; # else Printf("TLS handshake complete.\n"); - -# ifdef ENABLE_MASTER_SECRET_EXPORT - { - unsigned char *masterSecret = NULL; - psSizeL_t hsMasterSecretLen = 0; - matrixSslGetMasterSecret( - ssl, - &masterSecret, - &hsMasterSecretLen); - psTraceBytes("Master secret", - masterSecret, hsMasterSecretLen); - } -# endif /* ENABLE_MASTER_SECRET_EXPORT */ + print_connection_extra_details(ssl); /* We got the Finished SSL message, initiate the HTTP req */ if ((rc = httpWriteRequest(ssl)) < 0) @@ -1112,6 +1137,8 @@ static int32 process_cmd_options(int32 argc, char **argv) #define ARG_TLS13_BLOCK_SIZE 18 #define ARG_MIN_DH_P_SIZE 19 #define ARG_PSK_SHA384 20 +#define ARG_USE_SESSION_TICKETS 21 +#define ARG_HANDSHAKE_UNTIL_TICKET 22 static struct option long_options[] = { @@ -1152,6 +1179,8 @@ static int32 process_cmd_options(int32 argc, char **argv) {"req-ocsp-stapling", no_argument, NULL, ARG_REQ_OCSP_STAPLING}, {"disable-peer-authentication", no_argument, NULL, ARG_DISABLE_PEER_AUTHENTICATION}, {"min-dh-p-size", required_argument, NULL, ARG_MIN_DH_P_SIZE}, + {"use-session-tickets", no_argument, NULL, ARG_USE_SESSION_TICKETS}, + {"handshake-until-ticket", no_argument, NULL, ARG_HANDSHAKE_UNTIL_TICKET}, {0, 0, 0, 0} }; @@ -1442,6 +1471,12 @@ static int32 process_cmd_options(int32 argc, char **argv) } } break; + case ARG_USE_SESSION_TICKETS: + g_use_session_tickets = 1; + break; + case ARG_HANDSHAKE_UNTIL_TICKET: + g_handshake_until_ticket = 1; + break; #endif /* USE_GETOPT_LONG */ } @@ -1493,6 +1528,21 @@ int32 main(int32 argc, char **argv) WSAStartup(MAKEWORD(1, 1), &wsaData); # endif + rc = PS_CONFIG_CHECK_SSL; + printf("TLS configuration consistency check: "); + if (rc == PS_SUCCESS) + { + printf("OK\n"); + } + else + { + printf("FAILED\n"); + PS_CONFIG_PRINTF; + printf("Exiting: failed configuration consistency check " \ + "in main()\n"); + return EXIT_FAILURE; + } + exit_code = 0; clientconfigInitialize(); @@ -1598,7 +1648,8 @@ int32 main(int32 argc, char **argv) g_new = 1; } - for (i = 0; i < g_new; i++) + i = 0; + while (true) { matrixSslNewSessionId(&sid, NULL); # ifdef USE_CRL @@ -1626,11 +1677,52 @@ int32 main(int32 argc, char **argv) { Printf("N"); Fflush(stdout); } - /* Leave the final sessionID for resumed connections */ + psTraceBytes("stored session_id", + matrixSslSessionIdGetSessionId(sid), + matrixSslSessionIdGetSessionIdLen(sid)); +# ifdef USE_STATELESS_SESSION_TICKETS + /* Store the last session ticket we receive for resumptions. */ + if (matrixSslSessionIdGetSessionTicket(sid) != NULL && + matrixSslSessionIdGetSessionTicketLen(sid) > 0) + { + const unsigned char *pMasterSecret; + + pMasterSecret = matrixSslSessionIdGetMasterSecret(sid); + Printf("Stored a session ticket.\n"); + psTraceBytes("master secret associated with session ticket", + pMasterSecret, + 48); + /* Clear the session_id so that legacy session id based resumption + will not be attempted. */ + matrixSslSessionIdClearSessionId(sid); + if (g_handshake_until_ticket) + { + break; + } + } +# endif + /* Leave the final session ID for resumed connections. */ if (i + 1 < g_new) { matrixSslDeleteSessionId(sid); } + i++; + if (g_handshake_until_ticket) + { + /* Sanity limit. */ + if (i > 20) + { + break; + } + } + else + { + /* User-provided limit or 1. */ + if (i == g_new) + { + break; + } + } } Printf("\n"); if (g_bytes_requested > 0) @@ -1654,7 +1746,7 @@ int32 main(int32 argc, char **argv) else { Printf("Resumed session.\n"); - Printf("R"); Fflush(stdout); + Fflush(stdout); } } if (g_keepalive) @@ -1675,7 +1767,6 @@ int32 main(int32 argc, char **argv) out: matrixSslDeleteSessionId(sid); - matrixSslDeleteKeys(keys); matrixSslClose(); @@ -1834,10 +1925,34 @@ static int32 certCb(ssl_t *ssl, psX509Cert_t *cert, int32 alert) } if (next->authStatus == PS_CERT_AUTH_FAIL_DN) { + char *missingIssuerDN = NULL; +# ifdef USE_FULL_CERT_PARSE + size_t missingIssuerDNLen; +# endif /* USE_FULL_CERT_PARSE */ + psRes_t rc; + /* A CA file was never located to support this chain */ psTrace("No CA file was found to support server's certificate\n"); /* This should result in a SSL_ALERT_UNKNOWN_CA alert */ alert = SSL_ALERT_UNKNOWN_CA; + /* Print out the DN of the missing CA. */ +# ifdef USE_FULL_CERT_PARSE + rc = psX509GetOnelineDN(&next->issuer, + &missingIssuerDN, + &missingIssuerDNLen, + 0); +# else + rc = -1; +# endif /* USE_FULL_CERT_PARSE */ + if (rc < 0) + { + psTrace("psX509GetOnelineDN failed\n"); + } + else + { + psTraceStr("Missing CA cert:\n%s\n", missingIssuerDN); + psFree(missingIssuerDN, NULL); + } break; } if (next->authStatus == PS_CERT_AUTH_FAIL_AUTHKEY) diff --git a/apps/ssl/interactiveClient.c b/apps/ssl/interactiveClient.c index aa12f88..009b801 100644 --- a/apps/ssl/interactiveClient.c +++ b/apps/ssl/interactiveClient.c @@ -5,7 +5,7 @@ * Interactive client-side test tool. */ /* - * Copyright (c) 2013-2018 INSIDE Secure Corporation + * Copyright (c) 2013-2019 INSIDE Secure Corporation * Copyright (c) PeerSec Networks, 2002-2011 * All Rights Reserved * @@ -35,6 +35,7 @@ #include "osdep.h" # ifdef USE_CLIENT_SIDE_SSL +# include "interactiveCommon.h" # if defined(USE_TLS_1_2) && defined(USE_SECP256R1) && defined(USE_SHA256) && defined(USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) && defined(USE_IDENTITY_CERTIFICATES) @@ -44,35 +45,23 @@ # include # include -/* Key material. */ -# include "testkeys/EC/256_EC.h" -# include "testkeys/EC/256_EC_KEY.h" -# include "testkeys/EC/256_EC_CA.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/ALL_RSA_CAS.h" -# include "testkeys/EC/ALL_EC_CAS.h" -# include "testkeys/PSK/tls13_psk.h" - # define SERVER_IP_ADDRESS "127.0.0.1" # define SERVER_PORT 4433 /* Do we expect the server to the first piece of app data? */ -static int g_server_sends_first; +int g_server_sends_first; /* Use matrixSslEncodeToOutdata for encoding small app data? */ -static int g_encode_to_outdata; +int g_encode_to_outdata; /* Already received MATRIXSSL_HANDSHAKE_COMPLETE? */ -static int g_handshake_complete; +int g_handshake_complete; /* Skip server authentication entirely? */ -static psBool_t g_skip_server_auth; +psBool_t g_skip_server_auth; -static size_t leftNBytes; -static size_t sentNBytes; +size_t leftNBytes; +size_t sentNBytes; /* HTTP GET request header. */ -static unsigned char g_httpRequestHdr[] = "GET %s HTTP/1.1\r\n" +unsigned char g_httpRequestHdr[] = "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: MatrixSSL/" MATRIXSSL_VERSION "\r\n" "Accept: */*\r\n" @@ -94,871 +83,6 @@ static int32_t certCb(ssl_t *ssl, psX509Cert_t *cert, int32_t alert) } } -/* Returns a line of user input (without the newline character), - or < 0 on error. The returned string may be truncated if it - did not fit into buf. */ -int get_user_input(char *buf, int buf_len) -{ - char *s, *p; - char c; - - s = fgets(buf, buf_len, stdin); - if (s == NULL) - { - return PS_FAILURE; - } - - p = strchr(buf, '\n'); - if (p) - { - *p = '\0'; - } - else - { - /* Flush stdin up to newline or EOF. */ - c = getchar(); - while (c != '\n' && !feof(stdin) && !ferror(stdin)) - { - c = getchar(); - } - } - - //printf("Got: %s (len: %zu)\n", buf, strlen(buf)); - - return PS_SUCCESS; -} - -int get_user_input_char(char *c, char defaultChoice) -{ - char buf[2] = {0}; - size_t buf_len = sizeof(buf); - int rc; - - rc = get_user_input(buf, buf_len); - if (rc < 0) - { - return rc; - } - - if (Strlen(buf) == 0) - { - *c = defaultChoice; - } - else - { - *c = buf[0]; - } - - return PS_SUCCESS; -} - -static int32_t getAppDataFromUser(ssl_t *ssl, - unsigned char *data, - size_t *dataLen) -{ - int rc; - char buf[1024] = {0}; - size_t buf_len = sizeof(buf); - size_t max_len; - - max_len = buf_len; - if (*dataLen < buf_len && *dataLen < INT_MAX) - { - max_len = *dataLen; - } - - rc = get_user_input(buf, (int)max_len); - if (rc < 0) - { - printf("Failed to get user input\n"); - return PS_FAILURE; - } - - Memcpy(data, buf, Strlen(buf) + 1); - *dataLen = Strlen(buf) + 1; - - return PS_SUCCESS; -} - -/* - Ask the for app data to send over the encrypted connection, - or for some other action. - Return value: - < 0 on error, - PS_SUCCESS for nominal connection closure - MATRIXSSL_REQUEST_SEND to send app data. -*/ -static int32_t askSendAppData(ssl_t *ssl) -{ - int32_t rc; - unsigned char *buf; - unsigned char data[1024] = {0}; - size_t dataLen = sizeof(data); - size_t sendNBytes; - static unsigned char *fileData = NULL; - unsigned char *pData; - const char *s; - - if (leftNBytes > 0) - { - pData = fileData; - goto continue_sending; - } - - printf("You: "); - rc = getAppDataFromUser(ssl, data, &dataLen); - if (rc < 0) - { - return rc; - } - - if (data[0] == ':') - { - /* Handle commands. */ - - /* Handle :quit, :exit and :q */ - s = (char*)&data[1]; - if (!Strncmp(s, "quit", strlen("quit")) - || !Strncmp(s, "exit", strlen("exit")) - || (dataLen == 2 && data[1] == 'q')) - { - rc = matrixSslEncodeClosureAlert(ssl); - (void)rc; - return PS_SUCCESS; - } - if (!Strncmp(s, "file", strlen("file"))) - { -# ifdef MATRIX_USE_FILE_SYSTEM - printf("Enter file name: "); - dataLen = sizeof(data); - rc = getAppDataFromUser(ssl, data, &dataLen); - if (rc < 0) - { - goto out_fail; - } - rc = psGetFileBuf(NULL, (char*)data, &fileData, &dataLen); - if (rc < 0) - { - printf("Unable to open file\n"); - sprintf((char*)data, "%s", "[I tried to send a file, but failed]"); - } -# else - printf("Need MATRIX_USE_FILE_SYSTEM for this\n"); - rc = PS_UNSUPPORTED_FAIL; - goto out_fail; -# endif /* MATRIX_USE_FILE_SYSTEM */ - } - if (!Strncmp(s, "url", strlen("url"))) - { - unsigned char url[sizeof(data)] = {0}; - int n; - - printf("Enter URL to GET: "); - dataLen = sizeof(url); - rc = getAppDataFromUser(ssl, url, &dataLen); - if (rc < 0) - { - goto out_fail; - } - n = Snprintf((char*)data, - sizeof(data), - (char*)g_httpRequestHdr, - (char*)url, - "localhost"); - dataLen = n + 1; - printf("Sending: %s (len: %zu)\n", data, dataLen); - } - } - - if (fileData != NULL) - { - pData = fileData; - } - else - { - pData = data; - } - - leftNBytes = dataLen; - sentNBytes = 0; - -continue_sending: - /* Get pointer to the internal plaintext buffer and fill - it with the plaintext data. The returned buffer may - be smaller, in which case we'll come back here to - continue on next call. */ - if (g_encode_to_outdata && leftNBytes < 16384) - { - rc = matrixSslEncodeToOutdata(ssl, pData, leftNBytes); - if (rc < 0) - { - printf("matrixSslEncodeToOutdata failed: %d\n", rc); - goto out_fail; - } - leftNBytes = 0; - } - else - { - rc = matrixSslGetWritebuf(ssl, &buf, leftNBytes); - if (rc < 0) - { - rc = PS_FAILURE; - goto out_fail; - } - - if (rc < leftNBytes) - { - sendNBytes = rc; - } - else - { - sendNBytes = leftNBytes; - } - - memcpy(buf, pData, sendNBytes); - sentNBytes += sendNBytes; - leftNBytes -= sendNBytes; - - printf("Sent %zu/%zu bytes\n", sentNBytes, sentNBytes + leftNBytes); - - /* Encrypt. */ - rc = matrixSslEncodeWritebuf(ssl, sendNBytes); - if (rc < 0) - { - rc = PS_FAILURE; - goto out_fail; - } - } - - /* Ask the main loop to send it over the wire. */ - rc = MATRIXSSL_REQUEST_SEND; - -out_fail: - if (fileData != NULL) - { - if (leftNBytes == 0) - { - psFree(fileData, NULL); - fileData = NULL; - } - } - return rc; -} - -psRes_t getUserProtocolVersion(psProtocolVersion_t *verOut) -{ - const char *proto_ver_prompt = - "Select protocol version to use:\n" \ - "(4) TLS 1.3 (default)\n" \ - "(3) TLS 1.2\n" \ - "(2) TLS 1.1\n" \ - "(1) TLS 1.0\n"; - char c; - psProtocolVersion_t v; - int got_it = 0; - int rc; - - printf("%s", proto_ver_prompt); - - while (got_it == 0) - { - rc = get_user_input_char(&c, '4'); - if (rc < 0) - { - printf("getUserProtocolVersion failed\n"); - return PS_FAILURE; - } - got_it = 1; - switch (c) - { - case '4': - v = v_tls_1_3; - break; - case '3': - v = v_tls_1_2; - break; - case '2': - v = v_tls_1_1; - break; - case '1': - v = v_tls_1_0; - break; - case 'q': - return PS_FAILURE; - default: - printf("Invalid choice: %c\n", c); - got_it = 0; - } - } - - *verOut = v; - - return PS_SUCCESS; -} - -psRes_t getUserKeyPair(const unsigned char **cert, - int32_t *certLen, - const unsigned char **key, - int32_t *keyLen, - int32_t *keyType, - int32_t *pskLen) -{ - const char *key_prompt = - "Select authentication key pair to use:\n" \ - "(1) P-256 ECDSA (default)\n" \ - "(2) 2048-bit RSA\n" \ - "(3) 3072-bit RSA\n" \ - "(4) PSK (32 bytes)\n" \ - "(5) PSK (48 bytes)\n"; - char c; - int got_it = 0; - int rc; - - /* Default keys. */ - *cert = EC256; - *certLen = EC256_SIZE; - *key = EC256KEY; - *keyLen = EC256KEY_SIZE; - *keyType = PS_ECC; - *pskLen = 0; - - printf("%s", key_prompt); - - while (got_it == 0) - { - rc = get_user_input_char(&c, '1'); - if (rc < 0) - { - printf("getUserKeyPair failed\n"); - return PS_FAILURE; - } - got_it = 1; - switch (c) - { - case '1': - /* Use defaults from above. */ - break; - case '2': - *cert = RSA2048; - *certLen = RSA2048_SIZE; - *key = RSA2048KEY; - *keyLen = RSA2048KEY_SIZE; - *keyType = PS_RSA; - break; - case '3': - *cert = RSA3072; - *certLen = RSA3072_SIZE; - *key = RSA3072KEY; - *keyLen = RSA3072KEY_SIZE; - *keyType = PS_RSA; - break; - case '4': - *pskLen = 32; - /* Load default keys in addition to the PSK. */ - break; - case '5': - *pskLen = 48; - /* Load default keys in addition to the PSK. */ - break; - case 'q': - return PS_FAILURE; - default: - printf("Invalid choice: %c\n", c); - got_it = 0; - } - } - - return PS_SUCCESS; -} - -int load_keys(sslKeys_t *keys) -{ - const unsigned char *key, *cert; - int32_t keyLen, certLen; - int32_t keyType; - const unsigned char *psk; - const unsigned char *psk_id; - psSize_t psk_id_len; - int32_t pskLen; - int rc; - matrixSslLoadKeysOpts_t keyOpts; - - rc = getUserKeyPair(&key, &keyLen, &cert, &certLen, &keyType, &pskLen); - if (rc < 0) - { - return rc; - } - - Memset(&keyOpts, 0, sizeof(keyOpts)); - keyOpts.key_type = keyType; - -# ifdef USE_TLS_1_3 - if (pskLen > 0) - { - if (pskLen == 32) - { - psk = g_tls13_test_psk_256; - psk_id = g_tls13_test_psk_id_sha256; - psk_id_len = sizeof(g_tls13_test_psk_id_sha256); - } - else if (pskLen == 48) - { - psk = g_tls13_test_psk_384; - psk_id = g_tls13_test_psk_id_sha384; - psk_id_len = sizeof(g_tls13_test_psk_id_sha384); - } - else - { - printf("Invalid PSK length\n"); - return EXIT_FAILURE; - } - rc = matrixSslLoadTls13Psk( - keys, - psk, - pskLen, - psk_id, - psk_id_len, - NULL); - if (rc < 0) - { - printf("matrixSslLoadTls13Psk failed\n"); - return EXIT_FAILURE; - } - } -# endif - - rc = matrixSslLoadKeysMem( - keys, - key, - keyLen, - cert, - certLen, - RSACAS, - sizeof(RSACAS), - &keyOpts); - if (rc < 0) - { - printf("matrixSslLoadKeysMem failed for key pair: %d\n", rc); - return EXIT_FAILURE; - } - - if (keyType == PS_ECC) - { - rc = matrixSslLoadKeysMem( - keys, - NULL, - 0, - NULL, - 0, - ECCAS, - sizeof(ECCAS), - &keyOpts); - if (rc < 0) - { - printf("matrixSslLoadKeysMem failed for ECC CAs: %d\n", rc); - return EXIT_FAILURE; - } - } - - return PS_SUCCESS; -} - -psRes_t getUserFirstSender(void) -{ - const char *get_first_sender_prompt = - "Who will send app data first?\n" \ - "(1) client (default)\n" \ - "(2) server\n"; - int rc; - char c; - int got_it = 0; - - printf("%s", get_first_sender_prompt); - while (got_it == 0) - { - rc = get_user_input_char(&c, '1'); - if (rc < 0) - { - printf("getUserFirstSender failed\n"); - return PS_FAILURE; - } - got_it = 1; - switch (c) - { - case '1': - g_server_sends_first = 0; - break; - case '2': - g_server_sends_first = 1; - break; - case 'q': - return PS_FAILURE; - default: - printf("Invalid choice: %c\n", c); - got_it = 0; - } - } - - return PS_SUCCESS; -} - -psRes_t getEncodingFunc(void) -{ - const char *get_encoding_func_prompt = - "Use matrixSslEncodeToOutdata for small <16KB application data?\n" \ - "(1) no (default)\n" \ - "(2) yes\n"; - int rc; - char c; - int got_it = 0; - - printf("%s", get_encoding_func_prompt); - while (got_it == 0) - { - rc = get_user_input_char(&c, '1'); - if (rc < 0) - { - printf("getUserFirstSender failed\n"); - return PS_FAILURE; - } - got_it = 1; - switch (c) - { - case '1': - g_encode_to_outdata = 0; - break; - case '2': - g_encode_to_outdata = 1; - break; - case 'q': - return PS_FAILURE; - default: - printf("Invalid choice: %c\n", c); - got_it = 0; - } - } - - return PS_SUCCESS; -} - -psRes_t getUserSigAlgs(uint16_t *sigAlgs, psSize_t *numSigAlgs) -{ - const char *sig_algs_prompt = - "Signature algorithms to use:\n" \ - "(1) sigalg_ecdsa_secp256r1_sha256 (default)\n" \ - "(2) sigalg_rsa_pss_rsae_sha256\n" \ - "(3) sigalg_rsa_pkcs1_sha256\n"; - - int rc; - char c; - int got_it = 0; - psSize_t i = 0; - - printf("%s", sig_algs_prompt); - while (got_it == 0) - { - rc = get_user_input_char(&c, '1'); - if (rc < 0) - { - printf("getUserSigAlgs failed\n"); - return PS_FAILURE; - } - got_it = 1; - switch (c) - { - case '1': - sigAlgs[i++] = sigalg_ecdsa_secp256r1_sha256; - break; - case '2': - sigAlgs[i++] = sigalg_rsa_pss_rsae_sha256; - break; - case '3': - sigAlgs[i++] = sigalg_rsa_pkcs1_sha256; - break; - case 'q': - return PS_FAILURE; - default: - printf("Invalid choice: %c\n", c); - got_it = 0; - } - } - - *numSigAlgs = i; - - return PS_SUCCESS; -} - -psRes_t getUserCiphersuites(psCipher16_t *ciphersuites, - psSize_t *numCiphersuites) -{ - static const char *ciphersuites_prompt = - "Ciphersuite to use:\n" \ - "(1) TLS_AES_128_GCM_SHA256 (default)\n" \ - "(2) TLS_AES_256_GCM_SHA384\n" \ - "(3) TLS_CHACHA20_POLY1305_SHA256\n" \ - "(4) TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n" \ - "(5) TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n" \ - "(6) TLS_RSA_WITH_AES_128_GCM_SHA256\n" \ - "(7) All TLS 1.3 suites (prefer SHA256)\n" \ - "(8) All TLS 1.3 suites (prefer SHA384)\n"; - int rc; - char c; - int got_it = 0; - psSize_t i = 0; - - printf("%s", ciphersuites_prompt); - while (got_it == 0) - { - rc = get_user_input_char(&c, '1'); - if (rc < 0) - { - printf("getUserCiphersuites failed\n"); - return PS_FAILURE; - } - got_it = 1; - switch (c) - { - case '1': - ciphersuites[i++] = TLS_AES_128_GCM_SHA256; - break; - case '2': - ciphersuites[i++] = TLS_AES_256_GCM_SHA384; - break; - case '3': - ciphersuites[i++] = TLS_CHACHA20_POLY1305_SHA256; - break; - case '4': - ciphersuites[i++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; - break; - case '5': - ciphersuites[i++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; - break; - case '6': - ciphersuites[i++] = TLS_RSA_WITH_AES_128_GCM_SHA256; - break; - case '7': - ciphersuites[i++] = TLS_AES_128_GCM_SHA256; - ciphersuites[i++] = TLS_AES_256_GCM_SHA384; - ciphersuites[i++] = TLS_CHACHA20_POLY1305_SHA256; - break; - case '8': - ciphersuites[i++] = TLS_AES_256_GCM_SHA384; - ciphersuites[i++] = TLS_AES_128_GCM_SHA256; - ciphersuites[i++] = TLS_CHACHA20_POLY1305_SHA256; - break; - case 'q': - return PS_FAILURE; - default: - printf("Invalid choice: %c\n", c); - got_it = 0; - } - } - - *numCiphersuites = i; - - return PS_SUCCESS; -} - -psRes_t getMaximumFragmentLength(short *maxFragLen) -{ - const char *max_frag_len_prompt = - "Maximum fragment length\n" \ - "(1) none (default)\n" \ - "(2) 512\n" \ - "(3) 1024\n" \ - "(4) 2048\n" \ - "(5) 4096\n"; - int rc; - char c; - int got_it = 0; - - printf("%s", max_frag_len_prompt); - while (got_it == 0) - { - rc = get_user_input_char(&c, '1'); - if (rc < 0) - { - printf("getMaximumFragmentLength failed\n"); - return PS_FAILURE; - } - got_it = 1; - switch (c) - { - case '1': - *maxFragLen = 0; - break; - case '2': - *maxFragLen = 512; - break; - case '3': - *maxFragLen = 1024; - break; - case '4': - *maxFragLen = 2048; - break; - case '5': - *maxFragLen = 4096; - break; - default: - printf("Invalid choice: %c\n", c); - got_it = 0; - } - } - - return PS_SUCCESS; -} - -psRes_t getServerAddress(char *addr_out, int *addr_out_len) -{ - const char *server_address_prompt = - "Server IP address (default 127.0.0.1):\n"; - char addr[40]; - int addr_len = (int)sizeof(addr); - const char *addr_default = "127.0.0.1"; - int rc; - - printf("%s", server_address_prompt); - rc = get_user_input(addr, addr_len); - if (rc < 0) - { - return PS_FAILURE; - } - - if (Strlen(addr) == 0) - { - Strncpy(addr_out, addr_default, 39); - } - else - { - Strncpy(addr_out, addr, 39); - } - - *addr_out_len = strlen(addr); - - return PS_SUCCESS; -} - -psRes_t getServerPort(int *port_out) -{ - const char *server_port_prompt = - "Server port (default: 4433)\n"; - char buf[6]; - int buf_len = sizeof(buf); - long int port; - char *end; - int got_it = 0; - int rc; - - printf("%s", server_port_prompt); - - while (got_it == 0) - { - rc = get_user_input(buf, buf_len); - if (rc < 0) - { - return PS_FAILURE; - } - got_it = 1; - port = Strtol(buf, &end, 10); - if (port < 0 || port > 65536) - { - printf("Invalid port\n"); - got_it = 0; - } - if (buf == end) - { - port = 4433; - } - } - - *port_out = port; - return PS_SUCCESS; -} - -psRes_t getServerName( - char *name_out, - int name_out_len, - char *ip_addr) -{ - const char *server_name_prompt_fmt = - "Server name (default: %s)\n"; - char server_name_prompt[256]; - char buf[256]; - int buf_len = sizeof(buf); - int got_it = 0; - int rc; - - /* Default name = previously selected IP address. */ - snprintf(server_name_prompt, - 256, - server_name_prompt_fmt, - ip_addr); - printf("%s", server_name_prompt); - - while (got_it == 0) - { - rc = get_user_input(buf, buf_len); - if (rc < 0) - { - return PS_FAILURE; - } - got_it = 1; - } - - if (Strlen(buf) == 0) - { - if (name_out_len < Strlen(ip_addr)) - { - printf("Default server name won't fit into output buffer\n"); - return PS_FAILURE; - } - Strncpy(name_out, ip_addr, name_out_len - 1); - } - else - { - Strncpy(name_out, buf, buf_len - 1); - } - - return PS_SUCCESS; -} - -psRes_t getAllowAnon(psBool_t *allow) -{ - const char *allow_anon_prompt = - "Skip server authentication?\n" \ - "(1) no (default)\n" \ - "(2) yes\n"; - int rc; - char c; - int got_it = 0; - - printf("%s", allow_anon_prompt); - while (got_it == 0) - { - rc = get_user_input_char(&c, '1'); - if (rc < 0) - { - printf("getAllowAnon failed\n"); - return PS_FAILURE; - } - got_it = 1; - switch (c) - { - case '1': - *allow = PS_FALSE; - break; - case '2': - *allow = PS_TRUE; - break; - default: - printf("Invalid choice: %c\n", c); - got_it = 0; - } - } - - return PS_SUCCESS; -} - int main(int argc, char **argv) { uint16_t sigAlgs[16]; diff --git a/apps/ssl/interactiveCommon.c b/apps/ssl/interactiveCommon.c new file mode 100644 index 0000000..680f231 --- /dev/null +++ b/apps/ssl/interactiveCommon.c @@ -0,0 +1,950 @@ +/** + * @file interactiveCommon.c + * @version $Format:%h%d$ + * + * Common parts of interactiveClient.c and interactiveServer.c + */ +/* + * Copyright (c) 2013-2018 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "matrixssl/matrixsslApi.h" +#include "osdep.h" +#include "interactiveCommon.h" +#include + +/* Key material. */ +# include "testkeys/EC/256_EC.h" +# include "testkeys/EC/256_EC_KEY.h" +# include "testkeys/EC/256_EC_CA.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/ALL_RSA_CAS.h" +# include "testkeys/EC/ALL_EC_CAS.h" +# include "testkeys/PSK/tls13_psk.h" + +/* Global options. Should be defined in client and server. */ +extern int g_server_sends_first; +extern int g_encode_to_outdata; +extern int g_handshake_complete; +extern psBool_t g_skip_server_auth; +extern size_t leftNBytes; +extern size_t sentNBytes; +extern unsigned char *g_httpRequestHdr; + +/* Returns a line of user input (without the newline character), + or < 0 on error. The returned string may be truncated if it + did not fit into buf. */ +int get_user_input(char *buf, int buf_len) +{ + char *s, *p; + char c; + + s = fgets(buf, buf_len, stdin); + if (s == NULL) + { + return PS_FAILURE; + } + + p = strchr(buf, '\n'); + if (p) + { + *p = '\0'; + } + else + { + /* Flush stdin up to newline or EOF. */ + c = getchar(); + while (c != '\n' && !feof(stdin) && !ferror(stdin)) + { + c = getchar(); + } + } + + //printf("Got: %s (len: %zu)\n", buf, strlen(buf)); + + return PS_SUCCESS; +} + +int get_user_input_char(char *c, char defaultChoice) +{ + char buf[2] = {0}; + size_t buf_len = sizeof(buf); + int rc; + + rc = get_user_input(buf, buf_len); + if (rc < 0) + { + return rc; + } + + if (Strlen(buf) == 0) + { + *c = defaultChoice; + } + else + { + *c = buf[0]; + } + + return PS_SUCCESS; +} + +int32_t getAppDataFromUser(ssl_t *ssl, + unsigned char *data, + size_t *dataLen) +{ + int rc; + char buf[1024] = {0}; + size_t buf_len = sizeof(buf); + size_t max_len; + + max_len = buf_len; + if (*dataLen < buf_len && *dataLen < INT_MAX) + { + max_len = *dataLen; + } + + rc = get_user_input(buf, (int)max_len); + if (rc < 0) + { + printf("Failed to get user input\n"); + return PS_FAILURE; + } + + Memcpy(data, buf, Strlen(buf) + 1); + *dataLen = Strlen(buf) + 1; + + return PS_SUCCESS; +} + +/* + Ask the for app data to send over the encrypted connection, + or for some other action. + Return value: + < 0 on error, + PS_SUCCESS for nominal connection closure + MATRIXSSL_REQUEST_SEND to send app data. +*/ +int32_t askSendAppData(ssl_t *ssl) +{ + int32_t rc; + unsigned char *buf; + unsigned char data[1024] = {0}; + size_t dataLen = sizeof(data); + size_t sendNBytes; + static unsigned char *fileData = NULL; + unsigned char *pData; + const char *s; + + if (leftNBytes > 0) + { + pData = fileData; + goto continue_sending; + } + + printf("You: "); + rc = getAppDataFromUser(ssl, data, &dataLen); + if (rc < 0) + { + return rc; + } + + if (data[0] == ':') + { + /* Handle commands. */ + + /* Handle :quit, :exit and :q */ + s = (char*)&data[1]; + if (!Strncmp(s, "quit", strlen("quit")) + || !Strncmp(s, "exit", strlen("exit")) + || (dataLen == 2 && data[1] == 'q')) + { + rc = matrixSslEncodeClosureAlert(ssl); + (void)rc; + return PS_SUCCESS; + } + /* Handle :sendbindings and :s */ + if (!Strncmp(s, "sendbindings", strlen("sendbindings")) + || (dataLen == 2 && data[1] == 's')) + { +# ifdef USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS + unsigned char bindings[36]; + psSizeL_t bindingsLen = sizeof(bindings); + const char *bindingsPrefix = "tls-unique:"; + + rc = matrixSslGetTlsUniqueChannelBindings( + ssl, + bindings, + &bindingsLen); + (void)rc; + + memcpy(data, bindingsPrefix, strlen(bindingsPrefix)); + memcpy(data+strlen(bindingsPrefix), bindings, bindingsLen); + dataLen = bindingsLen + strlen(bindingsPrefix); + psTraceBytes("Sending tls-unique", data, dataLen); +# else + printf("Need USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS for " + "this command\n"); +# endif + } + if (!Strncmp(s, "file", strlen("file"))) + { +# ifdef MATRIX_USE_FILE_SYSTEM + printf("Enter file name: "); + dataLen = sizeof(data); + rc = getAppDataFromUser(ssl, data, &dataLen); + if (rc < 0) + { + goto out_fail; + } + rc = psGetFileBuf(NULL, (char*)data, &fileData, &dataLen); + if (rc < 0) + { + printf("Unable to open file\n"); + sprintf((char*)data, "%s", "[I tried to send a file, but failed]"); + } +# else + printf("Need MATRIX_USE_FILE_SYSTEM for this\n"); + rc = PS_UNSUPPORTED_FAIL; + goto out_fail; +# endif /* MATRIX_USE_FILE_SYSTEM */ + } + if (!Strncmp(s, "url", strlen("url"))) + { + unsigned char url[sizeof(data)] = {0}; + int n; + + printf("Enter URL to GET: "); + dataLen = sizeof(url); + rc = getAppDataFromUser(ssl, url, &dataLen); + if (rc < 0) + { + goto out_fail; + } + n = Snprintf((char*)data, + sizeof(data), + (char*)g_httpRequestHdr, + (char*)url, + "localhost"); + dataLen = n + 1; + printf("Sending: %s (len: %zu)\n", data, dataLen); + } + } + + if (fileData != NULL) + { + pData = fileData; + } + else + { + pData = data; + } + + leftNBytes = dataLen; + sentNBytes = 0; + +continue_sending: + /* Get pointer to the internal plaintext buffer and fill + it with the plaintext data. The returned buffer may + be smaller, in which case we'll come back here to + continue on next call. */ + if (g_encode_to_outdata && leftNBytes < 16384) + { + rc = matrixSslEncodeToOutdata(ssl, pData, leftNBytes); + if (rc < 0) + { + printf("matrixSslEncodeToOutdata failed: %d\n", rc); + goto out_fail; + } + leftNBytes = 0; + } + else + { + rc = matrixSslGetWritebuf(ssl, &buf, leftNBytes); + if (rc < 0) + { + rc = PS_FAILURE; + goto out_fail; + } + + if (rc < leftNBytes) + { + sendNBytes = rc; + } + else + { + sendNBytes = leftNBytes; + } + + memcpy(buf, pData, sendNBytes); + sentNBytes += sendNBytes; + leftNBytes -= sendNBytes; + + printf("Sent %zu/%zu bytes\n", sentNBytes, sentNBytes + leftNBytes); + + /* Encrypt. */ + rc = matrixSslEncodeWritebuf(ssl, sendNBytes); + if (rc < 0) + { + rc = PS_FAILURE; + goto out_fail; + } + } + + /* Ask the main loop to send it over the wire. */ + rc = MATRIXSSL_REQUEST_SEND; + +out_fail: + if (fileData != NULL) + { + if (leftNBytes == 0) + { + psFree(fileData, NULL); + fileData = NULL; + } + } + return rc; +} + +psRes_t getUserProtocolVersion(psProtocolVersion_t *verOut) +{ + const char *proto_ver_prompt = + "Select protocol version to use:\n" \ + "(4) TLS 1.3 (default)\n" \ + "(3) TLS 1.2\n" \ + "(2) TLS 1.1\n" \ + "(1) TLS 1.0\n"; + char c; + psProtocolVersion_t v; + int got_it = 0; + int rc; + + printf("%s", proto_ver_prompt); + + while (got_it == 0) + { + rc = get_user_input_char(&c, '4'); + if (rc < 0) + { + printf("getUserProtocolVersion failed\n"); + return PS_FAILURE; + } + got_it = 1; + switch (c) + { + case '4': + v = v_tls_1_3; + break; + case '3': + v = v_tls_1_2; + break; + case '2': + v = v_tls_1_1; + break; + case '1': + v = v_tls_1_0; + break; + case 'q': + return PS_FAILURE; + default: + printf("Invalid choice: %c\n", c); + got_it = 0; + } + } + + *verOut = v; + + return PS_SUCCESS; +} + +psRes_t getUserKeyPair(const unsigned char **cert, + int32_t *certLen, + const unsigned char **key, + int32_t *keyLen, + int32_t *keyType, + int32_t *pskLen) +{ + const char *key_prompt = + "Select authentication key pair to use:\n" \ + "(1) P-256 ECDSA (default)\n" \ + "(2) 2048-bit RSA\n" \ + "(3) 3072-bit RSA\n" \ + "(4) PSK (32 bytes)\n" \ + "(5) PSK (48 bytes)\n"; + char c; + int got_it = 0; + int rc; + + /* Default keys. */ + *cert = EC256; + *certLen = EC256_SIZE; + *key = EC256KEY; + *keyLen = EC256KEY_SIZE; + *keyType = PS_ECC; + *pskLen = 0; + + printf("%s", key_prompt); + + while (got_it == 0) + { + rc = get_user_input_char(&c, '1'); + if (rc < 0) + { + printf("getUserKeyPair failed\n"); + return PS_FAILURE; + } + got_it = 1; + switch (c) + { + case '1': + /* Use defaults from above. */ + break; + case '2': + *cert = RSA2048; + *certLen = RSA2048_SIZE; + *key = RSA2048KEY; + *keyLen = RSA2048KEY_SIZE; + *keyType = PS_RSA; + break; + case '3': + *cert = RSA3072; + *certLen = RSA3072_SIZE; + *key = RSA3072KEY; + *keyLen = RSA3072KEY_SIZE; + *keyType = PS_RSA; + break; + case '4': + *pskLen = 32; + /* Load default keys in addition to the PSK. */ + break; + case '5': + *pskLen = 48; + /* Load default keys in addition to the PSK. */ + break; + case 'q': + return PS_FAILURE; + default: + printf("Invalid choice: %c\n", c); + got_it = 0; + } + } + + return PS_SUCCESS; +} + +int load_keys(sslKeys_t *keys) +{ + const unsigned char *key, *cert; + int32_t keyLen, certLen; + int32_t keyType; +# ifdef USE_TLS_1_3 + const unsigned char *psk; + const unsigned char *psk_id; + psSize_t psk_id_len; +# endif + int32_t pskLen; + int rc; + matrixSslLoadKeysOpts_t keyOpts; + + rc = getUserKeyPair(&key, &keyLen, &cert, &certLen, &keyType, &pskLen); + if (rc < 0) + { + return rc; + } + + Memset(&keyOpts, 0, sizeof(keyOpts)); + keyOpts.key_type = keyType; + +# ifdef USE_TLS_1_3 + if (pskLen > 0) + { + if (pskLen == 32) + { + psk = g_tls13_test_psk_256; + psk_id = g_tls13_test_psk_id_sha256; + psk_id_len = sizeof(g_tls13_test_psk_id_sha256); + } + else if (pskLen == 48) + { + psk = g_tls13_test_psk_384; + psk_id = g_tls13_test_psk_id_sha384; + psk_id_len = sizeof(g_tls13_test_psk_id_sha384); + } + else + { + printf("Invalid PSK length\n"); + return EXIT_FAILURE; + } + rc = matrixSslLoadTls13Psk( + keys, + psk, + pskLen, + psk_id, + psk_id_len, + NULL); + if (rc < 0) + { + printf("matrixSslLoadTls13Psk failed\n"); + return EXIT_FAILURE; + } + } +# endif + + rc = matrixSslLoadKeysMem( + keys, + key, + keyLen, + cert, + certLen, + RSACAS, + sizeof(RSACAS), + &keyOpts); + if (rc < 0) + { + printf("matrixSslLoadKeysMem failed for key pair: %d\n", rc); + return EXIT_FAILURE; + } + + if (keyType == PS_ECC) + { + rc = matrixSslLoadKeysMem( + keys, + NULL, + 0, + NULL, + 0, + ECCAS, + sizeof(ECCAS), + &keyOpts); + if (rc < 0) + { + printf("matrixSslLoadKeysMem failed for ECC CAs: %d\n", rc); + return EXIT_FAILURE; + } + } + + return PS_SUCCESS; +} + +psRes_t getUserFirstSender(void) +{ + const char *get_first_sender_prompt = + "Who will send app data first?\n" \ + "(1) client (default)\n" \ + "(2) server\n"; + int rc; + char c; + int got_it = 0; + + printf("%s", get_first_sender_prompt); + while (got_it == 0) + { + rc = get_user_input_char(&c, '1'); + if (rc < 0) + { + printf("getUserFirstSender failed\n"); + return PS_FAILURE; + } + got_it = 1; + switch (c) + { + case '1': + g_server_sends_first = 0; + break; + case '2': + g_server_sends_first = 1; + break; + case 'q': + return PS_FAILURE; + default: + printf("Invalid choice: %c\n", c); + got_it = 0; + } + } + + return PS_SUCCESS; +} + +psRes_t getEncodingFunc(void) +{ + const char *get_encoding_func_prompt = + "Use matrixSslEncodeToOutdata for small <16KB application data?\n" \ + "(1) no (default)\n" \ + "(2) yes\n"; + int rc; + char c; + int got_it = 0; + + printf("%s", get_encoding_func_prompt); + while (got_it == 0) + { + rc = get_user_input_char(&c, '1'); + if (rc < 0) + { + printf("getUserFirstSender failed\n"); + return PS_FAILURE; + } + got_it = 1; + switch (c) + { + case '1': + g_encode_to_outdata = 0; + break; + case '2': + g_encode_to_outdata = 1; + break; + case 'q': + return PS_FAILURE; + default: + printf("Invalid choice: %c\n", c); + got_it = 0; + } + } + + return PS_SUCCESS; +} + +psRes_t getUserSigAlgs(uint16_t *sigAlgs, psSize_t *numSigAlgs) +{ + const char *sig_algs_prompt = + "Signature algorithms to use:\n" \ + "(1) sigalg_ecdsa_secp256r1_sha256 (default)\n" \ + "(2) sigalg_rsa_pss_rsae_sha256\n" \ + "(3) sigalg_rsa_pkcs1_sha256\n"; + + int rc; + char c; + int got_it = 0; + psSize_t i = 0; + + printf("%s", sig_algs_prompt); + while (got_it == 0) + { + rc = get_user_input_char(&c, '1'); + if (rc < 0) + { + printf("getUserSigAlgs failed\n"); + return PS_FAILURE; + } + got_it = 1; + switch (c) + { + case '1': + sigAlgs[i++] = sigalg_ecdsa_secp256r1_sha256; + break; + case '2': + sigAlgs[i++] = sigalg_rsa_pss_rsae_sha256; + break; + case '3': + sigAlgs[i++] = sigalg_rsa_pkcs1_sha256; + break; + case 'q': + return PS_FAILURE; + default: + printf("Invalid choice: %c\n", c); + got_it = 0; + } + } + + *numSigAlgs = i; + + return PS_SUCCESS; +} + +psRes_t getUserCiphersuites(psCipher16_t *ciphersuites, + psSize_t *numCiphersuites) +{ + static const char *ciphersuites_prompt = + "Ciphersuite to use:\n" \ + "(1) TLS_AES_128_GCM_SHA256 (default)\n" \ + "(2) TLS_AES_256_GCM_SHA384\n" \ + "(3) TLS_CHACHA20_POLY1305_SHA256\n" \ + "(4) TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n" \ + "(5) TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n" \ + "(6) TLS_RSA_WITH_AES_128_GCM_SHA256\n" \ + "(7) All TLS 1.3 suites (prefer SHA256)\n" \ + "(8) All TLS 1.3 suites (prefer SHA384)\n"; + int rc; + char c; + int got_it = 0; + psSize_t i = 0; + + printf("%s", ciphersuites_prompt); + while (got_it == 0) + { + rc = get_user_input_char(&c, '1'); + if (rc < 0) + { + printf("getUserCiphersuites failed\n"); + return PS_FAILURE; + } + got_it = 1; + switch (c) + { + case '1': + ciphersuites[i++] = TLS_AES_128_GCM_SHA256; + break; + case '2': + ciphersuites[i++] = TLS_AES_256_GCM_SHA384; + break; + case '3': + ciphersuites[i++] = TLS_CHACHA20_POLY1305_SHA256; + break; + case '4': + ciphersuites[i++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; + break; + case '5': + ciphersuites[i++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; + break; + case '6': + ciphersuites[i++] = TLS_RSA_WITH_AES_128_GCM_SHA256; + break; + case '7': + ciphersuites[i++] = TLS_AES_128_GCM_SHA256; + ciphersuites[i++] = TLS_AES_256_GCM_SHA384; + ciphersuites[i++] = TLS_CHACHA20_POLY1305_SHA256; + break; + case '8': + ciphersuites[i++] = TLS_AES_256_GCM_SHA384; + ciphersuites[i++] = TLS_AES_128_GCM_SHA256; + ciphersuites[i++] = TLS_CHACHA20_POLY1305_SHA256; + break; + case 'q': + return PS_FAILURE; + default: + printf("Invalid choice: %c\n", c); + got_it = 0; + } + } + + *numCiphersuites = i; + + return PS_SUCCESS; +} + +psRes_t getMaximumFragmentLength(short *maxFragLen) +{ + const char *max_frag_len_prompt = + "Maximum fragment length\n" \ + "(1) none (default)\n" \ + "(2) 512\n" \ + "(3) 1024\n" \ + "(4) 2048\n" \ + "(5) 4096\n"; + int rc; + char c; + int got_it = 0; + + printf("%s", max_frag_len_prompt); + while (got_it == 0) + { + rc = get_user_input_char(&c, '1'); + if (rc < 0) + { + printf("getMaximumFragmentLength failed\n"); + return PS_FAILURE; + } + got_it = 1; + switch (c) + { + case '1': + *maxFragLen = 0; + break; + case '2': + *maxFragLen = 512; + break; + case '3': + *maxFragLen = 1024; + break; + case '4': + *maxFragLen = 2048; + break; + case '5': + *maxFragLen = 4096; + break; + default: + printf("Invalid choice: %c\n", c); + got_it = 0; + } + } + + return PS_SUCCESS; +} + +psRes_t getServerAddress(char *addr_out, int *addr_out_len) +{ + const char *server_address_prompt = + "Server IP address (default 127.0.0.1):\n"; + char addr[40]; + int addr_len = (int)sizeof(addr); + const char *addr_default = "127.0.0.1"; + int rc; + + printf("%s", server_address_prompt); + rc = get_user_input(addr, addr_len); + if (rc < 0) + { + return PS_FAILURE; + } + + if (Strlen(addr) == 0) + { + Strncpy(addr_out, addr_default, 39); + } + else + { + Strncpy(addr_out, addr, 39); + } + + *addr_out_len = strlen(addr); + + return PS_SUCCESS; +} + +psRes_t getServerPort(int *port_out) +{ + const char *server_port_prompt = + "Server port (default: 4433)\n"; + char buf[6]; + int buf_len = sizeof(buf); + long int port; + char *end; + int got_it = 0; + int rc; + + printf("%s", server_port_prompt); + + while (got_it == 0) + { + rc = get_user_input(buf, buf_len); + if (rc < 0) + { + return PS_FAILURE; + } + got_it = 1; + port = Strtol(buf, &end, 10); + if (port < 0 || port > 65536) + { + printf("Invalid port\n"); + got_it = 0; + } + if (buf == end) + { + port = 4433; + } + } + + *port_out = port; + return PS_SUCCESS; +} + +psRes_t getServerName( + char *name_out, + int name_out_len, + char *ip_addr) +{ + const char *server_name_prompt_fmt = + "Server name (default: %s)\n"; + char server_name_prompt[256]; + char buf[256]; + int buf_len = sizeof(buf); + int got_it = 0; + int rc; + + /* Default name = previously selected IP address. */ + snprintf(server_name_prompt, + 256, + server_name_prompt_fmt, + ip_addr); + printf("%s", server_name_prompt); + + while (got_it == 0) + { + rc = get_user_input(buf, buf_len); + if (rc < 0) + { + return PS_FAILURE; + } + got_it = 1; + } + + if (Strlen(buf) == 0) + { + if (name_out_len < Strlen(ip_addr)) + { + printf("Default server name won't fit into output buffer\n"); + return PS_FAILURE; + } + Strncpy(name_out, ip_addr, name_out_len - 1); + } + else + { + Strncpy(name_out, buf, buf_len - 1); + } + + return PS_SUCCESS; +} + +psRes_t getAllowAnon(psBool_t *allow) +{ + const char *allow_anon_prompt = + "Skip server authentication?\n" \ + "(1) no (default)\n" \ + "(2) yes\n"; + int rc; + char c; + int got_it = 0; + + printf("%s", allow_anon_prompt); + while (got_it == 0) + { + rc = get_user_input_char(&c, '1'); + if (rc < 0) + { + printf("getAllowAnon failed\n"); + return PS_FAILURE; + } + got_it = 1; + switch (c) + { + case '1': + *allow = PS_FALSE; + break; + case '2': + *allow = PS_TRUE; + break; + default: + printf("Invalid choice: %c\n", c); + got_it = 0; + } + } + + return PS_SUCCESS; +} + diff --git a/apps/ssl/interactiveCommon.h b/apps/ssl/interactiveCommon.h new file mode 100644 index 0000000..9a067a4 --- /dev/null +++ b/apps/ssl/interactiveCommon.h @@ -0,0 +1,60 @@ +/** + * @file interactiveCommon.h + * @version $Format:%h%d$ + * + * Common parts of interactiveClient.c and interactiveServer.c + */ +/* + * Copyright (c) 2013-2018 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +int get_user_input(char *buf, int buf_len); +int get_user_input_char(char *c, char defaultChoice); +int32_t getAppDataFromUser(ssl_t *ssl, + unsigned char *data, + size_t *dataLen); +int32_t askSendAppData(ssl_t *ssl); +psRes_t getUserProtocolVersion(psProtocolVersion_t *verOut); +psRes_t getUserKeyPair(const unsigned char **cert, + int32_t *certLen, + const unsigned char **key, + int32_t *keyLen, + int32_t *keyType, + int32_t *pskLen); +int load_keys(sslKeys_t *keys); +psRes_t getEncodingFunc(void); +psRes_t getUserSigAlgs(uint16_t *sigAlgs, psSize_t *numSigAlgs); +psRes_t getUserCiphersuites(psCipher16_t *ciphersuites, + psSize_t *numCiphersuites); +psRes_t getMaximumFragmentLength(short *maxFragLen); +psRes_t getServerAddress(char *addr_out, int *addr_out_len); +psRes_t getServerPort(int *port_out); +psRes_t getServerName( + char *name_out, + int name_out_len, + char *ip_addr); +psRes_t getAllowAnon(psBool_t *allow); +psRes_t getUserFirstSender(void); diff --git a/apps/ssl/interactiveServer.c b/apps/ssl/interactiveServer.c new file mode 100644 index 0000000..7a66eda --- /dev/null +++ b/apps/ssl/interactiveServer.c @@ -0,0 +1,489 @@ +/** + * @file interactiveServer.c + * @version $Format:%h%d$ + * + * Interactive client-side test tool. + */ +/* + * Copyright (c) 2013-2019 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/ + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "matrixssl/matrixsslApi.h" +#include "osdep.h" + +# ifdef USE_SERVER_SIDE_SSL +# include "interactiveCommon.h" + +# if defined(USE_TLS_1_2) && defined(USE_SECP256R1) && defined(USE_SHA256) && defined(USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) && defined(USE_IDENTITY_CERTIFICATES) + +# include +# include +# include +# include +# include + +# define SERVER_IP_ADDRESS "127.0.0.1" +# define SERVER_PORT 4433 + +/* Do we expect the server to the first piece of app data? */ +int g_server_sends_first; +/* Use matrixSslEncodeToOutdata for encoding small app data? */ +int g_encode_to_outdata; +/* Already received MATRIXSSL_HANDSHAKE_COMPLETE? */ +int g_handshake_complete; +/* Skip server authentication entirely? */ +psBool_t g_skip_server_auth; +/* Don't authenticate the client's certificate? */ +psBool_t g_skip_client_auth; + +size_t leftNBytes; +size_t sentNBytes; + +/* HTTP GET request header. */ +unsigned char g_httpRequestHdr[] = "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: MatrixSSL/" MATRIXSSL_VERSION "\r\n" + "Accept: */*\r\n" + "Content-Length: 0\r\n" + "\r\n"; + +/* Certificate callback. See section 6 in the API manual for details. + In this test, we do no extra checks of our own; we simply accept + the result of MatrixSSL's internal certificate validation. */ +/*static int32_t certCb(ssl_t *ssl, psX509Cert_t *cert, int32_t alert) +{ + if (g_skip_client_auth) + { + return SSL_ALLOW_ANON_CONNECTION; + } + else + { + return alert; + } +}*/ + +int main(int argc, char **argv) +{ + uint16_t sigAlgs[16]; + psSize_t numSigAlgs; + psProtocolVersion_t versions[1]; + int serverPort; + sslSessOpts_t opts; + sslKeys_t *keys; + int32_t rc; + uint32_t len; + ssl_t *ssl = NULL; + unsigned char *buf; + ssize_t nrecv, nsent; + int fd = -1; + int sock_fd; + struct sockaddr_in addr; + + rc = matrixSslOpen(); + if (rc < 0) + { + return EXIT_FAILURE; + } + + Memset(&opts, 0, sizeof(opts)); + + rc = getUserProtocolVersion(&versions[0]); + if (rc < 0) + { + return EXIT_FAILURE; + } + rc = matrixSslSessOptsSetServerTlsVersions( + &opts, + versions, + 1); + if (rc < 0) + { + printf("matrixSslSessOptsSetClientTlsVersions failed: %d\n", rc); + return EXIT_FAILURE; + } + + rc = matrixSslNewKeys(&keys, NULL); + if (rc < 0) + { + return EXIT_FAILURE; + } + + rc = load_keys(keys); + if (rc < 0) + { + matrixSslDeleteKeys(keys); + return EXIT_FAILURE; + } + + /* Set P-256 as the supported ECC curve for signatures and key exchange. */ + opts.ecFlags = IS_SECP256R1; + + rc = getUserSigAlgs(sigAlgs, &numSigAlgs); + if (rc < 0) + { + goto out_fail; + } + rc = matrixSslSessOptsSetSigAlgs( + &opts, + sigAlgs, + numSigAlgs); + if (rc < 0) + { + printf("matrixSslSessOptsSetSigAlgs failed: %d\n", rc); + goto out_fail; + } + + rc = getMaximumFragmentLength(&opts.maxFragLen); + if (rc < 0) + { + goto out_fail; + } + + rc = getServerPort(&serverPort); + if (rc < 0) + { + goto out_fail; + } + + /* Create a new server session. */ + rc = matrixSslNewServerSession( + &ssl, + keys, + NULL, + &opts); + if (rc < 0) + { + printf("matrixSslNewClientSession failed: %d\n", rc); + goto out_fail; + } + + rc = getUserFirstSender(); + if (rc < 0) + { + goto out_fail; + } + + rc = getEncodingFunc(); + if (rc < 0) + { + goto out_fail; + } + + /* Start listening to a TCP port for connections. */ + Memset((char *) &addr, 0x0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons((short) serverPort); + addr.sin_addr.s_addr = INADDR_ANY; + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + { + printf("socket failed: %d\n", fd); + return EXIT_FAILURE; + } + rc = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (rc < 0) + { + printf("bind failed: %d\n", rc); + return EXIT_FAILURE; + } + rc = listen(fd, 1); + if (rc < 0) + { + printf("listen failed: %d\n", rc); + return EXIT_FAILURE; + } + printf("Listening for connections on port %d...\n", serverPort); + sock_fd = accept(fd, NULL, NULL); + if (rc < 0) + { + printf("accept failed: %d\n", rc); + return EXIT_FAILURE; + } + printf("Received new connection\n"); + + /* Try to receive ClientHello. */ + goto READ_MORE; + +WRITE_MORE: + /* Get pointer to the output data to send. */ + rc = matrixSslGetOutdata(ssl, &buf); + while (rc > 0) + { + len = rc; + + /* Send it over the wire. */ + nsent = send(sock_fd, buf, len, 0); + if (nsent <= 0) + { + printf("send() failed\n"); + goto out_fail; + } + + /* Inform the TLS library how much we managed to send. + Return code will tell us of what to do next. */ + rc = matrixSslSentData(ssl, nsent); + if (rc < 0) + { + printf("matrixSslSentData failed: %d\n", rc); + goto out_fail; + } + else if (rc == MATRIXSSL_REQUEST_CLOSE) + { + printf("Closing connection\n"); + goto out_ok; + } + else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) + { + printf("Handshake complete\n"); + g_handshake_complete = 1; + + if (g_server_sends_first) + { + /* Send app data over the encrypted connection. */ + get_more_user_data: + rc = askSendAppData(ssl); + if (rc == PS_SUCCESS) + { + goto out_ok; + } + else if (rc < 0) + { + goto out_fail; + } + goto WRITE_MORE; + } + else + { + goto READ_MORE; + } + } + /* rc == PS_SUCCESS. */ + + /* More data to send? */ + if (leftNBytes > 0) + { + goto get_more_user_data; + } + + rc = matrixSslGetOutdata(ssl, &buf); + } + +READ_MORE: + /* Get pointer to buffer where incoming data should be read into. */ + rc = matrixSslGetReadbuf(ssl, &buf); + if (rc < 0) + { + goto out_fail; + } + len = rc; + + /* Read data from the wire. */ + nrecv = recv(sock_fd, buf, len, 0); + if (nrecv < 0) + { + goto out_fail; + } + + /* Ask the TLS library to process the data we read. + Return code will tell us what to do next. */ + rc = matrixSslReceivedData( + ssl, + nrecv, + &buf, + &len); + if (rc < 0) + { + goto out_fail; + } + else if (rc == MATRIXSSL_RECEIVED_ALERT) + { + printf("Exiting on alert\n"); + goto out_fail; + } + else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) + { + if (g_handshake_complete) + { + /* This can happen when we receive further handshake messages + from the server after successful completion of the + handshake. In TLS 1.3, this occurs with NewSessionTicket + messages and post-handshake client authentication. + We already given whoever should transmit first a chance. + So now we try again to get app data from the server. */ + goto READ_MORE; + } + + printf("Handshake complete\n"); + g_handshake_complete = 1; + + if (g_server_sends_first) + { + /* Send app data over the encrypted connection. */ + rc = askSendAppData(ssl); + if (rc == PS_SUCCESS) + { + goto out_ok; + } + else if (rc < 0) + { + goto out_fail; + } + goto WRITE_MORE; + } + else + { + /* Wait for client to transmit first. */ + goto READ_MORE; + } + } + else if (rc == MATRIXSSL_REQUEST_SEND) + { + /* Handshake messages or an alert have been encoded. + These need to be sent over the wire. */ + goto WRITE_MORE; + } + else if (rc == MATRIXSSL_REQUEST_RECV) + { + /* Handshake still in progress. Need more messages + from the peer. */ + goto READ_MORE; + } + else if (rc == MATRIXSSL_APP_DATA) + { + char *tmp; + + /* We received encrypted application data from the peer. + Just print it out here. */ + tmp = malloc(len+1); + if (tmp == NULL) + { + goto out_fail; + } + Memcpy(tmp, buf, len); + tmp[len] = '\0'; + + printf("Client: %s", tmp); + if (strchr(tmp, '\n') == NULL) + { + printf("\n"); + } + if (!Strncmp(tmp, "tls-unique:", strlen("tls-unique:"))) + { + unsigned char bindings[36]; + psSizeL_t bindingsLen = sizeof(bindings); + + /* Possibly unused. */ + (void)bindings; + (void)bindingsLen; + + printf("Got tls-unique-id ID from client.\n"); +# ifdef USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS + printf(" Checking the client's tls-unique-id...\n"); + rc = matrixSslGetTlsUniqueChannelBindings( + ssl, + bindings, + &bindingsLen); + (void)rc; + if (len - strlen("tls-unique:") >= bindingsLen && + !Memcmp(tmp + strlen("tls-unique:"), + bindings, + bindingsLen)) + { + printf("It's the same as ours! No MITM.\n"); + } + else + { + printf("It's different from ours. WARNING: could be a MITM...\n"); + psTraceBytes("ours", bindings, bindingsLen); + psTraceBytes("received", + (const unsigned char*)tmp + strlen("tls-unique:"), + len - strlen("tls-unique:")); + } +# else + printf(" But would need USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS " + "to check!\n"); +# endif + } + free(tmp); + + /* Inform the TLS library that we "processed" the data. */ + rc = matrixSslProcessedData( + ssl, + &buf, + &len); + if (rc < 0) + { + goto out_fail; + } + + rc = askSendAppData(ssl); + if (rc == PS_SUCCESS) + { + goto out_ok; + } + else if (rc < 0) + { + goto out_fail; + } + goto WRITE_MORE; + } + +out_ok: + rc = PS_SUCCESS; + +out_fail: + matrixSslDeleteSession(ssl); + matrixSslDeleteKeys(keys); + matrixSslClose(); + close(sock_fd); + + if (rc == PS_SUCCESS) + { + return EXIT_SUCCESS; + } + else + { + return EXIT_FAILURE; + } +} + +# else +int main(int argc, char **argv) +{ + _psTrace("This test requires USE_TLS_1_2, USE_SECP256R1, " \ + "USE_SHA256 and USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.\n"); + return 1; +} +# endif /* USE_TLS_1_2 && USE_SECP256R1 && USE_SHA256 && USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 && USE_IDENTITY_CERTIFICATES */ +# else +int main(int argc, char **argv) +{ + _psTrace("This test requires USE_TLS_1_2, USE_SECP256R1, " \ + "USE_SHA256, USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 " \ + "and USE_IDENTITY_CERTIFICATES.\n"); + return 1; +} +# endif /* USE_CLIENT_SIDE_SSL */ diff --git a/apps/ssl/net.c b/apps/ssl/net.c index dcccace..3275ba7 100644 --- a/apps/ssl/net.c +++ b/apps/ssl/net.c @@ -60,8 +60,10 @@ static char start_remote_text[] = "\033[1m"; static char end_remote_text[] = "\033[0m"; +# ifdef USE_CLIENT_SIDE_SSL static int g_ciphers = 1; static uint16_t g_cipher[] = { 47 }; +# endif /* USE_CLIENT_SIDE_SSL */ # define HTTP_BUFFER_SIZE (1024 * 1024) diff --git a/apps/ssl/server.c b/apps/ssl/server.c index 7063cfb..c5ccfd2 100644 --- a/apps/ssl/server.c +++ b/apps/ssl/server.c @@ -40,6 +40,12 @@ # define NEED_PS_TIME_CONCRETE #endif +#ifdef __APPLE__ +# ifndef _DARWIN_C_SOURCE +# define _DARWIN_C_SOURCE +# endif +#endif + #include "app.h" #include "matrixssl/matrixsslApi.h" #include "core/psUtil.h" @@ -327,6 +333,43 @@ static void displayStats(void) } } +static +int32_t print_connection_extra_details(ssl_t *ssl) +{ + int32_t rc = PS_SUCCESS; + +# ifdef ENABLE_MASTER_SECRET_EXPORT + { + unsigned char *masterSecret = NULL; + psSizeL_t hsMasterSecretLen = 0; + matrixSslGetMasterSecret( + ssl, + &masterSecret, + &hsMasterSecretLen); + psTraceBytes("Master secret", + masterSecret, hsMasterSecretLen); + } +# endif /* ENABLE_MASTER_SECRET_EXPORT */ +# ifdef USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS + { + unsigned char bindings[36]; + psSizeL_t bindingsLen = sizeof(bindings); + + rc = matrixSslGetTlsUniqueChannelBindings( + ssl, + bindings, + &bindingsLen); + if (rc < 0) + { + goto out; + } + psTraceBytes("tls-unique", bindings, bindingsLen); + } +out: +# endif + + return rc; +} /******************************************************************************/ /* Non-blocking socket event handler @@ -628,6 +671,8 @@ WRITE_MORE: else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { Printf("Got HANDSHAKE_COMPLETE from SentData\n"); + (void)print_connection_extra_details(cp->ssl); + /* If the protocol is server initiated, send data here */ cp->handshakeComplete = 1; g_handshakes++; @@ -757,6 +802,7 @@ PROCESS_MORE: Printf("Got HANDSHAKE_COMPLETE from RecvData\n"); cp->handshakeComplete = 1; g_handshakes++; + (void)print_connection_extra_details(cp->ssl); /* If the protocol is server initiated, send data here */ goto READ_MORE; case MATRIXSSL_APP_DATA: diff --git a/apps/ssl/simpleClient.c b/apps/ssl/simpleClient.c index 1b16873..824bd77 100644 --- a/apps/ssl/simpleClient.c +++ b/apps/ssl/simpleClient.c @@ -9,7 +9,7 @@ * - Only 1 simultaneous connection. */ /* - * Copyright (c) 2013-2018 INSIDE Secure Corporation + * Copyright (c) 2013-2019 INSIDE Secure Corporation * Copyright (c) PeerSec Networks, 2002-2011 * All Rights Reserved * @@ -80,6 +80,12 @@ static const char *ip_address_str = "127.0.0.1"; # define SERVER_PORT 4433 # endif +/* Number of TLS connections to attempt. Connections after the + first one will try to use session resumption. */ +# ifndef NUM_TLS_CONNECTIONS +# define NUM_TLS_CONNECTIONS 1 +# endif + void cleanup(ssl_t *ssl, sslKeys_t *keys); int load_keys(sslKeys_t *keys); @@ -200,6 +206,9 @@ int main(int argc, char **argv) ssize_t nrecv, nsent; int fd; struct sockaddr_in addr; + sslSessionId_t *sid; + int i; + int num_resumptions = 0; rc = matrixSslOpen(); if (rc < 0) @@ -207,6 +216,13 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + /* Create new session ID structure for session resumption purposes. */ + rc = matrixSslNewSessionId(&sid, NULL); + if (rc < 0) + { + return EXIT_FAILURE; + } + /* Allocate a new key structure. */ rc = matrixSslNewKeys(&keys, NULL); if (rc < 0) @@ -264,74 +280,123 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - /* Create a new session and the ClientHello message. */ - rc = matrixSslNewClientSession( - &ssl, - keys, - NULL, - ciphersuites, - ciphersuitesLen, - certCb, - NULL, - NULL, - NULL, - &opts); - if (rc < 0) + for (i = 0; i < NUM_TLS_CONNECTIONS; i++) { - printf("matrixSslNewClientSession failed: %d\n", rc); - cleanup(ssl, keys); - return EXIT_FAILURE; - } - - /* Open the TCP connection. */ - Memset((char *) &addr, 0x0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons((short) SERVER_PORT); - addr.sin_addr.s_addr = inet_addr(ip_address_str); - fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd == -1) - { - printf("socket failed: %d\n", fd); - cleanup(ssl, keys); - return EXIT_FAILURE; - } - printf("Connecting to %s: %d\n", ip_address_str, SERVER_PORT); - rc = connect(fd, (struct sockaddr *) &addr, sizeof(addr)); - if (rc < 0) - { - close(fd); - printf("connect failed: %d\n", rc); - cleanup(ssl, keys); - return EXIT_FAILURE; - } - -WRITE_MORE: - /* Get pointer to the output data to send. */ - rc = matrixSslGetOutdata(ssl, &buf); - while (rc > 0) - { - len = rc; - - /* Send it over the wire. */ - nsent = send(fd, buf, len, 0); - if (nsent <= 0) - { - printf("send() failed\n"); - goto out_fail; - } - - /* Inform the TLS library how much we managed to send. - Return code will tell us of what to do next. */ - rc = matrixSslSentData(ssl, nsent); + /* Create a new session and the ClientHello message. */ + rc = matrixSslNewClientSession( + &ssl, + keys, + sid, + ciphersuites, + ciphersuitesLen, + certCb, + NULL, + NULL, + NULL, + &opts); + if (rc < 0) + { + printf("matrixSslNewClientSession failed: %d\n", rc); + cleanup(ssl, keys); + return EXIT_FAILURE; + } + + /* Open the TCP connection. */ + Memset((char *) &addr, 0x0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons((short) SERVER_PORT); + addr.sin_addr.s_addr = inet_addr(ip_address_str); + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + { + printf("socket failed: %d\n", fd); + cleanup(ssl, keys); + return EXIT_FAILURE; + } + printf("Connecting to %s: %d\n", ip_address_str, SERVER_PORT); + rc = connect(fd, (struct sockaddr *) &addr, sizeof(addr)); + if (rc < 0) + { + close(fd); + printf("connect failed: %d\n", rc); + cleanup(ssl, keys); + return EXIT_FAILURE; + } + + WRITE_MORE: + /* Get pointer to the output data to send. */ + rc = matrixSslGetOutdata(ssl, &buf); + while (rc > 0) + { + len = rc; + + /* Send it over the wire. */ + nsent = send(fd, buf, len, 0); + if (nsent <= 0) + { + printf("send() failed\n"); + goto out_fail; + } + + /* Inform the TLS library how much we managed to send. + Return code will tell us of what to do next. */ + rc = matrixSslSentData(ssl, nsent); + if (rc < 0) + { + printf("matrixSslSentData failed: %d\n", rc); + goto out_fail; + } + else if (rc == MATRIXSSL_REQUEST_CLOSE) + { + printf("Closing connection\n"); + goto out_ok; + } + else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) + { + printf("Handshake complete\n"); + /* Send app data over the encrypted connection. */ + rc = sendAppData( + ssl, + g_httpRequestHdr, + strlen((const char *)g_httpRequestHdr)); + if (rc < 0) + { + goto out_fail; + } + goto WRITE_MORE; + } + /* rc == PS_SUCCESS. */ + + /* More data to send? */ + rc = matrixSslGetOutdata(ssl, &buf); + } + +READ_MORE: + /* Get pointer to buffer where incoming data should be read into. */ + rc = matrixSslGetReadbuf(ssl, &buf); if (rc < 0) { - printf("matrixSslSentData failed: %d\n", rc); goto out_fail; } - else if (rc == MATRIXSSL_REQUEST_CLOSE) + len = rc; + + /* Read data from the wire. */ + nrecv = recv(fd, buf, len, 0); + if (nrecv < 0) { - printf("Closing connection\n"); - goto out_ok; + goto out_fail; + } + + /* Ask the TLS library to process the data we read. + Return code will tell us what to do next. */ + rc = matrixSslReceivedData( + ssl, + nrecv, + &buf, + &len); + if (rc < 0) + { + goto out_fail; } else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { @@ -347,92 +412,65 @@ WRITE_MORE: } goto WRITE_MORE; } - /* rc == PS_SUCCESS. */ - - /* More data to send? */ - rc = matrixSslGetOutdata(ssl, &buf); - } - -READ_MORE: - /* Get pointer to buffer where incoming data should be read into. */ - rc = matrixSslGetReadbuf(ssl, &buf); - if (rc < 0) - { - goto out_fail; - } - len = rc; - - /* Read data from the wire. */ - nrecv = recv(fd, buf, len, 0); - if (nrecv < 0) - { - goto out_fail; - } - - /* Ask the TLS library to process the data we read. - Return code will tell us what to do next. */ - rc = matrixSslReceivedData( - ssl, - nrecv, - &buf, - &len); - if (rc < 0) - { - goto out_fail; - } - else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) - { - printf("Handshake complete\n"); - /* Send app data over the encrypted connection. */ - rc = sendAppData( - ssl, - g_httpRequestHdr, - strlen((const char *)g_httpRequestHdr)); - if (rc < 0) + else if (rc == MATRIXSSL_REQUEST_SEND) { - goto out_fail; + /* Handshake messages or an alert have been encoded. + These need to be sent over the wire. */ + goto WRITE_MORE; } - goto WRITE_MORE; - } - else if (rc == MATRIXSSL_REQUEST_SEND) - { - /* Handshake messages or an alert have been encoded. - These need to be sent over the wire. */ - goto WRITE_MORE; - } - else if (rc == MATRIXSSL_REQUEST_RECV) - { - /* Handshake still in progress. Need more messages - from the peer. */ - goto READ_MORE; - } - else if (rc == MATRIXSSL_APP_DATA) - { - /* We received encrypted application data from the peer. */ + else if (rc == MATRIXSSL_REQUEST_RECV) + { + /* Handshake still in progress. Need more messages + from the peer. */ + goto READ_MORE; + } + else if (rc == MATRIXSSL_APP_DATA) + { + /* We received encrypted application data from the peer. */ # ifdef SIMPLE_CLIENT_PRINT_DECRYPTED_APP_DATA - /* For test purposes, just print it out. */ - psTraceBytes("Decrypted app data", buf, len); + /* For test purposes, just print it out. */ + psTraceBytes("Decrypted app data", buf, len); # endif - /* Inform the TLS library that we "processed" the data. */ - rc = matrixSslProcessedData( - ssl, - &buf, - &len); - if (rc < 0) - { - goto out_fail; + /* Inform the TLS library that we "processed" the data. */ + rc = matrixSslProcessedData( + ssl, + &buf, + &len); + if (rc < 0) + { + goto out_fail; + } + + /* This test ends after successful reception of encrypted + app data from the peer. */ + goto out_ok; } - /* This test ends after successful reception of encrypted - app data from the peer. */ - goto out_ok; - } out_ok: - rc = PS_SUCCESS; + rc = PS_SUCCESS; + if (matrixSslIsResumedSession(ssl)) + { + num_resumptions++; + } + if (NUM_TLS_CONNECTIONS > 1) + { + /* Delete connection object. */ + matrixSslDeleteSession(ssl); + ssl = NULL; + } + } /* end for (int i = 0; i < NUM_TLS_CONNECTIONS; i++). */ + + printf("Performed %d TLS connection(s):\n" \ + " %d Full session establishment(s)\n" \ + " %d Resumed session(s)\n", + i, + i - num_resumptions, + num_resumptions); out_fail: cleanup(ssl, keys); close(fd); + matrixSslDeleteSessionId(sid); if (rc == PS_SUCCESS) { @@ -474,10 +512,14 @@ void cleanup(ssl_t *ssl, sslKeys_t *keys) int load_keys(sslKeys_t *keys) { # ifdef LOAD_PRIVKEY_ASSET +# ifdef USE_ECC ValAssetId_t privAssetEcdsa = VAL_ASSETID_INVALID; +# endif ValAssetId_t privAssetRsa = VAL_ASSETID_INVALID; # else +# ifdef USE_ECC uint32_t privAssetEcdsa = 0; +# endif uint32_t privAssetRsa = 0; # endif int32_t rc; diff --git a/apps/ssl/simpleServer.c b/apps/ssl/simpleServer.c index 87c5fe4..d4f46b2 100644 --- a/apps/ssl/simpleServer.c +++ b/apps/ssl/simpleServer.c @@ -60,6 +60,11 @@ # define SERVER_PORT 4433 # endif +/* Number of TLS connections to accept. */ +# ifndef NUM_TLS_CONNECTIONS +# define NUM_TLS_CONNECTIONS 1 +# endif + static const char g_httpResponseHdr[] = "HTTP/1.0 200 OK\r\n" "Server: MatrixSSL 4.0.1\r\n" "Pragma: no-cache\r\n" @@ -156,6 +161,8 @@ int main(int argc, char **argv) int fd, sock_fd; struct sockaddr_in addr; int done_reading; + int i; + int num_resumptions = 0; rc = matrixSslOpen(); if (rc < 0) @@ -236,170 +243,191 @@ int main(int argc, char **argv) cleanup(ssl, keys, fd, 0); return EXIT_FAILURE; } - sock_fd = accept(fd, NULL, NULL); - if (rc < 0) - { - printf("accept failed: %d\n", rc); - cleanup(ssl, keys, fd, sock_fd); - return EXIT_FAILURE; - } - printf("Received new connection\n"); - /* Create the server TLS session. */ - rc = matrixSslNewServerSession( - &ssl, - keys, - NULL, /* No certCb -> no client auth required. */ - &opts); - if (rc < 0) + for (i = 0; i < NUM_TLS_CONNECTIONS; i++) { - printf("matrixSslNewServerSession failed: %d\n", rc); - cleanup(ssl, keys, fd, sock_fd); - return EXIT_FAILURE; - } + sock_fd = accept(fd, NULL, NULL); + if (rc < 0) + { + printf("accept failed: %d\n", rc); + cleanup(ssl, keys, fd, sock_fd); + return EXIT_FAILURE; + } + printf("Received new connection\n"); - done_reading = 0; + /* Create the server TLS session. */ + rc = matrixSslNewServerSession( + &ssl, + keys, + NULL, /* No certCb -> no client auth required. */ + &opts); + if (rc < 0) + { + printf("matrixSslNewServerSession failed: %d\n", rc); + cleanup(ssl, keys, fd, sock_fd); + return EXIT_FAILURE; + } - while(!done_reading) - { + done_reading = 0; + + while(!done_reading) + { READ_MORE: - /* Get pointer to buffer where incoming data should be read into. */ - rc = matrixSslGetReadbuf(ssl, &buf); - if (rc < 0) - { - goto out_fail; - } - len = rc; - - /* Read data from the wire. */ - nrecv = recv(sock_fd, buf, len, 0); - if (nrecv < 0) - { - goto out_fail; - } - - /* Ask the TLS library to process the data we read. - Return code will tell us what to do next. */ - rc = matrixSslReceivedData( - ssl, - nrecv, - &buf, - &len); - if (rc < 0) - { - goto out_fail; - } - else if (rc == MATRIXSSL_RECEIVED_ALERT) - { - /* Handle successful connection closure and and alerts caused - by errors. */ - if (buf[1] == SSL_ALERT_CLOSE_NOTIFY) - { - printf("Exiting: received close_notify from peer\n"); - goto out_ok; - } - else - { - printf("Exiting: received alert\n"); - goto out_fail; - } - } - else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) - { - printf("Handshake complete\n"); - /* Send app data over the encrypted connection. */ - rc = sendAppData( - ssl, - (const unsigned char *)g_httpResponseHdr, - strlen(g_httpResponseHdr)); + /* Get pointer to buffer where incoming data should be read into. */ + rc = matrixSslGetReadbuf(ssl, &buf); if (rc < 0) { goto out_fail; } - goto WRITE_MORE; - } - else if (rc == MATRIXSSL_REQUEST_SEND) - { - /* Handshake messages or an alert have been encoded. - These need to be sent over the wire. */ - goto WRITE_MORE; - } - else if (rc == MATRIXSSL_REQUEST_RECV) - { - /* Handshake still in progress. Need more messages - from the peer. */ - goto READ_MORE; - } - else if (rc == MATRIXSSL_APP_DATA) - { - /* We received encrypted application data from the peer. - Just print it out here. */ - psTraceBytes("Decrypted app data", buf, len); - /* Inform the TLS library that we "processed" the data. */ - rc = matrixSslProcessedData( + len = rc; + + /* Read data from the wire. */ + nrecv = recv(sock_fd, buf, len, 0); + if (nrecv < 0) + { + goto out_fail; + } + + /* Ask the TLS library to process the data we read. + Return code will tell us what to do next. */ + rc = matrixSslReceivedData( ssl, + nrecv, &buf, &len); if (rc < 0) { goto out_fail; } - /* Send our HTTP response over the encrypted connection. */ - rc = sendAppData( - ssl, - (const unsigned char *)g_httpResponseHdr, - strlen(g_httpResponseHdr)); - if (rc < 0) + else if (rc == MATRIXSSL_RECEIVED_ALERT) { - goto out_fail; - } - /* This test ends after we have sent our response. */ - done_reading = 1; - } - - WRITE_MORE: - /* Get pointer to the output data to send. */ - rc = matrixSslGetOutdata(ssl, &buf); - while (rc > 0) - { - len = rc; - - /* Send it over the wire. */ - nsent = send(sock_fd, buf, len, 0); - if (nsent <= 0) - { - printf("send() failed\n"); - goto out_fail; - } - - /* Inform the TLS library how much we managed to send. - Return code will tell us of what to do next. */ - rc = matrixSslSentData(ssl, nsent); - if (rc < 0) - { - printf("matrixSslSentData failed: %d\n", rc); - goto out_fail; - } - else if (rc == MATRIXSSL_REQUEST_CLOSE) - { - printf("Closing connection\n"); - goto out_ok; + /* Handle successful connection closure and and alerts caused + by errors. */ + if (buf[1] == SSL_ALERT_CLOSE_NOTIFY) + { + printf("Exiting: received close_notify from peer\n"); + goto out_ok; + } + else + { + printf("Exiting: received alert\n"); + goto out_fail; + } } else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { printf("Handshake complete\n"); - /* Try to receive encrypted app data from the client. */ + /* Send app data over the encrypted connection. */ + rc = sendAppData( + ssl, + (const unsigned char *)g_httpResponseHdr, + strlen(g_httpResponseHdr)); + if (rc < 0) + { + goto out_fail; + } + goto WRITE_MORE; + } + else if (rc == MATRIXSSL_REQUEST_SEND) + { + /* Handshake messages or an alert have been encoded. + These need to be sent over the wire. */ + goto WRITE_MORE; + } + else if (rc == MATRIXSSL_REQUEST_RECV) + { + /* Handshake still in progress. Need more messages + from the peer. */ goto READ_MORE; } - /* rc == PS_SUCCESS. */ + else if (rc == MATRIXSSL_APP_DATA) + { + /* We received encrypted application data from the peer. + Just print it out here. */ + psTraceBytes("Decrypted app data", buf, len); + /* Inform the TLS library that we "processed" the data. */ + rc = matrixSslProcessedData( + ssl, + &buf, + &len); + if (rc < 0) + { + goto out_fail; + } + /* Send our HTTP response over the encrypted connection. */ + rc = sendAppData( + ssl, + (const unsigned char *)g_httpResponseHdr, + strlen(g_httpResponseHdr)); + if (rc < 0) + { + goto out_fail; + } + /* This test ends after we have sent our response. */ + done_reading = 1; + } - /* More data to send? */ + WRITE_MORE: + /* Get pointer to the output data to send. */ rc = matrixSslGetOutdata(ssl, &buf); + while (rc > 0) + { + len = rc; + + /* Send it over the wire. */ + nsent = send(sock_fd, buf, len, 0); + if (nsent <= 0) + { + printf("send() failed\n"); + goto out_fail; + } + + /* Inform the TLS library how much we managed to send. + Return code will tell us of what to do next. */ + rc = matrixSslSentData(ssl, nsent); + if (rc < 0) + { + printf("matrixSslSentData failed: %d\n", rc); + goto out_fail; + } + else if (rc == MATRIXSSL_REQUEST_CLOSE) + { + printf("Closing connection\n"); + goto out_ok; + } + else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) + { + printf("Handshake complete\n"); + /* Try to receive encrypted app data from the client. */ + goto READ_MORE; + } + /* rc == PS_SUCCESS. */ + + /* More data to send? */ + rc = matrixSslGetOutdata(ssl, &buf); + } } - } out_ok: - rc = PS_SUCCESS; + rc = PS_SUCCESS; + if (matrixSslIsResumedSession(ssl)) + { + num_resumptions++; + } + if (NUM_TLS_CONNECTIONS > 1) + { + /* Delete connection object. */ + matrixSslDeleteSession(ssl); + ssl = NULL; + } + } /* end for (int i = 0; i < NUM_TLS_CONNECTIONS; i++). */ + + printf("Performed %d TLS connection(s):\n" \ + " %d Full session establishment(s)\n" \ + " %d Resumed session(s)\n", + i, + i - num_resumptions, + num_resumptions); out_fail: cleanup(ssl, keys, fd, sock_fd); @@ -538,6 +566,34 @@ int load_keys(sslKeys_t *keys) } # endif +# ifdef USE_STATELESS_SESSION_TICKETS + /* + If ticket-based resumption is enabled, load an dummmy example session + ticket keys. The keys will be used to encrypt session tickets, sent + to the client in a NewSessionTicket handshake message after a + successful handshake. + */ + { + const unsigned char key_name[16] = { 'k', 'e', 'y' }; + const unsigned char symkey[16] = { 's', 'y', 'm', 'k', 'e', 'y' }; + short symkey_len = 16; + const unsigned char hashkey[32] = { 'h', 'a', 's', 'h', 'k', 'e', 'y' }; + short hash_key_len = 32; + + rc = matrixSslLoadSessionTicketKeys(keys, + key_name, + symkey, + symkey_len, + hashkey, + hash_key_len); + if (rc < 0) + { + printf("matrixSslLoadSessionTicketKeys failed: %d\n", rc); + return PS_FAILURE; + } + } +# endif + return PS_SUCCESS; } diff --git a/configs/default/coreConfig.h b/configs/default/coreConfig.h index 0255323..e36e01f 100644 --- a/configs/default/coreConfig.h +++ b/configs/default/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/default/matrixsslConfig.h b/configs/default/matrixsslConfig.h index 8ddbe1c..b9a98ef 100644 --- a/configs/default/matrixsslConfig.h +++ b/configs/default/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { /* #define USE_TLS_1_2_AND_ABOVE *//**< @security better, if no backwards compatibility concerns */ /* #define USE_TLS_1_3_ONLY *//**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ # define USE_TLS_1_3_RESUMPTION @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/configs/fulltest/coreConfig.h b/configs/fulltest/coreConfig.h index 0255323..e36e01f 100644 --- a/configs/fulltest/coreConfig.h +++ b/configs/fulltest/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/fulltest/cryptoConfig.h b/configs/fulltest/cryptoConfig.h index 2552688..31da90d 100644 --- a/configs/fulltest/cryptoConfig.h +++ b/configs/fulltest/cryptoConfig.h @@ -232,7 +232,7 @@ # define USE_CERT_PARSE/**< Enable TBSCertificate parsing. Usually required. @pre USE_X509 */ # define USE_FULL_CERT_PARSE/**< @pre USE_CERT_PARSE */ /**< Support the certificatePolicy, policyMappings and policyContrainsts X.509 extensions. */ -/* #define USE_CERT_POLICY_EXTENSIONS */ +# define USE_CERT_POLICY_EXTENSIONS /**< Support extra distinguished name attributes that SHOULD be supported according to RFC 5280. */ # define USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD /**< Support extra distinguished name attributes not mentioned in RFC 5280. */ diff --git a/configs/fulltest/matrixsslConfig.h b/configs/fulltest/matrixsslConfig.h index 56747ca..a9e4556 100644 --- a/configs/fulltest/matrixsslConfig.h +++ b/configs/fulltest/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { /* #define USE_TLS_1_2_AND_ABOVE *//**< @security better, if no backwards compatibility concerns */ /* #define USE_TLS_1_3_ONLY *//**< @security best, if no backwards compatibility concerns */ # define USE_TLS_1_0_AND_ABOVE/**< @security no longer recommended. */ +# define USE_TLS_1_3_DRAFT_SPEC/**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ # define USE_TLS_1_3_RESUMPTION @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL # define ALLOW_SSLV2_CLIENT_HELLO_PARSE @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +# define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS + # ifdef __cplusplus } # endif diff --git a/configs/noecc/coreConfig.h b/configs/noecc/coreConfig.h index 0255323..e36e01f 100644 --- a/configs/noecc/coreConfig.h +++ b/configs/noecc/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/noecc/matrixsslConfig.h b/configs/noecc/matrixsslConfig.h index f950825..961dc3e 100644 --- a/configs/noecc/matrixsslConfig.h +++ b/configs/noecc/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { /* #define USE_TLS_1_2_AND_ABOVE *//**< @security better, if no backwards compatibility concerns */ /* #define USE_TLS_1_3_ONLY *//**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ # define USE_TLS_1_3_RESUMPTION @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/configs/psk/coreConfig.h b/configs/psk/coreConfig.h index e8b397f..8d31801 100644 --- a/configs/psk/coreConfig.h +++ b/configs/psk/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/psk/matrixsslConfig.h b/configs/psk/matrixsslConfig.h index 1758d10..33720c4 100644 --- a/configs/psk/matrixsslConfig.h +++ b/configs/psk/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { # define USE_TLS_1_2_AND_ABOVE/**< @security better, if no backwards compatibility concerns */ /* #define USE_TLS_1_3_ONLY *//**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ /* #define USE_TLS_1_3_RESUMPTION */ @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/configs/rsaonly/coreConfig.h b/configs/rsaonly/coreConfig.h index 0255323..e36e01f 100644 --- a/configs/rsaonly/coreConfig.h +++ b/configs/rsaonly/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/rsaonly/matrixsslConfig.h b/configs/rsaonly/matrixsslConfig.h index 2f81fe8..000ac11 100644 --- a/configs/rsaonly/matrixsslConfig.h +++ b/configs/rsaonly/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { /* #define USE_TLS_1_2_AND_ABOVE *//**< @security better, if no backwards compatibility concerns */ /* #define USE_TLS_1_3_ONLY *//**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ # define USE_TLS_1_3_RESUMPTION @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/configs/tls/coreConfig.h b/configs/tls/coreConfig.h index 0255323..e36e01f 100644 --- a/configs/tls/coreConfig.h +++ b/configs/tls/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/tls/matrixsslConfig.h b/configs/tls/matrixsslConfig.h index 8ddbe1c..b9a98ef 100644 --- a/configs/tls/matrixsslConfig.h +++ b/configs/tls/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { /* #define USE_TLS_1_2_AND_ABOVE *//**< @security better, if no backwards compatibility concerns */ /* #define USE_TLS_1_3_ONLY *//**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ # define USE_TLS_1_3_RESUMPTION @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/configs/tls12-minimal-client-ecc/coreConfig.h b/configs/tls12-minimal-client-ecc/coreConfig.h index 5c39747..98ac4cd 100644 --- a/configs/tls12-minimal-client-ecc/coreConfig.h +++ b/configs/tls12-minimal-client-ecc/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/tls12-minimal-client-ecc/matrixsslConfig.h b/configs/tls12-minimal-client-ecc/matrixsslConfig.h index 12c1d3e..11bf843 100644 --- a/configs/tls12-minimal-client-ecc/matrixsslConfig.h +++ b/configs/tls12-minimal-client-ecc/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { # define USE_TLS_1_2_AND_ABOVE/**< @security better, if no backwards compatibility concerns */ /* #define USE_TLS_1_3_ONLY *//**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ /* #define USE_TLS_1_3_RESUMPTION */ @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/configs/tls12-minimal/coreConfig.h b/configs/tls12-minimal/coreConfig.h index 5c39747..98ac4cd 100644 --- a/configs/tls12-minimal/coreConfig.h +++ b/configs/tls12-minimal/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/tls12-minimal/matrixsslConfig.h b/configs/tls12-minimal/matrixsslConfig.h index 04ed99c..4a34d34 100644 --- a/configs/tls12-minimal/matrixsslConfig.h +++ b/configs/tls12-minimal/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { # define USE_TLS_1_2_AND_ABOVE/**< @security better, if no backwards compatibility concerns */ /* #define USE_TLS_1_3_ONLY *//**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ /* #define USE_TLS_1_3_RESUMPTION */ @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/configs/tls13-minimal-client-ecc/coreConfig.h b/configs/tls13-minimal-client-ecc/coreConfig.h index 5c39747..98ac4cd 100644 --- a/configs/tls13-minimal-client-ecc/coreConfig.h +++ b/configs/tls13-minimal-client-ecc/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/tls13-minimal-client-ecc/matrixsslConfig.h b/configs/tls13-minimal-client-ecc/matrixsslConfig.h index d930cdf..7089c32 100644 --- a/configs/tls13-minimal-client-ecc/matrixsslConfig.h +++ b/configs/tls13-minimal-client-ecc/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { /* #define USE_TLS_1_2_AND_ABOVE *//**< @security better, if no backwards compatibility concerns */ # define USE_TLS_1_3_ONLY/**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ # define USE_TLS_1_3_RESUMPTION @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/configs/tls13-minimal/coreConfig.h b/configs/tls13-minimal/coreConfig.h index 5c39747..98ac4cd 100644 --- a/configs/tls13-minimal/coreConfig.h +++ b/configs/tls13-minimal/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/tls13-minimal/matrixsslConfig.h b/configs/tls13-minimal/matrixsslConfig.h index 81dfb5f..1fa0a24 100644 --- a/configs/tls13-minimal/matrixsslConfig.h +++ b/configs/tls13-minimal/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { /* #define USE_TLS_1_2_AND_ABOVE *//**< @security better, if no backwards compatibility concerns */ # define USE_TLS_1_3_ONLY/**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ # define USE_TLS_1_3_RESUMPTION @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/configs/tls13/coreConfig.h b/configs/tls13/coreConfig.h index 0255323..e36e01f 100644 --- a/configs/tls13/coreConfig.h +++ b/configs/tls13/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/configs/tls13/matrixsslConfig.h b/configs/tls13/matrixsslConfig.h index 8ddbe1c..b9a98ef 100644 --- a/configs/tls13/matrixsslConfig.h +++ b/configs/tls13/matrixsslConfig.h @@ -212,6 +212,8 @@ extern "C" { /* #define USE_TLS_1_2_AND_ABOVE *//**< @security better, if no backwards compatibility concerns */ /* #define USE_TLS_1_3_ONLY *//**< @security best, if no backwards compatibility concerns */ /* #define USE_TLS_1_0_AND_ABOVE *//**< @security no longer recommended. */ +/* #define USE_TLS_1_3_DRAFT_SPEC *//**< Support TLS 1.3 draft versions in addition to RFC 8446 + version. @security no longer recommended. */ /** Enable support for session resumption in TLS 1.3. */ # define USE_TLS_1_3_RESUMPTION @@ -249,6 +251,14 @@ extern "C" { 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. + + Note that MatrixSSL server will not accept SSL 2.0 ClientHellos if + TLS 1.3 has been enabled in the server run-time supported versions + list. This is because of the following recommendation in RFC 8446, + Appendix D.5.: + + "Implementations are NOT RECOMMENDED to accept an SSL version 2.0 + compatible CLIENT-HELLO in order to negotiate older versions of TLS." */ # ifdef USE_SERVER_SIDE_SSL /* #define ALLOW_SSLV2_CLIENT_HELLO_PARSE */ @@ -441,6 +451,9 @@ extern "C" { each supported hash algorithm. */ /* #define USE_BUFFERED_HS_HASH */ +/* Enable getter APIs for retrieving RFC 5929 tls-unique channel bindings. */ +/* #define USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS */ + # ifdef __cplusplus } # endif diff --git a/core/GNUmakefile b/core/GNUmakefile index 19bca06..8a0cddd 100644 --- a/core/GNUmakefile +++ b/core/GNUmakefile @@ -58,7 +58,7 @@ CFLAGS_GARBAGE_COLLECTION ?= -ffunction-sections -fdata-sections noinst_LIBRARIES=libcore_s.a libsfzutf_s.a libtestsupp_s.a libcore_s_a_SOURCES=$(SRC_CORE) libcore_s_a_API=core -libcore_s_a_CFLAGS=$(CFLAGS_POSITION_INDEPENDENT) $(CFLAGS_GARBAGE_COLLECTION) +libcore_s_a_CFLAGS=$(CFLAGS_POSITION_INDEPENDENT) $(CFLAGS_GARBAGE_COLLECTION) -fno-math-errno VPATH+=src libsfzutf_s_a_SOURCES=$(addprefix testsupp/src/sfzutf/, \ diff --git a/core/config/coreConfig.h b/core/config/coreConfig.h index 0255323..e36e01f 100644 --- a/core/config/coreConfig.h +++ b/core/config/coreConfig.h @@ -103,6 +103,37 @@ # define USE_PS_NETWORKING # endif /* NO_PS_NETWORKING */ +/** + Use the psStat statistics measurement for CL/SL. + + psStat is a generic statistics module. It contains features + e.g. required for measuring performance. + These capabilities can only be used on platforms with support for + thread-local storage and pthreads, such as Linux. Currently the support + will only be enabled for x86-64 Linux systems. + If statistics feature is not in use, the performance effect is minimal, + but for optimal performance in production environment, you may use + NO_PS_STAT_CL. + */ +# ifdef __x86_64__ +# ifndef NO_PS_STAT_CL +# define USE_PS_STAT_CL +# endif /* NO_PS_STAT_CL */ +# endif /* __x86_64__ */ + +/** + Use the psStat statistics measurement for CL/SL by default. + + When psStat support has been compiled in (see above), USE_PS_STAT_CL, + it is disabled by default. To enabled statistics framework, set + environment variable PS_ENABLE_STATS to any value. Enabled setting below + to get statistics measuring without any environment variable. When + statistics are on by default, they can still be disabled with + environment variable PS_SKIP_STATS. Disabling statistics is recommended + to minimize footprint. + */ +/* # define USE_PS_STAT_CL_BY_DEFAULT */ + #endif /* _h_PS_CORECONFIG */ /******************************************************************************/ diff --git a/core/include/psStat.h b/core/include/psStat.h index c0c4a1d..f20c4b8 100644 --- a/core/include/psStat.h +++ b/core/include/psStat.h @@ -31,6 +31,186 @@ #ifndef INCLUDE_GUARD_PSSTAT_H #define INCLUDE_GUARD_PSSTAT_H +typedef long long psStatItem_t; +typedef long double psStatItemFloat_t; + +/* Macros for printf formatting. */ +#define PR_PSSTAT "lld" +#define PR_PSSTATF "Lf" + +typedef struct +{ + psStatItem_t min; + psStatItem_t max; + psStatItem_t sum; + psStatItemFloat_t sumsq; + psStatItem_t count; +} psStat_t; + +psStat_t *psStatNew(void); +void psStatFree(psStat_t *stat); +psStat_t *psStatDup(psStat_t *stat); +void psStatInit(psStat_t *stat); +void psStatUpdate(psStat_t *stat, psStatItem_t new); +void psStatErase(psStat_t *stat); +int psStatIsClear(psStat_t * const stat); +psStatItem_t psStatGetCount(psStat_t * const stat); +psStatItem_t psStatGetSum(psStat_t * const stat); +psStatItemFloat_t psStatGetAverage(psStat_t * const stat); +psStatItem_t psStatGetMin(psStat_t * const stat); +psStatItem_t psStatGetMax(psStat_t * const stat); +psStatItemFloat_t psStatGetVariance(psStat_t * const stat); +psStatItemFloat_t psStatGetStdDeviation(psStat_t * const stat); + +typedef enum +{ + PS_STAT_ID_UNDEFINED, + PS_STAT_ID_CRYPT_AUTH_INIT, + PS_STAT_ID_CIPHER_CONTINUE, + PS_STAT_ID_CIPHER_CONTINUE_CBC_DEC, + PS_STAT_ID_CIPHER_CONTINUE_CBC_ENC, + PS_STAT_ID_CIPHER_FINISH, + PS_STAT_ID_CIPHER_INIT, + PS_STAT_ID_CIPHER_INIT_CBC_DEC, + PS_STAT_ID_CIPHER_INIT_CBC_ENC, + PS_STAT_ID_CRYPT_AUTH_CONTINUE, + PS_STAT_ID_CRYPT_GCM_AAD_CONTINUE, + PS_STAT_ID_CRYPT_GCM_AAD_FINISH, + PS_STAT_ID_DECRYPT_AUTH_FINISH, + PS_STAT_ID_DERIVE_TLS_PRF, + PS_STAT_ID_ENCRYPT_AUTH_FINISH, + PS_STAT_ID_ENCRYPT_AUTH_PACKET_FINISH, + PS_STAT_ID_MAC_GENERATE_CONTINUE, + PS_STAT_ID_MAC_GENERATE_FINISH, + PS_STAT_ID_MAC_GENERATE_INIT, + PS_STAT_ID_ASSET_FREE_LOCAL, + PS_STAT_ID_ASSET_FREE, + PS_STAT_ID_ASSET_STORE_STATUS, + PS_STAT_ID_LIB_INIT, + PS_STAT_ID_LIB_UNINIT, + PS_STAT_ID_ROOT_KEY_ALLOCATE_AND_LOAD_VALUE, + PS_STAT_ID_RBG_REQUEST_SECURITY_STRENGTH, + PS_STAT_ID_RBG_USE_NONBLOCKING_ENTROPY_SOURCE, + PS_STAT_ID_RBG_INSTALL_ENTROPY_SOURCE, + PS_STAT_ID_LIB_ENTER_USER_ROLE, + PS_STAT_ID_LIB_SELF_TEST, + PS_STAT_ID_ASSET_ALLOCATE_BASIC, + PS_STAT_ID_ASSET_ALLOCATE, + PS_STAT_ID_ASSET_ALLOCATE_AND_ASSOCIATE_KEY_EXTRA, + PS_STAT_ID_ASSET_LOAD_VALUE, + PS_STAT_ID_ASSET_LOAD_MULTIPART, + PS_STAT_ID_ASSET_LOAD_MULTIPART_CONVERT_BIG_INT, + PS_STAT_ID_ASSET_LOAD_RANDOM, + PS_STAT_ID_RBG_GENERATE_RANDOM, + PS_STAT_ID_RBG_RESEED, + PS_STAT_ID_ASSET_GENERATE_KEY_PAIR, + PS_STAT_ID_ASSET_SHOW, + PS_STAT_ID_ASSET_CHECK, + PS_STAT_ID_MAC_VERIFY_INIT, + PS_STAT_ID_MAC_VERIFY_CONTINUE, + PS_STAT_ID_MAC_VERIFY_FINISH, + PS_STAT_ID_HASH_INIT, + PS_STAT_ID_HASH_CONTINUE, + PS_STAT_ID_HASH_FINISH, + PS_STAT_ID_HASH_SINGLE, + PS_STAT_ID_RUNTIME_CONFIG_GET_PROPERTY, + PS_STAT_ID_RUNTIME_CONFIG_SET_PROPERTY, + PS_STAT_ID_ASSET_PEEK, + PS_STAT_ID_ASSET_POKE, + PS_STAT_ID_TRUSTED_KDK_DERIVE, + PS_STAT_ID_TRUSTED_KEKDK_DERIVE, + PS_STAT_ID_TRUSTED_KEY_DERIVE, + PS_STAT_ID_KEY_DERIVE_KDK, + PS_STAT_ID_KEY_DERIVE_PBKDF2, + PS_STAT_ID_ASSETS_WRAP_RSA_OAEP, + PS_STAT_ID_ASSETS_UNWRAP_RSA_OAEP, + PS_STAT_ID_CRYPT_KW, + PS_STAT_ID_ASSETS_WRAP_AES, + PS_STAT_ID_ASSETS_WRAP_AES_38F, + PS_STAT_ID_ASSETS_UNWRAP_AES, + PS_STAT_ID_ASSETS_UNWRAP_AES_38F, + PS_STAT_ID_ASSETS_WRAP_TRUSTED, + PS_STAT_ID_ASSETS_UNWRAP_TRUSTED, + PS_STAT_ID_PKCS1_RSAEP, + PS_STAT_ID_PKCS1_RSADP, + PS_STAT_ID_PKCS1_RSASP1, + PS_STAT_ID_PKCS1_RSAVP1, + PS_STAT_ID_ASSETS_WRAP_RSA_KEM, + PS_STAT_ID_ASSETS_UNWRAP_RSA_KEM, + PS_STAT_ID_ASSETS_WRAP_PKCS1V15, + PS_STAT_ID_ASSETS_UNWRAP_PKCS1V15, + PS_STAT_ID_HASH_SIGN_FIPS186_132, + PS_STAT_ID_HASH_SIGN_FIPS186, + PS_STAT_ID_HASH_SIGN_PKCS1, + PS_STAT_ID_HASH_VERIFY_FIPS186_132, + PS_STAT_ID_HASH_VERIFY_FIPS186, + PS_STAT_ID_HASH_VERIFY_RECOVER_PKCS1, + PS_STAT_ID_HASH_VERIFY_PKCS1, + PS_STAT_ID_HASH_SIGN_PKCS1_PSS, + PS_STAT_ID_HASH_VERIFY_PKCS1_PSS, + PS_STAT_ID_DERIVE_DH, + PS_STAT_ID_ENCRYPT_AUTH_INIT_RANDOM, + PS_STAT_ID_ENCRYPT_AUTH_INIT_DETERMINISTIC, + PS_STAT_ID_ASSET_COPY_VALUE, + PS_STAT_ID_ASSET_ALLOCATE_SAME_POLICY, + PS_STAT_ID_LOAD_FINISHED_HASH_STATE_ALGO, + PS_STAT_ID_LOAD_FINISHED_HASH_STATE, + PS_STAT_ID_HASH_FINISH_KEEP, + PS_STAT_ID_IKE_PRF_EXTRACT, + PS_STAT_ID_IKEV2_EXTRACT_SKEYSEED, + PS_STAT_ID_IKEV1_EXTRACT_SKEYID_DSA, + PS_STAT_ID_IKEV1_EXTRACT_SKEYID_PSK, + PS_STAT_ID_IKEV1_EXTRACT_SKEYID_PKE, + PS_STAT_ID_IKEV2_DERIVE_DKM, + PS_STAT_ID_IKEV2_EXTRACT_SKEYSEED_REKEY, + PS_STAT_ID_IKEV1_DERIVE_KEYING_MATERIAL, + PS_STAT_ID_RBG_TEST_VECTOR, + PS_STAT_ID_ASSET_ALLOCATE_EX, + PS_STAT_ID_ASSET_REBIND, + PS_STAT_ID_ASSET_ALLOCATE_AND_ASSOCIATE_KEY_EXTRA_EX, + PS_STAT_ID_DH_DERIVE, + PS_STAT_ID_DH_KEYGEN, + PS_STAT_ID_NUM +} psStatId_t; + +const char *resolve_ps_stat_id(psStatId_t id); + +typedef enum +{ + PS_STAT_EVENT_NORMAL_LOCK, + PS_STAT_EVENT_NORMAL_UNLOCK, + PS_STAT_EVENT_SKIP_LOCK, + PS_STAT_EVENT_SKIP_UNLOCK, + PS_STAT_EVENT_ERROR_CODE, + PS_STAT_EVENT_TEMPORARIES_ACCESS, + PS_STAT_EVENT_NUM +} psStatEvent_t; + +/* Per function statistics. */ +typedef struct +{ + psStat_t time; + psStat_t size; + psStat_t time_per_size; + psStat_t wait_time; +} psStatTimeSizeItem_t; + +typedef struct psStatTimeSize +{ + psStatTimeSizeItem_t stsi[(int)PS_STAT_ID_NUM]; + psStatItem_t events[(int)PS_STAT_ID_NUM][(int)PS_STAT_EVENT_NUM]; + struct psStatTimeSize *next; +} psStatTimeSize_t; + +#ifdef USE_PS_STAT_CL +/* Only provide psGetThreadSts and depent functions if USE_PS_STAT_CL + is set. */ +psStatTimeSize_t *psGetThreadSts(void); +void psGetThreadStsUpdate(psStatId_t id, psStatItem_t time, psStatItem_t size); +void psGetThreadStsUpdateWait(psStatId_t id, psStatItem_t wait_time); +void psGetThreadStsUpdateEvent(psStatId_t id, psStatEvent_t e); +#endif /* USE_PS_STAT_CL */ + typedef struct { int filled; diff --git a/core/include/psbuf.h b/core/include/psbuf.h index 5e74e40..dc55fb4 100644 --- a/core/include/psbuf.h +++ b/core/include/psbuf.h @@ -233,7 +233,7 @@ void *psDynBufSubFinish(psDynBuf_t *sub); # define psDynBufAppendStrf(ps_dyn_buf_p, ...) \ do { \ char tmp; \ - size_t len = 1 + Snprintf(&tmp, 1, __VA_ARGS__); \ + size_t len = 1 + Snprintf(&tmp, 0, __VA_ARGS__); \ char *target = psDynBufAppendSize((ps_dyn_buf_p), len); \ if (target) { \ Snprintf(target, len, __VA_ARGS__); \ diff --git a/core/makefiles/detect-and-rules.mk b/core/makefiles/detect-and-rules.mk index a5b1e71..682c4c6 100644 --- a/core/makefiles/detect-and-rules.mk +++ b/core/makefiles/detect-and-rules.mk @@ -8,6 +8,14 @@ # Allow building inclusion paths relative to location of common.mk file. #COMMON_MK_PATH:=$(dir $(lastword $(MAKEFILE_LIST))) +# clang on MACOS does not support -print-multiarch +ifeq ($(shell uname),Darwin) +PRINT_MULTIARCH = +else +PRINT_MULTIARCH = -print-multiarch +endif + + # Find core library. CORE_PATH:=$(patsubst %/,%/..,$(dir $(lastword $(MAKEFILE_LIST)))) include $(CORE_PATH)/Makefile.inc @@ -68,6 +76,24 @@ endif # Execute commands in environment with default locale. CLEAN_ENV=LC_ALL=POSIX +ifdef USE_FUZZ + # Use https://github.com/google/honggfuzz + CC=hfuzz-clang + CXX="$CC"++ + # Use address sanitizer, but disable leak checker as it does not work well + # (HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)) + # Also fuzzer does not have a LLVMFuzzerDeInitialize + # api to clean up so there are leaks. + HFUZZ_CC_ASAN=1 + ASAN_OPTIONS="detect_leaks=0" + export HFUZZ_CC_ASAN ASAN_OPTIONS + MATRIX_DEBUG:=1 + # -mssse3 added here as temporary hack to get chacha compiling + CFLAGS+=-DUSE_FUZZ -mssse3 + # clang does not support -print-multiarch + CCARCH:=$(shell $(CLEAN_ENV) $(CC) -dumpmachine) +endif + ## Based on the value of CC, determine the target, eg. # x86_64-redhat-linux # i686-linux-gnu @@ -81,7 +107,7 @@ 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) +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)' '' @@ -90,7 +116,7 @@ ifeq '$(CCARCH)' '' CCARCH:=$(shell $(CLEAN_ENV) $(CC) -dumpmachine) ifeq '$(CCARCH)' '' $(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.) +$(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 @@ -421,7 +447,6 @@ LIBCORE_S_A=$(CORE_PATH)/libcore_s$(A) LIBCRYPT_S_A=$(MATRIXSSL_ROOT)/crypto/libcrypt_s$(A) LIBCMS_S_A=$(MATRIXSSL_ROOT)/crypto/cms/libcms_s$(A) LIBSSL_S_A=$(MATRIXSSL_ROOT)/matrixssl/libssl_s$(A) -LIBROT_S_A=$(MATRIXSSL_ROOT)/crypto-rot/rot/lib/libdriver_val_up$(A) # Optional external libraries LIBZ=-lz diff --git a/core/makefiles/get_CCARCH.mk b/core/makefiles/get_CCARCH.mk index 5c8df9a..60a2060 100644 --- a/core/makefiles/get_CCARCH.mk +++ b/core/makefiles/get_CCARCH.mk @@ -1,8 +1,15 @@ # Get or detect compilation architecture. +# clang on MACOS does not support -print-multiarch +ifeq ($(shell uname),Darwin) +PRINT_MULTIARCH = +else +PRINT_MULTIARCH = -print-multiarch +endif + # Detect target architecture ifeq '$(CCARCH)' '' -CCARCH:=$(shell $(CLEAN_ENV) $(CC) $(CFLAGS_ARCHITECTURE_VARIANT) $(FLAGS_ARCHITECTURE_VARIANT) -print-multiarch) +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)' '' @@ -14,7 +21,7 @@ ARM_ARCH ?= armv7-a ifeq '$(CCARCH)' '' $(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.) +$(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 diff --git a/core/makefiles/rules.mk b/core/makefiles/rules.mk index 4e52be9..b4e9239 100644 --- a/core/makefiles/rules.mk +++ b/core/makefiles/rules.mk @@ -89,13 +89,16 @@ endif include $(CORE_DIR)/Makefile.inc # Common dependencies -DL=-ldl +DL=-ldl -lm +ifeq '$(origin PTHREAD)' 'undefined' PTHREAD=-lpthread +endif +LM=-lm # API spec for core (only) core_API_CFLAGS:=$(CFLAGS_CORE_INCLUDE) core_API_CXXFLAGS:=$(CFLAGS_CORE_INCLUDE) -core_API_LIBADD=$(CORE_DIR)/libcore_s.a $(PTHREAD) +core_API_LIBADD=$(CORE_DIR)/libcore_s.a $(PTHREAD) $(LM) # API spec for software using matrixssl API and/or psCrypto API. MATRIXSSL_PATH=$(CORE_PATH)/../matrixssl/matrixssl diff --git a/core/osdep/POSIX/osdep.c b/core/osdep/POSIX/osdep.c index fd7c5da..76969cb 100644 --- a/core/osdep/POSIX/osdep.c +++ b/core/osdep/POSIX/osdep.c @@ -168,8 +168,8 @@ int32 psGetTime(psTime_t *t, void *userPtr) { t = < } - *t.psTimeInternal = mach_absolute_time(); - return (int32) ((*t.psTimeInternal * hiresFreq.numer) / + t->psTimeInternal = mach_absolute_time(); + return (int32) ((t->psTimeInternal * hiresFreq.numer) / (hiresFreq.denom * 1000000000L)); } diff --git a/core/osdep/include/osdep-types.h b/core/osdep/include/osdep-types.h index ef9d614..e23d98d 100644 --- a/core/osdep/include/osdep-types.h +++ b/core/osdep/include/osdep-types.h @@ -210,7 +210,9 @@ # if defined(WIN32) # include "osdep_windows.h" # define strcasecmp LstrcmpiA -# define snprintf _snprintf +# if defined(_MSC_VER) && _MSC_VER < 1900 /* MSVC2015 */ +# define snprintf _snprintf +# endif # endif # include "osdep_stdint.h" typedef int32_t int32; diff --git a/core/osdep/include/osdep_libc-version.h b/core/osdep/include/osdep_libc-version.h index 65a0f72..c1b77c3 100644 --- a/core/osdep/include/osdep_libc-version.h +++ b/core/osdep/include/osdep_libc-version.h @@ -38,15 +38,20 @@ #ifndef OSDEP_LIBC_VERSION_H_DEFINED #define OSDEP_LIBC_VERSION_H_DEFINED 1 +/* Get (build time) libc version on Linux from GLIBC headers. + This header is no-op on other systems. + Android systems are autodetected, they do not use GLIBC. + There is -DPS_NO_GLIBC for other linux kernel based systems not using + GLIBC. */ +#ifdef __unix__ +#ifdef __linux__ +#ifndef __ANDROID__ +#ifndef PS_NO_GLIBC #include - -/* You may redefine the wrappers below in case your target system does not - provide all of the functions below. The functions are from C standard - ISO C99 and other common standards. - The defines may be overrided from command line. */ - - - +#endif /* PS_NO_GLIBC */ +#endif /* __ANDROID__ */ +#endif /* __linux__ */ +#endif /* __unix__ */ #endif /* OSDEP_LIBC_VERSION_H_DEFINED */ diff --git a/core/osdep/include/osdep_sys_random.h b/core/osdep/include/osdep_sys_random.h new file mode 100644 index 0000000..3530f99 --- /dev/null +++ b/core/osdep/include/osdep_sys_random.h @@ -0,0 +1,66 @@ +/** osdep_sys_random.h + * + * Wrapper for system header sys_random.h + */ + +/***************************************************************************** +* Copyright (c) 2018 INSIDE Secure Oy. All Rights Reserved. +* +* This confidential and proprietary software may be used only as authorized +* by a licensing agreement from INSIDE Secure. +* +* The entire notice above must be reproduced on all authorized copies that +* may only be made to the extent permitted by a licensing agreement from +* INSIDE Secure. +*****************************************************************************/ + +/* This file just includes system header sys_random.h. + In case your system does not include all functions + malloc/free/calloc/realloc/abort/getenv via that file or + does not have implementation of sys_random.h, please + customize this place holder header. +*/ + +#ifndef OSDEP_SYS_RANDOM_H_DEFINED +#define OSDEP_SYS_RANDOM_H_DEFINED 1 + +#ifdef OSDEP_HAVE_GLIBC_GETRANDOM +/* Obtain getrandom() if available. + It's available in Glibc starting with 2.25 (2017). */ +#include + +#define Getrandom getrandom +#elif defined(__linux__) && !defined(OSDEP_NO_LINUX_GETRANDOM) + +/* Emulate getrandom() function using the system call. + The system call is available starting with Linux 3.17 kernel. */ + +#include +#include +#include +#ifdef SYS_getrandom +#include +#endif /* SYS_getrandom */ + +/* Provide prototype for syscall function. */ +long syscall(long number, ...); + +#ifdef __GNUC__ +/* Request always inlining for this function. */ +static inline +ssize_t getrandom_inline(void *buf, size_t buflen, unsigned int flags) +__attribute__((__always_inline__)); +#endif + +#ifdef SYS_getrandom +static inline +ssize_t getrandom_inline(void *buf, size_t buflen, unsigned int flags) +{ + return syscall(__NR_getrandom, buf, buflen, flags); +} +#define Getrandom getrandom_inline +#endif /* SYS_getrandom */ + +#endif /* OSDEP_HAVE_GLIBC_GETRANDOM */ + +#endif /* OSDEP_SYS_RANDOM_H_DEFINED */ diff --git a/core/osdep/include/osdep_unistd.h b/core/osdep/include/osdep_unistd.h index 86ed8da..b324139 100644 --- a/core/osdep/include/osdep_unistd.h +++ b/core/osdep/include/osdep_unistd.h @@ -38,7 +38,7 @@ #ifndef OSDEP_UNISTD_H_DEFINED #define OSDEP_UNISTD_H_DEFINED 1 -#if defined _POSIX_C_SOURCE || defined __unix__ || defined __linux__ || defined __android__ +#if defined _POSIX_C_SOURCE || defined __unix__ || defined __linux__ || defined __android_ || defined __APPLE__ #include /* You may redefine the wrappers below in case your target system does not diff --git a/core/osdep/src/runtime.c b/core/osdep/src/runtime.c index 02f1c17..c8dcd2a 100644 --- a/core/osdep/src/runtime.c +++ b/core/osdep/src/runtime.c @@ -2,10 +2,8 @@ #if defined USE_SL_CHACHA20_POLY1305_IETF || defined USE_SL_SODIUM # include "osdep_stddef.h" # include "osdep_stdint.h" -# ifdef HAVE_ANDROID_GETCPUFEATURES -# include "osdep_cpu-features.h" -# endif - +# include "osdep_stdlib.h" +# include "osdep_stdbool.h" # include "private/common.h" # include "runtime.h" # include "pscompilerdep.h" @@ -44,27 +42,34 @@ static CPUFeatures _cpu_features; static int SLSodium_runtime_arm_cpu_features(CPUFeatures * const cpu_features) { -# ifndef __arm__ +# if !defined(__arm__) && !defined(__aarch64__) && !defined(__aarch32__) cpu_features->has_neon = 0; return -1; -# else +#else /* some ARM platform. */ # define NO_INTEL /* This architecture is definitely not x86/x86-64. No need to probe for Intel CPU features. */ -# ifdef __APPLE__ -# ifdef __ARM_NEON__ - cpu_features->has_neon = 1; -# else - cpu_features->has_neon = 0; -# endif -# elif defined(HAVE_ANDROID_GETCPUFEATURES) && \ - defined(ANDROID_CPU_ARM_FEATURE_NEON) - cpu_features->has_neon = - (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0x0; -# else - cpu_features->has_neon = 0; -# endif + /* Customization for INSIDE Secure FIPS Toolkit: */ + /* Use sl_cpu.c for ARM feature detection, instead of + the default sodium code. */ + + extern bool SL_ArmDetectionDone; + extern bool SL_hasNEON; + void SL_DetectArmFeatures(void); + + if (!SL_ArmDetectionDone) + { + if (!getenv("SAFEZONE_DISABLE_HW")) + { + SL_DetectArmFeatures(); + } + else + { + SL_ArmDetectionDone = 1; + } + } + cpu_features->has_neon = SL_hasNEON; return 0; -# endif +# endif /* ARM variant (including ARMv7 or ARMv8). */ } #ifndef NO_INTEL diff --git a/core/src/psStat.c b/core/src/psStat.c index 7a01df5..a2cb2f1 100644 --- a/core/src/psStat.c +++ b/core/src/psStat.c @@ -30,8 +30,14 @@ #include "osdep.h" #include "osdep_stdio.h" +#include "osdep_stdlib.h" +#include "osdep_string.h" +#include "osdep_math.h" #include "psStat.h" #include "psUtil.h" +#ifdef USE_PS_STAT_CL +#include "pthread.h" +#endif /* USE_PS_STAT_CL */ psStatCompByteSeqResult_t psStatCompByteSeq(const unsigned char *a, const char *aName, @@ -321,4 +327,628 @@ psRes_t psStatTest(void) } # endif /* PS_STAT_TEST */ + +void psStatInit(psStat_t *stat) +{ + if (stat) + { + Memset(stat, 0, sizeof(*stat)); + stat->sumsq = (psStatItemFloat_t)0.0; + } +} + +void psStatUpdate(psStat_t *stat, psStatItem_t new) +{ + psStatItemFloat_t newf = (psStatItemFloat_t) new; + + if (stat) + { + if (stat->count == 0) + { + stat->min = new; + stat->max = new; + } + else + { + if (new < stat->min) + { + stat->min = new; + } + if (new > stat->max) + { + stat->max = new; + } + } + stat->sum += new; + stat->count += 1; + stat->sumsq += newf * newf; + } +} + +void psStatErase(psStat_t *stat) +{ + psStatInit(stat); /* Initialization also erases. */ +} + +psStatItem_t psStatGetCount(psStat_t * const stat) +{ + return stat ? stat->count : 0; +} + +int psStatIsClear(psStat_t * const stat) +{ + return psStatGetCount(stat) == 0; +} + +psStatItem_t psStatGetSum(psStat_t * const stat) +{ + return stat ? stat->sum : 0; +} + +psStatItem_t psStatGetMin(psStat_t * const stat) +{ + return stat ? stat->min : 0; +} + +psStatItem_t psStatGetMax(psStat_t * const stat) +{ + return stat ? stat->max : 0; +} + +static psStatItemFloat_t psStatGetNan(void) +{ +#ifdef NAN + return (psStatItemFloat_t) NAN; +#else + return (psStatItemFloat_t) (0.0 / 0.0); +#endif +} + +psStatItemFloat_t psStatGetAverage(psStat_t * const stat) +{ + psStatItem_t div = psStatGetCount(stat); + psStatItemFloat_t sumf = (psStatItemFloat_t) psStatGetSum(stat); + + return div > 0 ? sumf / div : psStatGetNan(); +} + +psStatItemFloat_t psStatGetVariance(psStat_t * const stat) +{ + psStatItem_t div = psStatGetCount(stat); + + if (div > 0) + { + psStatItemFloat_t sumsqf; + + sumsqf = (psStatItemFloat_t) psStatGetSum(stat); + sumsqf = sumsqf * sumsqf; + + return (stat->sumsq - (sumsqf / div)) / div; + } + return psStatGetNan(); +} + +psStatItemFloat_t psStatGetStdDeviation(psStat_t * const stat) +{ + long double __builtin_sqrtl(long double x); + psStatItemFloat_t r = psStatGetVariance(stat); + + return __builtin_sqrtl(r); /* Note: Use built-in function to avoid need for -lm. On non-x86 platforms use sqrtl() instead and add -lm. */ +} + +psStat_t *psStatNew(void) +{ + psStat_t *stat = Malloc(sizeof(psStat_t)); + + psStatInit(stat); + return stat; +} + +void psStatFree(psStat_t *stat) +{ + psStatErase(stat); + Free(stat); +} + +psStat_t *psStatDup(psStat_t *stat) +{ + psStat_t *newStat = NULL; + + if (stat) + { + newStat = psStatNew(); + + if (newStat) + { + Memcpy(newStat, stat, sizeof(psStat_t)); + } + } + + return newStat; +} + +#ifdef USE_PS_STAT_CL +/* Only provide psGetThreadSts and depent functions if USE_PS_STAT_CL + is set. */ +static pthread_mutex_t stat_list_mutex = PTHREAD_MUTEX_INITIALIZER; +static psStatTimeSize_t *stat_list = NULL; +static __thread psStatTimeSize_t *thread_sts = NULL; + +psStatTimeSize_t *psGetThreadSts(void) +{ + psStatTimeSize_t *sts; + int count = 0; + + sts = thread_sts; + if (sts == NULL) + { + sts = malloc(sizeof(psStatTimeSize_t)); + + if (sts) + { + int i; + + for(i = 0; i < (int) PS_STAT_ID_NUM; i++) + { + psStatInit(&sts->stsi[i].time); + psStatInit(&sts->stsi[i].size); + psStatInit(&sts->stsi[i].time_per_size); + } + sts->next = NULL; + + /* Add statistics to the global list. */ + pthread_mutex_lock(&stat_list_mutex); + thread_sts = sts; + if (stat_list == NULL) + { + stat_list = thread_sts; + } + else + { + psStatTimeSize_t *next_ptr = NULL; + + next_ptr = stat_list; + while (next_ptr->next) + { + count++; + next_ptr = next_ptr->next; + } + next_ptr->next = sts; + } + pthread_mutex_unlock(&stat_list_mutex); + } + else + { + fprintf(stderr, "Memory allocation error: statistics\n"); + exit(1); + } + } + return sts; +} + +void psGetThreadStsUpdate(psStatId_t id, + psStatItem_t time, + psStatItem_t size) +{ + psStatTimeSize_t *sts = psGetThreadSts(); + + if (sts) + { + psStatTimeSizeItem_t *stsi = &sts->stsi[(int) id]; + + psStatUpdate(&stsi->time, time); + if (size > 0) + { + psStatItem_t time_per_size = time / size; + + psStatUpdate(&stsi->size, size); + psStatUpdate(&stsi->time_per_size, time_per_size); + } + } +} + +void psGetThreadStsUpdateWait(psStatId_t id, psStatItem_t wait_time) +{ + psStatTimeSize_t *sts = psGetThreadSts(); + + if (sts) + { + psStatTimeSizeItem_t *stsi = &sts->stsi[(int) id]; + + psStatUpdate(&stsi->wait_time, wait_time); + } +} + +void psGetThreadStsUpdateEvent(psStatId_t id, psStatEvent_t e) +{ + psStatTimeSize_t *sts = psGetThreadSts(); + + if (sts) + { + sts->events[id][e] ++; + } +} +#endif /* USE_PS_STAT_CL */ + +#include "osdep_math.h" +/* Print number that can be nan. + If number is nan, always produce "NaN" as output. */ +static char *printoptnan(char *buf, psStatItemFloat_t val) +{ + if (val == val) + { + /* Number. */ + sprintf(buf, "%.2"PR_PSSTATF, val); + } + else + { + /* Not a number. */ + memcpy(buf, "NaN", 4); + } + + return buf; +} + +const char *resolve_ps_stat_id(psStatId_t id) +{ + const char *name; + + switch(id) + { + case PS_STAT_ID_CRYPT_AUTH_INIT: name = "crypt_auth_init"; break; + case PS_STAT_ID_CIPHER_INIT: name = "cipher_init"; break; + case PS_STAT_ID_CIPHER_CONTINUE: name = "cipher_continue"; break; + case PS_STAT_ID_CIPHER_FINISH: name = "cipher_finish"; break; + case PS_STAT_ID_CIPHER_INIT_CBC_ENC: name = "cipher_init_cbc_enc"; break; + case PS_STAT_ID_CIPHER_CONTINUE_CBC_ENC: name = "cipher_continue_cbc_enc"; break; + case PS_STAT_ID_CIPHER_INIT_CBC_DEC: name = "cipher_init_cbc_dec"; break; + case PS_STAT_ID_CIPHER_CONTINUE_CBC_DEC: name = "cipher_continue_cbc_dec"; break; + case PS_STAT_ID_CRYPT_AUTH_CONTINUE: name = "crypt_auth_continue"; break; + case PS_STAT_ID_CRYPT_GCM_AAD_CONTINUE: name = "crypt_gcm_aad_continue"; break; + case PS_STAT_ID_CRYPT_GCM_AAD_FINISH: name = "crypt_gcm_aad_finish"; break; + case PS_STAT_ID_DECRYPT_AUTH_FINISH: name = "decrypt_auth_finish"; break; + case PS_STAT_ID_DERIVE_TLS_PRF: name = "derive_tls_prf"; break; + case PS_STAT_ID_ENCRYPT_AUTH_FINISH: name = "encrypt_auth_finish"; break; + case PS_STAT_ID_ENCRYPT_AUTH_PACKET_FINISH: name = "encrypt_auth_packet_finish"; break; + case PS_STAT_ID_MAC_GENERATE_CONTINUE: name = "mac_generate_continue"; break; + case PS_STAT_ID_MAC_GENERATE_FINISH: name = "mac_generate_finish"; break; + case PS_STAT_ID_MAC_GENERATE_INIT: name = "mac_generate_init"; break; + case PS_STAT_ID_ASSET_FREE_LOCAL: name = "asset_free_local"; break; + case PS_STAT_ID_ASSET_FREE: name = "asset_free"; break; + case PS_STAT_ID_ASSET_STORE_STATUS: name = "asset_store_status"; break; + case PS_STAT_ID_LIB_INIT: name = "lib_init"; break; + case PS_STAT_ID_LIB_UNINIT: name = "lib_uninit"; break; + case PS_STAT_ID_ROOT_KEY_ALLOCATE_AND_LOAD_VALUE: name = "root_key_allocate_and_load_value"; break; + case PS_STAT_ID_RBG_REQUEST_SECURITY_STRENGTH: name = "rbg_request_security_strength"; break; + case PS_STAT_ID_RBG_USE_NONBLOCKING_ENTROPY_SOURCE: name = "rbg_use_nonblocking_entropy_source"; break; + case PS_STAT_ID_RBG_INSTALL_ENTROPY_SOURCE: name = "rbg_install_entropy_source"; break; + case PS_STAT_ID_LIB_ENTER_USER_ROLE: name = "lib_enter_user_role"; break; + case PS_STAT_ID_LIB_SELF_TEST: name = "lib_self_test"; break; + case PS_STAT_ID_ASSET_ALLOCATE_BASIC: name = "asset_allocate_basic"; break; + case PS_STAT_ID_ASSET_ALLOCATE: name = "asset_allocate"; break; + case PS_STAT_ID_ASSET_ALLOCATE_AND_ASSOCIATE_KEY_EXTRA: name = "asset_allocate_and_associate_key_extra"; break; + case PS_STAT_ID_ASSET_LOAD_VALUE: name = "asset_load_value"; break; + case PS_STAT_ID_ASSET_LOAD_MULTIPART: name = "asset_load_multipart"; break; + case PS_STAT_ID_ASSET_LOAD_MULTIPART_CONVERT_BIG_INT: name = "asset_load_multipart_convert_big_int"; break; + case PS_STAT_ID_ASSET_LOAD_RANDOM: name = "asset_load_random"; break; + case PS_STAT_ID_RBG_GENERATE_RANDOM: name = "rbg_generate_random"; break; + case PS_STAT_ID_RBG_RESEED: name = "rbg_reseed"; break; + case PS_STAT_ID_ASSET_GENERATE_KEY_PAIR: name = "asset_generate_key_pair"; break; + case PS_STAT_ID_ASSET_SHOW: name = "asset_show"; break; + case PS_STAT_ID_ASSET_CHECK: name = "asset_check"; break; + case PS_STAT_ID_MAC_VERIFY_INIT: name = "mac_verify_init"; break; + case PS_STAT_ID_MAC_VERIFY_CONTINUE: name = "mac_verify_continue"; break; + case PS_STAT_ID_MAC_VERIFY_FINISH: name = "mac_verify_finish"; break; + case PS_STAT_ID_HASH_INIT: name = "hash_init"; break; + case PS_STAT_ID_HASH_CONTINUE: name = "hash_continue"; break; + case PS_STAT_ID_HASH_FINISH: name = "hash_finish"; break; + case PS_STAT_ID_HASH_SINGLE: name = "hash_single"; break; + case PS_STAT_ID_RUNTIME_CONFIG_GET_PROPERTY: name = "runtime_config_get_property"; break; + case PS_STAT_ID_RUNTIME_CONFIG_SET_PROPERTY: name = "runtime_config_set_property"; break; + case PS_STAT_ID_ASSET_PEEK: name = "asset_peek"; break; + case PS_STAT_ID_ASSET_POKE: name = "asset_poke"; break; + case PS_STAT_ID_TRUSTED_KDK_DERIVE: name = "trusted_kdk_derive"; break; + case PS_STAT_ID_TRUSTED_KEKDK_DERIVE: name = "trusted_kekdk_derive"; break; + case PS_STAT_ID_TRUSTED_KEY_DERIVE: name = "trusted_key_derive"; break; + case PS_STAT_ID_KEY_DERIVE_KDK: name = "key_derive_kdk"; break; + case PS_STAT_ID_KEY_DERIVE_PBKDF2: name = "key_derive_pbkdf2"; break; + case PS_STAT_ID_ASSETS_WRAP_RSA_OAEP: name = "assets_wrap_rsa_oaep"; break; + case PS_STAT_ID_ASSETS_UNWRAP_RSA_OAEP: name = "assets_unwrap_rsa_oaep"; break; + case PS_STAT_ID_CRYPT_KW: name = "crypt_kw"; break; + case PS_STAT_ID_ASSETS_WRAP_AES: name = "assets_wrap_aes"; break; + case PS_STAT_ID_ASSETS_WRAP_AES_38F: name = "assets_wrap_aes_38f"; break; + case PS_STAT_ID_ASSETS_UNWRAP_AES: name = "assets_unwrap_aes"; break; + case PS_STAT_ID_ASSETS_UNWRAP_AES_38F: name = "assets_unwrap_aes_38f"; break; + case PS_STAT_ID_ASSETS_WRAP_TRUSTED: name = "assets_wrap_trusted"; break; + case PS_STAT_ID_ASSETS_UNWRAP_TRUSTED: name = "assets_unwrap_trusted"; break; + case PS_STAT_ID_PKCS1_RSAEP: name = "pkcs1_rsaep"; break; + case PS_STAT_ID_PKCS1_RSADP: name = "pkcs1_rsadp"; break; + case PS_STAT_ID_PKCS1_RSASP1: name = "pkcs1_rsasp1"; break; + case PS_STAT_ID_PKCS1_RSAVP1: name = "pkcs1_rsavp1"; break; + case PS_STAT_ID_ASSETS_WRAP_RSA_KEM: name = "assets_wrap_rsa_kem"; break; + case PS_STAT_ID_ASSETS_UNWRAP_RSA_KEM: name = "assets_unwrap_rsa_kem"; break; + case PS_STAT_ID_ASSETS_WRAP_PKCS1V15: name = "assets_wrap_pkcs1v15"; break; + case PS_STAT_ID_ASSETS_UNWRAP_PKCS1V15: name = "assets_unwrap_pkcs1v15"; break; + case PS_STAT_ID_HASH_SIGN_FIPS186_132: name = "hash_sign_fips186_132"; break; + case PS_STAT_ID_HASH_SIGN_FIPS186: name = "hash_sign_fips186"; break; + case PS_STAT_ID_HASH_SIGN_PKCS1: name = "hash_sign_pkcs1"; break; + case PS_STAT_ID_HASH_VERIFY_FIPS186_132: name = "hash_verify_fips186_132"; break; + case PS_STAT_ID_HASH_VERIFY_FIPS186: name = "hash_verify_fips186"; break; + case PS_STAT_ID_HASH_VERIFY_RECOVER_PKCS1: name = "hash_verify_recover_pkcs1"; break; + case PS_STAT_ID_HASH_VERIFY_PKCS1: name = "hash_verify_pkcs1"; break; + case PS_STAT_ID_HASH_SIGN_PKCS1_PSS: name = "hash_sign_pkcs1_pss"; break; + case PS_STAT_ID_HASH_VERIFY_PKCS1_PSS: name = "hash_verify_pkcs1_pss"; break; + case PS_STAT_ID_DERIVE_DH: name = "derive_dh"; break; + case PS_STAT_ID_ENCRYPT_AUTH_INIT_RANDOM: name = "encrypt_auth_init_random"; break; + case PS_STAT_ID_ENCRYPT_AUTH_INIT_DETERMINISTIC: name = "encrypt_auth_init_deterministic"; break; + case PS_STAT_ID_ASSET_COPY_VALUE: name = "asset_copy_value"; break; + case PS_STAT_ID_ASSET_ALLOCATE_SAME_POLICY: name = "asset_allocate_same_policy"; break; + case PS_STAT_ID_LOAD_FINISHED_HASH_STATE_ALGO: name = "load_finished_hash_state_algo"; break; + case PS_STAT_ID_LOAD_FINISHED_HASH_STATE: name = "load_finished_hash_state"; break; + case PS_STAT_ID_HASH_FINISH_KEEP: name = "hash_finish_keep"; break; + case PS_STAT_ID_IKE_PRF_EXTRACT: name = "ike_prf_extract"; break; + case PS_STAT_ID_IKEV2_EXTRACT_SKEYSEED: name = "ikev2_extract_skeyseed"; break; + case PS_STAT_ID_IKEV1_EXTRACT_SKEYID_DSA: name = "ikev1_extract_skeyid_dsa"; break; + case PS_STAT_ID_IKEV1_EXTRACT_SKEYID_PSK: name = "ikev1_extract_skeyid_psk"; break; + case PS_STAT_ID_IKEV1_EXTRACT_SKEYID_PKE: name = "ikev1_extract_skeyid_pke"; break; + case PS_STAT_ID_IKEV2_DERIVE_DKM: name = "ikev2_derive_dkm"; break; + case PS_STAT_ID_IKEV2_EXTRACT_SKEYSEED_REKEY: name = "ikev2_extract_skeyseed_rekey"; break; + case PS_STAT_ID_IKEV1_DERIVE_KEYING_MATERIAL: name = "ikev1_derive_keying_material"; break; + case PS_STAT_ID_RBG_TEST_VECTOR: name = "rbg_test_vector"; break; + case PS_STAT_ID_ASSET_ALLOCATE_EX: name = "asset_allocate_ex"; break; + case PS_STAT_ID_ASSET_REBIND: name = "asset_rebind"; break; + case PS_STAT_ID_ASSET_ALLOCATE_AND_ASSOCIATE_KEY_EXTRA_EX: name = "asset_allocate_and_associate_key_extra_ex"; break; + case PS_STAT_ID_DH_DERIVE: name = "dh_derive"; break; + case PS_STAT_ID_DH_KEYGEN: name = "dh_keygen"; break; + default: /* PS_STAT_ID_UNDEFINED etc. */ + name = "undefined"; + } + + return name; +} + +static const char *resolve_ps_stat_event(psStatEvent_t event) +{ + const char *name; + + switch(event) + { + case PS_STAT_EVENT_NORMAL_LOCK: name = "locks"; break; + case PS_STAT_EVENT_NORMAL_UNLOCK: name = "unlocks"; break; + case PS_STAT_EVENT_SKIP_LOCK: name = "skip_lock"; break; + case PS_STAT_EVENT_SKIP_UNLOCK: name = "skip_unlock"; break; + case PS_STAT_EVENT_ERROR_CODE: name = "errors"; break; + case PS_STAT_EVENT_TEMPORARIES_ACCESS: name = "temp_access"; break; + default: /* PS_STAT_EVENT_UNDEFINED etc. */ + name = "undefined"; + } + + return name; +} + +#ifdef USE_PS_STAT_CL +/* Dump CL statistics at the end of software binary execution. + The intent is that statistics are not being updated during this function, + but unfortunately, the function cannot prevent that from happening. In the + most cases, operating system should call destructor when there is no longer + active processing with threads. + + This destructor assumes standard IO can be performed while executing the + destructor. +*/ +void psDumpThreadSts(void) __attribute__((__destructor__)); +void psDumpThreadSts(void) +{ + FILE *out = stderr; + int thread_idx; + int close_out = 0; + psStatTimeSize_t *sts; + int first = 1; + + if (getenv("STATS_FILE_APPEND") != NULL) + { + out = fopen(getenv("STATS_FILE_APPEND"), "a"); + if (out == NULL) + { + fprintf(stderr, "Cannot open %s for output; statistics skipped.\n", + getenv("STATS_FILE_APPEND")); + return; + } + close_out = 1; + } + else if (getenv("STATS_FILE") != NULL) + { + out = fopen(getenv("STATS_FILE"), "w"); + if (out == NULL) + { + fprintf(stderr, "Cannot open %s for output; statistics skipped.\n", + getenv("STATS_FILE")); + return; + } + close_out = 1; + } + + pthread_mutex_lock(&stat_list_mutex); + sts = stat_list; + thread_idx = 0; + while(sts != NULL) + { + int i; + + for(i = (int) PS_STAT_ID_UNDEFINED; i < (int) PS_STAT_ID_NUM; i++) + { + const char *name; + psStatTimeSizeItem_t *stsi; + char out2[100]; + char out3[100]; + psStat_t *s; + + name = resolve_ps_stat_id((psStatId_t) i); + + stsi = &sts->stsi[(int) i]; + s = &stsi->time; + + if (!psStatIsClear(s)) + { + if (first) + { + FILE *f; + + fprintf(out, "---statistics---\n"); + fprintf(out, "thread,stat,aspect,count,avg,min,max,std"); + f = popen("cat /proc/cpuinfo | grep 'cpu MHz'", "r"); + if (f) + { + char buf[128]; + char *s; + + memset(buf, 0, sizeof(buf)); + s = fgets(buf, 100, f); + if (s) + { + s = strchr(buf, ':'); + } + if (s) + { + fprintf(out, ",hz=%s", s + 2); + } + else + { + fprintf(out, "\n"); + } + pclose(f); + } + else + { + fprintf(out, "\n"); + } + first = 0; + } + fprintf(out, + "%d,%s,%s,%"PR_PSSTAT",%s,%"PR_PSSTAT",%"PR_PSSTAT + ",%s\n", + thread_idx, + name, + "time", + psStatGetCount(s), + printoptnan(out2, psStatGetAverage(s)), + psStatGetMin(s), + psStatGetMax(s), + printoptnan(out3, psStatGetStdDeviation(s))); + + s = &stsi->size; + if (!psStatIsClear(s)) + { + fprintf(out, + "%d,%s,%s,%"PR_PSSTAT",%s,%"PR_PSSTAT",%"PR_PSSTAT + ",%s\n", + thread_idx, + name, + "size", + psStatGetCount(s), + printoptnan(out2, psStatGetAverage(s)), + psStatGetMin(s), + psStatGetMax(s), + printoptnan(out3, psStatGetStdDeviation(s))); + } + + s = &stsi->time_per_size; + if (!psStatIsClear(s)) + { + fprintf(out, + "%d,%s,%s,%"PR_PSSTAT",%s,%"PR_PSSTAT",%"PR_PSSTAT + ",%s\n", + thread_idx, + name, + "time_per_size", + psStatGetCount(s), + printoptnan(out2, psStatGetAverage(s)), + psStatGetMin(s), + psStatGetMax(s), + printoptnan(out3, psStatGetStdDeviation(s))); + } + + s = &stsi->wait_time; + if (!psStatIsClear(s)) + { + fprintf(out, + "%d,%s,%s,%"PR_PSSTAT",%s,%"PR_PSSTAT",%"PR_PSSTAT + ",%s\n", + thread_idx, + name, + "wait_time", + psStatGetCount(s), + printoptnan(out2, psStatGetAverage(s)), + psStatGetMin(s), + psStatGetMax(s), + printoptnan(out3, psStatGetStdDeviation(s))); + } + } + } + sts = sts->next; + thread_idx ++; + } + if (first == 0) + { + fprintf(out, "---statistics---\n"); + } + + sts = stat_list; + thread_idx = 0; + first = 1; + while(sts != NULL) + { + int i; + int l; + + for(i = (int) PS_STAT_ID_UNDEFINED; i < (int) PS_STAT_ID_NUM; i++) + { + const char *name; + char out2[100]; + + name = resolve_ps_stat_id((psStatId_t) i); + for (l = 0; l < (int) PS_STAT_EVENT_NUM; l++) + { + psStatItem_t event = sts->events[i][l]; + if (event > 0) + { + if (first == 1) + { + fprintf(out, "---events---\n"); + fprintf(out, "thread,stat"); + for (l = 0; l < (int) PS_STAT_EVENT_NUM; l++) + { + fprintf(out, ",%s", + resolve_ps_stat_event((psStatEvent_t) l)); + } + fprintf(out, "\n"); + first = 0; + } + fprintf(out, "%d,%s", thread_idx, name); + for (l = 0; l < (int) PS_STAT_EVENT_NUM; l++) + { + psStatItem_t event = sts->events[i][l]; + fprintf(out, ",%"PR_PSSTAT, event); + } + fprintf(out, "\n"); + break; + } + } + } + sts = sts->next; + thread_idx ++; + } + if (first == 0) + { + fprintf(out, "---events---\n"); + } + pthread_mutex_unlock(&stat_list_mutex); + + if (close_out) + { + fclose(out); + } +} +#endif /* USE_PS_STAT_CL */ + /* end of file psStat.c */ diff --git a/core/src/psbuf.c b/core/src/psbuf.c index 5267823..f475135 100644 --- a/core/src/psbuf.c +++ b/core/src/psbuf.c @@ -302,7 +302,7 @@ void *psDynBufDetachPsSize(psDynBuf_t *db, psSize_t *len_p) } db->pool = NULL; - if (len > PS_SIZE_MAX) + if (len > (size_t) PS_SIZE_MAX) { psDynBufUninit(db); return NULL; @@ -1373,7 +1373,7 @@ int psParseTlsVariableLengthVec(const unsigned char *start, return PS_ARG_FAIL; } - if ((end - start) < numLenBytes) + if ((psSizeL_t) (end - start) < numLenBytes) { psTraceCore("Error parsing vec len\n"); return PS_LIMIT_FAIL; @@ -1392,7 +1392,7 @@ int psParseTlsVariableLengthVec(const unsigned char *start, } } - if ((end - p) < len) + if ((psSizeL_t) (end - p) < len) { psTraceCore("Error: vector has less data than indicated " \ "by the length encoding\n"); diff --git a/core/src/sl_cpu.c b/core/src/sl_cpu.c index af73b8f..d89c8f4 100644 --- a/core/src/sl_cpu.c +++ b/core/src/sl_cpu.c @@ -35,20 +35,42 @@ #if defined(__aarch64__) || defined(__aarch32__) || defined(__arm__) #include "pscompilerdep.h" + +#ifndef CRYPTOPP_NO_GETAUXV_AVAILABLE #include -// Capability queries, requires Glibc 2.16, http://lwn.net/Articles/519085/ -// CRYPTOPP_GLIBC_VERSION not used because config.h is missing +/* Capability queries, requires Glibc 2.16, http://lwn.net/Articles/519085/ + CRYPTOPP_GLIBC_VERSION not used because config.h is missing */ #if (((__GLIBC__ * 100) + __GLIBC_MINOR__) >= 216) -# define CRYPTOPP_GETAUXV_AVAILABLE 1 +# ifndef CRYPTOPP_GETAUXV_AVAILABLE +# define CRYPTOPP_GETAUXV_AVAILABLE 1 +# endif #endif +#ifdef __ANDROID__ +/* We also use getauxval() functionality on Android. */ +# ifndef CRYPTOPP_GETAUXV_AVAILABLE +# define CRYPTOPP_GETAUXV_AVAILABLE 1 +# endif +#endif +#endif /* CRYPTOPP_NO_GETAUXV_AVAILABLE */ #include "osdep_stdbool.h" #if CRYPTOPP_GETAUXV_AVAILABLE # include "osdep_sys_auxv.h" #else -unsigned long int getauxval(unsigned long int) { return 0; } +/* Provide stub for getauxval() API with AT_HWCAP and AT_HWCAP2. */ +unsigned long int getauxval(unsigned long int type) +{ + (void) type; /* Parameter not used. */ + return 0; +} +#ifndef AT_HWCAP +#define AT_HWCAP 16 +#endif +#ifndef AT_HWCAP2 +#define AT_HWCAP2 26 +#endif #endif #include "osdep_unistd.h" @@ -123,23 +145,32 @@ unsigned int SL_cacheLineSize; # define HWCAP2_SHA2 (1 << 3) #endif +/* Use generic pattern for hardware capabilities detection from auxval. */ +#if defined __linux__ && !defined PS_USE_GETAUXVAL +#define PS_USE_GETAUXVAL 1 +#endif + +#if defined __ANDROID__ && !defined PS_USE_GETAUXVAL +#define PS_USE_ANDROID_GET_CPU_FAMILY 1 /* Android can also use this. */ +#endif + static inline bool CPU_QueryNEON() { -#if defined(__ANDROID__) && defined(__aarch64__) +#if defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch64__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) && (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_ASIMD)) return true; -#elif defined(__ANDROID__) && defined(__arm__) +#elif defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__arm__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON)) return true; -#elif defined(__linux__) && defined(__aarch64__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch64__) if (getauxval(AT_HWCAP) & HWCAP_ASIMD) return true; -#elif defined(__linux__) && defined(__aarch32__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch32__) if (getauxval(AT_HWCAP2) & HWCAP2_ASIMD) return true; -#elif defined(__linux__) && defined(__arm__) +#elif defined(PS_USE_GETAUXVAL) && defined(__arm__) if (getauxval(AT_HWCAP) & HWCAP_ARM_NEON) return true; #elif defined(__APPLE__) && defined(__aarch64__) @@ -151,18 +182,18 @@ static inline bool CPU_QueryNEON() static inline bool CPU_QueryCRC32() { -#if defined(__ANDROID__) && defined(__aarch64__) +#if defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch64__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) && (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_CRC32)) return true; -#elif defined(__ANDROID__) && defined(__aarch32__) +#elif defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch32__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_CRC32)) return true; -#elif defined(__linux__) && defined(__aarch64__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch64__) if (getauxval(AT_HWCAP) & HWCAP_CRC32) return true; -#elif defined(__linux__) && defined(__aarch32__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch32__) if (getauxval(AT_HWCAP2) & HWCAP2_CRC32) return true; #elif defined(__APPLE__) && defined(__aarch64__) @@ -174,18 +205,18 @@ static inline bool CPU_QueryCRC32() static inline bool CPU_QueryPMULL() { -#if defined(__ANDROID__) && defined(__aarch64__) +#if defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch64__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) && (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_PMULL)) return true; -#elif defined(__ANDROID__) && defined(__aarch32__) +#elif defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch32__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_PMULL)) return true; -#elif defined(__linux__) && defined(__aarch64__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch64__) if (getauxval(AT_HWCAP) & HWCAP_PMULL) return true; -#elif defined(__linux__) && defined(__aarch32__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch32__) if (getauxval(AT_HWCAP2) & HWCAP2_PMULL) return true; #elif defined(__APPLE__) && defined(__aarch64__) @@ -197,18 +228,18 @@ static inline bool CPU_QueryPMULL() static inline bool CPU_QueryAES() { -#if defined(__ANDROID__) && defined(__aarch64__) +#if defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch64__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) && (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES)) return true; -#elif defined(__ANDROID__) && defined(__aarch32__) +#elif defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch32__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES)) return true; -#elif defined(__linux__) && defined(__aarch64__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch64__) if (getauxval(AT_HWCAP) & HWCAP_AES) return true; -#elif defined(__linux__) && defined(__aarch32__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch32__) if (getauxval(AT_HWCAP2) & HWCAP2_AES) return true; #elif defined(__APPLE__) && defined(__aarch64__) @@ -232,18 +263,18 @@ static inline bool CPU_QueryAES() static inline bool CPU_QuerySHA1() { -#if defined(__ANDROID__) && defined(__aarch64__) +#if defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch64__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) && (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA1)) return true; -#elif defined(__ANDROID__) && defined(__aarch32__) +#elif defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch32__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA1)) return true; -#elif defined(__linux__) && defined(__aarch64__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch64__) if (getauxval(AT_HWCAP) & HWCAP_SHA1) return true; -#elif defined(__linux__) && defined(__aarch32__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch32__) if (getauxval(AT_HWCAP2) & HWCAP2_SHA1) return true; #elif defined(__APPLE__) && defined(__aarch64__) @@ -264,20 +295,21 @@ static inline bool CPU_QuerySHA1() #endif return false; } + static inline bool CPU_QuerySHA2() { -#if defined(__ANDROID__) && defined(__aarch64__) +#if defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch64__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) && (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA2)) return true; -#elif defined(__ANDROID__) && defined(__aarch32__) +#elif defined(PS_USE_ANDROID_GET_CPU_FAMILY) && defined(__aarch32__) if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA2)) return true; -#elif defined(__linux__) && defined(__aarch64__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch64__) if (getauxval(AT_HWCAP) & HWCAP_SHA2) return true; -#elif defined(__linux__) && defined(__aarch32__) +#elif defined(PS_USE_GETAUXVAL) && defined(__aarch32__) if (getauxval(AT_HWCAP2) & HWCAP2_SHA2) return true; #elif defined(__APPLE__) && defined(__aarch64__) diff --git a/core/testsupp/src/testsupp.c b/core/testsupp/src/testsupp.c index 71d1ccc..791a0da 100644 --- a/core/testsupp/src/testsupp.c +++ b/core/testsupp/src/testsupp.c @@ -298,7 +298,8 @@ struct TestEntry AutoTestEntryDefault = TEST_ENABLED, OK, NULL, - NULL + NULL, + { NULL, NULL } }; /* Finish test, with handling of a special case: listing of tests. */ diff --git a/crypto/common/alg_info.c b/crypto/common/alg_info.c index 9c223eb..4662ede 100644 --- a/crypto/common/alg_info.c +++ b/crypto/common/alg_info.c @@ -636,3 +636,20 @@ uint16_t psGetNamedGroupId(const char *name) } return 0; } + +psBool_t psVerifyNeedPreHash(int32_t sigAlg) +{ + /* crypto-rot never uses pre-hashing for any sig alg. */ +# ifdef USE_ROT_CRYPTO + return PS_FALSE; +# endif +# ifdef USE_ED25519 + /* Ed25519 does not use pre-hashing. */ + if (sigAlg == OID_ED25519_KEY_ALG) + { + return PS_FALSE; + } +# endif + + return PS_TRUE; +} diff --git a/crypto/cryptoApi.h b/crypto/cryptoApi.h index 64f88c0..7c2d196 100644 --- a/crypto/cryptoApi.h +++ b/crypto/cryptoApi.h @@ -55,6 +55,11 @@ extern "C" { # ifndef USE_NON_CONSTANT_TIME_MODEXP # define USE_CONSTANT_TIME_MODEXP # endif +/* Use constant-time ECC scalar multiplication algorithm. + Enabled by default. */ +# ifndef USE_NON_CONSTANT_TIME_ECC_MULMOD +# define USE_CONSTANT_TIME_ECC_MULMOD +# endif /******************************************************************************/ /** @@ -1212,6 +1217,10 @@ PSPUBLIC uint16_t psGetNamedSigAlgId(const char *name); PSPUBLIC psBool_t psIsValidHashLenSigAlgCombination(psSize_t hashLen, int32_t sigAlg); +/** Return PS_TRUE if the given signature algorithm requires a pre-hash + operation with the current crypto provider. */ +PSPUBLIC psBool_t psVerifyNeedPreHash(int32_t sigAlg); + # ifdef USE_RSA /* Return the correct reference DigestInfo prefix for sigAlg, when len bytes were RSA-decrypted. */ diff --git a/crypto/keyformat/x509.c b/crypto/keyformat/x509.c index aef82f4..d0db849 100644 --- a/crypto/keyformat/x509.c +++ b/crypto/keyformat/x509.c @@ -58,32 +58,6 @@ # define IMPLICIT_SUBJECT_ID 2 # define EXPLICIT_EXTENSION 3 -/* - Distinguished Name attributes - */ -# define ATTRIB_COMMON_NAME 3 -# define ATTRIB_SURNAME 4 -# define ATTRIB_SERIALNUMBER 5 -# define ATTRIB_COUNTRY_NAME 6 -# define ATTRIB_LOCALITY 7 -# define ATTRIB_STATE_PROVINCE 8 -# define ATTRIB_STREET_ADDRESS 9 -# define ATTRIB_ORGANIZATION 10 -# define ATTRIB_ORG_UNIT 11 -# define ATTRIB_TITLE 12 -# define ATTRIB_POSTAL_ADDRESS 16 -# define ATTRIB_TELEPHONE_NUMBER 20 -# define ATTRIB_NAME 41 -# define ATTRIB_GIVEN_NAME 42 -# define ATTRIB_INITIALS 43 -# define ATTRIB_GEN_QUALIFIER 44 -# define ATTRIB_DN_QUALIFIER 46 -# define ATTRIB_PSEUDONYM 65 - -# define ATTRIB_DOMAIN_COMPONENT 25 -# define ATTRIB_UID 26 -# define ATTRIB_EMAIL 27 - /** Enumerate X.509 milestones for issuedBefore() api */ typedef enum { @@ -1040,7 +1014,15 @@ static int parse_single_cert(psPool_t *pool, const unsigned char **pp, # ifdef USE_RSA case OID_RSA_KEY_ALG: case OID_RSASSA_PSS: - psAssert(plen == 0); /* No parameters on RSA pub key OID */ + if (cert->pubKeyAlgorithm == OID_RSA_KEY_ALG) + { + psAssert(plen == 0); /* No parameters on RSA pub key OID */ + } + else + { + p += plen; + } + psInitPubKey(pool, &cert->publicKey, PS_RSA); if ((rc = psRsaParseAsnPubKey(pool, &p, (uint16_t) (end - p), &cert->publicKey.key.rsa, sha1KeyHash)) < 0) @@ -1218,24 +1200,14 @@ static int parse_single_cert(psPool_t *pool, const unsigned char **pp, return rc; } -# ifdef USE_ROT_CRYPTO - switch (cert->certAlgorithm) + /* Most algorithms and APIs use pre-hashing before signature + verification. Others (such as Ed25519) want the original + message (i.e. TBSCertificate) as input data. */ +# if defined(USE_ROT_CRYPTO) || defined(USE_ED25519) || (defined(USE_CL_RSA) && defined(USE_PKCS1_PSS)) + if (!psVerifyNeedPreHash(cert->certAlgorithm)) { -# ifdef USE_ROT_ECC - case OID_SHA256_ECDSA_SIG: -# ifdef USE_SECP384R1 - case OID_SHA384_ECDSA_SIG: -# endif -# ifdef USE_SECP521R1 - case OID_SHA512_ECDSA_SIG: -# endif -# endif /* USE_ROT_ECC */ -# ifdef USE_ROT_RSA - case OID_SHA256_RSA_SIG: - case OID_SHA384_RSA_SIG: -# endif /* USE_ROT_RSA */ - /* No pre-hashing used with crypto-rot. */ - (void)hashCtx; + /* Skip pre-hashing and instead buffer the TBS. */ + (void)hashCtx; /* Not used on this code path. */ cert->tbsCertStart = psMalloc(pool, certLen); if (cert->tbsCertStart == NULL) { @@ -1244,12 +1216,8 @@ static int parse_single_cert(psPool_t *pool, const unsigned char **pp, Memcpy(cert->tbsCertStart, tbsCertStart, certLen); cert->tbsCertLen = certLen; goto preprocessing_complete; - break; - default: - psTraceCrypto("Warning: cert sig alg not supported by crypto-rot\n"); - psTraceCrypto("Falling back to SW crypto\n"); } -# endif /* USE_ROT_CRYPTO */ +# endif /* Compute the hash of the cert here for CA validation @@ -1345,20 +1313,6 @@ static int parse_single_cert(psPool_t *pool, const unsigned char **pp, psSha512Final(&hashCtx.u.sha512, cert->sigHash); break; # endif -# ifdef USE_ED25519 - case OID_ED25519_KEY_ALG: - /* No pre-hashing used with Ed25519; the signature is computed - over the original message (TBSCertificate). Store it. */ - cert->tbsCertStart = psMalloc(pool, certLen); - if (cert->tbsCertStart == NULL) - { - return PS_MEM_FAIL; - } - Memcpy(cert->tbsCertStart, tbsCertStart, certLen); - cert->tbsCertLen = certLen; - cert->sigHash[0] = 0xfa; /* Kludge to pass the memcmp below. */ - break; -# endif # ifdef USE_PKCS1_PSS case OID_RSASSA_PSS: switch (cert->pssHash) @@ -1444,9 +1398,10 @@ unsupported_sig_alg: } # endif /* USE_CERT_PARSE */ -# ifdef USE_ROT_CRYPTO +# if defined(USE_ROT_CRYPTO) || defined(USE_ED25519) || (defined(USE_CL_RSA) && defined(USE_PKCS1_PSS)) preprocessing_complete: -# endif /* USE_ROT_CRYPTO */ +# endif /* USE_ROT_CRYPTO || USE_ED25519 || (USE_CL_RSA && USE_PKCS1_PSS) */ + if ((rc = psX509GetSignature(pool, &p, (uint32) (end - p), &cert->signature, &cert->signatureLen)) < 0) { @@ -1758,6 +1713,7 @@ void x509FreeExtensions(x509v3extensions_t *extensions) { inc = active->next; psFree(active->data, extensions->pool); + psFree(active->oid, extensions->pool); psFree(active, extensions->pool); active = inc; } @@ -1829,6 +1785,207 @@ void x509FreeExtensions(x509v3extensions_t *extensions) # endif /* USE_FULL_CERT_PARSE || USE_CERT_GEN */ } +int32_t psX509GetNumDNAttributes(const x509DNattributes_t *DN) +{ + int32_t i; + + if (DN == NULL) + { + return PS_ARG_FAIL; + } + + for (i = 0; i < DN_NUM_ATTRIBUTES_MAX; i++) + { + if (DN->attributeOrder[i] == 0) + { + break; + } + } + + return i; +} + +int32_t psX509GetDNAttributeTypeAndValue(const x509DNattributes_t *DN, + int32_t index, + x509DNAttributeType_t *attrType, + short *valueType, + psSize_t *valueLen, + char **value) +{ + int32_t numValues, maxIndex, i, nthOccurrence = 0; + x509OrgUnit_t *orgUnit; + x509DomainComponent_t *domainComponent; + + psAssert(DN && attrType && valueType && valueLen && value); + + numValues = psX509GetNumDNAttributes(DN); + if (numValues < 0) + { + return PS_ARG_FAIL; + } + if (numValues == 0) + { + return PS_ARG_FAIL; + } + + maxIndex = numValues - 1; + if (index > maxIndex) + { + psTraceIntCrypto("psX509GetDNAttributeTypeAndValue: index too high " \ + "(max for this DN is %d)\n", maxIndex); + return PS_ARG_FAIL; + } + +# define SET_VALUE(attr) \ + do \ + { \ + *valueType = DN->attr ## Type; \ + *valueLen = DN-> attr ## Len; \ + *value = DN->attr; \ + } \ + while (0) + + *attrType = DN->attributeOrder[index]; + for (i = 0; i < index; i++) + { + /* Compute number of preceeding attributes of the this type. + Currently needed only for orgUnit and domainComponent. */ + if (DN->attributeOrder[i] == *attrType) + { + nthOccurrence++; + } + } + + switch (*attrType) + { + case ATTRIB_COUNTRY_NAME: + SET_VALUE(country); + break; + case ATTRIB_STATE_PROVINCE: + SET_VALUE(state); + break; + case ATTRIB_ORGANIZATION: + SET_VALUE(organization); + break; + case ATTRIB_ORG_UNIT: + orgUnit = psX509GetOrganizationalUnit(DN, nthOccurrence); + if (orgUnit == NULL) + { + return PS_FAILURE; + } + *value = orgUnit->name; + *valueType = orgUnit->type; + *valueLen = orgUnit->len; + break; + case ATTRIB_DN_QUALIFIER: + SET_VALUE(dnQualifier); + break; + case ATTRIB_COMMON_NAME: + SET_VALUE(commonName); + break; + case ATTRIB_SERIALNUMBER: + SET_VALUE(serialNumber); + break; + case ATTRIB_DOMAIN_COMPONENT: + domainComponent = psX509GetDomainComponent(DN, nthOccurrence); + if (domainComponent == NULL) + { + return PS_FAILURE; + } + *value = domainComponent->name; + *valueType = domainComponent->type; + *valueLen = domainComponent->len; + break; +# ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + case ATTRIB_LOCALITY: + SET_VALUE(locality); + break; + case ATTRIB_TITLE: + SET_VALUE(title); + break; + case ATTRIB_SURNAME: + SET_VALUE(surname); + break; + case ATTRIB_GIVEN_NAME: + SET_VALUE(givenName); + break; + case ATTRIB_INITIALS: + SET_VALUE(initials); + break; + case ATTRIB_PSEUDONYM: + SET_VALUE(pseudonym); + break; + case ATTRIB_GEN_QUALIFIER: + SET_VALUE(generationQualifier); + break; +# endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ +# ifdef USE_EXTRA_DN_ATTRIBUTES + case ATTRIB_STREET_ADDRESS: + SET_VALUE(streetAddress); + break; + case ATTRIB_POSTAL_ADDRESS: + SET_VALUE(postalAddress); + break; + case ATTRIB_TELEPHONE_NUMBER: + SET_VALUE(telephoneNumber); + break; + case ATTRIB_UID: + SET_VALUE(uid); + break; + case ATTRIB_NAME: + SET_VALUE(name); + break; + case ATTRIB_EMAIL: + SET_VALUE(email); + break; +# endif /* USE_EXTRA_DN_ATTRIBUTES */ + default: + psTraceCrypto("Unsupported DN attribute type\n"); + psTraceCrypto("Maybe you need to enable " \ + "USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD or " \ + "USE_EXTRA_DN_ATTRIBUTES?\n"); + return PS_FAILURE; + } + + return PS_SUCCESS; +} + +int32_t psX509GetDNAttributeIndex(const x509DNattributes_t *DN, + x509DNAttributeType_t attrType, + int32_t nth_occurrence) +{ + x509DNAttributeType_t foundType; + short valueType; + psSize_t valueLen; + char *value; + int32_t rc, ix, numFound = 0; + + for (ix = 0; ix < DN_NUM_ATTRIBUTES_MAX; ix++) + { + rc = psX509GetDNAttributeTypeAndValue( + DN, + ix, + &foundType, + &valueType, + &valueLen, + &value); + if (rc < 0) + { + return rc; + } + if (foundType == attrType) + { + numFound++; + if (numFound == nth_occurrence) + { + return ix; + } + } + } + + return PS_FAILURE; +} + int32_t psX509GetNumOrganizationalUnits(const x509DNattributes_t *DN) { x509OrgUnit_t *ou; @@ -2065,7 +2222,11 @@ int32_t psX509GetConcatenatedDomainComponent(const x509DNattributes_t *DN, On success, the caller is responsible for freeing the returned string. -*/ + + Set userOriginalAttributeOrder to PS_TRUE to print out the attributes + in the order in which they were parsed. Otherwise, the function + will imitate the print order of the openssl x509 command-line tool. + */ static int32_t concatenate_dn(psPool_t *pool, const x509DNattributes_t *dn, psBool_t useOriginalAttributeOrder, @@ -2082,7 +2243,6 @@ static int32_t concatenate_dn(psPool_t *pool, const char *commonName_prefix = "CN="; const char *serialNumber_prefix = "/serialNumber="; const char *domainComponent_prefix = "DC="; - # ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD const char *locality_prefix = "L="; const char *title_prefix = "/title="; @@ -2100,21 +2260,71 @@ static int32_t concatenate_dn(psPool_t *pool, const char *name_prefix = "/name="; const char *email_prefix = "/emailAddress="; # endif /* USE_EXTRA_DN_ATTRIBUTES */ + x509DomainComponent_t *dc; int num_dcs; - int first_len = 1; - int first_field = 1; x509OrgUnit_t *orgUnit; int num_ous; + int first_len = 1; + int first_field = 1; + const x509DNAttributeType_t *parse_order = dn->attributeOrder; + x509DNAttributeType_t print_order[DN_NUM_ATTRIBUTES_MAX] = {0}; + const x509DNAttributeType_t ossl_order[] = { + ATTRIB_COUNTRY_NAME, + ATTRIB_STATE_PROVINCE, +# ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + ATTRIB_LOCALITY, +# endif + ATTRIB_ORGANIZATION, + ATTRIB_ORG_UNIT, + ATTRIB_COMMON_NAME, +# ifdef USE_EXTRA_DN_ATTRIBUTES + ATTRIB_NAME, +# endif +# ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + ATTRIB_GIVEN_NAME, + ATTRIB_SURNAME, +# endif +# ifdef USE_EXTRA_DN_ATTRIBUTES + ATTRIB_DOMAIN_COMPONENT, + ATTRIB_EMAIL, +# endif + ATTRIB_SERIALNUMBER, +# ifdef USE_EXTRA_DN_ATTRIBUTES + ATTRIB_STREET_ADDRESS, +# endif +# ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + ATTRIB_TITLE, +# endif +# ifdef USE_EXTRA_DN_ATTRIBUTES + ATTRIB_POSTAL_ADDRESS, + ATTRIB_TELEPHONE_NUMBER, +# endif +# ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD + ATTRIB_PSEUDONYM, + ATTRIB_GEN_QUALIFIER, + ATTRIB_INITIALS, +# endif + ATTRIB_DN_QUALIFIER, +# ifdef USE_EXTRA_DN_ATTRIBUTES + ATTRIB_UID, +# endif + }; + int32_t ossl_order_len = sizeof(ossl_order)/sizeof(ossl_order[0]); + int32_t i, j, k; + int32_t numAttributes; + int32_t nthOccurrenceOrgUnit = 0; + int32_t nthOccurrenceDC = 0; + x509DNAttributeType_t attr; -# define INC_LEN(X) \ - if (dn->X ## Len > 0) { \ - if (!first_len && X ## _prefix[0] != '/') { \ - total_len += 2; \ - } \ - first_len = 0; \ - total_len += Strlen(X ## _prefix) + \ - dn->X ## Len - \ - DN_NUM_TERMINATING_NULLS; \ +# define INC_LEN(X) \ + if (dn->X ## Len > 0) { \ + if (!first_len && X ## _prefix[0] != '/') { \ + total_len += 2; \ + } \ + first_len = 0; \ + total_len += Strlen(X ## _prefix) + \ + dn->X ## Len - \ + DN_NUM_TERMINATING_NULLS; \ } INC_LEN(country); @@ -2123,12 +2333,12 @@ static int32_t concatenate_dn(psPool_t *pool, num_ous = psX509GetNumOrganizationalUnits(dn); if (num_ous > 0) { - int i; for (i = 0; i < num_ous; i++) { orgUnit = psX509GetOrganizationalUnit(dn, i); if (orgUnit == NULL) { + psTraceCrypto("psX509GetOrganizationalUnit failed\n"); return PS_FAILURE; } if (first_len) @@ -2165,12 +2375,10 @@ static int32_t concatenate_dn(psPool_t *pool, INC_LEN(name); INC_LEN(email); # endif /* USE_EXTRA_DN_ATTRIBUTES */ + num_dcs = psX509GetNumDomainComponents(dn); if (num_dcs > 0) { - int i; - x509DomainComponent_t *dc; - for (i = 0; i < num_dcs; i++) { total_len += Strlen(domainComponent_prefix); @@ -2185,6 +2393,7 @@ static int32_t concatenate_dn(psPool_t *pool, dc = psX509GetDomainComponent(dn, i); if (dc == NULL) { + psTraceCrypto("psX509GetDomainComponent failed\n"); return PS_FAILURE; } total_len += dc->len - DN_NUM_TERMINATING_NULLS; @@ -2195,12 +2404,14 @@ static int32_t concatenate_dn(psPool_t *pool, Sanity check.*/ if (total_len > 100000) { + psTraceCrypto("concatenate_dn: sanity limit exceeded\n"); return PS_ARG_FAIL; } str = psMalloc(pool, total_len + 1); if (str == NULL) { + psTraceCrypto("concatenate_dn: out of mem\n"); return PS_MEM_FAIL; } Memset(str, 0, total_len + 1); @@ -2228,96 +2439,59 @@ static int32_t concatenate_dn(psPool_t *pool, /dnQualifier=123456789/UID=root */ -# define PRINT_FIELD(field) \ - if (dn->field ## Len > 0) { \ +# define PRINT_FIELD(field) \ + if (dn->field ## Len > 0) { \ if (first_field) { \ - first_field = 0; \ - } else { \ - if (field ## _prefix[0] != '/') { \ - *p++ = ','; \ - *p++ = ' '; \ - } \ - } \ + first_field = 0; \ + } else { \ + if (field ## _prefix[0] != '/') { \ + *p++ = ','; \ + *p++ = ' '; \ + } \ + } \ Memcpy(p, field ## _prefix, Strlen(field ## _prefix)); \ - p += Strlen(field ## _prefix); \ - Memcpy(p, dn->field, \ - dn->field ## Len - DN_NUM_TERMINATING_NULLS); \ - p += dn->field ## Len - DN_NUM_TERMINATING_NULLS; \ + p += Strlen(field ## _prefix); \ + Memcpy(p, dn->field, \ + dn->field ## Len - DN_NUM_TERMINATING_NULLS); \ + p += dn->field ## Len - DN_NUM_TERMINATING_NULLS; \ } - const int32 openSslAttributeOrder[] = { - ATTRIB_COUNTRY_NAME, - ATTRIB_STATE_PROVINCE, - -# ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD - ATTRIB_LOCALITY, -# endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ - - ATTRIB_ORGANIZATION, - ATTRIB_ORG_UNIT, - ATTRIB_COMMON_NAME, - -# ifdef USE_EXTRA_DN_ATTRIBUTES - ATTRIB_NAME, -# endif /* USE_EXTRA_DN_ATTRIBUTES */ - -# ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD - ATTRIB_GIVEN_NAME, - ATTRIB_SURNAME, -# endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ - -# ifdef USE_EXTRA_DN_ATTRIBUTES - ATTRIB_DOMAIN_COMPONENT, - ATTRIB_EMAIL, -# endif /* USE_EXTRA_DN_ATTRIBUTES */ - - ATTRIB_SERIALNUMBER, - -# ifdef USE_EXTRA_DN_ATTRIBUTES - ATTRIB_STREET_ADDRESS, -# endif /* USE_EXTRA_DN_ATTRIBUTES */ - -# ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD - ATTRIB_TITLE, -# endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ - -# ifdef USE_EXTRA_DN_ATTRIBUTES - ATTRIB_POSTAL_ADDRESS, - ATTRIB_TELEPHONE_NUMBER, -# endif /* USE_EXTRA_DN_ATTRIBUTES */ - -# ifdef USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD - ATTRIB_PSEUDONYM, - ATTRIB_GEN_QUALIFIER, - ATTRIB_INITIALS, -# endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ - - ATTRIB_DN_QUALIFIER, - -# ifdef USE_EXTRA_DN_ATTRIBUTES - ATTRIB_UID, -# endif /* USE_EXTRA_DN_ATTRIBUTES */ - }; - - const int32_t *attributeOrder; - uint32_t numAttributes; - unsigned int i; + numAttributes = psX509GetNumDNAttributes(dn); + if (numAttributes < 0) + { + psTraceCrypto("psX509GetNumDNAttributes failed\n"); + return PS_FAILURE; + } if (useOriginalAttributeOrder) { - attributeOrder = dn->attributeOrder; - numAttributes = DN_NUM_ATTRIBUTE_TYPES_MAX; + /* Print in parse order. */ + for (i = 0; i < numAttributes; i++) + { + print_order[i] = parse_order[i]; + } } else { - attributeOrder = openSslAttributeOrder; - numAttributes = - sizeof(openSslAttributeOrder) / sizeof(openSslAttributeOrder[0]); + /* Print in openssl x509's order. */ + k = 0; + for (i = 0; i < ossl_order_len; i++) + { + attr = ossl_order[i]; + for (j = 0; j < DN_NUM_ATTRIBUTES_MAX; j++) + { + if (parse_order[j] == attr) + { + print_order[k++] = attr; + } + } + } + psAssert(numAttributes == k); } for (i = 0; i < numAttributes; i++) { - switch (attributeOrder[i]) + switch (print_order[i]) { case ATTRIB_COUNTRY_NAME: PRINT_FIELD(country); @@ -2326,35 +2500,29 @@ static int32_t concatenate_dn(psPool_t *pool, PRINT_FIELD(organization); break; case ATTRIB_ORG_UNIT: - num_ous = psX509GetNumOrganizationalUnits(dn); - if (num_ous > 0) + orgUnit = psX509GetOrganizationalUnit(dn, nthOccurrenceOrgUnit); + if (orgUnit == NULL) { - int i; - for (i = 0; i < num_ous; i++) - { - orgUnit = psX509GetOrganizationalUnit(dn, i); - if (orgUnit == NULL) - { - psFree(str, pool); - return PS_FAILURE; - } - if (first_field) - { - first_field = 0; - } - else - { - *p++ = ','; - *p++ = ' '; - } - Memcpy(p, organizationalUnit_prefix, - Strlen(organizationalUnit_prefix)); - p += Strlen(organizationalUnit_prefix); - Memcpy(p, orgUnit->name, - orgUnit->len - DN_NUM_TERMINATING_NULLS); - p += orgUnit->len - DN_NUM_TERMINATING_NULLS; - } + psTraceCrypto("psX509GetOrganizationalUnit failed\n"); + psFree(str, pool); + return PS_FAILURE; } + nthOccurrenceOrgUnit++; + if (first_field) + { + first_field = 0; + } + else + { + *p++ = ','; + *p++ = ' '; + } + Memcpy(p, organizationalUnit_prefix, + Strlen(organizationalUnit_prefix)); + p += Strlen(organizationalUnit_prefix); + Memcpy(p, orgUnit->name, + orgUnit->len - DN_NUM_TERMINATING_NULLS); + p += orgUnit->len - DN_NUM_TERMINATING_NULLS; break; case ATTRIB_DN_QUALIFIER: PRINT_FIELD(dnQualifier); @@ -2365,6 +2533,30 @@ static int32_t concatenate_dn(psPool_t *pool, case ATTRIB_COMMON_NAME: PRINT_FIELD(commonName); break; + case ATTRIB_DOMAIN_COMPONENT: + dc = psX509GetDomainComponent(dn, nthOccurrenceDC); + if (dc == NULL) + { + psTraceCrypto("psX509GetDomainComponent failed\n"); + psFree(str, pool); + return PS_FAILURE; + } + nthOccurrenceDC++; + if (first_field) + { + first_field = 0; + } + else + { + *p++ = ','; + *p++ = ' '; + } + Memcpy(p, domainComponent_prefix, + Strlen(domainComponent_prefix)); + p += Strlen(domainComponent_prefix); + Memcpy(p, dc->name, dc->len - DN_NUM_TERMINATING_NULLS); + p += dc->len - DN_NUM_TERMINATING_NULLS; + break; case ATTRIB_SERIALNUMBER: PRINT_FIELD(serialNumber); break; @@ -2392,39 +2584,6 @@ static int32_t concatenate_dn(psPool_t *pool, break; # endif /* USE_EXTRA_DN_ATTRIBUTES_RFC5280_SHOULD */ # ifdef USE_EXTRA_DN_ATTRIBUTES - case ATTRIB_DOMAIN_COMPONENT: - /**/ - num_dcs = psX509GetNumDomainComponents(dn); - if (num_dcs > 0) - { - int i; - x509DomainComponent_t *dc; - - for (i = 0; i < num_dcs; i++) - { - if (first_field) - { - first_field = 0; - } - else - { - *p++ = ','; - *p++ = ' '; - } - Memcpy(p, domainComponent_prefix, - Strlen(domainComponent_prefix)); - p += Strlen(domainComponent_prefix); - dc = psX509GetDomainComponent(dn, i); - if (dc == NULL) - { - psFree(str, pool); - return PS_FAILURE; - } - Memcpy(p, dc->name, dc->len - DN_NUM_TERMINATING_NULLS); - p += dc->len - DN_NUM_TERMINATING_NULLS; - } - } - break; case ATTRIB_STREET_ADDRESS: PRINT_FIELD(streetAddress); break; @@ -2550,13 +2709,19 @@ void psX509FreeCert(psX509Cert_t *cert) psFree(curr->tbsCertStart, pool); } # endif - +# if defined(USE_CL_RSA) && defined(USE_PKCS1_PSS) + if (curr->pubKeyAlgorithm == OID_RSASSA_PSS) + { + psFree(curr->tbsCertStart, pool); + } +# endif if (curr->publicKey.type != PS_NOKEY) { switch (curr->pubKeyAlgorithm) { # ifdef USE_RSA case OID_RSA_KEY_ALG: + case OID_RSASSA_PSS: psRsaClearKey(&curr->publicKey.key.rsa); break; # endif @@ -2774,7 +2939,7 @@ static int32_t parseGeneralNames(psPool_t *pool, const unsigned char **buf, end = p + len; # define MIN_GENERALNAME_LEN 3 /* 1 tag, 1 length octet, 1 content octet.*/ - while (len > MIN_GENERALNAME_LEN) + while (len >= MIN_GENERALNAME_LEN) { if (firstName == NULL) { @@ -4969,6 +5134,13 @@ int32 validateDateRange(psX509Cert_t *cert) /* beforeTime is in future. */ cert->authFailFlags |= PS_CERT_AUTH_FAIL_DATE_FLAG; } + + if (psBrokenDownTimeCmp(&beforeTime, &afterTime) > 0) + { + /* beforeTime is later than afterTime. */ + cert->authFailFlags |= PS_CERT_AUTH_FAIL_DATE_FLAG; + } + return 0; } @@ -5131,7 +5303,7 @@ int32_t psX509GetDNAttributes(psPool_t *pool, const unsigned char **pp, # error USE_SHA1 or USE_SHA256 must be defined # endif - for (i = 0; i < DN_NUM_ATTRIBUTE_TYPES_MAX; i++) + for (i = 0; i < DN_NUM_ATTRIBUTES_MAX; i++) { attribs->attributeOrder[i] = 0; } @@ -5397,7 +5569,8 @@ oid_parsing_done: } p = p + llen; - llen += DN_NUM_TERMINATING_NULLS; /* Add null bytes for length assignments */ + /* Add null bytes for length assignments */ + llen += DN_NUM_TERMINATING_NULLS; break; default: psTraceIntCrypto("Unsupported DN attrib type %d\n", stringType); @@ -5431,7 +5604,7 @@ oid_parsing_done: orgUnit->name = stringOut; orgUnit->type = (short) stringType; orgUnit->len = llen; - /* Push the org unit onto the front of the list */ + /* Push the orgUnit onto the front of the list */ orgUnit->next = attribs->orgUnit; attribs->orgUnit = orgUnit; break; @@ -5476,7 +5649,7 @@ oid_parsing_done: domainComponent->name = stringOut; domainComponent->type = (short) stringType; domainComponent->len = llen; - /* Push the org unit onto the front of the list */ + /* Push the domainComponent onto the front of the list */ domainComponent->next = attribs->domainComponent; attribs->domainComponent = domainComponent; break; @@ -5611,16 +5784,20 @@ oid_parsing_done: if (attributeStored) { - for (i = 0; i < DN_NUM_ATTRIBUTE_TYPES_MAX; i++) + for (i = 0; i < DN_NUM_ATTRIBUTES_MAX; i++) { - if (attribs->attributeOrder[i] == id) + if (id != ATTRIB_ORG_UNIT && id != ATTRIB_DOMAIN_COMPONENT) { - /* Likely multiple domainComponent or orgUnit, for any - other attribute we store only one so we can skip - order too. */ - break; + if (attribs->attributeOrder[i] == id) + { + /* + Storing multiple instances of the same attribute type is + currently only supported for OU and DC. For other attributes, + a new instance overwrites the previous one. + */ + break; + } } - if (attribs->attributeOrder[i] == 0) { attribs->attributeOrder[i] = id; @@ -5882,6 +6059,10 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, opts.rsaPssHashLen = psPssHashAlgToHashLen(sc->pssHash); opts.rsaPssSaltLen = sc->saltLen; opts.useRsaPss = PS_TRUE; +# ifdef USE_CL_RSA + tbs = sc->tbsCertStart; + tbsLen = sc->tbsCertLen; +# endif } # endif /* USE_PKCS1_PSS */ # ifdef USE_ED25519 diff --git a/crypto/keyformat/x509.h b/crypto/keyformat/x509.h index 2931a00..50cf84e 100644 --- a/crypto/keyformat/x509.h +++ b/crypto/keyformat/x509.h @@ -73,6 +73,32 @@ enum # ifdef USE_CERT_PARSE +/* Distinguished Name attribute types. */ +typedef enum +{ + ATTRIB_COMMON_NAME = 3, + ATTRIB_SURNAME = 4, + ATTRIB_SERIALNUMBER = 5, + ATTRIB_COUNTRY_NAME = 6, + ATTRIB_LOCALITY = 7, + ATTRIB_STATE_PROVINCE = 8, + ATTRIB_STREET_ADDRESS = 9, + ATTRIB_ORGANIZATION = 10, + ATTRIB_ORG_UNIT = 11, + ATTRIB_TITLE = 12, + ATTRIB_POSTAL_ADDRESS = 16, + ATTRIB_TELEPHONE_NUMBER = 20, + ATTRIB_NAME = 41, + ATTRIB_GIVEN_NAME = 42, + ATTRIB_INITIALS = 43, + ATTRIB_GEN_QUALIFIER = 44, + ATTRIB_DN_QUALIFIER = 46, + ATTRIB_PSEUDONYM = 65, + ATTRIB_DOMAIN_COMPONENT = 25, + ATTRIB_UID = 26, + ATTRIB_EMAIL = 27 +} x509DNAttributeType_t; + /* Per specification, any critical extension in an X.509 cert should cause the connection to fail. SECURITY - Uncomment at your own risk */ /* #define ALLOW_UNKNOWN_CRITICAL_EXTENSIONS */ @@ -98,14 +124,11 @@ typedef struct x509DomainComponent /* Number of null-bytes to terminate parsed string-type DN attributes with. */ # define DN_NUM_TERMINATING_NULLS 2 -/* Number of attribute types supported - (only one per type stored save domainComponent and orgUnit) */ -# define DN_NUM_ATTRIBUTE_TYPES_MAX 22 +/* Max number of DN attributes types supported. */ +# define DN_NUM_ATTRIBUTES_MAX 32 -/* - DN attributes are used outside the X509 area for cert requests, - which have been included in the RSA portions of the code - */ +/* Type for representing a parsed distinguished name (DN) such as a + X.509 certificate subject or issuer field Name. */ typedef struct { /* MUST support according to RFC 5280: */ @@ -181,7 +204,7 @@ typedef struct psSize_t emailLen; # endif /* USE_EXTRA_DN_ATTRIBUTES */ - int32 attributeOrder[DN_NUM_ATTRIBUTE_TYPES_MAX]; + x509DNAttributeType_t attributeOrder[DN_NUM_ATTRIBUTES_MAX]; } x509DNattributes_t; @@ -625,7 +648,7 @@ typedef struct psCert int32 certAlgorithm; /* TBSCertificate sig alg OID */ unsigned char *signature; psSize_t signatureLen; -# if defined(USE_ED25519) || defined(USE_ROT_ECC) || defined(USE_ROT_RSA) +# if defined(USE_ED25519) || defined(USE_ROT_ECC) || defined(USE_ROT_RSA) || (defined(USE_CL_RSA) && defined(USE_PKCS1_PSS)) unsigned char *tbsCertStart; psSizeL_t tbsCertLen; # endif @@ -692,6 +715,25 @@ extern void x509FreeExtensions(x509v3extensions_t *extensions); extern int32_t psX509ValidateGeneralName(const char *n); extern int32_t validateDateRange(psX509Cert_t *cert); +/** Return the number of parsed attributes in DN. */ +extern int32_t psX509GetNumDNAttributes(const x509DNattributes_t *DN); + +/** Given a DN and index, return the corresponding attribute type and + value. The indexing is in the order in which the attributes were + encoded. */ +extern int32_t psX509GetDNAttributeTypeAndValue(const x509DNattributes_t *DN, + int32_t index, + x509DNAttributeType_t *attrType, + short *valueType, + psSize_t *valueLen, + char **value); + +/** Given a DN attribute type, return the index of its nth occurrence, + or < 0 if the attribute type is not present. */ +extern int32_t psX509GetDNAttributeIndex(const x509DNattributes_t *DN, + x509DNAttributeType_t attrType, + int32_t nth_occurence); + /** Get the number of organizationalUnits in a distinguished name (DN). */ extern int32_t psX509GetNumOrganizationalUnits(const x509DNattributes_t *DN); @@ -727,9 +769,9 @@ extern x509DomainComponent_t *psX509GetDomainComponent( /** Get the concatenation of all domainComponents in a DN as a C string. - This function returns the concanated domainComponents as a string terminated + This function returns the concatenated domainComponents as a string terminated with DN_NUM_TERMINATING_NULLS NULL characters. The output string will - contain the components in the reverse order compared to the order in which + contain the components in the reverse order compared to the order in which they were encoded in the certificate. Usually, this will result in the usual print order, i.e. top-level component (.com, .org, ...) last. diff --git a/crypto/layer/layer.h b/crypto/layer/layer.h index 08a0d39..665721b 100644 --- a/crypto/layer/layer.h +++ b/crypto/layer/layer.h @@ -412,7 +412,9 @@ The memory savings for optimizing for ram is around 50% */ # if defined(USE_MATRIX_RSA) || defined(USE_MATRIX_ECC) || defined(USE_MATRIX_DH) -# define PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM +# if !defined(PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED) +# define PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM +# endif # endif # endif /* OPTIMIZE_SIZE */ diff --git a/crypto/pubkey/ecc_math.c b/crypto/pubkey/ecc_math.c index 18eb0b9..6c535e0 100644 --- a/crypto/pubkey/ecc_math.c +++ b/crypto/pubkey/ecc_math.c @@ -79,6 +79,248 @@ static pstm_digit get_digit(const pstm_int *a, uint8_t n) return (n >= a->used) ? (pstm_digit) 0 : a->dp[n]; } +# ifdef USE_CONSTANT_TIME_ECC_MULMOD +/******************************************************************************/ +/** + Perform a point multiplication in a timing-resistant manner. + @param[in] pool Memory pool + @param[in] k The scalar to multiply by + @param[in] G The base point + @param[out] R Destination for kG + @param modulus The modulus of the field the ECC curve is in + @param map Boolean whether to map back to affine or not (1==map) + @param[in,out] tmp_int Temporary scratch big integer (memory optimization) + @return PS_SUCCESS on success, < 0 on error + */ +int32_t eccMulmodCt(psPool_t *pool, const pstm_int *k, const psEccPoint_t *G, + psEccPoint_t *R, pstm_int *modulus, uint8_t map, pstm_int *tmp_int) +{ + psEccPoint_t *tG, *M[3]; + int32 i, j, err; + pstm_int mu; + pstm_digit mp; + unsigned long buf; + int32 bitcnt, mode, digidx; + + /* init montgomery reduction */ + err = pstm_montgomery_setup(modulus, &mp); + if (err != PS_SUCCESS) + { + return err; + } + err = pstm_init_size(pool, &mu, modulus->alloc); + if (err != PS_SUCCESS) + { + return err; + } + err = pstm_montgomery_calc_normalization(&mu, modulus); + if (err != PS_SUCCESS) + { + pstm_clear(&mu); + return err; + } + + /* alloc ram for window temps */ + for (i = 0; i < 3; i++) + { + M[i] = eccNewPoint(pool, (G->x.used * 2) + 1); + if (M[i] == NULL) + { + for (j = 0; j < i; j++) + { + eccFreePoint(M[j]); + } + pstm_clear(&mu); + return PS_MEM_FAIL; + } + } + + /* make a copy of G incase R==G */ + tG = eccNewPoint(pool, G->x.alloc); + if (tG == NULL) + { + err = PS_MEM_FAIL; + goto done; + } + + /* tG = G and convert to montgomery */ + if (pstm_cmp_d(&mu, 1) == PSTM_EQ) + { + if ((err = pstm_copy(&G->x, &tG->x)) != PS_SUCCESS) + { + goto done; + } + if ((err = pstm_copy(&G->y, &tG->y)) != PS_SUCCESS) + { + goto done; + } + if ((err = pstm_copy(&G->z, &tG->z)) != PS_SUCCESS) + { + goto done; + } + } + else + { + if ((err = pstm_mulmod(pool, &G->x, &mu, modulus, &tG->x)) != PS_SUCCESS) + { + goto done; + } + if ((err = pstm_mulmod(pool, &G->y, &mu, modulus, &tG->y)) != PS_SUCCESS) + { + goto done; + } + if ((err = pstm_mulmod(pool, &G->z, &mu, modulus, &tG->z)) != PS_SUCCESS) + { + goto done; + } + } + pstm_clear(&mu); + + /* M[0] = tG = P. */ + err = pstm_copy(&tG->x, &M[0]->x); + if (err != PS_SUCCESS) + { + goto done; + } + err = pstm_copy(&tG->y, &M[0]->y); + if (err != PS_SUCCESS) + { + goto done; + } + err = pstm_copy(&tG->z, &M[0]->z); + if (err != PS_SUCCESS) + { + goto done; + } + /* M[1] = 2P. */ + err = eccProjectiveDblPoint(pool, tG, M[1], modulus, &mp, tmp_int); + if (err != PS_SUCCESS) + { + goto done; + } + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = get_digit_count(k) - 1; + + /* perform ops */ + for (;; ) + { + /* grab next digit as required */ + if (--bitcnt == 0) + { + if (digidx == -1) + { + break; + } + buf = get_digit(k, digidx); + bitcnt = DIGIT_BIT; + --digidx; + } + + /* grab the next msb from the ltiplicand */ + i = (buf >> (DIGIT_BIT - 1)) & 1; + buf <<= 1; + + if (mode == 0 && i == 0) + { + /* Dummy operations. */ + err = eccProjectiveAddPoint(pool, + M[0], M[1], M[2], + modulus, &mp, tmp_int); + if (err != PS_SUCCESS) + { + goto done; + } + err = eccProjectiveDblPoint(pool, + M[1], M[2], + modulus, &mp, tmp_int); + if (err != PS_SUCCESS) + { + goto done; + } + continue; + } + if (mode == 0 && i == 1) + { + mode = 1; + /* Dummy operations. */ + err = eccProjectiveAddPoint(pool, + M[0], M[1], M[2], + modulus, &mp, tmp_int); + if (err != PS_SUCCESS) + { + goto done; + } + err = eccProjectiveDblPoint(pool, + M[1], M[2], + modulus, &mp, tmp_int); + if (err != PS_SUCCESS) + { + goto done; + } + continue; + } + + /* M[i^1] = M[0] + M[1]. */ + err = eccProjectiveAddPoint(pool, + M[0], M[1], M[i^1], + modulus, &mp, tmp_int); + if (err != PS_SUCCESS) + { + goto done; + } + /* M[i] = 2M[i] */ + err = eccProjectiveDblPoint(pool, + M[i], M[i], + modulus, &mp, tmp_int); + if (err != PS_SUCCESS) + { + goto done; + } + } + + err = pstm_copy(&M[0]->x, &R->x); + if (err != PS_SUCCESS) + { + goto done; + } + err = pstm_copy(&M[0]->y, &R->y); + if (err != PS_SUCCESS) + { + goto done; + } + err = pstm_copy(&M[0]->z, &R->z); + if (err != PS_SUCCESS) + { + goto done; + } + + + /* map R back from projective space */ + if (map) + { + err = eccMap(pool, R, modulus, &mp); + } + else + { + err = PS_SUCCESS; + } +done: + + pstm_clear(&mu); + eccFreePoint(tG); + for (i = 0; i < 3; i++) + { + eccFreePoint(M[i]); + } + return err; +} +# endif /* USE_CONSTANT_TIME_ECC_MULMOD */ + +# ifndef USE_CONSTANT_TIME_ECC_MULMOD /******************************************************************************/ /** Perform a point multiplication @@ -93,8 +335,7 @@ static pstm_digit get_digit(const pstm_int *a, uint8_t n) */ /* size of sliding window, don't change this! */ # define ECC_MULMOD_WINSIZE 4 - -int32_t eccMulmod(psPool_t *pool, const pstm_int *k, const psEccPoint_t *G, +int32_t eccMulmodOld(psPool_t *pool, const pstm_int *k, const psEccPoint_t *G, psEccPoint_t *R, pstm_int *modulus, uint8_t map, pstm_int *tmp_int) { psEccPoint_t *tG, *M[8]; /* @note large on stack */ @@ -365,6 +606,23 @@ done: } return err; } +# endif /* !USE_CONSTANT_TIME_ECC_MULMOD */ + +int32_t eccMulmod(psPool_t *pool, + const pstm_int *k, + const psEccPoint_t *G, + psEccPoint_t *R, + pstm_int *modulus, + uint8_t map, + pstm_int *tmp_int) +{ +# ifdef USE_CONSTANT_TIME_ECC_MULMOD + return eccMulmodCt(pool, k, G, R, modulus, map, tmp_int); +# else +# warning Using non-constant-time ECC scalar multiplication + return eccMulmodOld(pool, k, G, R, modulus, map, tmp_int); +# endif +} int32 eccTestPoint(psPool_t *pool, psEccPoint_t *P, pstm_int *prime, pstm_int *b) diff --git a/crypto/pubkey/pubkey_parse_file.c b/crypto/pubkey/pubkey_parse_file.c index 641d895..7756352 100644 --- a/crypto/pubkey/pubkey_parse_file.c +++ b/crypto/pubkey/pubkey_parse_file.c @@ -642,10 +642,10 @@ static int32_t psTryParsePubKeyFilePEM(psPool_t *pool, const char *keyfile, int32_t psPkcs1DecodePrivFile(psPool_t *pool, const char *fileName, const char *password, unsigned char **DERout, psSize_t *DERlen) { +# ifdef USE_PEM_DECODE psSizeL_t DERlen2 = 0; int32_t rc; -# ifdef USE_PEM_DECODE if (DERlen == NULL) { return PS_ARG_FAIL; diff --git a/crypto/test/Makefile.dev b/crypto/test/Makefile.dev index 5ac59ed..c92a1d3 100644 --- a/crypto/test/Makefile.dev +++ b/crypto/test/Makefile.dev @@ -1,6 +1,6 @@ # # Makefile for crypto testing: Additional development features. # -# Copyright (c) 2017 INSIDE Secure Oy. All Rights Reserved. +# Copyright (c) 2019 INSIDE Secure Oy. All Rights Reserved. # diff --git a/crypto/test/rsaTest.c b/crypto/test/rsaTest.c index 7ba5073..7e77545 100644 --- a/crypto/test/rsaTest.c +++ b/crypto/test/rsaTest.c @@ -161,7 +161,9 @@ int main(void) psRsaKey_t privkey; unsigned char buffer[BUFFER_SIZE]; psSize_t sz = 0; +#if defined(USE_RSA) && defined(USE_PRIVATE_KEY_PARSING) psPool_t *misc = NULL; +#endif int res; if (psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS) diff --git a/crypto/test/throughputTest.c b/crypto/test/throughputTest.c index d2a5f95..cc65daf 100644 --- a/crypto/test/throughputTest.c +++ b/crypto/test/throughputTest.c @@ -321,9 +321,20 @@ static void runTime(psCipherContext_t *ctx, psCipherGivContext_t *ctx_giv, chunk, (unsigned long long) diffu, round, mod); #else diffm = psDiffMsecs(start, end, NULL); - round = (bytesToSend / diffm) / 1000; - Printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n", + if (diffm > 0) + { + round = (bytesToSend / diffm) / 1000; + Printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n", + chunk, diffm, round); + } + else + { + diffm = 1; + round = (bytesToSend / diffm) / 1000; + Printf("%d byte chunks in less than %d msec total for rate of more than %d MB/sec\n", chunk, diffm, round); + Printf("Use USE_HIGHRES_TIME for more accurate results.\n"); + } #endif } diff --git a/doc/CHANGES_v4.x.html b/doc/CHANGES_v4.x.html index af8db4d..3816ab2 100644 --- a/doc/CHANGES_v4.x.html +++ b/doc/CHANGES_v4.x.html @@ -9,6 +9,26 @@

MatrixSSL 4.x changelog

+

Changes between 4.2.2 and 4.3.0 [June 2020]

+
* Added a constant-time variant of eccMulmod, in response to the Minerva attack.
+* Fixed a possible infinite loop in message parsing discovered by 
+  Andreas Walz (ivESK).
+* Timing sidechannel mitigation (Github issue #23).
+* Change hard coded values to enums in matrixSslLoadKeys (Github issue #35).
+* Disabled TLS 1.3 draft versions by default.
+* Fixes TLS 1.2 session ticket based resumption.
+* May only enable either PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED or
+  PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM (Github issue #37). 
+* Channel Bindings for TLS (only for TLS 1.2 and below), new APIs added
+    - matrixSslGetFinished
+    - matrixSslGetPeerFinished
+    - matrixSslGetTlsUniqueChannelBindings
+* Added API for accessing MatrixSSL structures without direct access
+  to structure members. Use of this API will slightly enlarge the
+  MatrixSSL binary but will enable building software that is not
+  dependent on exact binary layout of structures such as ssl_t.
+* Fixes the bug when NULL keydata was used in sslLoadKeyPair() function.
+* Other bug fixes.

Changes between 4.2.1 and 4.2.2 [August 2019]

This version fixes a few security issues related to DTLS and handshake message length. It also defines the size of psBool_t to be equivalent to bool on both x86 and ARM platforms.

    diff --git a/doc/CHANGES_v4.x.md b/doc/CHANGES_v4.x.md index ae0a976..4e54014 100644 --- a/doc/CHANGES_v4.x.md +++ b/doc/CHANGES_v4.x.md @@ -1,5 +1,27 @@ # MatrixSSL 4.x changelog +## Changes between 4.2.2 and 4.3.0 [June 2020] + + * Added a constant-time variant of eccMulmod, in response to the Minerva attack. + * Fixed a possible infinite loop in message parsing discovered by + Andreas Walz (ivESK). + * Timing sidechannel mitigation (Github issue #23). + * Change hard coded values to enums in matrixSslLoadKeys (Github issue #35). + * Disabled TLS 1.3 draft versions by default. + * Fixes TLS 1.2 session ticket based resumption. + * May only enable either PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED or + PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM (Github issue #37). + * Channel Bindings for TLS (only for TLS 1.2 and below), new APIs added + - matrixSslGetFinished + - matrixSslGetPeerFinished + - matrixSslGetTlsUniqueChannelBindings + * Added API for accessing MatrixSSL structures without direct access + to structure members. Use of this API will slightly enlarge the + MatrixSSL binary but will enable building software that is not + dependent on exact binary layout of structures such as ssl_t. + * Fixes the bug when NULL keydata was used in sslLoadKeyPair() function. + * Other bug fixes. + ## Changes between 4.2.1 and 4.2.2 [August 2019] This version fixes a few security issues related to DTLS and diff --git a/doc/CHANGES_v4.x.txt b/doc/CHANGES_v4.x.txt index 647d990..52d11f6 100644 --- a/doc/CHANGES_v4.x.txt +++ b/doc/CHANGES_v4.x.txt @@ -3,6 +3,29 @@ MATRIXSSL 4.X CHANGELOG +Changes between 4.2.2 and 4.3.0 [June 2020] + + * Added a constant-time variant of eccMulmod, in response to the Minerva attack. + * Fixed a possible infinite loop in message parsing discovered by + Andreas Walz (ivESK). + * Timing sidechannel mitigation (Github issue #23). + * Change hard coded values to enums in matrixSslLoadKeys (Github issue #35). + * Disabled TLS 1.3 draft versions by default. + * Fixes TLS 1.2 session ticket based resumption. + * May only enable either PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED or + PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM (Github issue #37). + * Channel Bindings for TLS (only for TLS 1.2 and below), new APIs added + - matrixSslGetFinished + - matrixSslGetPeerFinished + - matrixSslGetTlsUniqueChannelBindings + * Added API for accessing MatrixSSL structures without direct access + to structure members. Use of this API will slightly enlarge the + MatrixSSL binary but will enable building software that is not + dependent on exact binary layout of structures such as ssl_t. + * Fixes the bug when NULL keydata was used in sslLoadKeyPair() function. + * Other bug fixes. + + Changes between 4.2.1 and 4.2.2 [August 2019] This version fixes a few security issues related to DTLS and handshake diff --git a/doc/MatrixCMS_API.pdf b/doc/MatrixCMS_API.pdf index 02bcf27..738bbee 100644 Binary files a/doc/MatrixCMS_API.pdf and b/doc/MatrixCMS_API.pdf differ diff --git a/doc/MatrixDTLS_DeveloperGuide.pdf b/doc/MatrixDTLS_DeveloperGuide.pdf index e80bf99..2431804 100644 Binary files a/doc/MatrixDTLS_DeveloperGuide.pdf and b/doc/MatrixDTLS_DeveloperGuide.pdf differ diff --git a/doc/MatrixKeyAndCertGeneration.pdf b/doc/MatrixKeyAndCertGeneration.pdf index 4436e4c..b003b8c 100644 Binary files a/doc/MatrixKeyAndCertGeneration.pdf and b/doc/MatrixKeyAndCertGeneration.pdf differ diff --git a/doc/MatrixSSL_API.pdf b/doc/MatrixSSL_API.pdf index db76286..e9c3455 100644 Binary files a/doc/MatrixSSL_API.pdf and b/doc/MatrixSSL_API.pdf differ diff --git a/doc/MatrixSSL_CertificatesAndCRLs.pdf b/doc/MatrixSSL_CertificatesAndCRLs.pdf index 9de307d..bbb3190 100644 Binary files a/doc/MatrixSSL_CertificatesAndCRLs.pdf and b/doc/MatrixSSL_CertificatesAndCRLs.pdf differ diff --git a/doc/MatrixSSL_DiffieHellman.pdf b/doc/MatrixSSL_DiffieHellman.pdf index 1456b1e..48adaa0 100644 Binary files a/doc/MatrixSSL_DiffieHellman.pdf and b/doc/MatrixSSL_DiffieHellman.pdf differ diff --git a/doc/MatrixSSL_EllipticCurveCiphers.pdf b/doc/MatrixSSL_EllipticCurveCiphers.pdf index 93a75f7..0c331f2 100644 Binary files a/doc/MatrixSSL_EllipticCurveCiphers.pdf and b/doc/MatrixSSL_EllipticCurveCiphers.pdf differ diff --git a/doc/MatrixSSL_ExternalModuleIntegration.pdf b/doc/MatrixSSL_ExternalModuleIntegration.pdf index 2ddb16c..c5d0b8b 100644 Binary files a/doc/MatrixSSL_ExternalModuleIntegration.pdf and b/doc/MatrixSSL_ExternalModuleIntegration.pdf differ diff --git a/doc/MatrixSSL_GettingStarted.pdf b/doc/MatrixSSL_GettingStarted.pdf index c5e8b98..d9e4fe2 100644 Binary files a/doc/MatrixSSL_GettingStarted.pdf and b/doc/MatrixSSL_GettingStarted.pdf differ diff --git a/doc/MatrixSSL_PortingGuide.pdf b/doc/MatrixSSL_PortingGuide.pdf index 649077b..e0a2036 100644 Binary files a/doc/MatrixSSL_PortingGuide.pdf and b/doc/MatrixSSL_PortingGuide.pdf differ diff --git a/doc/MatrixSSL_PreSharedKeys.pdf b/doc/MatrixSSL_PreSharedKeys.pdf index 41913b7..4dc8f20 100644 Binary files a/doc/MatrixSSL_PreSharedKeys.pdf and b/doc/MatrixSSL_PreSharedKeys.pdf differ diff --git a/matrixssl/Makefile b/matrixssl/Makefile index e915c35..7ff8835 100644 --- a/matrixssl/Makefile +++ b/matrixssl/Makefile @@ -10,6 +10,7 @@ MATRIXSSL_ROOT:=.. include $(MATRIXSSL_ROOT)/common.mk SRC:=\ + matrixsslGetSet.c \ cipherSuite.c \ dtls.c \ extDecode.c \ diff --git a/matrixssl/cipherSuite.c b/matrixssl/cipherSuite.c index 3c4a876..e18567d 100644 --- a/matrixssl/cipherSuite.c +++ b/matrixssl/cipherSuite.c @@ -2042,15 +2042,15 @@ static psRes_t validateKeyForExtensions(ssl_t *ssl, const sslCipherSpec_t *spec, { if ( # ifdef USE_SHA1 - !(ssl->hashSigAlg & HASH_SIG_SHA1_RSA_MASK) && + !(ssl->peerSigAlg & HASH_SIG_SHA1_RSA_MASK) && # endif # ifdef USE_SHA384 - !(ssl->hashSigAlg & HASH_SIG_SHA384_RSA_MASK) && + !(ssl->peerSigAlg & HASH_SIG_SHA384_RSA_MASK) && # endif # ifdef USE_SHA512 - !(ssl->hashSigAlg & HASH_SIG_SHA512_RSA_MASK) && + !(ssl->peerSigAlg & HASH_SIG_SHA512_RSA_MASK) && # endif - !(ssl->hashSigAlg & HASH_SIG_SHA256_RSA_MASK)) + !(ssl->peerSigAlg & HASH_SIG_SHA256_RSA_MASK)) { return PS_UNSUPPORTED_FAIL; } @@ -2061,15 +2061,15 @@ static psRes_t validateKeyForExtensions(ssl_t *ssl, const sslCipherSpec_t *spec, { if ( # ifdef USE_SHA1 - !(ssl->hashSigAlg & HASH_SIG_SHA1_ECDSA_MASK) && + !(ssl->peerSigAlg & HASH_SIG_SHA1_ECDSA_MASK) && # endif # ifdef USE_SHA384 - !(ssl->hashSigAlg & HASH_SIG_SHA384_ECDSA_MASK) && + !(ssl->peerSigAlg & HASH_SIG_SHA384_ECDSA_MASK) && # endif # ifdef USE_SHA512 - !(ssl->hashSigAlg & HASH_SIG_SHA512_ECDSA_MASK) && + !(ssl->peerSigAlg & HASH_SIG_SHA512_ECDSA_MASK) && # endif - !(ssl->hashSigAlg & HASH_SIG_SHA256_ECDSA_MASK)) + !(ssl->peerSigAlg & HASH_SIG_SHA256_ECDSA_MASK)) { return PS_UNSUPPORTED_FAIL; } @@ -2079,7 +2079,7 @@ static psRes_t validateKeyForExtensions(ssl_t *ssl, const sslCipherSpec_t *spec, } # endif /* USE_DHE_CIPHER_SUITE */ - if (!peerSupportsSigAlg(crt->sigAlgorithm, ssl->hashSigAlg)) + if (!peerSupportsSigAlg(crt->sigAlgorithm, ssl->peerSigAlg)) { psTraceErrr("Peer doesn't support all sig/hash algorithm " \ "pairs in our certificate chain.\n"); @@ -2132,7 +2132,12 @@ static psBool_t certValidForUse(psX509Cert_t *certs, for (cert = certs; cert; cert = cert->next) { - if (keyAlg == 0 || cert->pubKeyAlgorithm == keyAlg) + /* Allow both OID_RSA_KEY_ALG and OID_RSASSA_PSS for suites + with RSA authentication. */ + if (keyAlg == 0 || + cert->pubKeyAlgorithm == keyAlg || + (cert->pubKeyAlgorithm == OID_RSASSA_PSS && + keyAlg == OID_RSA_KEY_ALG)) { return PS_TRUE; } @@ -3375,6 +3380,12 @@ int32_t sslGetCipherSpecListExt(const ssl_t *ssl, supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2) { ignored += 2; +# ifdef DEBUG_FILTER_CIPHERLIST + psTracePrintCiphersuiteName(INDENT_HS_MSG, + "Filtered out (SHA-2/3 not supported)", + supportedCiphers[i].ident, + PS_TRUE); +# endif continue; } } @@ -3386,6 +3397,12 @@ int32_t sslGetCipherSpecListExt(const ssl_t *ssl, && supportedCiphers[i].type != CS_TLS13) { ignored += 2; +# ifdef DEBUG_FILTER_CIPHERLIST + psTracePrintCiphersuiteName(INDENT_HS_MSG, + "Filtered out (TLS 1.2 and below not supported)", + supportedCiphers[i].ident, + PS_TRUE); +# endif continue; } /* Remove TLS1.3 ciphers in case TLS1.3 is not enabled */ @@ -3393,6 +3410,12 @@ int32_t sslGetCipherSpecListExt(const ssl_t *ssl, && (supportedCiphers[i].type == CS_TLS13)) { ignored += 2; +# ifdef DEBUG_FILTER_CIPHERLIST + psTracePrintCiphersuiteName(INDENT_HS_MSG, + "Filtered out (TLS 1.3 not supported)", + supportedCiphers[i].ident, + PS_TRUE); +# endif continue; } # endif /* USE_TLS_1_3 */ @@ -3400,6 +3423,12 @@ int32_t sslGetCipherSpecListExt(const ssl_t *ssl, if (!ciphersuiteAllowedBySecConfig(ssl, supportedCiphers[i].ident)) { ignored += 2; +# ifdef DEBUG_FILTER_CIPHERLIST + psTracePrintCiphersuiteName(INDENT_HS_MSG, + "Filtered out (not allowed by security config)", + supportedCiphers[i].ident, + PS_TRUE); +# endif continue; } # endif /* USE_SEC_CONFIG */ @@ -3407,6 +3436,12 @@ int32_t sslGetCipherSpecListExt(const ssl_t *ssl, if (haveKeyMaterial(ssl, &supportedCiphers[i], 0) != PS_SUCCESS) { ignored += 2; +# ifdef DEBUG_FILTER_CIPHERLIST + psTracePrintCiphersuiteName(INDENT_HS_MSG, + "Filtered out (no suitable key material)", + supportedCiphers[i].ident, + PS_TRUE); +# endif continue; } #endif diff --git a/matrixssl/extDecode.c b/matrixssl/extDecode.c index 5695f99..a94113f 100644 --- a/matrixssl/extDecode.c +++ b/matrixssl/extDecode.c @@ -101,18 +101,19 @@ int32_t tlsParseSignatureAlgorithms(ssl_t *ssl, { sigAlg = (c[0] << 8) + c[1]; /* Those algorithms that are not supported by us will be filtered - out here */ + out here; ssl->hashSigAlg will contain the shared ones. */ if (findFromUint16Array(ssl->supportedSigAlgs, ssl->supportedSigAlgsLen, sigAlg) != PS_FAILURE) { /* This client supplied sig_alg is on our supported list */ ssl->hashSigAlg |= HASH_SIG_MASK(c[0], c[1]); - if (keySelect->peerSigAlgsLen < TLS_MAX_SIGNATURE_ALGORITHMS) - { - keySelect->peerSigAlgs[keySelect->peerSigAlgsLen++] = sigAlg; - } } + if (keySelect->peerSigAlgsLen < TLS_MAX_SIGNATURE_ALGORITHMS) + { + keySelect->peerSigAlgs[keySelect->peerSigAlgsLen++] = sigAlg; + } + ssl->peerSigAlg |= HASH_SIG_MASK(c[0], c[1]); c += 2; tmpLen -= 2; extLen -= 2; @@ -120,7 +121,7 @@ int32_t tlsParseSignatureAlgorithms(ssl_t *ssl, psTracePrintSigAlgs(INDENT_EXTENSION, "signature_algorithms", - ssl->hashSigAlg, + ssl->peerSigAlg, PS_FALSE); return MATRIXSSL_SUCCESS; @@ -725,7 +726,7 @@ static int ClientHelloExt(ssl_t *ssl, psTracePrintExtensionParse(ssl, EXT_ELLIPTIC_POINTS); if (extLen < 1) { - psTraceErrr("Invaid ECC Points len\n"); + psTraceErrr("Invalid ECC Points len\n"); ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; return MATRIXSSL_ERROR; } @@ -1196,6 +1197,13 @@ static int ServerHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext ssl->extFlags.req_elliptic_points = 0; rc = 0; } +# ifdef ALLOW_UNSOLICITED_SERVER_HELLO_ELLIPTIC_POINTS + /* Some servers send the extension regardless of whether we sent + it in our ClientHello. This is strictly not RFC-compliant. + Allow it if the above compatibility option is enabled. */ + psTraceInfo("Allowing unsolicited elliptic_point_format extension\n"); + rc = 0; +# endif if (*c++ != (extLen - 1)) { ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; diff --git a/matrixssl/hsDecode.c b/matrixssl/hsDecode.c index 27b3cc0..46c1fc9 100644 --- a/matrixssl/hsDecode.c +++ b/matrixssl/hsDecode.c @@ -48,6 +48,100 @@ /******************************************************************************/ #ifdef USE_SERVER_SIDE_SSL + +int32 parseSslv2ClientHelloContent(ssl_t *ssl, + unsigned char **readPos, + unsigned char *end, + uint32 *suiteLen, + unsigned char **suiteStart) +{ +# ifdef ALLOW_SSLV2_CLIENT_HELLO_PARSE + /* + Parse a SSLv2 ClientHello message contents, starting from the + cipher_spec_length field. See RFC 5246, Appendix E.2. for the + accepted SSLv2 ClientHello format. + + struct { + unit8 msg_type; + Version version; + uint16 cipher_spec_length; + uint16 session_id_length; + uint16 challenge_length; + V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length]; + opaque session_id[V2ClientHello.session_id_length]; + Random challenge; + } V2ClientHello; + */ + uint32_t challengeLen; + unsigned char *c = *readPos; + + psTraceInfo("Parsing SSLv2 ClientHello\n"); + if (end - c < 6) + { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceErrr("Can't parse hello message\n"); + return MATRIXSSL_ERROR; + } + /* uint16 cipher_spec_length; */ + *suiteLen = *c << 8; c++; + *suiteLen += *c; c++; + if (*suiteLen == 0 || *suiteLen % 3 != 0) + { + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceErrr("Illegal ciphersuite length in SSLv2 ClientHello\n"); + return MATRIXSSL_ERROR; + } + /* uint16 session_id_length; */ + ssl->sessionIdLen = *c << 8; c++; + ssl->sessionIdLen += *c; c++; + if (ssl->sessionIdLen > 0) + { + /* We don't allow session IDs for v2 ClientHellos. */ + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceErrr("SSLv2 sessions not allowed\n"); + return MATRIXSSL_ERROR; + } + /* uint16_t challenge_length; */ + challengeLen = *c << 8; c++; + challengeLen += *c; c++; + if (challengeLen != 32) /* Allow only 32-bit, as per RFC 5246, E.2. */ + { + psTraceErrr("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; + psTraceErrr("Malformed SSLv2 ClientHello\n"); + return MATRIXSSL_ERROR; + } + /* + V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length]; + Jump over the vector; ciphersuites will be parsed later. + */ + *suiteStart = c; + c += *suiteLen; + + /* Random challenge; */ + Memset(ssl->sec.clientRandom, 0x0, SSL_HS_RANDOM_SIZE); + Memcpy(ssl->sec.clientRandom + (SSL_HS_RANDOM_SIZE - challengeLen), + c, challengeLen); + c += challengeLen; + + *readPos = c; + + return MATRIXSSL_SUCCESS; +# else + ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; + psTraceErrr("SSLV2 CLIENT_HELLO not supported.\n"); + return MATRIXSSL_ERROR; +# endif +} + int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end) { unsigned char *suiteStart, *suiteEnd; @@ -336,82 +430,11 @@ 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; - psTraceErrr("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; - psTraceErrr("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; - psTraceErrr("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 - { - psTraceErrr("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; - psTraceErrr("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; - - /* We don't allow session IDs for v2 ClientHellos */ - if (ssl->sessionIdLen > 0) - { - ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; - psTraceErrr("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; - psTraceErrr("SSLV2 CLIENT_HELLO not supported.\n"); - return MATRIXSSL_ERROR; -# endif + rc = parseSslv2ClientHelloContent(ssl, + &c, + end, + &suiteLen, + &suiteStart); } #ifdef USE_TLS_1_3 @@ -1584,7 +1607,8 @@ int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp, { if (ssl->sessionIdLen > 0) { - if (Memcmp(ssl->sessionId, c, sessionIdLen) == 0) + if (sessionIdLen == ssl->sessionIdLen && + Memcmp(ssl->sessionId, c, sessionIdLen) == 0) { ssl->flags |= SSL_FLAGS_RESUMED; } @@ -1639,6 +1663,7 @@ int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp, # endif } } + /* Next is the two byte cipher suite */ if (end - c < 2) { @@ -2516,21 +2541,21 @@ int32 parseCertificateRequest(ssl_t *ssl, return MATRIXSSL_ERROR; } /* Parse supported_signature_algorithms list. */ - ssl->serverSigAlgs = 0; + ssl->peerSigAlg = 0; while (len >= 2) { uint32_t val = HASH_SIG_MASK(c[0], c[1]); keySelect->peerSigAlgs[nSigAlg++] = val; - ssl->serverSigAlgs |= val; + ssl->peerSigAlg |= val; c += 2; len -= 2; } keySelect->peerSigAlgsLen = nSigAlg; - keySelect->peerSigAlgMask = ssl->serverSigAlgs; + keySelect->peerSigAlgMask = ssl->peerSigAlg; c += len; psTracePrintSigAlgs(INDENT_HS_MSG, "supported_signature_algorithms", - ssl->serverSigAlgs, + ssl->peerSigAlg, PS_TRUE); } else @@ -2698,6 +2723,10 @@ int32 parseFinished(ssl_t *ssl, int32 hsLen, Memcpy(ssl->peerVerifyData, c, hsLen); ssl->peerVerifyDataLen = hsLen; #endif /* ENABLE_SECURE_REHANDSHAKES */ +#ifdef USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS + Memcpy(ssl->peerFinished, c, hsLen); + ssl->peerFinishedLen = hsLen; +#endif c += hsLen; ssl->hsState = SSL_HS_DONE; /* Now that we've parsed the Finished message, if we're a resumed diff --git a/matrixssl/hsNegotiateVersion.c b/matrixssl/hsNegotiateVersion.c index 5a3d8ac..36e97d4 100644 --- a/matrixssl/hsNegotiateVersion.c +++ b/matrixssl/hsNegotiateVersion.c @@ -448,6 +448,16 @@ int32_t checkSupportedVersions(ssl_t *ssl) SET_NGTD_VER(ssl, v_tls_1_3); return PS_SUCCESS; } +# ifndef USE_TLS_1_3_DRAFT_SPEC + /* Don't negotiate a TLS 1.3 draft version unless enabled + from compile-time config. */ + forbiddenVer[i++] = TLS_1_3_DRAFT_22_VER; + forbiddenVer[i++] = TLS_1_3_DRAFT_23_VER; + forbiddenVer[i++] = TLS_1_3_DRAFT_24_VER; + forbiddenVer[i++] = TLS_1_3_DRAFT_26_VER; + forbiddenVer[i++] = TLS_1_3_DRAFT_28_VER; + forbiddenVerLen = i; +# endif } /* Choose version from the intersection of our and the client's diff --git a/matrixssl/matrixssl.c b/matrixssl/matrixssl.c index 6f867b6..2ce99f8 100644 --- a/matrixssl/matrixssl.c +++ b/matrixssl/matrixssl.c @@ -415,9 +415,6 @@ int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys, psPool_t *pool = NULL; ssl_t *lssl; int32_t flags, rc; -#ifdef USE_STATELESS_SESSION_TICKETS - uint32_t i; -#endif /* SERVER_SIDE and CLIENT_AUTH and others will have been added to versionFlag by callers */ @@ -674,21 +671,8 @@ int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys, { Memcpy(lssl->sec.masterSecret, session->masterSecret, SSL_HS_MASTER_SIZE); - lssl->sessionIdLen = SSL_MAX_SESSION_ID_SIZE; - Memcpy(lssl->sessionId, session->id, SSL_MAX_SESSION_ID_SIZE); -#ifdef USE_STATELESS_SESSION_TICKETS - /* Possible no sessionId here at all if tickets used instead. - Will know if all 0s */ - lssl->sessionIdLen = 0; - for (i = 0; i < SSL_MAX_SESSION_ID_SIZE; i++) - { - if (session->id[i] != 0x0) - { - lssl->sessionIdLen = SSL_MAX_SESSION_ID_SIZE; - break; - } - } -#endif + lssl->sessionIdLen = session->idLen; + Memcpy(lssl->sessionId, session->id, session->idLen); } } lssl->sid = session; @@ -1968,22 +1952,32 @@ int32 matrixSslGetSessionId(ssl_t *ssl, sslSessionId_t *session) # endif if (ssl->cipher != NULL && ssl->cipher->ident != SSL_NULL_WITH_NULL_NULL && - ssl->sessionIdLen == SSL_MAX_SESSION_ID_SIZE) + ssl->sessionIdLen > 0) { + psBool_t secureRenegotiation = PS_FALSE; + (void)secureRenegotiation; /* Possibly unused. */ + +# ifdef ENABLE_SECURE_REHANDSHAKES + secureRenegotiation = ssl->secureRenegotiationInProgress; +# endif # ifdef USE_STATELESS_SESSION_TICKETS + /* There is only one sessionId_t structure for any given session and it is possible a re-handshake on a session ticket connection will agree on using standard resumption and so the old master secret for the session ticket will be overwritten. Check for this case here and do not update our session if a ticket is in use */ - if (session->sessionTicket != NULL && session->sessionTicketLen > 0) + if (secureRenegotiation == PS_TRUE && + session->sessionTicket != NULL && + session->sessionTicketLen > 0) { return PS_SUCCESS; } # endif session->cipherId = ssl->cipher->ident; Memcpy(session->id, ssl->sessionId, ssl->sessionIdLen); + session->idLen = ssl->sessionIdLen; Memcpy(session->masterSecret, ssl->sec.masterSecret, SSL_HS_MASTER_SIZE); return PS_SUCCESS; diff --git a/matrixssl/matrixsslApi.c b/matrixssl/matrixsslApi.c index 62a0f2f..5d1043d 100644 --- a/matrixssl/matrixsslApi.c +++ b/matrixssl/matrixsslApi.c @@ -170,6 +170,7 @@ int32_t matrixSslNewClientSession(ssl_t **ssl, const sslKeys_t *keys, { psTraceInfo("Explicit cipher suite will override session cache\n"); Memset(sid->id, 0, SSL_MAX_SESSION_ID_SIZE); + sid->idLen = 0; Memset(sid->masterSecret, 0, SSL_HS_MASTER_SIZE); sid->cipherId = 0; } @@ -215,8 +216,9 @@ int32_t matrixSslNewClientSession(ssl_t **ssl, const sslKeys_t *keys, { if (psX509ValidateGeneralName((char *) expectedName) < 0) { + psTraceErrr("Invalid expectedName\n"); matrixSslDeleteSession(lssl); - return rc; + return PS_ARG_FAIL; } rc = Strlen(expectedName); lssl->expectedName = psMalloc(lssl->sPool, rc + 1); @@ -382,6 +384,30 @@ void matrixSslDeleteSessionId(sslSessionId_t *sess) psFree(sess, NULL); } +# ifdef USE_STATELESS_SESSION_TICKETS +unsigned char* matrixSslSessionIdGetSessionTicket(sslSessionId_t *id) +{ + return id->sessionTicket; +} +psSizeL_t matrixSslSessionIdGetSessionTicketLen(sslSessionId_t *id) +{ + return id->sessionTicketLen; +} +# endif +unsigned char* matrixSslSessionIdGetSessionId(sslSessionId_t *id) +{ + return id->id; +} +psSizeL_t matrixSslSessionIdGetSessionIdLen(sslSessionId_t *id) +{ + return id->idLen; +} +void matrixSslSessionIdClearSessionId(sslSessionId_t *id) +{ + memset(id->id, 0, SSL_MAX_SESSION_ID_SIZE); + id->idLen = 0; +} + # ifdef USE_EAP_FAST /** Set the TLS connection to connect using an externally provisioned EAP-FAST @@ -2212,11 +2238,6 @@ sslKeys_t *matrixSslGetKeys(ssl_t *ssl) return ssl->keys; } -void *matrixSslGetUserPtr(ssl_t *ssl) -{ - return ssl->userPtr; -} - psProtocolVersion_t matrixSslGetNegotiatedVersion(ssl_t *ssl) { return GET_NGTD_VER(ssl); @@ -2309,4 +2330,130 @@ int32 matrixSslGetMasterSecret( } # endif /* ENABLE_MASTER_SECRET_EXPORT */ +psBool_t matrixSslIsResumedSession( + const ssl_t *ssl) +{ + return isResumedHandshake(ssl); +} + +/** Returns a pointer to MatrixSSL's internal configuration string. + The string is an encoding of the TLS configuration MatrixSSL + was compiled with. */ +const char *matrixSslConfigGetInternalStr(void) +{ + return psConfigStrSsl; +} + +/** Returns PS_SUCCESS if callerConfig is identical to MatrixSSL's + internal config string; returns PS_FAILURE otherwise. */ +int32_t matrixSslConfigCheck(const char *callerConfig) +{ + const char *own_str = matrixSslConfigGetInternalStr(); + size_t own_len = Strlen(own_str); + size_t caller_len = Strlen(callerConfig); + + if (own_len != caller_len) + { + psTraceErrr("Configuration string length mismatch\n"); + psTraceIntInfo("Internal: %zu\n", own_len); + psTraceIntInfo("Caller : %zu\n", caller_len); + return PS_FAILURE; + } + + if (Strcmp(own_str, callerConfig)) + { + psTraceErrr("Configuration string mismatch\n"); + return PS_FAILURE; + } + + return PS_SUCCESS; +} + +# ifdef USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS +psRes_t matrixSslGetFinished( + const ssl_t *ssl, + unsigned char *finished, + psSizeL_t *finishedLen) +{ + if (ssl == NULL || finished == NULL || finishedLen == NULL) + { + return PS_ARG_FAIL; + } + if (!matrixSslHandshakeIsComplete(ssl)) + { + *finishedLen = 0; + return PS_FAILURE; + } + if (*finishedLen < ssl->myFinishedLen) + { + *finishedLen = ssl->myFinishedLen; + return PS_OUTPUT_LENGTH; + } + memcpy(finished, ssl->myFinished, ssl->myFinishedLen); + *finishedLen = ssl->myFinishedLen; + + return MATRIXSSL_SUCCESS; +} + +psRes_t matrixSslGetPeerFinished( + const ssl_t *ssl, + unsigned char *finished, + psSizeL_t *finishedLen) +{ + if (ssl == NULL || finished == NULL || finishedLen == NULL) + { + return PS_ARG_FAIL; + } + if (!matrixSslHandshakeIsComplete(ssl)) + { + *finishedLen = 0; + return PS_FAILURE; + } + if (*finishedLen < ssl->peerFinishedLen) + { + *finishedLen = ssl->peerFinishedLen; + return PS_OUTPUT_LENGTH; + } + memcpy(finished, ssl->peerFinished, ssl->peerFinishedLen); + *finishedLen = ssl->peerFinishedLen; + + return MATRIXSSL_SUCCESS; +} + +psRes_t matrixSslGetTlsUniqueChannelBindings( + const ssl_t *ssl, + unsigned char *tls_unique, + psSizeL_t *tls_unique_len) +{ + if (ssl == NULL || tls_unique == NULL || tls_unique_len == NULL) + { + return PS_ARG_FAIL; + } + if (matrixSslIsResumedSession(ssl)) + { + /* In resumed handshakes, the server's Finished is the first one. */ + if (MATRIX_IS_CLIENT(ssl)) + { + return matrixSslGetPeerFinished(ssl, tls_unique, tls_unique_len); + } + else + { + return matrixSslGetPeerFinished(ssl, tls_unique, tls_unique_len); + } + } + else + { + /* In standard handshakes, client's Finished is the first one. */ + if (MATRIX_IS_CLIENT(ssl)) + { + return matrixSslGetFinished(ssl, tls_unique, tls_unique_len); + } + else + { + return matrixSslGetPeerFinished(ssl, tls_unique, tls_unique_len); + } + } +} +# endif + /******************************************************************************/ diff --git a/matrixssl/matrixsslApi.h b/matrixssl/matrixsslApi.h index 465fd71..94edb8d 100644 --- a/matrixssl/matrixsslApi.h +++ b/matrixssl/matrixsslApi.h @@ -51,6 +51,7 @@ extern "C" { # include "matrixsslApiExt.h" /* TLS extension IDs. */ # include "matrixsslApiCipher.h" /* Ciphersuite IDs. */ # include "matrixsslApiTypes.h" /* TLS and configuration data types. */ +# include "matrixsslConfigStr.h" /* Encoding of the compile-time configuration. */ /* For API documentation, see the separate MatrixSSL APIs manual. */ @@ -175,6 +176,18 @@ PSPUBLIC void matrixSslSetSessionTicketCallback( int32 (*ticket_cb)(void *, unsigned char[16], short)); +/* Setter/getter API for sslSessionId_t objects. */ +PSPUBLIC unsigned char* matrixSslSessionIdGetSessionId( + sslSessionId_t *id); +PSPUBLIC psSizeL_t matrixSslSessionIdGetSessionIdLen( + sslSessionId_t *id); +PSPUBLIC unsigned char* matrixSslSessionIdGetSessionTicket( + sslSessionId_t *id); +PSPUBLIC psSizeL_t matrixSslSessionIdGetSessionTicketLen( + sslSessionId_t *id); +PSPUBLIC void matrixSslSessionIdClearSessionId( + sslSessionId_t *id); + /* Configuring extensions. */ PSPUBLIC void matrixSslRegisterSNICallback( ssl_t *ssl, @@ -300,6 +313,21 @@ PSPUBLIC psProtocolVersion_t matrixSslGetNegotiatedVersion( PSPUBLIC psBool_t matrixSslHandshakeIsComplete( const ssl_t *ssl); +/* API for getting RFC 5929 tls-unique channel bindings for the current + TLS connection. */ +PSPUBLIC psRes_t matrixSslGetFinished( + const ssl_t *ssl, + unsigned char *finished, + psSizeL_t *finishedLen); +PSPUBLIC psRes_t matrixSslGetPeerFinished( + const ssl_t *ssl, + unsigned char *peerFinished, + psSizeL_t *peerFinishedLen); +PSPUBLIC psRes_t matrixSslGetTlsUniqueChannelBindings( + const ssl_t *ssl, + unsigned char *tls_unique, + psSizeL_t *tls_unique_len); + /** Configuration options for a single connection. */ PSPUBLIC int32 matrixSslDisableRehandshakes( ssl_t *ssl); @@ -360,8 +388,6 @@ PSPUBLIC char* matrixSslGetExpectedName( const ssl_t *ssl); PSPUBLIC sslKeys_t *matrixSslGetKeys( ssl_t *ssl); -PSPUBLIC void* matrixSslGetUserPtr( - ssl_t *ssl); PSPUBLIC psBool_t matrixSslTlsVersionRangeSupported( psProtocolVersion_t low, psProtocolVersion_t high); @@ -376,6 +402,24 @@ PSPUBLIC int32 matrixSslGetMasterSecret( ssl_t *ssl, unsigned char **masterSecret, psSizeL_t *hsMasterSecretLen); +PSPUBLIC psBool_t matrixSslIsResumedSession( + const ssl_t *ssl); + +PSPUBLIC int32_t matrixSslConfigCheck( + const char *callerConfig); +PSPUBLIC const char* matrixSslConfigGetInternalStr( + void); + +#define PS_CONFIG_GET_SSL_CALLER \ + psConfigStrSsl +#define PS_CONFIG_CHECK_SSL \ + matrixSslConfigCheck(PS_CONFIG_GET_SSL_CALLER) +#define PS_CONFIG_GET_SSL \ + matrixSslConfigGetInternalStr() +#define PS_CONFIG_PRINTF \ + printf("Internal config:\n%s\nCaller config:\n%s\n", \ + PS_CONFIG_GET_SSL_CALLER, \ + PS_CONFIG_GET_SSL) /******************************************************************************/ @@ -641,6 +685,8 @@ PSPUBLIC int32 matrixSslLoadEcKeysMem( } # endif +# include "matrixsslGetSet.h" + /******************************************************************************/ #endif /* _h_MATRIXSSL */ diff --git a/matrixssl/matrixsslApiPre.h b/matrixssl/matrixsslApiPre.h index bffbeec..a67fec9 100644 --- a/matrixssl/matrixsslApiPre.h +++ b/matrixssl/matrixsslApiPre.h @@ -1,10 +1,9 @@ /** - * @file matrixsslApiVer.h + * @file matrixsslApiPre.h * @version $Format:%h%d$ * * Public header file for MatrixSSL. - * This sub-header of matrixsslApi.h contains protocol version related - * defines. + * This sub-header of matrixsslApi.h contains a preamble. */ /* * Copyright (c) 2013-2018 INSIDE Secure Corporation diff --git a/matrixssl/matrixsslApiTypes.h b/matrixssl/matrixsslApiTypes.h index 2c0e24e..6c698ff 100644 --- a/matrixssl/matrixsslApiTypes.h +++ b/matrixssl/matrixsslApiTypes.h @@ -40,6 +40,9 @@ /* Forward declarations for opaque types. */ typedef struct ssl ssl_t; typedef struct sslKeys sslKeys_t; +typedef struct sslSec sslSec_t; +typedef struct sslRec sslRec_t; +typedef struct sslCipherSpec sslCipherSpec_t; typedef struct tlsExtension tlsExtension_t; typedef struct sslSessionId sslSessionId_t; typedef struct psTls13SessionParams psTls13SessionParams_t; diff --git a/matrixssl/matrixsslApiVer.h b/matrixssl/matrixsslApiVer.h index 42265db..b2ebd63 100644 --- a/matrixssl/matrixsslApiVer.h +++ b/matrixssl/matrixsslApiVer.h @@ -190,9 +190,8 @@ enum PACKED | v_tls_1_3_draft_28), /** Any supported version that uses an explicit IV in CBC mode. */ v_tls_explicit_iv = (v_dtls_1_0 | v_dtls_1_2 | v_tls_1_1 | v_tls_1_2), - /** Any recommended TLS version. TODO: remove draft #28 once the - RFC version becomes widely supported enough. */ - v_tls_recommended = (v_tls_1_2 | v_tls_1_3 | v_tls_1_3_draft_28), + /** Any recommended TLS version. */ + v_tls_recommended = (v_tls_1_2 | v_tls_1_3), /** Any recommended DTLS version. */ v_dtls_recommended = v_dtls_1_2, /** Any version that allows SHA-2 based ciphersuites. */ diff --git a/matrixssl/matrixsslConfigStr.h b/matrixssl/matrixsslConfigStr.h new file mode 100644 index 0000000..fb35455 --- /dev/null +++ b/matrixssl/matrixsslConfigStr.h @@ -0,0 +1,506 @@ +static const char psConfigStrSsl[] = +"Version: SSL 4-2-2-comm\n" +"===== BEGIN CONFIG STRING =====\n" +# ifdef DISABLE_SSLV3 + "DISABLE_SSLV3\n" +# endif +# ifdef DISABLE_TLS_1_0 + "DISABLE_TLS_1_0\n" +# endif +# ifdef DISABLE_TLS_1_1 + "DISABLE_TLS_1_1\n" +# endif +# ifdef DISABLE_TLS_1_2 + "DISABLE_TLS_1_2\n" +# endif +# ifdef DISABLE_TLS_1_3 + "DISABLE_TLS_1_3\n" +# endif +# ifdef ENABLE_CA_CERT_HASH + "ENABLE_CA_CERT_HASH\n" +# endif +# ifdef ENABLE_INSECURE_REHANDSHAKES + "ENABLE_INSECURE_REHANDSHAKES\n" +# endif +# ifdef ENABLE_MASTER_SECRET_EXPORT + "ENABLE_MASTER_SECRET_EXPORT\n" +# endif +# ifdef ENABLE_SECURE_REHANDSHAKES + "ENABLE_SECURE_REHANDSHAKES\n" +# endif + "MATRIX_OPENSOURCE\n" +# ifdef MATRIX_USE_FILE_SYSTEM + "MATRIX_USE_FILE_SYSTEM\n" +# endif +# ifdef NO_ECC_EPHEMERAL_CACHE + "NO_ECC_EPHEMERAL_CACHE\n" +# endif +# ifdef POSIX + "POSIX\n" +# endif +# ifdef REQUIRE_DH_PARAMS + "REQUIRE_DH_PARAMS\n" +# endif +# ifdef REQUIRE_SECURE_REHANDSHAKES + "REQUIRE_SECURE_REHANDSHAKES\n" +# endif +# ifdef SEND_HELLO_RANDOM_TIME + "SEND_HELLO_RANDOM_TIME\n" +# endif +# ifdef SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG + "SERVER_WILL_ACCEPT_EMPTY_CLIENT_CERT_MSG\n" +# endif +# ifdef SSL_OPTION_FULL_HANDSHAKE + "SSL_OPTION_FULL_HANDSHAKE\n" +# endif +# ifdef SSL_REHANDSHAKES_ENABLED + "SSL_REHANDSHAKES_ENABLED\n" +# endif +# ifdef TLS_1_3_DEFAULT_DRAFT_MIN_VER + "TLS_1_3_DEFAULT_DRAFT_MIN_VER\n" +# endif +# ifdef TLS_1_3_DRAFT_MIN_VER + "TLS_1_3_DRAFT_MIN_VER\n" +# endif +# ifdef USE_3DES + "USE_3DES\n" +# endif +# ifdef USE_3DES_CIPHER_SUITE + "USE_3DES_CIPHER_SUITE\n" +# endif +# ifdef USE_AES + "USE_AES\n" +# endif +# ifdef USE_AES_CCM + "USE_AES_CCM\n" +# endif +# ifdef USE_AES_CIPHER_SUITE + "USE_AES_CIPHER_SUITE\n" +# endif +# ifdef USE_AES_GCM + "USE_AES_GCM\n" +# endif +# ifdef USE_ALPN + "USE_ALPN\n" +# endif +# ifdef USE_ARC4 + "USE_ARC4\n" +# endif +# ifdef USE_ARC4_CIPHER_SUITE + "USE_ARC4_CIPHER_SUITE\n" +# endif +# ifdef USE_BRAIN224R1 + "USE_BRAIN224R1\n" +# endif +# ifdef USE_BRAIN256R1 + "USE_BRAIN256R1\n" +# endif +# ifdef USE_BRAIN384R1 + "USE_BRAIN384R1\n" +# endif +# ifdef USE_BRAIN512R1 + "USE_BRAIN512R1\n" +# endif +# ifdef USE_BUFFERED_HS_HASH + "USE_BUFFERED_HS_HASH\n" +# endif +# ifdef USE_CA_CERTIFICATES + "USE_CA_CERTIFICATES\n" +# endif +# ifdef USE_CERT_CHAIN_PARSING + "USE_CERT_CHAIN_PARSING\n" +# endif +# ifdef USE_CERT_PARSE + "USE_CERT_PARSE\n" +# endif +# ifdef USE_CERT_VALIDATE + "USE_CERT_VALIDATE\n" +# endif +# ifdef USE_CHACHA20_POLY1305_IETF + "USE_CHACHA20_POLY1305_IETF\n" +# endif +# ifdef USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE + "USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE\n" +# endif +# ifdef USE_CLIENT_AUTH + "USE_CLIENT_AUTH\n" +# endif +# ifdef USE_CLIENT_SIDE_SSL + "USE_CLIENT_SIDE_SSL\n" +# endif +# ifdef USE_DH + "USE_DH\n" +# endif +# ifdef USE_DH_CIPHER_SUITE + "USE_DH_CIPHER_SUITE\n" +# endif +# ifdef USE_DHE_PSK_CIPHER_SUITE + "USE_DHE_PSK_CIPHER_SUITE\n" +# endif +# ifdef USE_DTLS + "USE_DTLS\n" +# endif +# ifdef USE_DTLS_DEBUG_TRACE + "USE_DTLS_DEBUG_TRACE\n" +# endif +# ifdef USE_EAP_FAST + "USE_EAP_FAST\n" +# endif +# ifdef USE_ECC + "USE_ECC\n" +# endif +# ifdef USE_ECC_CIPHER_SUITE + "USE_ECC_CIPHER_SUITE\n" +# endif +# ifdef USE_ECDSA_CIPHER_SUITE + "USE_ECDSA_CIPHER_SUITE\n" +# endif +# ifdef USE_ED25519 + "USE_ED25519\n" +# endif +# ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING + "USE_EXT_CERTIFICATE_VERIFY_SIGNING\n" +# endif +# ifdef USE_EXT_CLIENT_CERT_KEY_LOADING + "USE_EXT_CLIENT_CERT_KEY_LOADING\n" +# endif +# ifdef USE_HKDF + "USE_HKDF\n" +# endif +# ifdef USE_HMAC_SHA256 + "USE_HMAC_SHA256\n" +# endif +# ifdef USE_IDEA + "USE_IDEA\n" +# endif +# ifdef USE_IDEA_CIPHER_SUITE + "USE_IDEA_CIPHER_SUITE\n" +# endif +# ifdef USE_IDENTITY_CERTIFICATES + "USE_IDENTITY_CERTIFICATES\n" +# endif +# ifdef USE_MATRIX_OPENSSL_LAYER + "USE_MATRIX_OPENSSL_LAYER\n" +# endif +# ifdef USE_MATRIXSSL_STATS + "USE_MATRIXSSL_STATS\n" +# endif +# ifdef USE_MD5_MAC + "USE_MD5_MAC\n" +# endif +# ifdef USE_MD5SHA1 + "USE_MD5SHA1\n" +# endif +# ifdef USE_MULTITHREADING + "USE_MULTITHREADING\n" +# endif +# ifdef USE_NATIVE_SYMMETRIC + "USE_NATIVE_SYMMETRIC\n" +# endif +# ifdef USE_NATIVE_TLS_ALGS + "USE_NATIVE_TLS_ALGS\n" +# endif +# ifdef USE_NATIVE_TLS_HS_HASH + "USE_NATIVE_TLS_HS_HASH\n" +# endif +# ifdef USE_OCSP_RESPONSE + "USE_OCSP_RESPONSE\n" +# endif +# ifdef USE_ONLY_PSK_CIPHER_SUITE + "USE_ONLY_PSK_CIPHER_SUITE\n" +# endif +# ifdef USE_ONLY_TLS_1_2 + "USE_ONLY_TLS_1_2\n" +# endif +# ifdef USE_PKCS12 + "USE_PKCS12\n" +# endif +# ifdef USE_PKCS1_PSS + "USE_PKCS1_PSS\n" +# endif +# ifdef USE_PSK_CIPHER_SUITE + "USE_PSK_CIPHER_SUITE\n" +# endif +# ifdef USE_REHANDSHAKING + "USE_REHANDSHAKING\n" +# endif +# ifdef USE_RSA + "USE_RSA\n" +# endif +# ifdef USE_RSA_CIPHER_SUITE + "USE_RSA_CIPHER_SUITE\n" +# endif +# ifdef USE_SEC_CONFIG + "USE_SEC_CONFIG\n" +# endif +# ifdef USE_SEED + "USE_SEED\n" +# endif +# ifdef USE_SEED_CIPHER_SUITE + "USE_SEED_CIPHER_SUITE\n" +# endif +# ifdef USE_SERVER_SIDE_FALSE_START_SUPPORT + "USE_SERVER_SIDE_FALSE_START_SUPPORT\n" +# endif +# ifdef USE_SERVER_SIDE_SSL + "USE_SERVER_SIDE_SSL\n" +# endif +# ifdef USE_SHA1 + "USE_SHA1\n" +# endif +# ifdef USE_SHA256 + "USE_SHA256\n" +# endif +# ifdef USE_SHA384 + "USE_SHA384\n" +# endif +# ifdef USE_SHA512 + "USE_SHA512\n" +# endif +# ifdef USE_SHA_MAC + "USE_SHA_MAC\n" +# endif +# ifdef USE_SHARED_SESSION_CACHE + "USE_SHARED_SESSION_CACHE\n" +# endif +# ifdef USE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA + "USE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA\n" +# endif +# ifdef USE_SSL_DH_anon_WITH_RC4_128_MD5 + "USE_SSL_DH_anon_WITH_RC4_128_MD5\n" +# endif +# ifdef USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA + "USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA\n" +# endif +# ifdef USE_SSL_HANDSHAKE_MSG_TRACE + "USE_SSL_HANDSHAKE_MSG_TRACE\n" +# endif +# ifdef USE_SSL_INFORMATIONAL_TRACE + "USE_SSL_INFORMATIONAL_TRACE\n" +# endif +# ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA + "USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA\n" +# endif +# ifdef USE_SSL_RSA_WITH_NULL_MD5 + "USE_SSL_RSA_WITH_NULL_MD5\n" +# endif +# ifdef USE_SSL_RSA_WITH_NULL_SHA + "USE_SSL_RSA_WITH_NULL_SHA\n" +# endif +# ifdef USE_SSL_RSA_WITH_RC4_128_MD5 + "USE_SSL_RSA_WITH_RC4_128_MD5\n" +# endif +# ifdef USE_SSL_RSA_WITH_RC4_128_SHA + "USE_SSL_RSA_WITH_RC4_128_SHA\n" +# endif +# ifdef USE_STATELESS_SESSION_TICKETS + "USE_STATELESS_SESSION_TICKETS\n" +# endif +# ifdef USE_TLS + "USE_TLS\n" +# endif +# ifdef USE_TLS_1_1 + "USE_TLS_1_1\n" +# endif +# ifdef USE_TLS_1_2 + "USE_TLS_1_2\n" +# endif +# ifdef USE_TLS_1_3 + "USE_TLS_1_3\n" +# endif +# ifdef USE_TLS_1_3_CIPHER_SUITE + "USE_TLS_1_3_CIPHER_SUITE\n" +# endif +# ifdef USE_TLS_1_3_ONLY + "USE_TLS_1_3_ONLY\n" +# endif +# ifdef USE_TLS_1_3_RESUMPTION + "USE_TLS_1_3_RESUMPTION\n" +# endif +# ifdef USE_TLS_AES_128_GCM_SHA256 + "USE_TLS_AES_128_GCM_SHA256\n" +# endif +# ifdef USE_TLS_AES_256_GCM_SHA384 + "USE_TLS_AES_256_GCM_SHA384\n" +# endif +# ifdef USE_TLS_CHACHA20_POLY1305_SHA256 + "USE_TLS_CHACHA20_POLY1305_SHA256\n" +# endif +# ifdef USE_TLS_DH_anon_WITH_AES_128_CBC_SHA + "USE_TLS_DH_anon_WITH_AES_128_CBC_SHA\n" +# endif +# ifdef USE_TLS_DH_anon_WITH_AES_256_CBC_SHA + "USE_TLS_DH_anon_WITH_AES_256_CBC_SHA\n" +# endif +# ifdef USE_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + "USE_TLS_DHE_PSK_WITH_AES_128_CBC_SHA\n" +# endif +# ifdef USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + "USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA\n" +# endif +# ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + "USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n" +# endif +# ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + "USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\n" +# endif +# ifdef USE_TLS_DHE_RSA_WITH_AES_128_GCM_SHA + "USE_TLS_DHE_RSA_WITH_AES_128_GCM_SHA\n" +# endif +# ifdef USE_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + "USE_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256\n" +# endif +# ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + "USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n" +# endif +# ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + "USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\n" +# endif +# ifdef USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA + "USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA\n" +# endif +# ifdef USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA256 + "USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA256\n" +# endif +# ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + "USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA\n" +# endif +# ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + "USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256\n" +# endif +# ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + "USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256\n" +# endif +# ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + "USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA\n" +# endif +# ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + "USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384\n" +# endif +# ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + "USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384\n" +# endif +# ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + "USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA\n" +# endif +# ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + "USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\n" +# endif +# ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + "USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n" +# endif +# ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + "USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA\n" +# endif +# ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + "USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384\n" +# endif +# ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + "USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\n" +# endif +# ifdef USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + "USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\n" +# endif +# ifdef USE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + "USE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA\n" +# endif +# ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + "USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n" +# endif +# ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + "USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\n" +# endif +# ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + "USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n" +# endif +# ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + "USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\n" +# endif +# ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + "USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384\n" +# endif +# ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + "USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n" +# endif +# ifdef USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + "USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\n" +# endif +# ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + "USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA\n" +# endif +# ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + "USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256\n" +# endif +# ifdef USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + "USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256\n" +# endif +# ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + "USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA\n" +# endif +# ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + "USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384\n" +# endif +# ifdef USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + "USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384\n" +# endif +# ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA + "USE_TLS_PSK_WITH_AES_128_CBC_SHA\n" +# endif +# ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA256 + "USE_TLS_PSK_WITH_AES_128_CBC_SHA256\n" +# endif +# ifdef USE_TLS_PSK_WITH_AES_128_GCM_SHA + "USE_TLS_PSK_WITH_AES_128_GCM_SHA\n" +# endif +# ifdef USE_TLS_PSK_WITH_AES_128_GCM_SHA256 + "USE_TLS_PSK_WITH_AES_128_GCM_SHA256\n" +# endif +# ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA + "USE_TLS_PSK_WITH_AES_256_CBC_SHA\n" +# endif +# ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA384 + "USE_TLS_PSK_WITH_AES_256_CBC_SHA384\n" +# endif +# ifdef USE_TLS_PSK_WITH_AES_256_GCM_SHA + "USE_TLS_PSK_WITH_AES_256_GCM_SHA\n" +# endif +# ifdef USE_TLS_PSK_WITH_AES_256_GCM_SHA384 + "USE_TLS_PSK_WITH_AES_256_GCM_SHA384\n" +# endif +# ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA + "USE_TLS_RSA_WITH_AES_128_CBC_SHA\n" +# endif +# ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA256 + "USE_TLS_RSA_WITH_AES_128_CBC_SHA256\n" +# endif +# ifdef USE_TLS_RSA_WITH_AES_128_GCM_SHA256 + "USE_TLS_RSA_WITH_AES_128_GCM_SHA256\n" +# endif +# ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA + "USE_TLS_RSA_WITH_AES_256_CBC_SHA\n" +# endif +# ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA256 + "USE_TLS_RSA_WITH_AES_256_CBC_SHA256\n" +# endif +# ifdef USE_TLS_RSA_WITH_AES_256_GCM_SHA384 + "USE_TLS_RSA_WITH_AES_256_GCM_SHA384\n" +# endif +# ifdef USE_TLS_RSA_WITH_IDEA_CBC_SHA + "USE_TLS_RSA_WITH_IDEA_CBC_SHA\n" +# endif +# ifdef USE_TLS_RSA_WITH_RC4_128_SHA + "USE_TLS_RSA_WITH_RC4_128_SHA\n" +# endif +# ifdef USE_TLS_RSA_WITH_SEED_CBC_SHA + "USE_TLS_RSA_WITH_SEED_CBC_SHA\n" +# endif +# ifdef USE_TRUSTED_CA_INDICATION + "USE_TRUSTED_CA_INDICATION\n" +# endif +# ifdef USE_X25519 + "USE_X25519\n" +# endif +# ifdef USE_X509 + "USE_X509\n" +# endif +"===== END CONFIG STRING ====="; diff --git a/matrixssl/matrixsslGetSet.c b/matrixssl/matrixsslGetSet.c new file mode 100644 index 0000000..60daa4e --- /dev/null +++ b/matrixssl/matrixsslGetSet.c @@ -0,0 +1,844 @@ +/** + * @file matrixsslGetSet.c + * @version $Format:%h%d$ + * + * Add-on API for accessing MatrixSSL structures without direct access + * to structure members. Use of this API will slightly enlarge the + * MatrixSSL binary but will enable building software that is not + * dependent on exact binary layout of structures such as ssl_t. + */ + +/* + * Copyright (c) 2019 Verimatrix + * Copyright (c) 2013-2019 INSIDE Secure Corporation + * All Rights Reserved + * + * This file can be edited to modify exact set of accessor functions + * provided. + * + * The copyright notice above does not evidence any actual or intended + * publication of such source code. + * + * This Module contains Proprietary Information of INSIDE and should be + * treated as Confidential. + * + * The information in this file is provided for the exclusive use of the + * licensees of INSIDE. Such users have the right to use, modify, + * and incorporate this code into products for purposes authorized by the + * license agreement provided they include this notice and the associated + * copyright notice with any such product. + * + * The information in this file is provided "AS IS" without warranty. + */ + +#include "matrixsslImpl.h" +#include "matrixsslGetSet.h" +#include "osdep_stddef.h" +#ifdef MATRIX_LOG_GET +# include "osdep_stdio.h" +#endif +#ifdef MATRIX_LOG_SET +# include "osdep_stdio.h" +#endif + + +/* Get value of ssl_t member userPtr. */ +void *matrixSslGetUserPtr(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->userPtr is %p\n", (void*)(uintptr_t) (ssl->userPtr)); +#endif + return ssl->userPtr; + } + + return NULL; +} + +/* Set value of ssl_t member userPtr. */ +psRes_t matrixSslSetUserPtr(ssl_t *ssl, void *value) +{ + psRes_t res = PS_ARG_FAIL; + + if (ssl != NULL) + { + ssl->userPtr = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("ssl->userPtr=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of ssl_t member userDataPtr. */ +void *matrixSslGetUserDataPtr(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->userDataPtr is %p\n", (void*)(uintptr_t) (ssl->userDataPtr)); +#endif + return ssl->userDataPtr; + } + + return NULL; +} + +/* Set value of ssl_t member userDataPtr. */ +psRes_t matrixSslSetUserDataPtr(ssl_t *ssl, void *value) +{ + psRes_t res = PS_ARG_FAIL; + + if (ssl != NULL) + { + ssl->userDataPtr = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("ssl->userDataPtr=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of ssl_t member sec.cert. */ +# ifndef USE_ONLY_PSK_CIPHER_SUITE +# if defined(USE_IDENTITY_CERTIFICATES) || defined(USE_CERT_VALIDATE) +psX509Cert_t *matrixSslGetCerts(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->sec.cert is %p\n", (void*)(uintptr_t) (ssl->sec.cert)); +#endif + return ssl->sec.cert; + } + + return NULL; +} +# endif /* USE_IDENTITY_CERTIFICATES */ +# endif /* USE_ONLY_PSK_CIPHER_SUITE */ + +/* Get value of ssl_t member cipher. */ +const sslCipherSpec_t *matrixSslGetCipher(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->cipher is %p\n", (void*)(uintptr_t) (ssl->cipher)); +#endif + return ssl->cipher; + } + + return NULL; +} + +/* Get value of ssl_t member sid. */ +sslSessionId_t *matrixSslGetSid(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->sid is %p\n", (void*)(uintptr_t) (ssl->sid)); +#endif + return ssl->sid; + } + + return NULL; +} + +/* Get value of ssl_t member activeReadCipher. */ +const sslCipherSpec_t *matrixSslGetActiveReadCipher(const ssl_t *ssl) +{ +# ifdef USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->activeReadCipher is %p\n", (void*)(uintptr_t) (ssl->activeReadCipher)); +#endif + return ssl->activeReadCipher; + } +#endif /* USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE */ + + return NULL; +} + +/* Get value of ssl_t member activeWriteCipher. */ +const sslCipherSpec_t *matrixSslGetActiveWriteCipher(const ssl_t *ssl) +{ +# ifdef USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->activeWriteCipher is %p\n", (void*)(uintptr_t) (ssl->activeWriteCipher)); +#endif + return ssl->activeWriteCipher; + } +#endif /* USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE */ + + return NULL; +} + +/* Get value of ssl_t member flags. */ +uint32_t matrixSslGetFlags(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->flags is %p\n", (void*)(uintptr_t) (ssl->flags)); +#endif + return ssl->flags; + } + + return 0; +} + +/* Get value of ssl_t member hsState. */ +uint8_t matrixSslGetHsState(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->hsState is %p\n", (void*)(uintptr_t) (ssl->hsState)); +#endif + return ssl->hsState; + } + + return 0; +} + +/* Get value of ssl_t member decState. */ +uint8_t matrixSslGetDecState(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->decState is %p\n", (void*)(uintptr_t) (ssl->decState)); +#endif + return ssl->decState; + } + + return 0; +} + +/* Get value of ssl_t member encState. */ +uint8_t matrixSslGetEncState(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->encState is %p\n", (void*)(uintptr_t) (ssl->encState)); +#endif + return ssl->encState; + } + + return 0; +} + +#ifdef USE_ECC +/* Get value of ssl_t member ecInfo.ecFlags. */ +uint32 matrixSslGetEcInfoEcFlags(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->ecInfo.ecFlags is %p\n", (void*)(uintptr_t) (ssl->ecInfo.ecFlags)); +#endif + return ssl->ecInfo.ecFlags; + } + + return 0; +} + +/* Get value of ssl_t member ecInfo.ecCurveId. */ +uint32 matrixSslGetEcInfoEcCurveId(const ssl_t *ssl) +{ + if (ssl != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("ssl->ecInfo.ecCurveId is %p\n", (void*)(uintptr_t) (ssl->ecInfo.ecCurveId)); +#endif + return ssl->ecInfo.ecCurveId; + } + + return 0; +} +#endif + +/* Get value of sslCipherSpec_t member ident. */ +uint16_t matrixSslCipherSpecGetIdent(const sslCipherSpec_t *cipher) +{ + if (cipher != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cipher->ident is %p\n", (void*)(uintptr_t) (cipher->ident)); +#endif + return cipher->ident; + } + + return 0; +} + +/* Get value of sslCipherSpec_t member type. */ +uint16_t matrixSslCipherSpecGetType(const sslCipherSpec_t *cipher) +{ + if (cipher != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cipher->type is %p\n", (void*)(uintptr_t) (cipher->type)); +#endif + return cipher->type; + } + + return 0; +} + +/* Get value of sslCipherSpec_t member flags. */ +uint32_t matrixSslCipherSpecGetFlags(const sslCipherSpec_t *cipher) +{ + if (cipher != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cipher->flags is %p\n", (void*)(uintptr_t) (cipher->flags)); +#endif + return cipher->flags; + } + + return 0; +} + +/* Get value of sslCipherSpec_t member macSize. */ +uint8_t matrixSslCipherSpecGetMacSize(const sslCipherSpec_t *cipher) +{ + if (cipher != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cipher->macSize is %p\n", (void*)(uintptr_t) (cipher->macSize)); +#endif + return cipher->macSize; + } + + return 0; +} + +/* Get value of sslCipherSpec_t member keySize. */ +uint8_t matrixSslCipherSpecGetKeySize(const sslCipherSpec_t *cipher) +{ + if (cipher != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cipher->keySize is %p\n", (void*)(uintptr_t) (cipher->keySize)); +#endif + return cipher->keySize; + } + + return 0; +} + +/* Get value of sslCipherSpec_t member ivSize. */ +uint8_t matrixSslCipherSpecGetIvSize(const sslCipherSpec_t *cipher) +{ + if (cipher != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cipher->ivSize is %p\n", (void*)(uintptr_t) (cipher->ivSize)); +#endif + return cipher->ivSize; + } + + return 0; +} + +/* Get value of sslCipherSpec_t member blockSize. */ +uint8_t matrixSslCipherSpecGetBlockSize(const sslCipherSpec_t *cipher) +{ + if (cipher != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cipher->blockSize is %p\n", (void*)(uintptr_t) (cipher->blockSize)); +#endif + return cipher->blockSize; + } + + return 0; +} + +psSizeL_t matrixSslSessOptsSizeof(void) +{ + return (psSizeL_t)sizeof(sslSessOpts_t); +} + +void matrixSslSessOptsInit(sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { + /* Default initialization: all zeroized. */ + Memset(sessopts, 0, matrixSslSessOptsSizeof()); + } +} + +void matrixSslSessOptsUninit(sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { + /* Zeroize contents upon freeing. */ + Memset(sessopts, 0, matrixSslSessOptsSizeof()); + } +} + +void matrixSslSessOptsFree(sslSessOpts_t *sessopts) +{ + matrixSslSessOptsUninit(sessopts); + Free(sessopts); +} + +sslSessOpts_t *matrixSslSessOptsNew(void) +{ + sslSessOpts_t *sessopts; + + sessopts = Malloc(matrixSslSessOptsSizeof()); + matrixSslSessOptsInit(sessopts); + return sessopts; +} + +/* Get value of sslSessOpts_t member OCSPstapling. */ +short matrixSslSessOptsGetOCSPstapling(const sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sessopts->OCSPstapling is %p\n", (void*)(uintptr_t) (sessopts->OCSPstapling)); +#endif + return sessopts->OCSPstapling; + } + + return 0; +} + +/* Set value of sslSessOpts_t member OCSPstapling. */ +psRes_t matrixSslSessOptsSetOCSPstapling(sslSessOpts_t *sessopts, short value) +{ + psRes_t res = PS_ARG_FAIL; + + if (sessopts != NULL) + { + sessopts->OCSPstapling = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("sessopts->OCSPstapling=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of sslSessOpts_t member ecFlags. */ +int32 matrixSslSessOptsGetEcFlags(const sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sessopts->ecFlags is %p\n", (void*)(uintptr_t) (sessopts->ecFlags)); +#endif + return sessopts->ecFlags; + } + + return -1; +} + +/* Set value of sslSessOpts_t member ecFlags. */ +psRes_t matrixSslSessOptsSetEcFlags(sslSessOpts_t *sessopts, int32 value) +{ + psRes_t res = PS_ARG_FAIL; + + if (sessopts != NULL) + { + sessopts->ecFlags = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("sessopts->ecFlags=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of sslSessOpts_t member useExtCvSigOp. */ +int32 matrixSslSessOptsGetUseExtCvSigOp(const sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sessopts->useExtCvSigOp is %p\n", (void*)(uintptr_t) (sessopts->useExtCvSigOp)); +#endif + return sessopts->useExtCvSigOp; + } + + return -1; +} + +/* Set value of sslSessOpts_t member useExtCvSigOp. */ +psRes_t matrixSslSessOptsSetUseExtCvSigOp(sslSessOpts_t *sessopts, int32 value) +{ + psRes_t res = PS_ARG_FAIL; + + if (sessopts != NULL) + { + sessopts->useExtCvSigOp = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("sessopts->useExtCvSigOp=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of sslSessOpts_t member userPtr. */ +void *matrixSslSessOptsGetUserPtr(const sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sessopts->userPtr is %p\n", (void*)(uintptr_t) (sessopts->userPtr)); +#endif + return sessopts->userPtr; + } + + return NULL; +} + +/* Set value of sslSessOpts_t member userPtr. */ +psRes_t matrixSslSessOptsSetUserPtr(sslSessOpts_t *sessopts, void *value) +{ + psRes_t res = PS_ARG_FAIL; + + if (sessopts != NULL) + { + sessopts->userPtr = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("sessopts->userPtr=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of sslSessOpts_t member memAllocPtr. */ +void *matrixSslSessOptsGetMemAllocPtr(const sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sessopts->memAllocPtr is %p\n", (void*)(uintptr_t) (sessopts->memAllocPtr)); +#endif + return sessopts->memAllocPtr; + } + + return NULL; +} + +/* Set value of sslSessOpts_t member memAllocPtr. */ +psRes_t matrixSslSessOptsSetMemAllocPtr(sslSessOpts_t *sessopts, void *value) +{ + psRes_t res = PS_ARG_FAIL; + + if (sessopts != NULL) + { + sessopts->memAllocPtr = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("sessopts->memAllocPtr=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of sslSessOpts_t member bufferPool. */ +psPool_t *matrixSslSessOptsGetBufferPool(const sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sessopts->bufferPool is %p\n", (void*)(uintptr_t) (sessopts->bufferPool)); +#endif + return sessopts->bufferPool; + } + + return NULL; +} + +/* Set value of sslSessOpts_t member bufferPool. */ +psRes_t matrixSslSessOptsSetBufferPool(sslSessOpts_t *sessopts, psPool_t *value) +{ + psRes_t res = PS_ARG_FAIL; + + if (sessopts != NULL) + { + sessopts->bufferPool = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("sessopts->bufferPool=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of sslSessOpts_t member keep_peer_cert_der. */ +int32 matrixSslSessOptsGetKeepPeerCertDer(const sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sessopts->keep_peer_cert_der is %p\n", (void*)(uintptr_t) (sessopts->keep_peer_cert_der)); +#endif + return sessopts->keep_peer_cert_der; + } + + return -1; +} + +/* Set value of sslSessOpts_t member keep_peer_cert_der. */ +psRes_t matrixSslSessOptsSetKeepPeerCertDer(sslSessOpts_t *sessopts, int32 value) +{ + psRes_t res = PS_ARG_FAIL; + + if (sessopts != NULL) + { + sessopts->keep_peer_cert_der = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("sessopts->keep_peer_cert_der=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of sslSessOpts_t member keep_peer_certs. */ +int32 matrixSslSessOptsGetKeepPeerCerts(const sslSessOpts_t *sessopts) +{ + if (sessopts != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sessopts->keep_peer_certs is %p\n", (void*)(uintptr_t) (sessopts->keep_peer_certs)); +#endif + return sessopts->keep_peer_certs; + } + + return -1; +} + +/* Set value of sslSessOpts_t member keep_peer_certs. */ +psRes_t matrixSslSessOptsSetKeepPeerCerts(sslSessOpts_t *sessopts, int32 value) +{ + psRes_t res = PS_ARG_FAIL; + + if (sessopts != NULL) + { + sessopts->keep_peer_certs = value; + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("sessopts->keep_peer_certs=%p\n", (void*)(uintptr_t) (value)); +#endif + } + + return res; +} + +/* Get value of sslSessionId_t member id. */ +const unsigned char *matrixSslSessionIdGetId(const sslSessionId_t *sid) +{ + if (sid != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sid->id is %p\n", (void*)(uintptr_t) (sid->id)); +#endif + return sid->id; + } + + return NULL; +} + +/* Set value of sslSessionId_t member id. */ +psRes_t matrixSslSessionIdSetId(sslSessionId_t *sid, + const unsigned char *sessionId, + psSizeL_t sessionIdSize) +{ + psRes_t res = PS_ARG_FAIL; + + if (sid != NULL && sessionIdSize <= SSL_MAX_SESSION_ID_SIZE) + { + Memset(sid->id, 0, SSL_MAX_SESSION_ID_SIZE); + Memcpy(sid->id, sessionId, sessionIdSize); + res = PS_SUCCESS; +#ifdef MATRIX_LOG_SET + Printf("ssl->id=0x"); + { + psSizeL_t i; + + for(i = 0; i < sessionIdSize; i++) + { + Printf("%02x", sessionId[i]); + } + } + Printf("\n"); +#endif + } + + return res; +} + +/* Get value of sslSessionId_t member masterSecret. */ +const unsigned char *matrixSslSessionIdGetMasterSecret(const sslSessionId_t *sid) +{ + if (sid != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sid->masterSecret is %p\n", (void*)(uintptr_t) (sid->masterSecret)); +#endif + return sid->masterSecret; + } + + return NULL; +} + +/* Get value of sslSessionId_t member cipherId. */ +uint32 matrixSslSessionIdGetCipherId(const sslSessionId_t *sid) +{ + if (sid != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("sid->cipherId is %p\n", (void*)(uintptr_t) (sid->cipherId)); +#endif + return sid->cipherId; + } + + return 0; +} + +/* The following functions are for crypto library. */ + +# ifdef USE_X509 +# ifdef USE_CERT_PARSE +/* Get value of psX509Cert_t member pubKeyAlgorithm. */ +int32 psX509CertGetPubKeyAlgorithm(const psX509Cert_t *cert) +{ + if (cert != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cert->pubKeyAlgorithm is %p\n", (void*)(uintptr_t) (cert->pubKeyAlgorithm)); +#endif + return cert->pubKeyAlgorithm; + } + + return -1; +} + +/* Get value of psX509Cert_t member publicKey.keysize. */ +psSize_t psX509CertGetPubKeySize(const psX509Cert_t *cert) +{ + if (cert != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cert->publicKey.keysize is %p\n", (void*)(uintptr_t) (cert->publicKey.keysize)); +#endif + return cert->publicKey.keysize; + } + + return 0; +} + +/* Get value of psX509Cert_t member publicKey.type. */ +uint8_t psX509CertGetPubKeyType(const psX509Cert_t *cert) +{ + if (cert != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cert->publicKey.type is %p\n", (void*)(uintptr_t) (cert->publicKey.type)); +#endif + return cert->publicKey.type; + } + + return 0; +} +# endif /* USE_CERT_PARSE */ + +/* Get value of psX509Cert_t member sigAlgorithm. */ +int32 psX509CertGetSigAlgorithm(const psX509Cert_t *cert) +{ + if (cert != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cert->sigAlgorithm is %p\n", (void*)(uintptr_t) (cert->sigAlgorithm)); +#endif + return cert->sigAlgorithm; + } + + return -1; +} + +/* Get value of psX509Cert_t member certAlgorithm. */ +int32 psX509CertGetCertAlgorithm(const psX509Cert_t *cert) +{ + if (cert != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cert->certAlgorithm is %p\n", (void*)(uintptr_t) (cert->certAlgorithm)); +#endif + return cert->certAlgorithm; + } + + return -1; +} + +/* Get value of psX509Cert_t member unparsedBin. */ +unsigned char *psX509CertGetUnparsedBin(const psX509Cert_t *cert) +{ + if (cert != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cert->unparsedBin is %p\n", (void*)(uintptr_t) (cert->unparsedBin)); +#endif + return cert->unparsedBin; + } + + return NULL; +} + +/* Get value of psX509Cert_t member binLen. */ +psSize_t psX509CertGetBinLen(const psX509Cert_t *cert) +{ + if (cert != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cert->binLen is %p\n", (void*)(uintptr_t) (cert->binLen)); +#endif + return cert->binLen; + } + + return 0; +} + +/* Get value of psX509Cert_t member next. */ +psX509Cert_t *psX509CertGetNext(const psX509Cert_t *cert) +{ + if (cert != NULL) + { +#ifdef MATRIX_LOG_GET + Printf("cert->next is %p\n", (void*)(uintptr_t) (cert->next)); +#endif + return cert->next; + } + + return NULL; +} +# endif /* USE_X509 */ + +/******************************************************************************/ diff --git a/matrixssl/matrixsslGetSet.h b/matrixssl/matrixsslGetSet.h new file mode 100644 index 0000000..0c6cd3f --- /dev/null +++ b/matrixssl/matrixsslGetSet.h @@ -0,0 +1,194 @@ +/** + * @file matrixsslGetSet.h + * @version $Format:%h%d$ + * + * Add-on API for accessing MatrixSSL structures without direct access + * to structure members. Use of this API will slightly enlarge the + * MatrixSSL binary but will enable building software that is not + * dependent on exact binary layout of structures such as ssl_t. + */ + +/* + * Copyright (c) 2019 Verimatrix + * Copyright (c) 2013-2019 INSIDE Secure Corporation + * All Rights Reserved + * + * This file can be edited to modify exact set of accessor functions + * provided. + * + * The copyright notice above does not evidence any actual or intended + * publication of such source code. + * + * This Module contains Proprietary Information of INSIDE and should be + * treated as Confidential. + * + * The information in this file is provided for the exclusive use of the + * licensees of INSIDE. Such users have the right to use, modify, + * and incorporate this code into products for purposes authorized by the + * license agreement provided they include this notice and the associated + * copyright notice with any such product. + * + * The information in this file is provided "AS IS" without warranty. + */ + +#ifndef _h_MATRIXSSL_GETSET +# define _h_MATRIXSSL_GETSET + +# ifdef __cplusplus +extern "C" { +# endif + +#ifndef _h_MATRIXSSL +# include "matrixsslApi.h" +#endif /* _h_MATRIXSSL */ + + +void *matrixSslGetUserPtr(const ssl_t *ssl); +psRes_t matrixSslSetUserPtr(ssl_t *ssl, void *value); + +void *matrixSslGetUserDataPtr(const ssl_t *ssl); +psRes_t matrixSslSetUserDataPtr(ssl_t *ssl, void *value); + +# ifndef USE_ONLY_PSK_CIPHER_SUITE +# if defined(USE_IDENTITY_CERTIFICATES) || defined(USE_CERT_VALIDATE) +psX509Cert_t *matrixSslGetCerts(const ssl_t *ssl); +# endif /* USE_IDENTITY_CERTIFICATES */ +# endif /* USE_ONLY_PSK_CIPHER_SUITE */ + +const sslCipherSpec_t *matrixSslGetCipher(const ssl_t *ssl); + +sslSessionId_t *matrixSslGetSid(const ssl_t *ssl); + +const sslCipherSpec_t *matrixSslGetActiveReadCipher(const ssl_t *ssl); + +const sslCipherSpec_t *matrixSslGetActiveWriteCipher(const ssl_t *ssl); + +uint32_t matrixSslGetFlags(const ssl_t *ssl); + +uint8_t matrixSslGetHsState(const ssl_t *ssl); + +uint8_t matrixSslGetDecState(const ssl_t *ssl); + +uint8_t matrixSslGetEncState(const ssl_t *ssl); + +# ifdef USE_ECC +uint32 matrixSslGetEcInfoEcFlags(const ssl_t *ssl); + +uint32 matrixSslGetEcInfoEcCurveId(const ssl_t *ssl); +# endif + +uint16_t matrixSslCipherSpecGetIdent(const sslCipherSpec_t *cipher); + +uint16_t matrixSslCipherSpecGetType(const sslCipherSpec_t *cipher); + +uint32_t matrixSslCipherSpecGetFlags(const sslCipherSpec_t *cipher); + +uint8_t matrixSslCipherSpecGetMacSize(const sslCipherSpec_t *cipher); + +uint8_t matrixSslCipherSpecGetKeySize(const sslCipherSpec_t *cipher); + +uint8_t matrixSslCipherSpecGetIvSize(const sslCipherSpec_t *cipher); + +uint8_t matrixSslCipherSpecGetBlockSize(const sslCipherSpec_t *cipher); + +/* Dynamically allocate sslSessOpts_t. + */ +sslSessOpts_t *matrixSslSessOptsNew(void); + +/* Free dynamically allocated sslSessOpts_t. + */ +void matrixSslSessOptsFree(sslSessOpts_t *sessopts); + +/* Get size of sslSessOpts_t. + + It is recommended to use + sslSessOpts_t *matrixSslSessOptsNew() for allocation + of sslSessOpts_t. This function can be used + to implement alternative allocation + facilities, which do not use heap, + such as allocation via alloc(). +*/ +psSizeL_t matrixSslSessOptsSizeof(void); + +/* Initialize sslSessOpts_t. + + This function can be used to manually + initialize sslSessOpts_t. + It is recommended to use + sslSessOpts_t *matrixSslSessOptsNew() for allocation + and initialization. + */ +void matrixSslSessOptsInit(sslSessOpts_t *sessopts); + +/* Uninitialize sslSessOpts_t. + + This function can be used to manually + deinitialize sslSessOpts_t. + It is recommended to use + sslSessOpts_t *matrixSslSessOptsFree() for deallocation + including deinitialization. + */ +void matrixSslSessOptsUninit(sslSessOpts_t *sessopts); + +short matrixSslSessOptsGetOCSPstapling(const sslSessOpts_t *sessopts); +psRes_t matrixSslSessOptsSetOCSPstapling(sslSessOpts_t *sessopts, short value); + +int32 matrixSslSessOptsGetEcFlags(const sslSessOpts_t *sessopts); +psRes_t matrixSslSessOptsSetEcFlags(sslSessOpts_t *sessopts, int32 value); + +int32 matrixSslSessOptsGetUseExtCvSigOp(const sslSessOpts_t *sessopts); +psRes_t matrixSslSessOptsSetUseExtCvSigOp(sslSessOpts_t *sessopts, int32 value); + +void *matrixSslSessOptsGetUserPtr(const sslSessOpts_t *sessopts); +psRes_t matrixSslSessOptsSetUserPtr(sslSessOpts_t *sessopts, void *value); + +void *matrixSslSessOptsGetMemAllocPtr(const sslSessOpts_t *sessopts); +psRes_t matrixSslSessOptsSetMemAllocPtr(sslSessOpts_t *sessopts, void *value); + +psPool_t *matrixSslSessOptsGetBufferPool(const sslSessOpts_t *sessopts); +psRes_t matrixSslSessOptsSetBufferPool(sslSessOpts_t *sessopts, psPool_t *value); + +int32 matrixSslSessOptsGetKeepPeerCertDer(const sslSessOpts_t *sessopts); +psRes_t matrixSslSessOptsSetKeepPeerCertDer(sslSessOpts_t *sessopts, int32 value); + +int32 matrixSslSessOptsGetKeepPeerCerts(const sslSessOpts_t *sessopts); +psRes_t matrixSslSessOptsSetKeepPeerCerts(sslSessOpts_t *sessopts, int32 value); + +const unsigned char *matrixSslSessionIdGetId(const sslSessionId_t *sid); +psRes_t matrixSslSessionIdSetId(sslSessionId_t *sid, + const unsigned char *sessionId, + psSizeL_t sessionIdSize); + +const unsigned char *matrixSslSessionIdGetMasterSecret(const sslSessionId_t *sid); + +uint32 matrixSslSessionIdGetCipherId(const sslSessionId_t *sid); + +/* The following functions are for crypto library. */ + +# ifdef USE_X509 +# ifdef USE_CERT_PARSE +int32 psX509CertGetPubKeyAlgorithm(const psX509Cert_t *cert); + +psSize_t psX509CertGetPubKeySize(const psX509Cert_t *cert); + +uint8_t psX509CertGetPubKeyType(const psX509Cert_t *cert); +# endif /* USE_CERT_PARSE*/ + +int32 psX509CertGetSigAlgorithm(const psX509Cert_t *cert); + +int32 psX509CertGetCertAlgorithm(const psX509Cert_t *cert); + +unsigned char *psX509CertGetUnparsedBin(const psX509Cert_t *cert); + +psSize_t psX509CertGetBinLen(const psX509Cert_t *cert); + +psX509Cert_t *psX509CertGetNext(const psX509Cert_t *cert); +# endif /* USE_X509 */ + +# ifdef __cplusplus +} +# endif + +/******************************************************************************/ + +#endif /* _h_MATRIXSSL_GETSET */ diff --git a/matrixssl/matrixsslKeys.c b/matrixssl/matrixsslKeys.c index d5327f0..777b2cf 100644 --- a/matrixssl/matrixsslKeys.c +++ b/matrixssl/matrixsslKeys.c @@ -378,8 +378,10 @@ static psRes_t sslLoadKeyPair(psPool_t *pool, if (keydata == NULL || keydata_len == 0) { - psTraceInfo("slLoadKeyPair(): no key material"); - return PS_SUCCESS; + psTraceInfo("sslLoadKeyPair(): no key material"); + key->type = PS_NOKEY; + key->keysize = 0; + return PS_SUCCESS; } rc = psPemTryDecode(pool, keydata, @@ -597,6 +599,8 @@ matrixSslCreateIdentityFromData(sslKeys_t *keys, memset(&idkey, 0, sizeof(idkey)); + Memset(&idkey, 0, sizeof idkey); /* Zeroize idkey. */ + err = sslLoadCert(keys->pool, &idcert, cert, cert_len, opts); if (err < PS_SUCCESS) { @@ -888,6 +892,8 @@ int32 matrixSslLoadPkcs12Mem(sslKeys_t *keys, psPubKey_t idkey; sslIdentity_t *id; + Memset(&idkey, 0, sizeof idkey); /* Zeroize idkey. */ + if (keys == NULL) { return PS_ARG_FAIL; @@ -1377,6 +1383,10 @@ psRes_t matrixSslLoadKeys(sslKeys_t *keys, keytype = opts->key_type; } +# ifdef USE_ALWAYS_ALLOW_OUT_OF_DATE_CERT_PARSE + opts.flags |= LOAD_KEYS_OPT_ALLOW_OUT_OF_DATE_CERT_PARSE; +# endif + if (privFile == NULL) { keytype = 1; @@ -1384,7 +1394,7 @@ psRes_t matrixSslLoadKeys(sslKeys_t *keys, switch (keytype) { - case 1: /* RSA */ + case PS_RSA: rc = matrixSslLoadKeyMaterial(keys, certFile, privFile, @@ -1393,7 +1403,7 @@ psRes_t matrixSslLoadKeys(sslKeys_t *keys, PS_RSA, opts); break; - case 2: /* ECC */ + case PS_ECC: rc = matrixSslLoadKeyMaterial(keys, certFile, privFile, @@ -1402,7 +1412,7 @@ psRes_t matrixSslLoadKeys(sslKeys_t *keys, PS_ECC, opts); break; - case 3: /* ED25519 */ + case PS_ED25519: rc = matrixSslLoadKeyMaterial(keys, certFile, privFile, diff --git a/matrixssl/matrixsslNet.c b/matrixssl/matrixsslNet.c index 5ed1682..76cbfee 100644 --- a/matrixssl/matrixsslNet.c +++ b/matrixssl/matrixsslNet.c @@ -70,6 +70,7 @@ void matrixSslInteractBegin(matrixSslInteract_t *i, ssl_t *ssl, i->sock = sock; i->prev_rc = PS_SUCCESS; i->handshake_complete = PS_FALSE; + i->must_send = 0; } /* Adjust amount to read according to record header size or @@ -267,6 +268,12 @@ int32 matrixSslInteractInt3(matrixSslInteract_t *i, int block = 1; # endif /* USE_MATRIX_NET_DEBUG */ + /* If there is a write ongoing, resume it. */ + if (i->must_send) + { + goto must_send; + } + if (i->receive_buf && i->receive_len_left == 0) { /* Continuation of previous receive operation: */ @@ -344,6 +351,8 @@ int32 matrixSslInteractInt3(matrixSslInteract_t *i, if (can_send && i->send_len_left > 0) { int32 len; + + must_send: buf = i->send_buf; len = i->send_len_left; @@ -351,8 +360,10 @@ int32 matrixSslInteractInt3(matrixSslInteract_t *i, i->sock, buf, len < MATRIXSSL_INTERACT_MAX_TRANSFER ? len : MATRIXSSL_INTERACT_MAX_TRANSFER, 0); + i->must_send = 0; if (transferred == PS_EAGAIN) { + i->must_send = 1; return MATRIXSSL_REQUEST_SEND; } if (transferred < 0) @@ -370,6 +381,7 @@ int32 matrixSslInteractInt3(matrixSslInteract_t *i, i->send_len_left -= transferred; if (i->send_len_left > 0) { + i->must_send = 1; return MATRIXSSL_REQUEST_SEND; } rc = matrixSslSentData(i->ssl, (uint32) i->send_len); diff --git a/matrixssl/matrixsslNet.h b/matrixssl/matrixsslNet.h index 1d090ad..008ff8f 100644 --- a/matrixssl/matrixsslNet.h +++ b/matrixssl/matrixsslNet.h @@ -68,6 +68,7 @@ typedef struct matrixSslInteract loaded. */ size_t num_last_read_transferred; #endif + int must_send; /* send is ongoing. */ } matrixSslInteract_t; /* Lower-level API for interacting with MatrixSSL API. */ diff --git a/matrixssl/matrixssllib.h b/matrixssl/matrixssllib.h index 9c98053..81731fb 100644 --- a/matrixssl/matrixssllib.h +++ b/matrixssl/matrixssllib.h @@ -447,7 +447,8 @@ typedef enum psk_key_exchange_mode { psk_keyex_mode_none = 0, psk_keyex_mode_psk_ke = 1, - psk_keyex_mode_psk_dhe_ke = 2 + psk_keyex_mode_psk_dhe_ke = 2, + psk_keyex_mode_force_32_bits_datatype = 65537 /* Only for datatype size, the value is actually never used. */ } psk_key_exchange_mode_e; # ifdef USE_TLS_1_3 @@ -796,7 +797,7 @@ struct sslKeys /* SSL record and session structures */ -typedef struct +struct sslRec { unsigned short len; unsigned char majVer; @@ -814,9 +815,9 @@ typedef struct # endif unsigned char type; unsigned char pad[3]; /* Padding for 64 bit compat */ -} sslRec_t; +}; -typedef struct +struct sslSec { unsigned char clientRandom[SSL_HS_RANDOM_SIZE]; /* From ClientHello */ unsigned char serverRandom[SSL_HS_RANDOM_SIZE]; /* From ServerHello */ @@ -877,6 +878,7 @@ typedef struct psBool_t tls13ClientCookieOk; short tls13ExtendedMasterSecretOpt; + psBool_t tls13SentEcdheGroup; psTls13Psk_t *tls13SessionPskList; psTls13Psk_t *tls13ChosenPsk; @@ -1000,9 +1002,9 @@ typedef struct psPubKey_t *tls13KeyAgreeKeys[TLS_1_3_MAX_GROUPS]; # endif int32 anon; -} sslSec_t; +}; -typedef struct +struct sslCipherSpec { uint16_t ident; /* Official cipher ID */ uint16_t type; /* Key exchange method */ @@ -1022,7 +1024,7 @@ typedef struct uint32 len, unsigned char *mac); int32 (*verifyMac)(void *ssl, unsigned char type, unsigned char *data, uint32 len, unsigned char *mac); -} sslCipherSpec_t; +}; # ifdef USE_STATELESS_SESSION_TICKETS @@ -1045,6 +1047,7 @@ typedef struct sslSessionId { psPool_t *pool; unsigned char id[SSL_MAX_SESSION_ID_SIZE]; + psSize_t idLen; unsigned char masterSecret[SSL_HS_MASTER_SIZE]; uint32 cipherId; # ifdef USE_STATELESS_SESSION_TICKETS @@ -1370,6 +1373,13 @@ struct ssl int32 rehandshakeBytes; /* Make this an internal define of 10MB */ # endif /* SSL_REHANDSHAKES_ENABLED */ +# ifdef USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS + unsigned char myFinished[36]; /* SSL 3.0 uses 36 bytes, TLS 12 bytes. */ + psSizeL_t myFinishedLen; + unsigned char peerFinished[36]; + psSizeL_t peerFinishedLen; +# endif + # ifdef USE_ECC struct { @@ -1379,7 +1389,7 @@ struct ssl # endif # ifdef USE_TLS_1_2 uint16_t hashSigAlg; - uint16_t serverSigAlgs; + uint16_t peerSigAlg; # endif /* USE_TLS_1_2 */ # ifdef USE_DTLS @@ -1604,7 +1614,7 @@ int32_t matrixSslGenEphemeralEcKey( # ifdef USE_TLS_1_3 static inline -psBool_t tls13IsResumedHandshake(ssl_t *ssl) +psBool_t tls13IsResumedHandshake(const ssl_t *ssl) { if (ssl->sec.tls13UsingPsk && ssl->sec.tls13ChosenPsk && @@ -1620,7 +1630,7 @@ psBool_t tls13IsResumedHandshake(ssl_t *ssl) # endif /* USE_TLS_1_3 */ static inline -psBool_t isResumedHandshake(ssl_t *ssl) +psBool_t isResumedHandshake(const ssl_t *ssl) { # ifdef USE_TLS_1_3 if (NGTD_VER(ssl, v_tls_1_3_any)) @@ -2548,6 +2558,10 @@ void psPrintSigAlgs(psSize_t indentLevel, const char *where, uint16_t sigAlgs, psBool_t addNewline); +void psPrintMatrixSigAlg(psSize_t indentLevel, + const char *where, + int32_t alg, + psBool_t addNewline); void psPrintTls13SigAlg(psSize_t indentLevel, const char *where, uint16_t alg, @@ -2647,8 +2661,10 @@ void psPrintTranscriptHashUpdate(ssl_t *ssl, psPrintEncodedCipherList(indentLevel, where, cipherList, cipherListLen, addNewline) # define psTracePrintCipherList(indentLevel, where, cipherList, numCiphers, addNewline) \ psPrintCipherList(indentLevel, where, cipherList, numCiphers, addNewline) -# define psTracePrintSigAlgs(indentLevel, sigAlgs, where, addNewline) \ - psPrintSigAlgs(indentLevel, sigAlgs, where, addNewline) +# define psTracePrintSigAlgs(indentLevel, where, sigAlgs, addNewline) \ + psPrintSigAlgs(indentLevel, where, sigAlgs, addNewline) +# define psTracePrintMatrixSigAlg(indentLevel, where, alg, addNewline) \ + psPrintMatrixSigAlg(indentLevel, where, alg, addNewline) # define psTracePrintPubKeyTypeAndSize(ssl, key) \ psPrintPubKeyTypeAndSize(ssl, key) # define psTracePrintTls13SigAlg(indentLevel, where, alg, bigEndian, addNewline) \ @@ -2702,7 +2718,8 @@ void psPrintTranscriptHashUpdate(ssl_t *ssl, # define psTracePrintCiphersuiteName(indentLevel, where, cipher, addNewline) # define psTracePrintEncodedCipherList(indentLevel, where, cipherList, cipherListLen, addNewline) # define psTracePrintCipherList(indentLevel, where, cipherList, numCiphers, addNewline) -# define psTracePrintSigAlgs(indentlevel, sigAlgs, where, addNewLine) +# define psTracePrintSigAlgs(indentlevel, where, sigAlgs, addNewLine) +# define psTracePrintMatrixSigAlg(indentLevel, where, alg, addNewline) # define psTracePrintPubKeyTypeAndSize(ssl, key) # define psTracePrintTls13SigAlg(indentLevel, where, sigAlg, bigEndian, addNewline) # define psTracePrintTls13SigAlgList(indentLevel, where, algs, numAlg, addNewline) diff --git a/matrixssl/matrixssllib_version.h b/matrixssl/matrixssllib_version.h index 8cc619d..6215986 100644 --- a/matrixssl/matrixssllib_version.h +++ b/matrixssl/matrixssllib_version.h @@ -298,7 +298,8 @@ psProtocolVersion_t psFlagToVer(int32_t flag); backwards compatibility. The version flags are translated to MatrixSSL internal IDs during session configuration. */ /** Any version flag. */ -# define ANY_VERSION_FLAG \ +# ifdef USE_TLS_1_3_DRAFT_SPEC +# define ANY_VERSION_FLAG \ (SSL_FLAGS_TLS_1_0 \ | SSL_FLAGS_TLS_1_1 \ | SSL_FLAGS_TLS_1_2 \ @@ -309,5 +310,12 @@ psProtocolVersion_t psFlagToVer(int32_t flag); | SSL_FLAGS_TLS_1_3_DRAFT_26 \ | SSL_FLAGS_TLS_1_3_DRAFT_28 \ | SSL_FLAGS_DTLS) - +# else +# define ANY_VERSION_FLAG \ + (SSL_FLAGS_TLS_1_0 \ + | SSL_FLAGS_TLS_1_1 \ + | SSL_FLAGS_TLS_1_2 \ + | SSL_FLAGS_TLS_1_3 \ + | SSL_FLAGS_DTLS) +# endif #endif /* _h_MATRIXSSLLIB_VERSION */ diff --git a/matrixssl/sslDecode.c b/matrixssl/sslDecode.c index 10b6487..11ea845 100644 --- a/matrixssl/sslDecode.c +++ b/matrixssl/sslDecode.c @@ -60,26 +60,6 @@ static int32 parseSingleCert(ssl_t *ssl, unsigned char *c, unsigned char *end, int32 certLen); #endif /* USE_CERT_CHAIN_PARSING */ -static inline -psResSize_t parseSslv2RecordHdr(ssl_t *ssl, - unsigned char *c) -{ -#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; - return PS_SUCCESS; -#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; - psTraceErrr("SSLv2 records not supported\n"); - return MATRIXSSL_ERROR; -#endif -} - static inline psRes_t validateRecordHdrType(ssl_t *ssl) { @@ -215,6 +195,49 @@ psRes_t validateRecordHdrLen(ssl_t *ssl) return MATRIXSSL_SUCCESS; } +# ifdef ALLOW_SSLV2_CLIENT_HELLO_PARSE +static inline +psBool_t isSslv2ClientHelloRecord(ssl_t *ssl, + unsigned char *c, + unsigned char *end) +{ + /* + Conditions for accepting an SSL 2.0 record: + - A. It must be an SSL 2.0 ClientHello record. + - B. It must conform to E.2. of RFC 5246. + - C. We must be in the initial handshake state with no protocol + negotiated yet. + + Note that (*c & 0x80) will never be true for TLS 1.0 or later, + because none of the valid record types has the high bit set. + */ + if ((end - c >= 3) + /* Conditions A & B: */ + && (*c & 0x80) && (*(c+2) == 1) + /* Condition C: */ + && ssl->hsState == SSL_HS_CLIENT_HELLO + && !VersionNegotiationComplete(ssl)) + { + return PS_TRUE; + } + + return PS_FALSE; +} + +static inline +psResSize_t handleSslv2Record(ssl_t *ssl, + unsigned char *c) +{ + ssl->rec.type = SSL_RECORD_TYPE_HANDSHAKE; + ssl->rec.majVer = SSL2_MAJ_VER; + ssl->rec.minVer = 0; + ssl->rec.len = (*c & 0x7f) << 8; c++; + ssl->rec.len += *c; + + return 2; +} +# endif /* ALLOW_SSLV2_CLIENT_HELLO_PARSE */ + /** Parse and validate a record header. Returns the number of bytes parsed or < 0 on error. */ static inline @@ -227,15 +250,12 @@ psResSize_t handleRecordHdr(ssl_t *ssl, unsigned char *orig_c = c; psRes_t res; - if ((*c & 0x80) && (GET_NGTD_VER(ssl) == v_undefined)) +# ifdef ALLOW_SSLV2_CLIENT_HELLO_PARSE + if (isSslv2ClientHelloRecord(ssl, c, end)) { - res = parseSslv2RecordHdr(ssl, c); - if (res < 0) - { - return res; - } - c += 2; + return handleSslv2Record(ssl, c); } +# endif psAssert(ssl->recordHeadLen == SSL3_HEADER_LEN || ssl->recordHeadLen == DTLS_HEADER_LEN); @@ -352,8 +372,6 @@ int32 matrixSslDecode(ssl_t *ssl, unsigned char *alertLevel, unsigned char *alertDescription) { - int32_t rc = PS_FAILURE; - *error = PS_SUCCESS; /* If we've had a protocol error, don't allow further use of the session */ @@ -367,6 +385,7 @@ int32 matrixSslDecode(ssl_t *ssl, # ifdef USE_TLS_1_3 if (ACTV_VER(ssl, v_tls_1_3_any)) { + int32_t rc = PS_FAILURE; rc = matrixSslDecodeTls13(ssl, buf, len, @@ -1121,48 +1140,66 @@ ADVANCE_TO_APP_DATA: */ if (ssl->deBlockSize > 1) { - /* Run this helper regardless of error status thus far */ - (void) addCompressCount(ssl, padLen); + unsigned char tmp[128]; + psDigestContext_t md; + + /* set up the hash independent of the padding status */ + switch (ssl->deMacSize) + { +# ifdef USE_SHA256 + case SHA256_HASH_SIZE: + psSha256PreInit(&md.u.sha256); + break; +# endif +# ifdef USE_SHA384 + case SHA384_HASH_SIZE: + psSha384PreInit(&md.u.sha384); + psSha384Init(&md.u.sha384); + break; +# endif +# ifdef USE_SHA1 + case SHA1_HASH_SIZE: + psSha1PreInit(&md.u.sha1); + psSha1Init(&md.u.sha1); + break; +# endif + default: + psAssert(0); + break; + } + + rc = addCompressCount(ssl, padLen); + /* Perform a an update on the padding that is not cut off in case of a padding error */ if (macError == 0) { - psDigestContext_t md; - unsigned char tmp[128]; switch (ssl->deMacSize) { # ifdef USE_SHA256 case SHA256_HASH_SIZE: - psSha256PreInit(&md.u.sha256); psSha256Init(&md.u.sha256); while (rc > 0) { psSha256Update(&md.u.sha256, tmp, 64); rc--; } - psSha256Final(&md.u.sha256, tmp); break; # endif # ifdef USE_SHA384 case SHA384_HASH_SIZE: - psSha384PreInit(&md.u.sha384); - psSha384Init(&md.u.sha384); while (rc > 0) { psSha384Update(&md.u.sha384, tmp, 128); rc--; } - psSha384Final(&md.u.sha384, tmp); break; # endif # ifdef USE_SHA1 case SHA1_HASH_SIZE: - psSha1PreInit(&md.u.sha1); - psSha1Init(&md.u.sha1); while (rc > 0) { psSha1Update(&md.u.sha1, tmp, 64); rc--; } - psSha1Final(&md.u.sha1, tmp); break; # endif default: @@ -1170,6 +1207,31 @@ ADVANCE_TO_APP_DATA: break; } } + + /* Finish the hash independent of the padding status. Not necessary to thwart the timing side channel + but it could free the resources if necessary */ + switch (ssl->deMacSize) + { +# ifdef USE_SHA256 + case SHA256_HASH_SIZE: + psSha256Final(&md.u.sha256, tmp); + break; +# endif +# ifdef USE_SHA384 + case SHA384_HASH_SIZE: + psSha384Final(&md.u.sha384, tmp); + break; +# endif +# ifdef USE_SHA1 + case SHA1_HASH_SIZE: + psSha1Final(&md.u.sha1, tmp); + break; +# endif + default: + psAssert(0); + break; + } + } #endif /* LUCKY13 */ @@ -2303,7 +2365,7 @@ hsStateDetermined: if (ssl->hsState == SSL_HS_CLIENT_HELLO) { /* This is for Client Hello. - Note: "Client Hello" is determined according to + Note: *Client Hello* is determined according to expected state of server, rather than examining of the message. Therefore, this limit applies to any first protocol handshake message received. */ @@ -2334,7 +2396,8 @@ hsStateDetermined: /* The (fragmented) packet is considered overly large and dropped. */ ssl->err = SSL_ALERT_DECODE_ERROR; - psTraceInt("Maximum length exceeded (%d)\n", (int) hsLenMax); + psTraceErrr("Maximum length exceeded.\n"); + psTraceIntInfo("%d\n", (int) hsLen); return MATRIXSSL_ERROR; } #ifdef USE_DTLS @@ -2436,7 +2499,7 @@ hsStateDetermined: (int) hsLen); return MATRIXSSL_ERROR; } - + /* Need to save the hs header info aside as well so that we may pass the fragments through the handshake hash mechanism in diff --git a/matrixssl/sslEncode.c b/matrixssl/sslEncode.c index bcf3125..7cf8b1b 100644 --- a/matrixssl/sslEncode.c +++ b/matrixssl/sslEncode.c @@ -2474,6 +2474,10 @@ int32_t processFinished(ssl_t *ssl, flightEncode_t *msg) Memcpy(ssl->myVerifyData, ssl->delayHsHash, rc); ssl->myVerifyDataLen = rc; # endif /* ENABLE_SECURE_REHANDSHAKES */ +# ifdef USE_RFC5929_TLS_UNIQUE_CHANNEL_BINDINGS + Memcpy(ssl->myFinished, ssl->delayHsHash, rc); + ssl->myFinishedLen = rc; +# endif } /* End SSL_HS_FINISHED processing */ return PS_SUCCESS; @@ -3709,6 +3713,7 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) /* This empty extension is ALWAYS an indication to the client that a NewSessionTicket handshake message will be sent */ psTracePrintExtensionCreate(ssl, EXT_SESSION_TICKET); + psTraceInfoIndent(INDENT_EXTENSION, "(empty extension)\n"); *c = (EXT_SESSION_TICKET & 0xFF00) >> 8; c++; *c = EXT_SESSION_TICKET & 0xFF; c++; *c = 0; c++; @@ -3720,6 +3725,7 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out) if (ssl->extFlags.sni && ssl->extFlags.sni_in_last_client_hello) { psTracePrintExtensionCreate(ssl, EXT_SNI); + psTraceInfoIndent(INDENT_EXTENSION, "(empty extension)\n"); *c = (EXT_SNI & 0xFF00) >> 8; c++; *c = EXT_SNI & 0xFF; c++; *c = 0; c++; @@ -5834,6 +5840,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, ssl->sid->sessionTicketState != SESS_TICKET_STATE_USING_TICKET) { psTracePrintExtensionCreate(ssl, EXT_SESSION_TICKET); + psTraceInfoIndent(INDENT_EXTENSION, "(empty extension)\n"); ssl->extFlags.req_session_ticket = 1; *c = (EXT_SESSION_TICKET & 0xFF00) >> 8; c++; *c = EXT_SESSION_TICKET & 0xFF; c++; @@ -5844,6 +5851,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out, else { psTracePrintExtensionCreate(ssl, EXT_SESSION_TICKET); + psTraceInfoIndent(INDENT_EXTENSION, "(contains ticket)\n"); ssl->extFlags.req_session_ticket = 1; *c = (EXT_SESSION_TICKET & 0xFF00) >> 8; c++; *c = EXT_SESSION_TICKET & 0xFF; c++; @@ -7169,7 +7177,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out) in parseCertificateRequest that the server supports that. */ sigAlg = chooseSigAlg(chosen->cert, &chosen->privKey, - ssl->serverSigAlgs); + ssl->peerSigAlg); if (sigAlg <= 0) { psTraceErrr("Need more hash support for certVerify\n"); diff --git a/matrixssl/tls.c b/matrixssl/tls.c index adf1f85..90a00a7 100644 --- a/matrixssl/tls.c +++ b/matrixssl/tls.c @@ -55,6 +55,10 @@ /*# define DEBUG_TLS_LOG_SECRETS */ # endif +# ifdef DEBUG_TLS_LOG_SECRETS +# warning "Do NOT enable DEBUG_TLS_LOG_SECRETS in production builds" +# endif + static int32_t genKeyBlock(ssl_t *ssl) { unsigned char msSeed[SSL_HS_RANDOM_SIZE * 2 + LABEL_SIZE]; @@ -164,8 +168,18 @@ static int32_t genKeyBlock(ssl_t *ssl) # endif } + rc = SSL_HS_MASTER_SIZE; +# ifdef DEBUG_TLS_LOG_SECRETS + psTraceBytes("ssl->sec.masterSecret", + ssl->sec.masterSecret, + SSL_HS_MASTER_SIZE); + psTraceBytes("ssl->sec.keyBlock", + ssl->sec.keyBlock, + reqKeyLen); +# endif + L_RETURN: memzero_s(msSeed, sizeof(msSeed)); if (rc < 0) diff --git a/matrixssl/tls13CipherSuite.c b/matrixssl/tls13CipherSuite.c index 7cd3310..484e9af 100644 --- a/matrixssl/tls13CipherSuite.c +++ b/matrixssl/tls13CipherSuite.c @@ -94,9 +94,47 @@ void tls13MakeDecryptAad(ssl_t *ssl, unsigned char aadOut[5]) aadOut[4] = (ssl->rec.len & 0xff); } +#ifdef CL_EncryptAuthTls13 + +/* Allocate and load Key and State Assets from CL local storage, so + that this application doesn't have to care about memory + management. */ +static CL_RV tls13_aesgcm_assets(psAesGcm_t *gcm) +{ + CL_AssetAllocateExInfo_t exinfo = {0}; + CL_RV rv; + + exinfo.flags |= CL_ASSET_ALLOCATE_EX_LOCAL; + rv = CL_AssetAllocateEx((CL_ALLOCATE_EXTRA_POLICY | + CL_POLICY_ALGO_GCM_AES_ENCRYPT | + CL_POLICY_ALGO_GCM_AES_DECRYPT), + gcm->keylength, &exinfo, &gcm->multipart_gcm_key); + if (rv == CLR_OK) + { + rv = CL_AssetLoadValue(gcm->multipart_gcm_key, gcm->key, gcm->keylength); + } + if (rv == CLR_OK) + { + rv = CL_AssetAllocateEx((CL_ALLOCATE_EXTRA_POLICY | + CL_POLICY_FLAG_TEMPORARY | + CL_POLICY_FLAG_EXPORTABLE), + CL_ASSET_STATE_MIN_LENGTH, &exinfo, &gcm->multipart_gcm_state); + } + if (rv != CLR_OK) + { + CL_AssetFree(gcm->multipart_gcm_key); + CL_AssetFree(gcm->multipart_gcm_state); + } + return rv; +} +#endif + int32 csAesGcmInitTls13(sslSec_t *sec, int32 type, uint32 keysize) { - int32 err; + int32 err = 0; +#ifdef CL_EncryptAuthTls13 + psAesGcm_t *gcm; +#endif if (type == INIT_ENCRYPT_CIPHER) { @@ -106,6 +144,14 @@ int32 csAesGcmInitTls13(sslSec_t *sec, int32 type, uint32 keysize) { return err; } +#ifdef CL_EncryptAuthTls13 + gcm = &sec->encryptCtx.aesgcm; + gcm->algo = CL_ALGO_GCM_AES_ENCRYPT; + gcm->tlsInfo = CL_Tls13ContextNew(); + CL_Tls13ContextSetWriteIv(gcm->tlsInfo, sec->tls13WriteIv); + CL_Tls13ContextSetSeq(gcm->tlsInfo, sec->seq); + err = tls13_aesgcm_assets(gcm) != CLR_OK; +#endif } else { @@ -115,10 +161,128 @@ int32 csAesGcmInitTls13(sslSec_t *sec, int32 type, uint32 keysize) { return err; } +#ifdef CL_EncryptAuthTls13 + gcm = &sec->decryptCtx.aesgcm; + gcm->algo = CL_ALGO_GCM_AES_DECRYPT; + gcm->tlsInfo = CL_Tls13ContextNew(); + CL_Tls13ContextSetWriteIv(gcm->tlsInfo, sec->tls13ReadIv); + CL_Tls13ContextSetSeq(gcm->tlsInfo, sec->remSeq); + err = tls13_aesgcm_assets(gcm) != CLR_OK; +#endif + } - return 0; + return err; } +static inline void psAesIncrSec(unsigned char *seq) +{ + int i; + + for (i = (TLS_AEAD_SEQNB_LEN - 1); i >= 0; i--) + { + seq[i]++; + if (seq[i] != 0) + { + break; + } + } +} + +#ifdef CL_EncryptAuthTls13 + +/* XXX: consider dispatching here based on underlying FL version. See + TODO above. */ + +psResSize_t csAesGcmEncryptTls13(void *pssl, + unsigned char *pt, unsigned char *ct, + uint32 ptLen) +{ + ssl_t *ssl = pssl; + psAesGcm_t *gcm; + CL_DataOutPtr_t tag = ct + ptLen; + CL_DataLen_t tagLen = 16; + CL_DataLen_t aadLen = 5; + unsigned char aadBuf[5]; + CL_DataInPtr_t aad = (CL_DataInPtr_t)aadBuf; + CL_RV rv; + + gcm = &ssl->sec.encryptCtx.aesgcm; + + tls13MakeEncryptAad(ssl, aadBuf); + rv = CLS_EncryptAuthTls13(flps_getCLS(), + gcm->multipart_gcm_key, + gcm->multipart_gcm_state, + gcm->tlsInfo, + gcm->algo, + aad, aadLen, + pt, ptLen, + ct, + tag, tagLen); + if (rv == CLR_OK) + { + /* encrypted; commit to packet, increment sequence (the encrypt did that for tlsInfo) */ + /* XXX: maybe copy out the tlsInfo ... */ + psAesIncrSec(ssl->sec.seq); + psAssert(memcmp(ssl->sec.seq, gcm->tlsInfo->Seq, 8) == 0); + } + return rv == CLR_OK ? ptLen : PS_FAILURE; +} + +/* inLen includes tag */ +psResSize_t csAesGcmDecryptTls13(void *pssl, + unsigned char *ct, unsigned char *pt, + uint32 inLen) +{ + ssl_t *ssl = pssl; + psAesGcm_t *gcm; + CL_DataOutPtr_t tag; + CL_DataLen_t tagLen = 16; + unsigned char aadBuf[5]; + CL_DataInPtr_t aad = (CL_DataInPtr_t)aadBuf; + CL_DataLen_t aadLen = 5; + CL_RV rv; + ssize_t ptLen; + + ptLen = (inLen - tagLen); + if (ptLen <= 0) + { + return PS_LIMIT_FAIL; + } + + tag = ct + ptLen; + gcm = &ssl->sec.decryptCtx.aesgcm; + + if (!USING_TLS_1_3_AAD(ssl)) + { + aadLen = 0; + aad = NULL; + } + else + { + tls13MakeDecryptAad(ssl, aadBuf); + } + /* Assume the caller has already verified ssl->sec.seq == ssl->sec.remSeq */ + psAssert(memcmp(ssl->sec.remSeq, gcm->tlsInfo->Seq, 8) == 0); + rv = CLS_DecryptAuthTls13(flps_getCLS(), + gcm->multipart_gcm_key, + gcm->multipart_gcm_state, + gcm->tlsInfo, + gcm->algo, + aad, aadLen, + ct, ptLen, + tag, tagLen, + pt); + + if (rv == CLR_OK) + { + /* OK, commit to packet, increment sequence (the decrypt did that for tlsInfo) */ + psAesIncrSec(ssl->sec.remSeq); + psAssert(memcmp(ssl->sec.remSeq, gcm->tlsInfo->Seq, 8) == 0); + } + return rv == CLR_OK ? ptLen : PS_FAILURE; +} +#else /* CL_EncryptAuthTls13 */ + int32 csAesGcmEncryptTls13(void *ssl, unsigned char *pt, unsigned char *ct, uint32 ptLen) { @@ -126,7 +290,6 @@ int32 csAesGcmEncryptTls13(void *ssl, unsigned char *pt, psAesGcm_t *ctx; unsigned char nonce[12]; unsigned char aad[5]; - int32 i; if (ptLen == 0) { @@ -151,14 +314,7 @@ int32 csAesGcmEncryptTls13(void *ssl, unsigned char *pt, psAesGetGCMTag(ctx, 16, ct + ptLen); /* Normally HMAC would increment the sequence */ - for (i = 7; i >= 0; i--) - { - lssl->sec.seq[i]++; - if (lssl->sec.seq[i] != 0) - { - break; - } - } + psAesIncrSec(lssl->sec.seq); #ifdef DEBUG_TLS_1_3_GCM psTraceBytes("csAesGcmEncryptTls13 output with tag", ct, @@ -174,7 +330,7 @@ int32 csAesGcmDecryptTls13(void *ssl, unsigned char *ct, { ssl_t *lssl = ssl; psAesGcm_t *ctx; - int32 i, ctLen, bytes; + int32 ctLen, bytes; unsigned char nonce[12]; unsigned char aad[5]; @@ -203,14 +359,7 @@ int32 csAesGcmDecryptTls13(void *ssl, unsigned char *ct, { return -1; } - for (i = 7; i >= 0; i--) - { - lssl->sec.remSeq[i]++; - if (lssl->sec.remSeq[i] != 0) - { - break; - } - } + psAesIncrSec(lssl->sec.remSeq); #ifdef DEBUG_TLS_1_3_GCM psTraceBytes("csAesGcmDecryptTls13 output with tag", ct, @@ -220,6 +369,7 @@ int32 csAesGcmDecryptTls13(void *ssl, unsigned char *ct, return bytes; } +#endif /* CL_EncryptAuthTls13 */ #if defined(USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE) || defined(USE_CHACHA20_POLY1305_IETF) int32 csChacha20Poly1305IetfEncryptTls13(void *ssl, unsigned char *pt, @@ -229,7 +379,7 @@ int32 csChacha20Poly1305IetfEncryptTls13(void *ssl, unsigned char *pt, psChacha20Poly1305Ietf_t *ctx; unsigned char nonce[TLS_AEAD_NONCE_MAXLEN]; unsigned char aad[5]; - int32 i, ptLen; + int32 ptLen; if (len == 0) { @@ -279,14 +429,7 @@ int32 csChacha20Poly1305IetfEncryptTls13(void *ssl, unsigned char *pt, # endif /* Normally HMAC would increment the sequence */ - for (i = (TLS_AEAD_SEQNB_LEN - 1); i >= 0; i--) - { - lssl->sec.seq[i]++; - if (lssl->sec.seq[i] != 0) - { - break; - } - } + psAesIncrSec(lssl->sec.seq); return len; } @@ -295,7 +438,7 @@ int32 csChacha20Poly1305IetfDecryptTls13(void *ssl, unsigned char *ct, { ssl_t *lssl = ssl; psChacha20Poly1305Ietf_t *ctx; - int32 i, bytes; + int32 bytes; # ifdef DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE int32 ctLen; # endif @@ -352,15 +495,7 @@ int32 csChacha20Poly1305IetfDecryptTls13(void *ssl, unsigned char *ct, # endif return -1; } - - for (i = (TLS_AEAD_SEQNB_LEN - 1); i >= 0; i--) - { - lssl->sec.remSeq[i]++; - if (lssl->sec.remSeq[i] != 0) - { - break; - } - } + psAesIncrSec(lssl->sec.remSeq); return bytes + TLS_CHACHA20_POLY1305_IETF_TAG_LEN; } diff --git a/matrixssl/tls13Decode.c b/matrixssl/tls13Decode.c index 7a8760a..f5d23e4 100644 --- a/matrixssl/tls13Decode.c +++ b/matrixssl/tls13Decode.c @@ -416,6 +416,7 @@ parse_next_record_header: /* Deal with the decrypted message. */ if (innerType == SSL_RECORD_TYPE_HANDSHAKE) { + unsigned char *p_start = p; end = p + ptLen; /* Parse handshake messages until buffer runs out */ while (p != end) @@ -445,6 +446,12 @@ parse_next_record_header: * Either handshake message or alert */ goto encodeResponse; } + /* If we got a parse return of >= 0 but p did not move forward, + * return an error to avoid infinite loop */ + if (p_start == p) + { + return PS_FAILURE; + } } } else if (innerType == SSL_RECORD_TYPE_APPLICATION_DATA) @@ -1871,6 +1878,13 @@ static int32_t tls13ParseCertificateVerify(ssl_t *ssl, ssl->err = SSL_ALERT_HANDSHAKE_FAILURE; return PS_PARSE_FAIL; } + + psTracePrintTls13SigAlg(INDENT_HS_MSG, + "algorithm", + algorithm, + PS_FALSE, + PS_TRUE); + /* Make sure the algorithm is on our supported list */ if (findFromUint16Array(ssl->supportedSigAlgs, ssl->supportedSigAlgsLen, @@ -1882,12 +1896,6 @@ static int32_t tls13ParseCertificateVerify(ssl_t *ssl, return MATRIXSSL_ERROR; } - psTracePrintTls13SigAlg(INDENT_HS_MSG, - "algorithm", - algorithm, - PS_FALSE, - PS_TRUE); - ssl->sec.tls13PeerCvSigAlg = algorithm; rc = psParseBufTryParseBigEndianUint16(pb, diff --git a/matrixssl/tls13DecodeExt.c b/matrixssl/tls13DecodeExt.c index 105ad82..4f8c027 100644 --- a/matrixssl/tls13DecodeExt.c +++ b/matrixssl/tls13DecodeExt.c @@ -372,7 +372,8 @@ int32_t tls13ParseSingleExtension(ssl_t *ssl, rc = tls13ParseSignatureAlgorithms(ssl, (const unsigned char **)&extDataBuf.buf.start, extDataLen, - (hsMsgType == SSL_HS_CERTIFICATE) ? PS_TRUE : PS_FALSE); + (extType == EXT_SIGNATURE_ALGORITHMS_CERT) ? \ + PS_TRUE : PS_FALSE); if (rc < 0) { return rc; @@ -2011,6 +2012,8 @@ int32_t tls13ParseServerHelloExtensions(ssl_t *ssl, psParseBuf_t extBuf, extDataBuf; psBool_t gotSupportedVersions = PS_FALSE; psBool_t gotForbiddenExtension = PS_FALSE; + psBool_t gotKeyShare = PS_FALSE; + psBool_t gotPreSharedKey = PS_FALSE; /* Minimum length is 0 for the vector here since this could still be < TLS1.3 ServerHello which might not have extensions. @@ -2084,6 +2087,7 @@ int32_t tls13ParseServerHelloExtensions(ssl_t *ssl, { return rc; } + gotKeyShare = PS_TRUE; break; # endif case EXT_PRE_SHARED_KEY: @@ -2092,6 +2096,7 @@ int32_t tls13ParseServerHelloExtensions(ssl_t *ssl, { return rc; } + gotPreSharedKey = PS_TRUE; break; case EXT_SUPPORTED_VERSIONS: rc = tls13ParseServerSupportedVersions(ssl, &extDataBuf); @@ -2116,6 +2121,11 @@ int32_t tls13ParseServerHelloExtensions(ssl_t *ssl, pb->buf.start = extBuf.buf.start; + if (!gotKeyShare) + { + ssl->sec.tls13ChosenPskMode = psk_keyex_mode_psk_ke; + } + if (!gotSupportedVersions) { ssl->hsState = SSL_HS_SERVER_HELLO; @@ -2134,6 +2144,13 @@ int32_t tls13ParseServerHelloExtensions(ssl_t *ssl, goto out_illegal_parameter; } + if (!gotKeyShare && !gotPreSharedKey) + { + psTraceErrr("Error: no key_share or pre_shared_key " \ + "in TLS 1.3 ServerHello\n"); + goto out_illegal_parameter; + } + if (ssl->tls13IncorrectDheKeyShare) { /* This was a HelloRetryRequest. Need to trigger sending of diff --git a/matrixssl/tls13EncodeExt.c b/matrixssl/tls13EncodeExt.c index 404e30a..01197d5 100644 --- a/matrixssl/tls13EncodeExt.c +++ b/matrixssl/tls13EncodeExt.c @@ -273,6 +273,10 @@ static int32_t tls13WriteClientSupportedGroups(ssl_t *ssl, psDynBuf_t *extBuf) while (ssl->tls13SupportedGroups[i] != 0) { psDynBufAppendAsBigEndianUint16(&workBuf, ssl->tls13SupportedGroups[i]); + if (psIsEcdheGroup(ssl->tls13SupportedGroups[i])) + { + ssl->sec.tls13SentEcdheGroup = PS_TRUE; + } i++; } @@ -1119,10 +1123,13 @@ int32 tls13WriteServerHelloExtensions(ssl_t *ssl, return rc; } # ifndef USE_ONLY_PSK_CIPHER_SUITE - rc = tls13WriteServerKeyShare(ssl, extBuf, isHelloRetryRequest); - if (rc < 0) + if (ssl->sec.tls13ChosenPskMode != psk_keyex_mode_psk_ke) { - return rc; + rc = tls13WriteServerKeyShare(ssl, extBuf, isHelloRetryRequest); + if (rc < 0) + { + return rc; + } } # endif if (ssl->sec.tls13UsingPsk) @@ -1352,6 +1359,22 @@ out_internal_error: # endif /* USE_OCSP_RESPONSE */ # ifdef USE_CLIENT_SIDE_SSL +int32_t tlsWriteEcPointFormats(ssl_t *ssl, + psDynBuf_t *extBuf) +{ + /* See RFC 8422, Section 5.1.2. */ + unsigned char octets[] = + { + 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00 + }; + + psTracePrintExtensionCreate(ssl, EXT_ELLIPTIC_POINTS); + + psDynBufAppendOctets(extBuf, octets, sizeof(octets)); + + return PS_SUCCESS; +} + int32_t tls13WriteClientHelloExtensions(ssl_t *ssl, psDynBuf_t *extBuf, tlsExtension_t *userExt, @@ -1402,6 +1425,7 @@ int32_t tls13WriteClientHelloExtensions(ssl_t *ssl, { return rc; } + # endif /* USE_ONLY_PSK_CIPHER_SUITE */ if (ssl->tls13IncorrectDheKeyShare) { @@ -1465,6 +1489,28 @@ int32_t tls13WriteClientHelloExtensions(ssl_t *ssl, return rc; } # endif + /* + RFC 8422, Section 5.1.2: + + "For backwards compatibility purposes, the point format list extension + MAY still be included and contain exactly one value: the uncompressed + point format (0)." + + Some servers always send an EC Point Formats extension in ServerHello. + According to RFC 8446, Section 6.2., the proper reponse to such an + unsolicited ServerHello extension is to send the unsupported_extension + alert. To allow handshaking with such misbehaving servers, we include + the extension in ClientHello. This is allowed by RFC 8422. + */ + if (ssl->sec.tls13SentEcdheGroup) + { + rc = tlsWriteEcPointFormats(ssl, extBuf); + if (rc < 0) + { + return rc; + } + ssl->extFlags.req_elliptic_points = 1; + } } if (ssl->sec.tls13SessionPskList != NULL || diff --git a/matrixssl/tls13KeySchedule.c b/matrixssl/tls13KeySchedule.c index e97b1a3..4762db4 100644 --- a/matrixssl/tls13KeySchedule.c +++ b/matrixssl/tls13KeySchedule.c @@ -342,11 +342,21 @@ int32_t tls13DeriveHandshakeTrafficSecrets(ssl_t *ssl) psTraceBytes("\"derived\" secret", derivedSecret, secretLen); #endif - rc = tls13GenSharedSecret(ssl, &sharedSecret, &sharedSecretLen); - if (rc < 0) + if (ssl->sec.tls13ChosenPskMode == psk_keyex_mode_psk_ke) { - ssl->err = SSL_ALERT_INTERNAL_ERROR; - return rc; + /* psk_ke uses a dummy all-zero shared secret. */ + sharedSecret = psMalloc(ssl->hsPool, secretLen); + Memset(sharedSecret, 0, secretLen); + sharedSecretLen = secretLen; + } + else + { + rc = tls13GenSharedSecret(ssl, &sharedSecret, &sharedSecretLen); + if (rc < 0) + { + ssl->err = SSL_ALERT_INTERNAL_ERROR; + return rc; + } } /* HKDF-Extract(ECDHE, derivedSecret) == Handshake Secret */ diff --git a/matrixssl/tlsDefaults.c b/matrixssl/tlsDefaults.c index 73bffbf..0cb7456 100644 --- a/matrixssl/tlsDefaults.c +++ b/matrixssl/tlsDefaults.c @@ -281,11 +281,22 @@ int32 getDefaultVersions(ssl_t *ssl) { uint32_t k; psProtocolVersion_t mask; + psBool_t supportTls13Draft = PS_FALSE; + +# ifdef USE_TLS_1_3_DRAFT_SPEC + supportTls13Draft = PS_TRUE; +# endif /* Loop over versions from latest to earliest (priority order). */ mask = (1 << 23); for (k = 23; k >= 1; k--) { + /* No longer advertise TLS 1.3 draft versions unless specifically + enabled via compile-time config. */ + if (!supportTls13Draft && (mask & v_tls_1_3_draft_any)) + { + continue; + } /* Supported by the build-time config? */ if (mask & v_compiled_in) { diff --git a/matrixssl/tlsSelectKeys.c b/matrixssl/tlsSelectKeys.c index 06c7bfd..671e06c 100644 --- a/matrixssl/tlsSelectKeys.c +++ b/matrixssl/tlsSelectKeys.c @@ -243,7 +243,12 @@ int32_t matrixSslChooseClientKeys(ssl_t *ssl, sslKeySelectInfo_t *keySelect) /* Approach 1: the identity callback. */ if (ssl->sec.identityCb) { - psTraceInfo("matrixSslChooseClientKeys: trying callback\n"); +#if defined USE_SSL_HANDSHAKE_MSG_TRACE || defined USE_SSL_INFORMATIONAL_TRACE + static int num_called = 0; + + psTraceIntInfo("matrixSslChooseClientKeys: trying callback (%d)\n", + num_called++); +#endif rc = ssl->sec.identityCb(ssl, keySelect); if (rc == PS_SUCCESS && ssl->chosenIdentity != NULL) { diff --git a/matrixssl/tlsSigVer.c b/matrixssl/tlsSigVer.c index c218f21..6ca4524 100644 --- a/matrixssl/tlsSigVer.c +++ b/matrixssl/tlsSigVer.c @@ -195,8 +195,30 @@ static inline int32_t chooseSkeSigAlgTls12(ssl_t *ssl, sslIdentity_t *id) { int32_t sigAlg; + uint16_t sigAlgMask; - sigAlg = chooseSigAlg(id->cert, &id->privKey, ssl->hashSigAlg); + if (MATRIX_IS_CLIENT(ssl)) + { + /* The client will always receive the servers sigalg + list in CertificateRequest. */ + sigAlgMask = ssl->peerSigAlg; + } + else + { + if (ssl->peerSigAlg != 0) + { + /* Got signature_algorithms in ClientHello. */ + sigAlgMask = ssl->peerSigAlg; + } + else + { + /* No signature_algorithms received, use the "shared" + list, which in this case is equal to our list. */ + sigAlgMask = ssl->hashSigAlg; + } + } + + sigAlg = chooseSigAlg(id->cert, &id->privKey, sigAlgMask); if (sigAlg == PS_UNSUPPORTED_FAIL) { psTraceInfo("Unavailable sigAlgorithm for SKE write\n"); @@ -616,6 +638,9 @@ psBool_t tlsIsSupportedRsaSigAlg(int32_t alg) case sigalg_rsa_pss_rsae_sha256: case sigalg_rsa_pss_rsae_sha384: case sigalg_rsa_pss_rsae_sha512: + case sigalg_rsa_pss_pss_sha256: + case sigalg_rsa_pss_pss_sha384: + case sigalg_rsa_pss_pss_sha512: # endif return PS_TRUE; default: @@ -654,14 +679,17 @@ psResSize_t tlsSigAlgToHashLen(uint16_t alg) return SHA1_HASH_SIZE; case sigalg_rsa_pkcs1_sha256: case sigalg_rsa_pss_rsae_sha256: + case sigalg_rsa_pss_pss_sha256: case sigalg_ecdsa_secp256r1_sha256: return SHA256_HASH_SIZE; case sigalg_rsa_pkcs1_sha384: case sigalg_rsa_pss_rsae_sha384: + case sigalg_rsa_pss_pss_sha384: case sigalg_ecdsa_secp384r1_sha384: return SHA384_HASH_SIZE; case sigalg_rsa_pkcs1_sha512: case sigalg_rsa_pss_rsae_sha512: + case sigalg_rsa_pss_pss_sha512: case sigalg_ecdsa_secp521r1_sha512: return SHA512_HASH_SIZE; default: @@ -684,6 +712,9 @@ int32_t tlsSigAlgToMatrix(uint16_t alg) case sigalg_rsa_pss_rsae_sha256: case sigalg_rsa_pss_rsae_sha384: case sigalg_rsa_pss_rsae_sha512: + case sigalg_rsa_pss_pss_sha256: + case sigalg_rsa_pss_pss_sha384: + case sigalg_rsa_pss_pss_sha512: return OID_RSASSA_PSS; case sigalg_ecdsa_sha1: return OID_SHA1_ECDSA_SIG; @@ -759,20 +790,29 @@ int32_t tlsVerify(ssl_t *ssl, { goto out_decode_error; } + psTracePrintTls13SigAlg(INDENT_HS_MSG, + "signature algorithm", + sigAlgTls, + PS_FALSE, + PS_TRUE); + # ifdef USE_PKCS1_PSS switch (sigAlgTls) { case sigalg_rsa_pss_rsae_sha256: + case sigalg_rsa_pss_pss_sha256: opts->useRsaPss = PS_TRUE; opts->rsaPssHashAlg = PKCS1_SHA256_ID; opts->rsaPssSaltLen = SHA256_HASH_SIZE; break; case sigalg_rsa_pss_rsae_sha384: + case sigalg_rsa_pss_pss_sha384: opts->useRsaPss = PS_TRUE; opts->rsaPssHashAlg = PKCS1_SHA384_ID; opts->rsaPssSaltLen = SHA384_HASH_SIZE; break; case sigalg_rsa_pss_rsae_sha512: + case sigalg_rsa_pss_pss_sha512: opts->useRsaPss = PS_TRUE; opts->rsaPssHashAlg = PKCS1_SHA512_ID; opts->rsaPssSaltLen = SHA512_HASH_SIZE; @@ -897,6 +937,14 @@ int32_t tlsVerify(ssl_t *ssl, matrixSigAlg = tlsSigAlgToMatrix(sigAlgTls); } + if (!NGTD_VER(ssl, v_tls_with_signature_algorithms)) + { + psTracePrintMatrixSigAlg(INDENT_HS_MSG, + "signature algorithm", + matrixSigAlg, + PS_TRUE); + } + rc = psVerifySig(ssl->hsPool, refTbs, refTbsLen, @@ -1367,7 +1415,7 @@ int32_t chooseSigAlgInt(int32_t certSigAlg, } /* - For RSA signatures, RFC 5746 allows to pick any hash algorithm, + For RSA signatures, RFC 5246 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. diff --git a/matrixssl/tlsTrace.c b/matrixssl/tlsTrace.c index b079e1c..2b8e8a3 100644 --- a/matrixssl/tlsTrace.c +++ b/matrixssl/tlsTrace.c @@ -556,6 +556,75 @@ void psPrintSigAlgs(psSize_t indentLevel, } # endif /* USE_TLS_1_3_ONLY */ +void psPrintMatrixSigAlg(psSize_t indentLevel, + const char *where, + int32_t alg, + psBool_t addNewline) +{ + tlsTraceIndent(indentLevel, NULL); + + if (where) + { + tlsTraceStr("%s: ", where); + } + + switch(alg) + { + case OID_MD2_RSA_SIG: + tlsTrace("rsa_md2"); + break; + case OID_MD4_RSA_SIG: + tlsTrace("rsa_md4"); + break; + case OID_MD5_RSA_SIG: + tlsTrace("rsa_md5"); + break; + case OID_SHA1_RSA_SIG: + tlsTrace("rsa_sha1"); + break; + case OID_SHA224_RSA_SIG: + tlsTrace("rsa_sha224"); + break; + case OID_SHA256_RSA_SIG: + tlsTrace("rsa_sha256"); + break; + case OID_SHA384_RSA_SIG: + tlsTrace("rsa_sha384"); + break; + case OID_SHA512_RSA_SIG: + tlsTrace("rsa_sha512"); + break; + case OID_SHA1_DSA_SIG: + tlsTrace("dsa_sha1"); + break; + case OID_SHA1_ECDSA_SIG: + tlsTrace("ecdsa_sha1"); + break; + case OID_SHA224_ECDSA_SIG: + tlsTrace("ecdsa_sha224"); + break; + case OID_SHA256_ECDSA_SIG: + tlsTrace("ecdsa_sha256"); + break; + case OID_SHA384_ECDSA_SIG: + tlsTrace("ecdsa_sha384"); + break; + case OID_SHA512_ECDSA_SIG: + tlsTrace("ecdsa_sha512"); + break; + case OID_RSA_TLS_SIG_ALG: + tlsTrace("rsa_md5sha1"); + break; + default: + tlsTraceInt("Unknown/unexpected sig alg: %d", alg); + } + + if (addNewline) + { + tlsTrace("\n"); + } +} + void psPrintTls13SigAlg(psSize_t indentLevel, const char *where, uint16_t alg, @@ -1944,7 +2013,7 @@ void matrixSslPrintHSDetails(ssl_t *ssl) { if (ssl->sec.tls13ChosenPskMode == psk_keyex_mode_psk_ke) { - tlsTrace(" Keyex mode: PSK only\n"); + tlsTrace(" Keyex mode: PSK only\n"); } else { @@ -2045,7 +2114,8 @@ void matrixSslPrintHSDetails(ssl_t *ssl) tlsTrace(" No client authentication\n"); } # ifdef USE_IDENTITY_CERTIFICATES - if (!RESUMED_HANDSHAKE(ssl)) + if (!RESUMED_HANDSHAKE(ssl) && + !(ssl->flags & SSL_FLAGS_PSK_CIPHER)) { if (MATRIX_IS_SERVER(ssl)) { diff --git a/matrixssl/version.h b/matrixssl/version.h index 2c8c3aa..2a1a650 100644 --- a/matrixssl/version.h +++ b/matrixssl/version.h @@ -1,5 +1,5 @@ /* - Copyright 2019 INSIDE Secure Corporation + Copyright 2020 INSIDE Secure Corporation This file is auto-generated */ #ifndef _h_MATRIXSSL_VERSION @@ -8,10 +8,10 @@ extern "C" { #endif -#define MATRIXSSL_VERSION "4.2.2-OPEN" +#define MATRIXSSL_VERSION "4.3.0-OPEN" #define MATRIXSSL_VERSION_MAJOR 4 -#define MATRIXSSL_VERSION_MINOR 2 -#define MATRIXSSL_VERSION_PATCH 2 +#define MATRIXSSL_VERSION_MINOR 3 +#define MATRIXSSL_VERSION_PATCH 0 #define MATRIXSSL_VERSION_CODE "OPEN" #ifdef __cplusplus diff --git a/release_notes-4-2-2-open.html b/release_notes-4-3-0-open.html similarity index 92% rename from release_notes-4-2-2-open.html rename to release_notes-4-3-0-open.html index af8db4d..3816ab2 100644 --- a/release_notes-4-2-2-open.html +++ b/release_notes-4-3-0-open.html @@ -9,6 +9,26 @@

    MatrixSSL 4.x changelog

    +

    Changes between 4.2.2 and 4.3.0 [June 2020]

    +
    * Added a constant-time variant of eccMulmod, in response to the Minerva attack.
    +* Fixed a possible infinite loop in message parsing discovered by 
    +  Andreas Walz (ivESK).
    +* Timing sidechannel mitigation (Github issue #23).
    +* Change hard coded values to enums in matrixSslLoadKeys (Github issue #35).
    +* Disabled TLS 1.3 draft versions by default.
    +* Fixes TLS 1.2 session ticket based resumption.
    +* May only enable either PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED or
    +  PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM (Github issue #37). 
    +* Channel Bindings for TLS (only for TLS 1.2 and below), new APIs added
    +    - matrixSslGetFinished
    +    - matrixSslGetPeerFinished
    +    - matrixSslGetTlsUniqueChannelBindings
    +* Added API for accessing MatrixSSL structures without direct access
    +  to structure members. Use of this API will slightly enlarge the
    +  MatrixSSL binary but will enable building software that is not
    +  dependent on exact binary layout of structures such as ssl_t.
    +* Fixes the bug when NULL keydata was used in sslLoadKeyPair() function.
    +* Other bug fixes.

    Changes between 4.2.1 and 4.2.2 [August 2019]

    This version fixes a few security issues related to DTLS and handshake message length. It also defines the size of psBool_t to be equivalent to bool on both x86 and ARM platforms.