2249 lines
63 KiB
C
2249 lines
63 KiB
C
/**
|
|
* @file sslTest_nonfips.c
|
|
* @version $Format:%h%d$
|
|
*
|
|
* Self-test of the MatrixSSL handshake protocol and encrypted data exchange..
|
|
* Each enabled cipher suite is run through all configured SSL handshake paths
|
|
* This version of the test is for native crypto library.
|
|
*/
|
|
/*
|
|
* Copyright (c) 2014-2016 INSIDE Secure Corporation
|
|
* Copyright (c) PeerSec Networks, 2002-2011
|
|
* All Rights Reserved
|
|
*
|
|
* The latest version of this code is available at http://www.matrixssl.org
|
|
*
|
|
* This software is open source; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This General Public License does NOT permit incorporating this software
|
|
* into proprietary programs. If you are unable to comply with the GPL, a
|
|
* commercial license for this software may be purchased from INSIDE at
|
|
* http://www.insidesecure.com/
|
|
*
|
|
* This program is distributed in WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
/******************************************************************************/
|
|
|
|
#include "matrixssl/matrixsslApi.h"
|
|
|
|
#ifdef USE_PSK_CIPHER_SUITE
|
|
#include "testkeys/PSK/psk.h"
|
|
#endif /* USE_PSK_CIPHER_SUITE */
|
|
|
|
/*
|
|
This test application can also run in a mode that measures the time of
|
|
SSL connections. If USE_HIGHRES time is disabled the granularity is
|
|
milliseconds so most non-embedded platforms will report 0 msecs/conn for
|
|
most stats.
|
|
|
|
Standard handshakes and client-auth handshakes (commercial only) are timed
|
|
for each enabled cipher suite. The other handshake types will still run
|
|
but will not be timed
|
|
*/
|
|
//#define ENABLE_PERF_TIMING
|
|
|
|
#if !defined(POSIX) && !defined(WIN32)
|
|
#define EMBEDDED
|
|
#endif
|
|
|
|
#ifndef EMBEDDED
|
|
#define DELIM "\t"
|
|
#if defined(__x86_64__) && defined(ENABLE_PERF_TIMING)
|
|
#define CONN_ITER 10 /* number of connections per type of hs */
|
|
#elif defined(__arm__) && defined(ENABLE_PERF_TIMING)
|
|
#define CONN_ITER 2 /* number of connections per type of hs */
|
|
#else
|
|
#define CONN_ITER 1 /* number of connections per type of hs */
|
|
#endif
|
|
#else
|
|
#define DELIM ","
|
|
#define CONN_ITER 1 /* number of connections per type of hs */
|
|
#endif
|
|
|
|
#define CLI_APP_DATA 128
|
|
#define SVR_APP_DATA 2048
|
|
|
|
#define THROUGHPUT_NREC 100
|
|
#define THROUGHPUT_RECSIZE SSL_MAX_PLAINTEXT_LEN
|
|
|
|
#define BYTES_PER_MB 1048576
|
|
#ifdef ENABLE_PERF_TIMING
|
|
#define testTrace(x)
|
|
#ifdef USE_HIGHRES_TIME
|
|
#define psDiffMsecs(A, B, C) psDiffUsecs(A, B)
|
|
#define TIME_UNITS "usecs/connection\n"
|
|
#define TIME_SCALE 1000000
|
|
#else /* !USE_HIGHRES_TIME */
|
|
#define TIME_UNITS "msecs/connection\n"
|
|
#define TIME_SCALE 1000
|
|
#endif /* USE_HIGHRES_TIME */
|
|
#else /* !ENABLE_PERF_TIMING */
|
|
#define testTrace(x) _psTrace(x)
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
#define CPS(A) ((A) != 0 ? (TIME_SCALE/(A)): 0)
|
|
#define MBS(A) ((A) != 0 ? (uint32_t)(((uint64_t)THROUGHPUT_NREC * THROUGHPUT_RECSIZE * TIME_SCALE / BYTES_PER_MB) / (A)) : 0)
|
|
|
|
#ifdef USE_MATRIXSSL_STATS
|
|
static void statCback(void *ssl, void *stat_ptr, int32 type, int32 value);
|
|
#endif
|
|
|
|
//#define TEST_RESUMPTIONS_WITH_SESSION_TICKETS
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
Must define in matrixConfig.h:
|
|
USE_SERVER_SIDE_SSL
|
|
USE_CLIENT_SIDE_SSL
|
|
USE_CLIENT_AUTH (commercial only)
|
|
*/
|
|
#if !defined(USE_SERVER_SIDE_SSL) || !defined(USE_CLIENT_SIDE_SSL)
|
|
#warning "Must enable both USE_SERVER_SIDE_SSL and USE_CLIENT_SIDE_SSL to run"
|
|
#endif
|
|
|
|
#ifdef USE_ONLY_PSK_CIPHER_SUITE
|
|
#ifdef USE_CLIENT_AUTH
|
|
#error "Disable client auth if using only PSK ciphers"
|
|
#endif
|
|
#endif
|
|
|
|
typedef struct {
|
|
ssl_t *ssl;
|
|
sslKeys_t *keys;
|
|
#ifdef ENABLE_PERF_TIMING
|
|
uint32 hsTime;
|
|
uint32 appTime;
|
|
#endif
|
|
} sslConn_t;
|
|
|
|
enum {
|
|
TLS_TEST_SKIP = 1,
|
|
TLS_TEST_PASS,
|
|
TLS_TEST_FAIL,
|
|
};
|
|
|
|
enum {
|
|
STANDARD_HANDSHAKE,
|
|
RE_HANDSHAKE_TEST_CLIENT_INITIATED,
|
|
RESUMED_HANDSHAKE_TEST_NEW_CONNECTION,
|
|
RE_HANDSHAKE_TEST_SERVER_INITIATED,
|
|
RESUMED_RE_HANDSHAKE_TEST_CLIENT_INITIATED,
|
|
SECOND_PASS_RESUMED_RE_HANDSHAKE_TEST,
|
|
RESUMED_RE_HANDSHAKE_TEST_SERVER_INITIATED,
|
|
UPGRADE_CERT_CALLBACK_RE_HANDSHAKE,
|
|
UPGRADE_KEYS_RE_HANDSHAKE,
|
|
CHANGE_CIPHER_SUITE_RE_HANDSHAKE_TEST,
|
|
STANDARD_CLIENT_AUTH_HANDSHAKE,
|
|
RESUMED_CLIENT_AUTH_HANDSHAKE,
|
|
REHANDSHAKE_ADDING_CLIENT_AUTHENTICATION_TEST
|
|
};
|
|
|
|
typedef struct {
|
|
uint32_t c_hs;
|
|
uint32_t s_hs;
|
|
uint32_t c_rhs;
|
|
uint32_t s_rhs;
|
|
uint32_t c_resume;
|
|
uint32_t s_resume;
|
|
uint32_t c_cauth;
|
|
uint32_t s_cauth;
|
|
uint32_t c_app;
|
|
uint32_t s_app;
|
|
uint16_t keysize; /* Pubkey size for key exchange */
|
|
uint16_t authsize; /* Pubkey size for auth */
|
|
uint8_t cid; /* Array index of testCipherSpec_t */
|
|
uint8_t ver; /* TLS version */
|
|
} testResult_t;
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
static testResult_t g_results[4 * 3 * 48]; /* 4 versions, 3 keysizes, 48 ciphers */
|
|
#endif
|
|
|
|
typedef struct {
|
|
const char name[64];
|
|
uint16_t id;
|
|
} testCipherSpec_t;
|
|
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
static sslSessionId_t *clientSessionId;
|
|
#endif
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
Key loading. The header files are a bit easier to work with because
|
|
it is better to get a compile error that a header isn't found rather
|
|
than a run-time error that a .pem file isn't found
|
|
*/
|
|
#define USE_HEADER_KEYS /* comment out this line to test with .pem files */
|
|
|
|
#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS)
|
|
#ifdef USE_RSA
|
|
static char svrKeyFile[] = "../../testkeys/RSA/1024_RSA_KEY.pem";
|
|
static char svrCertFile[] = "../../testkeys/RSA/1024_RSA.pem";
|
|
static char svrCAfile[] = "../../testkeys/RSA/1024_RSA_CA.pem";
|
|
static char clnCAfile[] = "../../testkeys/RSA/2048_RSA_CA.pem";
|
|
static char clnKeyFile[] = "../../testkeys/RSA/2048_RSA_KEY.pem";
|
|
static char clnCertFile[] = "../../testkeys/RSA/2048_RSA.pem";
|
|
#endif /* USE_RSA */
|
|
#ifdef USE_ECC
|
|
static char svrEcKeyFile[] = "../../testkeys/EC/192_EC_KEY.pem";
|
|
static char svrEcCertFile[] = "../../testkeys/EC/192_EC.pem";
|
|
static char svrEcCAfile[] = "../../testkeys/EC/192_EC_CA.pem";
|
|
static char clnEcKeyFile[] = "../../testkeys/EC/224_EC_KEY.pem";
|
|
static char clnEcCertFile[] = "../../testkeys/EC/224_EC.pem";
|
|
static char clnEcCAfile[] = "../../testkeys/EC/224_EC_CA.pem";
|
|
/* ECDH_RSA certs */
|
|
static char svrEcRsaKeyFile[] = "../../testkeys/ECDH_RSA/192_ECDH-RSA_KEY.pem";
|
|
static char svrEcRsaCertFile[] = "../../testkeys/ECDH_RSA/192_ECDH-RSA.pem";
|
|
static char svrEcRsaCAfile[] = "../../testkeys/ECDH_RSA/1024_ECDH-RSA_CA.pem";
|
|
static char clnEcRsaKeyFile[] = "../../testkeys/ECDH_RSA/256_ECDH-RSA_KEY.pem";
|
|
static char clnEcRsaCertFile[] = "../../testkeys/ECDH_RSA/256_ECDH-RSA.pem";
|
|
static char clnEcRsaCAfile[] = "../../testkeys/ECDH_RSA/2048_ECDH-RSA_CA.pem";
|
|
#endif /* USE_ECC */
|
|
#ifdef REQUIRE_DH_PARAMS
|
|
static char dhParamFile[] = "../../testkeys/DH/1024_DH_PARAMS.pem";
|
|
#endif /* REQUIRE_DH_PARAMS */
|
|
#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */
|
|
|
|
#ifdef USE_HEADER_KEYS
|
|
|
|
#ifdef USE_RSA
|
|
#include "testkeys/RSA/1024_RSA_KEY.h"
|
|
#include "testkeys/RSA/1024_RSA.h"
|
|
#include "testkeys/RSA/1024_RSA_CA.h"
|
|
#include "testkeys/RSA/2048_RSA_KEY.h"
|
|
#include "testkeys/RSA/2048_RSA.h"
|
|
#include "testkeys/RSA/2048_RSA_CA.h"
|
|
#include "testkeys/RSA/4096_RSA_KEY.h"
|
|
#include "testkeys/RSA/4096_RSA.h"
|
|
#include "testkeys/RSA/4096_RSA_CA.h"
|
|
static const unsigned char *RSAKEY, *RSACERT, *RSACA;
|
|
static uint32_t RSAKEY_SIZE, RSA_SIZE, RSACA_SIZE;
|
|
#endif /* USE_RSA */
|
|
|
|
#ifdef USE_ECC
|
|
#include "testkeys/EC/192_EC_KEY.h"
|
|
#include "testkeys/EC/192_EC.h"
|
|
#include "testkeys/EC/192_EC_CA.h"
|
|
#include "testkeys/EC/224_EC_KEY.h"
|
|
#include "testkeys/EC/224_EC.h"
|
|
#include "testkeys/EC/224_EC_CA.h"
|
|
#include "testkeys/EC/256_EC_KEY.h"
|
|
#include "testkeys/EC/256_EC.h"
|
|
#include "testkeys/EC/256_EC_CA.h"
|
|
#include "testkeys/EC/384_EC_KEY.h"
|
|
#include "testkeys/EC/384_EC.h"
|
|
#include "testkeys/EC/384_EC_CA.h"
|
|
#include "testkeys/EC/521_EC_KEY.h"
|
|
#include "testkeys/EC/521_EC.h"
|
|
#include "testkeys/EC/521_EC_CA.h"
|
|
static const unsigned char *ECCKEY, *ECC, *ECCCA;
|
|
static uint32_t ECCKEY_SIZE, ECC_SIZE, ECCCA_SIZE;
|
|
|
|
#include "testkeys/ECDH_RSA/256_ECDH-RSA_KEY.h"
|
|
#include "testkeys/ECDH_RSA/256_ECDH-RSA.h"
|
|
#include "testkeys/ECDH_RSA/1024_ECDH-RSA_CA.h"
|
|
#include "testkeys/ECDH_RSA/521_ECDH-RSA_KEY.h"
|
|
#include "testkeys/ECDH_RSA/521_ECDH-RSA.h"
|
|
#include "testkeys/ECDH_RSA/2048_ECDH-RSA_CA.h"
|
|
static uint32_t ECDHRSA_SIZE;
|
|
#endif /* USE_ECC */
|
|
|
|
#ifdef REQUIRE_DH_PARAMS
|
|
#include "testkeys/DH/1024_DH_PARAMS.h"
|
|
#include "testkeys/DH/2048_DH_PARAMS.h"
|
|
#include "testkeys/DH/4096_DH_PARAMS.h"
|
|
static const unsigned char *DHPARAM;
|
|
static uint32_t DH_SIZE;
|
|
#endif /* REQUIRE_DH_PARAMS */
|
|
|
|
#endif /* USE_HEADER_KEYS */
|
|
|
|
/******************************************************************************/
|
|
|
|
int sslTest(void);
|
|
|
|
static void freeSessionAndConnection(sslConn_t *cpp);
|
|
|
|
static int32 initializeServer(sslConn_t *svrConn, uint16_t cipher);
|
|
static int32 initializeClient(sslConn_t *clnConn, uint16_t cipher,
|
|
sslSessionId_t *sid);
|
|
|
|
static int32 initializeHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
|
|
uint16_t cipherSuite,
|
|
sslSessionId_t *sid);
|
|
|
|
static int32 initializeResumedHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
|
|
uint16_t cipherSuite);
|
|
|
|
#ifdef SSL_REHANDSHAKES_ENABLED
|
|
static int32 initializeReHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
|
|
uint16_t cipherSuite);
|
|
|
|
static int32 initializeResumedReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite);
|
|
static int32 initializeServerInitiatedReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite);
|
|
static int32 initializeServerInitiatedResumedReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite);
|
|
static int32 initializeUpgradeCertCbackReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite);
|
|
static int32 initializeUpgradeKeysReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite);
|
|
static int32 initializeChangeCipherReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite);
|
|
#ifdef USE_CLIENT_AUTH
|
|
static int32 initializeReHandshakeClientAuth(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite);
|
|
#endif /* USE_CLIENT_AUTH */
|
|
#endif /* SSL_REHANDSHAKES_ENABLED */
|
|
|
|
#ifdef USE_CLIENT_AUTH
|
|
static int32 initializeClientAuthHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite,
|
|
sslSessionId_t *sid);
|
|
#endif /* USE_CLIENT_AUTH */
|
|
|
|
static int32 performHandshake(sslConn_t *sendingSide, sslConn_t *receivingSide);
|
|
static int32 exchangeAppData(sslConn_t *sendingSide, sslConn_t *receivingSide, uint32_t bytes);
|
|
#ifdef ENABLE_PERF_TIMING
|
|
static int32_t throughputTest(sslConn_t *s, sslConn_t *r, uint16_t nrec, uint16_t reclen);
|
|
static void print_throughput(void);
|
|
#endif
|
|
|
|
/*
|
|
Client-authentication. Callback that is registered to receive client
|
|
certificate information for custom validation
|
|
*/
|
|
static int32 clnCertChecker(ssl_t *ssl, psX509Cert_t *cert, int32 alert);
|
|
|
|
#ifdef SSL_REHANDSHAKES_ENABLED
|
|
static int32 clnCertCheckerUpdate(ssl_t *ssl, psX509Cert_t *cert, int32 alert);
|
|
#endif
|
|
|
|
#ifdef USE_CLIENT_AUTH
|
|
static int32 svrCertChecker(ssl_t *ssl, psX509Cert_t *cert, int32 alert);
|
|
#endif /* USE_CLIENT_AUTH */
|
|
|
|
/******************************************************************************/
|
|
|
|
static uint32_t g_versionFlag= 0;
|
|
|
|
/* Protocol versions to test for each suite */
|
|
const static uint32_t g_versions[] = {
|
|
#if defined(USE_TLS_1_2)
|
|
SSL_FLAGS_TLS_1_2,
|
|
#endif
|
|
#if defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
|
|
SSL_FLAGS_TLS_1_1,
|
|
#endif
|
|
#if defined(USE_TLS) && !defined(DISABLE_TLS_1_0)
|
|
SSL_FLAGS_TLS_1_0,
|
|
#endif
|
|
#if !defined(DISABLE_SSLV3)
|
|
SSL_FLAGS_SSLV3,
|
|
#endif
|
|
#if defined(USE_DTLS) && defined(USE_TLS_1_2)
|
|
SSL_FLAGS_TLS_1_2 | SSL_FLAGS_DTLS,
|
|
#endif
|
|
#if defined(USE_DTLS) && defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
|
|
SSL_FLAGS_TLS_1_1 | SSL_FLAGS_DTLS,
|
|
#endif
|
|
0 /* 0 Must be last to terminate list */
|
|
};
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
const static char *g_version_str[] = {
|
|
#if defined(USE_TLS_1_2)
|
|
"TLS 1.2",
|
|
#endif
|
|
#if defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
|
|
"TLS 1.1",
|
|
#endif
|
|
#if defined(USE_TLS) && !defined(DISABLE_TLS_1_0)
|
|
"TLS 1.0",
|
|
#endif
|
|
#if !defined(DISABLE_SSLV3)
|
|
"SSL 3.0",
|
|
#endif
|
|
#if defined(USE_TLS) && defined(USE_TLS_1_2)
|
|
"DTLS 1.2",
|
|
#endif
|
|
#if defined(USE_DTLS) && defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
|
|
"DTLS 1.0", /* There is no DTLS 1.1 */
|
|
#endif
|
|
0 /* 0 Must be last to terminate list */
|
|
};
|
|
#endif
|
|
|
|
/* Ciphersuites to test */
|
|
|
|
#define CS(A) { #A, A }
|
|
|
|
const static testCipherSpec_t ciphers[] = {
|
|
|
|
/* RSA */
|
|
#ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA
|
|
CS(TLS_RSA_WITH_AES_128_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA
|
|
CS(TLS_RSA_WITH_AES_256_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA256
|
|
CS(TLS_RSA_WITH_AES_128_CBC_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA256
|
|
CS(TLS_RSA_WITH_AES_256_CBC_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_RSA_WITH_AES_128_GCM_SHA256
|
|
CS(TLS_RSA_WITH_AES_128_GCM_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_RSA_WITH_AES_256_GCM_SHA384
|
|
CS(TLS_RSA_WITH_AES_256_GCM_SHA384),
|
|
#endif
|
|
|
|
#ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA
|
|
CS(SSL_RSA_WITH_3DES_EDE_CBC_SHA),
|
|
#endif
|
|
|
|
/* ECDHE-ECDSA */
|
|
|
|
#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
|
|
CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
|
|
CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
|
|
CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
|
|
CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
|
|
CS(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
|
|
CS(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
|
CS(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
|
|
#endif
|
|
|
|
/* ECDH-ECDSA */
|
|
|
|
#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
|
|
CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
|
|
CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
|
|
CS(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
|
|
CS(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
|
|
CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
|
|
CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA),
|
|
#endif
|
|
|
|
/* ECDHE-RSA */
|
|
|
|
#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
|
CS(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
|
CS(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
|
|
CS(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
|
|
CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
|
|
CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
|
|
CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
|
CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDHE_RSA_WITH_3DES_EDE_SHA
|
|
CS(TLS_ECDHE_RSA_WITH_3DES_EDE_SHA),
|
|
#endif
|
|
|
|
/* ECDH-RSA */
|
|
|
|
#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
|
|
CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
|
|
CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
|
|
CS(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
|
|
CS(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
|
|
CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
|
|
CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA),
|
|
#endif
|
|
|
|
/* DHE-RSA */
|
|
|
|
#ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
|
|
CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
|
|
CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
|
|
CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
|
|
CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
|
|
CS(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA),
|
|
#endif
|
|
|
|
/* PSK */
|
|
|
|
#ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA
|
|
CS(TLS_PSK_WITH_AES_128_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA
|
|
CS(TLS_PSK_WITH_AES_256_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_PSK_WITH_AES_128_CBC_SHA256
|
|
CS(TLS_PSK_WITH_AES_128_CBC_SHA256),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_PSK_WITH_AES_256_CBC_SHA384
|
|
CS(TLS_PSK_WITH_AES_256_CBC_SHA384),
|
|
#endif
|
|
|
|
/* DHE-PSK */
|
|
|
|
#ifdef USE_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
|
|
CS(TLS_DHE_PSK_WITH_AES_128_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
|
|
CS(TLS_DHE_PSK_WITH_AES_256_CBC_SHA),
|
|
#endif
|
|
|
|
/* Deprecated / Weak ciphers */
|
|
|
|
#ifdef USE_SSL_RSA_WITH_RC4_128_SHA
|
|
CS(SSL_RSA_WITH_RC4_128_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_SSL_RSA_WITH_RC4_128_MD5
|
|
CS(SSL_RSA_WITH_RC4_128_MD5),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_RSA_WITH_SEED_CBC_SHA
|
|
CS(TLS_RSA_WITH_SEED_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_RSA_WITH_IDEA_CBC_SHA
|
|
CS(TLS_RSA_WITH_IDEA_CBC_SHA),
|
|
#endif
|
|
|
|
/* DH-anon */
|
|
|
|
#ifdef USE_TLS_DH_anon_WITH_AES_128_CBC_SHA
|
|
CS(TLS_DH_anon_WITH_AES_128_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_TLS_DH_anon_WITH_AES_256_CBC_SHA
|
|
CS(TLS_DH_anon_WITH_AES_256_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
|
|
CS(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_SSL_DH_anon_WITH_RC4_128_MD5
|
|
CS(SSL_DH_anon_WITH_RC4_128_MD5),
|
|
#endif
|
|
|
|
/* RSA-NULL */
|
|
|
|
#ifdef USE_SSL_RSA_WITH_NULL_SHA
|
|
CS(SSL_RSA_WITH_NULL_SHA),
|
|
#endif
|
|
|
|
#ifdef USE_SSL_RSA_WITH_NULL_MD5
|
|
CS(SSL_RSA_WITH_NULL_MD5),
|
|
#endif
|
|
|
|
{"NULL", 0} /* must be last */
|
|
};
|
|
|
|
#ifdef SSL_REHANDSHAKES_ENABLED
|
|
static const char *cipher_name(uint16_t cid)
|
|
{
|
|
int id;
|
|
for (id = 0; ciphers[id].id > 0; id++) {
|
|
if (ciphers[id].id == cid) {
|
|
break;
|
|
}
|
|
}
|
|
return ciphers[id].name;
|
|
}
|
|
#endif /* !SSL_REHANDSHAKES_ENABLED */
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
This test application will exercise the SSL/TLS handshake and app
|
|
data exchange for every eligible cipher.
|
|
*/
|
|
|
|
#ifndef EMBEDDED
|
|
int main(int argc, char **argv)
|
|
{
|
|
return sslTest();
|
|
}
|
|
#endif
|
|
|
|
int sslTest(void)
|
|
{
|
|
sslConn_t *svrConn, *clnConn;
|
|
const sslCipherSpec_t *spec;
|
|
uint8_t id, v;
|
|
uint16_t keysize = 0, authsize = 0;
|
|
#ifdef ENABLE_PERF_TIMING
|
|
int32 perfIter;
|
|
uint32 clnTime, svrTime;
|
|
testResult_t *result = g_results;
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
if (matrixSslOpen() < 0) {
|
|
fprintf(stderr, "matrixSslOpen failed, exiting...\n");
|
|
return -1;
|
|
}
|
|
|
|
svrConn = psMalloc(MATRIX_NO_POOL, sizeof(sslConn_t));
|
|
clnConn = psMalloc(MATRIX_NO_POOL, sizeof(sslConn_t));
|
|
memset(svrConn, 0, sizeof(sslConn_t));
|
|
memset(clnConn, 0, sizeof(sslConn_t));
|
|
|
|
#ifdef USE_RSA
|
|
RSA_SIZE = 0;
|
|
#endif
|
|
#ifdef USE_ECC
|
|
ECC_SIZE = ECDHRSA_SIZE = 0;
|
|
#endif
|
|
#ifdef REQUIRE_DH_PARAMS
|
|
DH_SIZE = 0;
|
|
#endif
|
|
for (id = 0; ciphers[id].id > 0; id++) {
|
|
|
|
if ((spec = sslGetDefinedCipherSpec(ciphers[id].id)) == NULL) {
|
|
_psTrace(" FAILED: cipher spec lookup\n");
|
|
goto LBL_FREE;
|
|
}
|
|
keysize = authsize = 0;
|
|
#ifdef USE_RSA
|
|
L_NEXT_RSA:
|
|
if (spec->type == CS_RSA) {
|
|
switch (RSA_SIZE) {
|
|
case 0:
|
|
RSAKEY = RSA1024KEY; RSAKEY_SIZE = RSA1024KEY_SIZE;
|
|
RSACERT = RSA1024; RSA_SIZE = RSA1024_SIZE;
|
|
RSACA = RSA1024CA; RSACA_SIZE = RSA1024CA_SIZE;
|
|
keysize = authsize = 1024;
|
|
break;
|
|
case RSA1024_SIZE:
|
|
RSAKEY = RSA2048KEY; RSAKEY_SIZE = RSA2048KEY_SIZE;
|
|
RSACERT = RSA2048; RSA_SIZE = RSA2048_SIZE;
|
|
RSACA = RSA2048CA; RSACA_SIZE = RSA2048CA_SIZE;
|
|
keysize = authsize = 2048;
|
|
break;
|
|
case RSA2048_SIZE:
|
|
#ifndef EMBEDDED
|
|
RSAKEY = RSA4096KEY; RSAKEY_SIZE = RSA4096KEY_SIZE;
|
|
RSACERT = RSA4096; RSA_SIZE = RSA4096_SIZE;
|
|
RSACA = RSA4096CA; RSACA_SIZE = RSA4096CA_SIZE;
|
|
keysize = authsize = 4096;
|
|
break;
|
|
case RSA4096_SIZE:
|
|
#endif
|
|
RSA_SIZE = 0;
|
|
break;
|
|
}
|
|
if (RSA_SIZE == 0) {
|
|
continue; /* Next cipher suite */
|
|
}
|
|
}
|
|
/* For other ciphersuites that use RSA for auth only, default to 1024 */
|
|
if (spec->type == CS_DHE_RSA ||
|
|
spec->type == CS_ECDH_RSA || spec->type == CS_ECDHE_RSA) {
|
|
RSAKEY = RSA1024KEY; RSAKEY_SIZE = RSA1024KEY_SIZE;
|
|
RSACERT = RSA1024; RSA_SIZE = RSA1024_SIZE;
|
|
RSACA = RSA1024CA; RSACA_SIZE = RSA1024CA_SIZE;
|
|
authsize = 1024;
|
|
#ifdef USE_ECC
|
|
ECCKEY = EC256KEY; ECCKEY_SIZE = EC256KEY_SIZE;
|
|
ECC = EC256; ECC_SIZE = EC256_SIZE;
|
|
ECCCA = EC256CA; ECCCA_SIZE = EC256CA_SIZE;
|
|
keysize = 256;
|
|
#endif
|
|
}
|
|
#endif /* USE_RSA */
|
|
|
|
#ifdef USE_ECC
|
|
L_NEXT_ECC:
|
|
if (spec->type == CS_ECDH_ECDSA || spec->type == CS_ECDHE_ECDSA) {
|
|
switch (ECC_SIZE) {
|
|
case 0:
|
|
ECCKEY = EC192KEY; ECCKEY_SIZE = EC192KEY_SIZE;
|
|
ECC = EC192; ECC_SIZE = EC192_SIZE;
|
|
ECCCA = EC192CA; ECCCA_SIZE = EC192CA_SIZE;
|
|
keysize = authsize = 192;
|
|
break;
|
|
case EC192_SIZE:
|
|
ECCKEY = EC224KEY; ECCKEY_SIZE = EC224KEY_SIZE;
|
|
ECC = EC224; ECC_SIZE = EC224_SIZE;
|
|
ECCCA = EC224CA; ECCCA_SIZE = EC224CA_SIZE;
|
|
keysize = authsize = 224;
|
|
break;
|
|
case EC224_SIZE:
|
|
ECCKEY = EC256KEY; ECCKEY_SIZE = EC256KEY_SIZE;
|
|
ECC = EC256; ECC_SIZE = EC256_SIZE;
|
|
ECCCA = EC256CA; ECCCA_SIZE = EC256CA_SIZE;
|
|
keysize = authsize = 256;
|
|
break;
|
|
case EC256_SIZE:
|
|
#ifndef EMBEDDED
|
|
ECCKEY = EC384KEY; ECCKEY_SIZE = EC384KEY_SIZE;
|
|
ECC = EC384; ECC_SIZE = EC384_SIZE;
|
|
ECCCA = EC384CA; ECCCA_SIZE = EC384CA_SIZE;
|
|
keysize = authsize = 384;
|
|
break;
|
|
case EC384_SIZE:
|
|
ECCKEY = EC521KEY; ECCKEY_SIZE = EC521KEY_SIZE;
|
|
ECC = EC521; ECC_SIZE = EC521_SIZE;
|
|
ECCCA = EC521CA; ECCCA_SIZE = EC521CA_SIZE;
|
|
keysize = authsize = 521;
|
|
break;
|
|
case EC521_SIZE:
|
|
#endif
|
|
ECC_SIZE = 0;
|
|
break;
|
|
}
|
|
if (ECC_SIZE == 0) {
|
|
continue; /* Next cipher suite */
|
|
}
|
|
}
|
|
#endif /* USE_ECC */
|
|
|
|
#ifdef REQUIRE_DH_PARAMS
|
|
L_NEXT_DH:
|
|
if (spec->type == CS_DHE_RSA || spec->type == CS_DHE_PSK) {
|
|
switch (DH_SIZE) {
|
|
case 0:
|
|
DHPARAM = DHPARAM1024; DH_SIZE = DHPARAM1024_SIZE;
|
|
keysize = 1024;
|
|
break;
|
|
case DHPARAM1024_SIZE:
|
|
DHPARAM = DHPARAM2048; DH_SIZE = DHPARAM2048_SIZE;
|
|
keysize = 2048;
|
|
break;
|
|
case DHPARAM2048_SIZE:
|
|
#ifndef EMBEDDED
|
|
DHPARAM = DHPARAM4096; DH_SIZE = DHPARAM4096_SIZE;
|
|
keysize = 4096;
|
|
break;
|
|
case DHPARAM4096_SIZE:
|
|
#endif
|
|
DH_SIZE = 0;
|
|
break;
|
|
}
|
|
if (DH_SIZE == 0) {
|
|
continue; /* Next cipher suite */
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef USE_PSK_CIPHER_SUITE
|
|
if (spec->type == CS_PSK) {
|
|
keysize = authsize = sizeof(PSK_HEADER_TABLE[0].key) * 8;
|
|
}
|
|
if (spec->type == CS_DHE_PSK) {
|
|
authsize = sizeof(PSK_HEADER_TABLE[0].key) * 8;
|
|
}
|
|
#endif
|
|
|
|
/* Loop through each defined version (note: not indented) */
|
|
for (v = 0; g_versions[v] != 0; v++) {
|
|
|
|
g_versionFlag = g_versions[v];
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
result->keysize = keysize;
|
|
result->authsize = authsize;
|
|
#endif
|
|
/* Some ciphers are not supported in some versions of TLS */
|
|
if (spec->flags & (CRYPTO_FLAGS_SHA2 | CRYPTO_FLAGS_SHA3)) {
|
|
if (!(g_versionFlag & SSL_FLAGS_TLS_1_2)) {
|
|
_psTraceStr("Skipping %s < TLS 1.2\n\n", (char *)ciphers[id].name);
|
|
continue;
|
|
}
|
|
} else if (spec->flags & CRYPTO_FLAGS_MD5) {
|
|
if (g_versionFlag & SSL_FLAGS_TLS_1_2) {
|
|
_psTraceStr("Skipping %s TLS 1.2\n\n", (char *)ciphers[id].name);
|
|
continue;
|
|
}
|
|
}
|
|
#ifdef USE_LIBSODIUM_AES_GCM
|
|
/* Libsodium supports only aes256-gcm, not 128 */
|
|
if ((spec->flags & CRYPTO_FLAGS_AES) && (spec->flags & CRYPTO_FLAGS_GCM)) {
|
|
_psTraceStr("Skipping %s libsodium\n\n", (char *)ciphers[id].name);
|
|
continue;
|
|
}
|
|
#endif
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
matrixSslNewSessionId(&clientSessionId, NULL);
|
|
#endif
|
|
switch(g_versions[v]) {
|
|
case SSL_FLAGS_SSLV3:
|
|
_psTraceStr("Testing %s SSL 3.0 ", (char *)ciphers[id].name);
|
|
break;
|
|
case SSL_FLAGS_TLS_1_0:
|
|
_psTraceStr("Testing %s TLS 1.0 ", (char *)ciphers[id].name);
|
|
break;
|
|
case SSL_FLAGS_TLS_1_1:
|
|
_psTraceStr("Testing %s TLS 1.1 ", (char *)ciphers[id].name);
|
|
break;
|
|
case SSL_FLAGS_TLS_1_2:
|
|
_psTraceStr("Testing %s TLS 1.2 ", (char *)ciphers[id].name);
|
|
break;
|
|
case SSL_FLAGS_TLS_1_1 | SSL_FLAGS_DTLS:
|
|
_psTraceStr("Testing %s DTLS 1.0 ", (char *)ciphers[id].name);
|
|
break;
|
|
case SSL_FLAGS_TLS_1_2 | SSL_FLAGS_DTLS:
|
|
_psTraceStr("Testing %s DTLS 1.2 ", (char *)ciphers[id].name);
|
|
break;
|
|
}
|
|
_psTraceInt("KeySize %hu ", keysize);
|
|
_psTraceInt("AuthSize %hu\n", authsize);
|
|
|
|
/* Standard Handshake */
|
|
_psTrace(" Standard handshake test\n");
|
|
#ifdef ENABLE_PERF_TIMING
|
|
/*
|
|
Each matrixSsl call in the handshake is wrapped by a timer. Data
|
|
exchange is NOT included in the timer
|
|
*/
|
|
result->cid = id;
|
|
result->ver = v;
|
|
clnTime = svrTime = 0;
|
|
_psTraceInt(" %d connections\n", (int32)CONN_ITER);
|
|
for (perfIter = 0; perfIter < CONN_ITER; perfIter++) {
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
if (initializeHandshake(clnConn, svrConn, ciphers[id].id, clientSessionId) < 0) {
|
|
#else
|
|
if (initializeHandshake(clnConn, svrConn, ciphers[id].id, NULL) < 0) {
|
|
#endif
|
|
_psTrace(" FAILED: initializing Standard handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
#ifdef USE_MATRIXSSL_STATS
|
|
matrixSslRegisterStatCallback(clnConn->ssl, statCback, NULL);
|
|
matrixSslRegisterStatCallback(svrConn->ssl, statCback, NULL);
|
|
#endif
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Standard handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Standard handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
#ifdef ENABLE_PERF_TIMING
|
|
if (throughputTest(clnConn, svrConn, THROUGHPUT_NREC, THROUGHPUT_RECSIZE) < 0) {
|
|
_psTrace(" but FAILED throughputTest\n");
|
|
goto LBL_FREE;
|
|
}
|
|
result->c_app = clnConn->appTime;
|
|
result->s_app = svrConn->appTime;
|
|
#endif
|
|
}
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
clnTime += clnConn->hsTime;
|
|
svrTime += svrConn->hsTime;
|
|
/* Have to reset conn for full handshake... except last time through */
|
|
if (perfIter + 1 != CONN_ITER) {
|
|
matrixSslDeleteSession(clnConn->ssl);
|
|
matrixSslDeleteSession(svrConn->ssl);
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
matrixSslClearSessionId(clientSessionId);
|
|
#endif
|
|
}
|
|
} /* iteration loop close */
|
|
result->c_hs = clnTime/CONN_ITER;
|
|
result->s_hs = svrTime/CONN_ITER;
|
|
_psTraceInt(" CLIENT: %d " TIME_UNITS, (int32)clnTime/CONN_ITER);
|
|
_psTraceInt(" SERVER: %d " TIME_UNITS, (int32)svrTime/CONN_ITER);
|
|
_psTrace("\n");
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
#if defined(SSL_REHANDSHAKES_ENABLED) && !defined(USE_ZLIB_COMPRESSION)
|
|
/* Re-Handshake (full handshake over existing connection) */
|
|
testTrace(" Re-handshake test (client-initiated)\n");
|
|
if (initializeReHandshake(clnConn, svrConn, ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: initializing Re-handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Re-handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Re-handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
#else
|
|
_psTrace(" Re-handshake tests are disabled (ENABLE_SECURE_REHANDSHAKES)\n");
|
|
#endif
|
|
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
/* Resumed handshake (fast handshake over new connection) */
|
|
testTrace(" Resumed handshake test (new connection)\n");
|
|
if (initializeResumedHandshake(clnConn, svrConn,
|
|
ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: initializing Resumed handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Resumed handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Resumed handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
#else
|
|
_psTrace(" Session resumption tests are disabled (USE_ONLY_PSK_CIPHER_SUITE)\n");
|
|
#endif
|
|
|
|
#if defined(SSL_REHANDSHAKES_ENABLED) && !defined(USE_ZLIB_COMPRESSION)
|
|
/*
|
|
Re-handshake initiated by server (full handshake over existing conn)
|
|
Cipher Suite negotiations can get a little fuzzy on the server
|
|
initiated rehandshakes based on what is enabled in matrixsslConfig.h
|
|
because the client will send the entire cipher suite list. In theory,
|
|
the server could disable specific suites to force desired ones but
|
|
we're not doing that here so the cipher suite might be changing
|
|
underneath us now.
|
|
*/
|
|
testTrace(" Re-handshake test (server initiated)\n");
|
|
if (initializeServerInitiatedReHandshake(clnConn, svrConn,
|
|
ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: initializing Re-handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(svrConn, clnConn) < 0) {
|
|
_psTrace(" FAILED: Re-handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
if (ciphers[id].id != clnConn->ssl->cipher->ident) {
|
|
_psTraceStr(" (new cipher %s)\n",
|
|
cipher_name(clnConn->ssl->cipher->ident));
|
|
}
|
|
testTrace(" PASSED: Re-handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
|
|
/* Testing 6 more re-handshake paths. Add some credits */
|
|
matrixSslAddRehandshakeCredits(svrConn->ssl, 6);
|
|
matrixSslAddRehandshakeCredits(clnConn->ssl, 6);
|
|
/*
|
|
Resumed re-handshake (fast handshake over existing connection)
|
|
If the above handshake test did change cipher suites this next test
|
|
will not take a resumption path because the client is specifying the
|
|
specific cipher which will not match the current. So, we'll run this
|
|
test twice to make sure we reset the cipher on the first one and are
|
|
sure to hit the resumed re-handshake test on the second.
|
|
*/
|
|
testTrace(" Resumed Re-handshake test (client initiated)\n");
|
|
if (initializeResumedReHandshake(clnConn, svrConn,
|
|
ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: initializing Resumed Re-handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Resumed Re-handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Resumed Re-handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
testTrace(" Second Pass Resumed Re-handshake test\n");
|
|
if (initializeResumedReHandshake(clnConn, svrConn,
|
|
ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: initializing Resumed Re-handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Second Pass Resumed Re-handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Second Pass Resumed Re-handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
|
|
/* Resumed re-handshake initiated by server (fast handshake over conn) */
|
|
testTrace(" Resumed Re-handshake test (server initiated)\n");
|
|
if (initializeServerInitiatedResumedReHandshake(clnConn, svrConn,
|
|
ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: initializing Resumed Re-handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(svrConn, clnConn) < 0) {
|
|
_psTrace(" FAILED: Resumed Re-handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Resumed Re-handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
|
|
/* Re-handshaking with "upgraded" parameters */
|
|
testTrace(" Change cert callback Re-handshake test\n");
|
|
if (initializeUpgradeCertCbackReHandshake(clnConn, svrConn,
|
|
ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: init upgrade certCback Re-handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Upgrade cert callback Re-handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Upgrade cert callback Re-handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
|
|
/* Upgraded keys */
|
|
testTrace(" Change keys Re-handshake test\n");
|
|
if (initializeUpgradeKeysReHandshake(clnConn, svrConn,
|
|
ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: init upgrade keys Re-handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Upgrade keys Re-handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Upgrade keys Re-handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
/*
|
|
Change cipher spec test. Changing to a hardcoded RSA suite so this
|
|
will not work on suites that don't have RSA material loaded
|
|
*/
|
|
if (spec->type == CS_RSA || spec->type == CS_DHE_RSA ||
|
|
spec->type == CS_ECDH_RSA || spec->type == CS_ECDHE_RSA) {
|
|
testTrace(" Change cipher suite Re-handshake test\n");
|
|
if (initializeChangeCipherReHandshake(clnConn, svrConn,
|
|
ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: init change cipher Re-handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Change cipher suite Re-handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Change cipher suite Re-handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
}
|
|
#endif /* !SSL_REHANDSHAKES_ENABLED */
|
|
|
|
#ifdef USE_CLIENT_AUTH
|
|
/* Client Authentication handshakes */
|
|
if (spec->type != CS_PSK && spec->type != CS_DHE_PSK) {
|
|
_psTrace(" Standard Client Authentication test\n");
|
|
#ifdef ENABLE_PERF_TIMING
|
|
clnTime = svrTime = 0;
|
|
_psTraceInt(" %d connections\n", (int32)CONN_ITER);
|
|
for (perfIter = 0; perfIter < CONN_ITER; perfIter++) {
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
matrixSslClearSessionId(clientSessionId);
|
|
if (initializeClientAuthHandshake(clnConn, svrConn,
|
|
ciphers[id].id, clientSessionId) < 0) {
|
|
_psTrace(" FAILED: initializing Standard Client Auth handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Standard Client Auth handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Standard Client Auth handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
#ifdef ENABLE_PERF_TIMING
|
|
clnTime += clnConn->hsTime;
|
|
svrTime += svrConn->hsTime;
|
|
} /* iteration loop */
|
|
result->c_cauth = clnTime/CONN_ITER;
|
|
result->s_cauth = svrTime/CONN_ITER;
|
|
_psTraceInt(" CLIENT: %d " TIME_UNITS, (int32)clnTime/CONN_ITER);
|
|
_psTraceInt(" SERVER: %d " TIME_UNITS, (int32)svrTime/CONN_ITER);
|
|
_psTrace("\n==========\n");
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
|
|
testTrace(" Resumed client authentication test\n");
|
|
if (initializeResumedHandshake(clnConn, svrConn, ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: initializing resumed Client Auth handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
if (performHandshake(clnConn, svrConn) < 0) {
|
|
_psTrace(" FAILED: Resumed Client Auth handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace(" PASSED: Resumed Client Auth handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
#if defined(SSL_REHANDSHAKES_ENABLED) && !defined(USE_ZLIB_COMPRESSION)
|
|
testTrace(" Rehandshake adding client authentication test\n");
|
|
if (initializeReHandshakeClientAuth(clnConn, svrConn,
|
|
ciphers[id].id) < 0) {
|
|
_psTrace(" FAILED: initializing reshandshke Client Auth handshake\n");
|
|
goto LBL_FREE;
|
|
}
|
|
/* Must be server initiatated if client auth is being turned on */
|
|
if (performHandshake(svrConn, clnConn) < 0) {
|
|
_psTrace(" FAILED: Rehandshake Client Auth handshake\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
if (ciphers[id].id != clnConn->ssl->cipher->ident) {
|
|
_psTraceStr(" (new cipher %s)\n",
|
|
cipher_name(clnConn->ssl->cipher->ident));
|
|
}
|
|
testTrace(" PASSED: Rehandshake Client Auth handshake");
|
|
if (exchangeAppData(clnConn, svrConn, CLI_APP_DATA) < 0 ||
|
|
exchangeAppData(svrConn, clnConn, SVR_APP_DATA) < 0) {
|
|
_psTrace(" but FAILED to exchange application data\n");
|
|
goto LBL_FREE;
|
|
} else {
|
|
testTrace("\n");
|
|
}
|
|
}
|
|
#endif /* SSL_REHANDSHAKES_ENABLED */
|
|
}
|
|
#endif /* USE_CLIENT_AUTH */
|
|
|
|
freeSessionAndConnection(svrConn);
|
|
freeSessionAndConnection(clnConn);
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
matrixSslDeleteSessionId(clientSessionId);
|
|
#endif
|
|
#ifdef ENABLE_PERF_TIMING
|
|
result++;
|
|
#endif
|
|
|
|
continue; /* Next version */
|
|
|
|
LBL_FREE:
|
|
_psTrace("EXITING ON ERROR\n");
|
|
freeSessionAndConnection(svrConn);
|
|
freeSessionAndConnection(clnConn);
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
matrixSslDeleteSessionId(clientSessionId);
|
|
#endif
|
|
break;
|
|
|
|
} /* End version loop (unindented) */
|
|
#ifdef USE_RSA
|
|
if (spec->type == CS_RSA) {
|
|
goto L_NEXT_RSA;
|
|
}
|
|
#endif
|
|
#ifdef USE_ECC
|
|
if (spec->type == CS_ECDH_ECDSA || spec->type == CS_ECDHE_ECDSA) {
|
|
goto L_NEXT_ECC;
|
|
}
|
|
#endif
|
|
#ifdef REQUIRE_DH_PARAMS
|
|
if (spec->type == CS_DHE_RSA || spec->type == CS_DHE_PSK) {
|
|
goto L_NEXT_DH;
|
|
}
|
|
#endif
|
|
|
|
} /* End cipher suite loop */
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
printf("Ciphersuite" DELIM "Keysize" DELIM "Authsize" DELIM
|
|
"Version" DELIM "CliHS" DELIM "SvrHs" DELIM "CliAHS" DELIM "SvrAHS" DELIM
|
|
"MiBs" "\n");
|
|
do {
|
|
result--;
|
|
printf("%s" DELIM "%hu" DELIM "%hu" DELIM
|
|
"%s" DELIM "%u" DELIM "%u" DELIM "%u" DELIM "%u" DELIM
|
|
"%u" "\n",
|
|
ciphers[result->cid].name,
|
|
result->keysize,
|
|
result->authsize,
|
|
g_version_str[result->ver],
|
|
CPS(result->c_hs), CPS(result->s_hs),
|
|
CPS(result->c_cauth), CPS(result->s_cauth),
|
|
MBS(result->c_app)
|
|
);
|
|
} while (result != g_results);
|
|
print_throughput();
|
|
#endif
|
|
|
|
psFree(svrConn, NULL);
|
|
psFree(clnConn, NULL);
|
|
matrixSslClose();
|
|
|
|
#ifdef WIN32
|
|
_psTrace("Press any key to close");
|
|
getchar();
|
|
#endif
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
static int32 initializeHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
|
|
uint16_t cipherSuite, sslSessionId_t *sid)
|
|
{
|
|
int32 rc;
|
|
|
|
if ((rc = initializeServer(svrConn, cipherSuite)) < 0) {
|
|
return rc;
|
|
}
|
|
return initializeClient(clnConn, cipherSuite, sid);
|
|
|
|
}
|
|
|
|
#ifdef SSL_REHANDSHAKES_ENABLED
|
|
static int32 initializeReHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
|
|
uint16_t cipherSuite)
|
|
{
|
|
return matrixSslEncodeRehandshake(clnConn->ssl, NULL, NULL,
|
|
SSL_OPTION_FULL_HANDSHAKE, &cipherSuite, 1);
|
|
}
|
|
|
|
static int32 initializeServerInitiatedReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite)
|
|
{
|
|
return matrixSslEncodeRehandshake(svrConn->ssl, NULL, NULL,
|
|
SSL_OPTION_FULL_HANDSHAKE, &cipherSuite, 1);
|
|
}
|
|
|
|
static int32 initializeServerInitiatedResumedReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite)
|
|
{
|
|
return matrixSslEncodeRehandshake(svrConn->ssl, NULL, NULL, 0, &cipherSuite,
|
|
1);
|
|
|
|
}
|
|
|
|
static int32 initializeResumedReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite)
|
|
{
|
|
return matrixSslEncodeRehandshake(clnConn->ssl, NULL, NULL, 0, &cipherSuite,
|
|
1);
|
|
}
|
|
|
|
static int32 initializeUpgradeCertCbackReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite)
|
|
{
|
|
return matrixSslEncodeRehandshake(clnConn->ssl, NULL, clnCertCheckerUpdate,
|
|
0, &cipherSuite, 1);
|
|
}
|
|
|
|
static int32 initializeUpgradeKeysReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite)
|
|
{
|
|
/*
|
|
Not really changing the keys but this still tests that passing a
|
|
valid arg will force a full handshake
|
|
*/
|
|
return matrixSslEncodeRehandshake(clnConn->ssl, clnConn->ssl->keys, NULL,
|
|
0, &cipherSuite, 1);
|
|
}
|
|
|
|
static int32 initializeChangeCipherReHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite)
|
|
{
|
|
/*
|
|
Just picking the most common suite
|
|
*/
|
|
#ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA
|
|
uint16_t suite;
|
|
suite = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
|
|
return matrixSslEncodeRehandshake(clnConn->ssl, NULL, NULL,
|
|
0, &suite, 1);
|
|
#else
|
|
return matrixSslEncodeRehandshake(clnConn->ssl, NULL, NULL, 0, 0, 0);
|
|
#endif
|
|
}
|
|
|
|
#ifdef USE_CLIENT_AUTH
|
|
static int32 initializeReHandshakeClientAuth(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite)
|
|
{
|
|
return matrixSslEncodeRehandshake(svrConn->ssl, NULL, svrCertChecker, 0,
|
|
&cipherSuite, 1);
|
|
}
|
|
#endif /* USE_CLIENT_AUTH */
|
|
#endif /* SSL_REHANDSHAKES_ENABLED */
|
|
|
|
static int32 initializeResumedHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
|
|
uint16_t cipherSuite)
|
|
{
|
|
sslSessionId_t *sessionId;
|
|
sslSessOpts_t options;
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psTime_t start, end;
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
sessionId = clnConn->ssl->sid;
|
|
|
|
memset(&options, 0x0, sizeof(sslSessOpts_t));
|
|
options.versionFlag = g_versionFlag;
|
|
#ifdef USE_ECC_CIPHER_SUITE
|
|
options.ecFlags = clnConn->ssl->ecInfo.ecFlags;
|
|
#endif
|
|
#ifdef TEST_RESUMPTIONS_WITH_SESSION_TICKETS
|
|
options.ticketResumption = 1;
|
|
#endif
|
|
|
|
matrixSslDeleteSession(clnConn->ssl);
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
clnConn->hsTime = 0;
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
if (matrixSslNewClientSession(&clnConn->ssl, clnConn->keys, sessionId,
|
|
&cipherSuite, 1, clnCertChecker, "localhost", NULL, NULL,
|
|
&options)
|
|
< 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
clnConn->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
matrixSslDeleteSession(svrConn->ssl);
|
|
#ifdef ENABLE_PERF_TIMING
|
|
svrConn->hsTime = 0;
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
#ifdef USE_SERVER_SIDE_SSL
|
|
if (matrixSslNewServerSession(&svrConn->ssl, svrConn->keys, NULL,
|
|
&options) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
svrConn->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
#ifdef USE_CLIENT_AUTH
|
|
static int32 initializeClientAuthHandshake(sslConn_t *clnConn,
|
|
sslConn_t *svrConn, uint16_t cipherSuite, sslSessionId_t *sid)
|
|
{
|
|
sslSessOpts_t options;
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psTime_t start, end;
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
memset(&options, 0x0, sizeof(sslSessOpts_t));
|
|
options.versionFlag = g_versionFlag;
|
|
#ifdef USE_ECC_CIPHER_SUITE
|
|
options.ecFlags = clnConn->ssl->ecInfo.ecFlags;
|
|
#endif
|
|
#ifdef TEST_RESUMPTIONS_WITH_SESSION_TICKETS
|
|
options.ticketResumption = 1;
|
|
#endif
|
|
|
|
matrixSslDeleteSession(clnConn->ssl);
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
clnConn->hsTime = 0;
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
if (matrixSslNewClientSession(&clnConn->ssl, clnConn->keys, sid,
|
|
&cipherSuite, 1, clnCertChecker, "localhost", NULL, NULL,
|
|
&options) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
clnConn->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
matrixSslDeleteSession(svrConn->ssl);
|
|
#ifdef ENABLE_PERF_TIMING
|
|
svrConn->hsTime = 0;
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
#ifdef USE_SERVER_SIDE_SSL
|
|
if (matrixSslNewServerSession(&svrConn->ssl, svrConn->keys, svrCertChecker,
|
|
&options) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
svrConn->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
return PS_SUCCESS;
|
|
}
|
|
#endif /* USE_CLIENT_AUTH */
|
|
|
|
/*
|
|
Recursive handshake
|
|
*/
|
|
static int32 performHandshake(sslConn_t *sendingSide, sslConn_t *receivingSide)
|
|
{
|
|
unsigned char *inbuf, *outbuf, *plaintextBuf;
|
|
int32 inbufLen, outbufLen, rc, dataSent;
|
|
uint32 ptLen;
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psTime_t start, end;
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
/*
|
|
Sending side will have outdata ready
|
|
*/
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
#ifdef USE_DTLS
|
|
if (sendingSide->ssl->flags & SSL_FLAGS_DTLS) {
|
|
outbufLen = matrixDtlsGetOutdata(sendingSide->ssl, &outbuf);
|
|
} else {
|
|
outbufLen = matrixSslGetOutdata(sendingSide->ssl, &outbuf);
|
|
}
|
|
#else
|
|
outbufLen = matrixSslGetOutdata(sendingSide->ssl, &outbuf);
|
|
#endif
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
sendingSide->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
/*
|
|
Receiving side must ask for storage space to receive data into
|
|
*/
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
inbufLen = matrixSslGetReadbuf(receivingSide->ssl, &inbuf);
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
receivingSide->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
/*
|
|
The indata is the outdata from the sending side. copy it over
|
|
*/
|
|
dataSent = min(outbufLen, inbufLen);
|
|
memcpy(inbuf, outbuf, dataSent);
|
|
|
|
/*
|
|
Now update the sending side that data has been "sent"
|
|
*/
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
#ifdef USE_DTLS
|
|
if (sendingSide->ssl->flags & SSL_FLAGS_DTLS) {
|
|
matrixDtlsSentData(sendingSide->ssl, dataSent);
|
|
} else {
|
|
matrixSslSentData(sendingSide->ssl, dataSent);
|
|
}
|
|
#else
|
|
matrixSslSentData(sendingSide->ssl, dataSent);
|
|
#endif
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
sendingSide->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
/*
|
|
Received data
|
|
*/
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
rc = matrixSslReceivedData(receivingSide->ssl, dataSent, &plaintextBuf,
|
|
&ptLen);
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
receivingSide->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
if (rc == MATRIXSSL_REQUEST_SEND) {
|
|
/*
|
|
Success case. Switch roles and continue
|
|
*/
|
|
return performHandshake(receivingSide, sendingSide);
|
|
|
|
} else if (rc == MATRIXSSL_REQUEST_RECV) {
|
|
/*
|
|
This pass didn't take care of it all. Don't switch roles and
|
|
try again
|
|
*/
|
|
return performHandshake(sendingSide, receivingSide);
|
|
|
|
} else if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) {
|
|
return PS_SUCCESS;
|
|
|
|
} else if (rc == MATRIXSSL_RECEIVED_ALERT) {
|
|
/*
|
|
Just continue if warning level alert
|
|
*/
|
|
if (plaintextBuf[0] == SSL_ALERT_LEVEL_WARNING) {
|
|
if (matrixSslProcessedData(receivingSide->ssl, &plaintextBuf,
|
|
&ptLen) != 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
return performHandshake(sendingSide, receivingSide);
|
|
} else {
|
|
return PS_FAILURE;
|
|
}
|
|
|
|
} else {
|
|
printf("Unexpected error in performHandshake: %d\n", rc);
|
|
return PS_FAILURE;
|
|
}
|
|
return PS_FAILURE; /* can't get here */
|
|
}
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
static void ciphername(uint32_t flags, char s[32])
|
|
{
|
|
s[0] = '\0';
|
|
if (flags & CRYPTO_FLAGS_AES) {
|
|
strcat(s, "AES");
|
|
} else if (flags & CRYPTO_FLAGS_AES256) {
|
|
strcat(s, "AES256");
|
|
} else if (flags & CRYPTO_FLAGS_3DES) {
|
|
strcat(s, "3DES");
|
|
} else if (flags & CRYPTO_FLAGS_ARC4) {
|
|
strcat(s, "RC4");
|
|
} else if (flags & CRYPTO_FLAGS_SEED) {
|
|
strcat(s, "SEED");
|
|
} else if (flags & CRYPTO_FLAGS_IDEA) {
|
|
strcat(s, "IDEA");
|
|
}
|
|
if (flags & CRYPTO_FLAGS_GCM) {
|
|
strcat(s, "_GCM");
|
|
} else if (flags & CRYPTO_FLAGS_SHA1) {
|
|
strcat(s, "_SHA");
|
|
} else if (flags & CRYPTO_FLAGS_SHA2) {
|
|
strcat(s, "_SHA256");
|
|
} else if (flags & CRYPTO_FLAGS_SHA3) {
|
|
strcat(s, "_SHA384");
|
|
} else if (flags & CRYPTO_FLAGS_MD5) {
|
|
strcat(s, "_MD5");
|
|
}
|
|
}
|
|
|
|
static uint32_t g_ttest[64];
|
|
static uint32_t g_ttest_val[64];
|
|
static uint16_t g_ttest_count = 0;
|
|
|
|
static void print_throughput(void)
|
|
{
|
|
char name[32];
|
|
int i;
|
|
|
|
printf("Cipher" DELIM "MiB/s\n");
|
|
for (i = 0; i < g_ttest_count; i++) {
|
|
ciphername(g_ttest[i], name);
|
|
printf("%s" DELIM "%u\n", name, MBS(g_ttest_val[i]));
|
|
}
|
|
}
|
|
|
|
static int32_t throughputTest(sslConn_t *s, sslConn_t *r, uint16_t nrec, uint16_t reclen)
|
|
{
|
|
uint32_t i, len, flags;
|
|
int32_t rc, buflen;
|
|
unsigned char *rb, *wb, *pt;
|
|
char name[32];
|
|
|
|
psTime_t start, end;
|
|
#ifndef USE_HIGHRES_TIME
|
|
psTime_t tstart;
|
|
#endif
|
|
|
|
#ifdef USE_DTLS
|
|
if (s->ssl->flags & SSL_FLAGS_DTLS) {
|
|
return PS_SUCCESS;
|
|
}
|
|
#endif
|
|
flags = s->ssl->cipher->flags;
|
|
for (i = 0; i < g_ttest_count; i++) {
|
|
if (g_ttest[i] == flags) {
|
|
s->appTime = r->appTime = g_ttest_val[i];
|
|
return PS_SUCCESS;
|
|
}
|
|
}
|
|
s->appTime = r->appTime = 0;
|
|
ciphername(flags, name);
|
|
printf("%s throughput test for %hu byte records (%u bytes total)\n",
|
|
name, reclen, nrec * reclen);
|
|
|
|
#ifndef USE_HIGHRES_TIME
|
|
psGetTime(&tstart, NULL);
|
|
#endif
|
|
for (i = 0; i < nrec; i++) {
|
|
buflen = matrixSslGetWritebuf(s->ssl, &wb, reclen);
|
|
if (buflen < reclen) {
|
|
return PS_FAIL;
|
|
}
|
|
psGetTime(&start, NULL);
|
|
buflen = matrixSslEncodeWritebuf(s->ssl, reclen);
|
|
if (buflen < 0) {
|
|
return buflen;
|
|
}
|
|
#ifdef USE_DTLS
|
|
if (flags & SSL_FLAGS_DTLS) {
|
|
buflen = matrixDtlsGetOutdata(s->ssl, &wb);
|
|
} else {
|
|
buflen = matrixSslGetOutdata(s->ssl, &wb);
|
|
}
|
|
#else
|
|
buflen = matrixSslGetOutdata(s->ssl, &wb);
|
|
#endif
|
|
psGetTime(&end, NULL);
|
|
s->appTime += psDiffMsecs(start, end, NULL);
|
|
|
|
len = matrixSslGetReadbufOfSize(r->ssl, buflen, &rb);
|
|
if (len < buflen) {
|
|
return PS_FAIL;
|
|
}
|
|
memcpy(rb, wb, buflen);
|
|
|
|
psGetTime(&start, NULL);
|
|
#ifdef USE_DTLS
|
|
if (flags & SSL_FLAGS_DTLS) {
|
|
rc = matrixDtlsSentData(s->ssl, buflen);
|
|
} else {
|
|
rc = matrixSslSentData(s->ssl, buflen);
|
|
}
|
|
#else
|
|
rc = matrixSslSentData(s->ssl, buflen);
|
|
#endif
|
|
psGetTime(&end, NULL);
|
|
s->appTime += psDiffMsecs(start, end, NULL);
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
psGetTime(&start, NULL);
|
|
rc = matrixSslReceivedData(r->ssl, buflen, &pt, &len);
|
|
if (rc != MATRIXSSL_APP_DATA) {
|
|
return rc;
|
|
}
|
|
/* This is a loop, since with BEAST mode, 2 records may result from one encode */
|
|
while (rc == MATRIXSSL_APP_DATA) {
|
|
rc = matrixSslProcessedData(r->ssl, &pt, &len);
|
|
}
|
|
psGetTime(&end, NULL);
|
|
r->appTime += psDiffMsecs(start, end, NULL);
|
|
if (rc != 0) {
|
|
return PS_FAIL;
|
|
}
|
|
}
|
|
#ifndef USE_HIGHRES_TIME
|
|
s->appTime = psDiffMsecs(tstart, end, NULL) / 2;
|
|
r->appTime = s->appTime;
|
|
#endif
|
|
printf(" throughput send %u MiB/s\n", MBS(s->appTime));
|
|
printf(" throughput recv %u MiB/s\n", MBS(r->appTime));
|
|
g_ttest[g_ttest_count] = flags;
|
|
g_ttest_val[g_ttest_count] = s->appTime;
|
|
g_ttest_count++;
|
|
return PS_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
If bytes == 0, does not exchange data.
|
|
return 0 on successful encryption/decryption communication
|
|
return -1 on failed comm
|
|
*/
|
|
static int32 exchangeAppData(sslConn_t *sendingSide, sslConn_t *receivingSide, uint32_t bytes)
|
|
{
|
|
int32 writeBufLen, inBufLen, dataSent, rc, sentRc;
|
|
uint32 ptLen, requestedLen, copyLen, halfReqLen;
|
|
unsigned char *writeBuf, *inBuf, *plaintextBuf;
|
|
unsigned char copyByte;
|
|
|
|
if (bytes == 0) {
|
|
return PS_SUCCESS;
|
|
}
|
|
requestedLen = bytes;
|
|
copyByte = 0x1;
|
|
/*
|
|
Split the data into two records sends. Exercises the API a bit more
|
|
having the extra buffer management for multiple records
|
|
*/
|
|
while (requestedLen > 1) {
|
|
copyByte++;
|
|
halfReqLen = requestedLen / 2;
|
|
writeBufLen = matrixSslGetWritebuf(sendingSide->ssl, &writeBuf, halfReqLen);
|
|
if (writeBufLen <= 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
copyLen = min(halfReqLen, (uint32)writeBufLen);
|
|
//memset(writeBuf, copyByte, copyLen);
|
|
requestedLen -= copyLen;
|
|
//psTraceBytes("sending", writeBuf, copyLen);
|
|
|
|
writeBufLen = matrixSslEncodeWritebuf(sendingSide->ssl, copyLen);
|
|
if (writeBufLen < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
copyByte++;
|
|
writeBufLen = matrixSslGetWritebuf(sendingSide->ssl, &writeBuf,
|
|
halfReqLen);
|
|
if (writeBufLen <= 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
copyLen = min(halfReqLen, (uint32)writeBufLen);
|
|
//memset(writeBuf, copyByte, copyLen);
|
|
requestedLen -= copyLen;
|
|
//psTraceBytes("sending", writeBuf, copyLen);
|
|
|
|
writeBufLen = matrixSslEncodeWritebuf(sendingSide->ssl, copyLen);
|
|
if (writeBufLen < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
}
|
|
|
|
SEND_MORE:
|
|
#ifdef USE_DTLS
|
|
if (sendingSide->ssl->flags & SSL_FLAGS_DTLS) {
|
|
writeBufLen = matrixDtlsGetOutdata(sendingSide->ssl, &writeBuf);
|
|
} else {
|
|
writeBufLen = matrixSslGetOutdata(sendingSide->ssl, &writeBuf);
|
|
}
|
|
#else
|
|
writeBufLen = matrixSslGetOutdata(sendingSide->ssl, &writeBuf);
|
|
#endif
|
|
|
|
/*
|
|
Receiving side must ask for storage space to receive data into.
|
|
|
|
A good optimization of the buffer management can be seen here if a
|
|
second pass was required: the inBufLen should exactly match the
|
|
writeBufLen because when matrixSslReceivedData was called below the
|
|
record length was parsed off and the buffer was reallocated to the
|
|
exact necessary length
|
|
*/
|
|
inBufLen = matrixSslGetReadbuf(receivingSide->ssl, &inBuf);
|
|
|
|
dataSent = min(writeBufLen, inBufLen);
|
|
memcpy(inBuf, writeBuf, dataSent);
|
|
|
|
/* Now update the sending side that data has been "sent" */
|
|
#ifdef USE_DTLS
|
|
if (sendingSide->ssl->flags & SSL_FLAGS_DTLS) {
|
|
sentRc = matrixDtlsSentData(sendingSide->ssl, dataSent);
|
|
} else {
|
|
sentRc = matrixSslSentData(sendingSide->ssl, dataSent);
|
|
}
|
|
#else
|
|
sentRc = matrixSslSentData(sendingSide->ssl, dataSent);
|
|
#endif
|
|
|
|
/* Received data */
|
|
rc = matrixSslReceivedData(receivingSide->ssl, dataSent, &plaintextBuf,
|
|
&ptLen);
|
|
|
|
if (rc == MATRIXSSL_REQUEST_RECV) {
|
|
goto SEND_MORE;
|
|
} else if (rc == MATRIXSSL_APP_DATA || rc == MATRIXSSL_APP_DATA_COMPRESSED){
|
|
while (rc == MATRIXSSL_APP_DATA || rc == MATRIXSSL_APP_DATA_COMPRESSED){
|
|
//psTraceBytes("received", plaintextBuf, ptLen);
|
|
if ((rc = matrixSslProcessedData(receivingSide->ssl, &plaintextBuf,
|
|
&ptLen)) != 0) {
|
|
if (rc == MATRIXSSL_APP_DATA ||
|
|
rc == MATRIXSSL_APP_DATA_COMPRESSED) {
|
|
continue;
|
|
} else if (rc == MATRIXSSL_REQUEST_RECV) {
|
|
goto SEND_MORE;
|
|
} else {
|
|
return PS_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
if (sentRc == MATRIXSSL_REQUEST_SEND) {
|
|
goto SEND_MORE;
|
|
}
|
|
} else {
|
|
printf("Unexpected error in exchangeAppData: %d\n", rc);
|
|
return PS_FAILURE;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
|
|
static int32 initializeServer(sslConn_t *conn, uint16_t cipherSuite)
|
|
{
|
|
sslKeys_t *keys = NULL;
|
|
ssl_t *ssl = NULL;
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psTime_t start, end;
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
sslSessOpts_t options;
|
|
const sslCipherSpec_t *spec;
|
|
|
|
memset(&options, 0x0, sizeof(sslSessOpts_t));
|
|
options.versionFlag = g_versionFlag;
|
|
|
|
if (conn->keys == NULL) {
|
|
if ((spec = sslGetDefinedCipherSpec(cipherSuite)) == NULL) {
|
|
return PS_FAIL;
|
|
}
|
|
if (matrixSslNewKeys(&keys, NULL) < PS_SUCCESS) {
|
|
return PS_MEM_FAIL;
|
|
}
|
|
conn->keys = keys;
|
|
|
|
|
|
#ifdef USE_ECC
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
if (spec->type == CS_ECDH_ECDSA || spec->type == CS_ECDHE_ECDSA) {
|
|
#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS)
|
|
if (matrixSslLoadEcKeys(keys, svrEcCertFile, svrEcKeyFile, NULL,
|
|
clnEcCAfile) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */
|
|
|
|
#ifdef USE_HEADER_KEYS
|
|
if (matrixSslLoadEcKeysMem(keys, ECC, ECC_SIZE,
|
|
ECCKEY, ECCKEY_SIZE,
|
|
ECCCA, ECCCA_SIZE) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* USE_HEADER_KEYS */
|
|
}
|
|
|
|
/* ECDH_RSA suites have a different cert pair */
|
|
if (spec->type == CS_ECDH_RSA) {
|
|
#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS)
|
|
if (matrixSslLoadEcKeys(keys, svrEcRsaCertFile, svrEcRsaKeyFile,
|
|
NULL, clnEcRsaCAfile) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */
|
|
|
|
#ifdef USE_HEADER_KEYS
|
|
if (matrixSslLoadEcKeysMem(keys, ECDHRSA256, sizeof(ECDHRSA256),
|
|
ECDHRSA256KEY, sizeof(ECDHRSA256KEY),
|
|
ECDHRSA2048CA, sizeof(ECDHRSA2048CA)) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* USE_HEADER_KEYS */
|
|
}
|
|
#endif /* !USE_ONLY_PSK_CIPHER_SUITE */
|
|
#endif /* USE_ECC */
|
|
|
|
|
|
#ifdef USE_RSA
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
if (spec->type == CS_RSA || spec->type == CS_DHE_RSA ||
|
|
spec->type == CS_ECDHE_RSA) {
|
|
#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS)
|
|
if (matrixSslLoadRsaKeys(keys, svrCertFile, svrKeyFile, NULL,
|
|
clnCAfile) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */
|
|
|
|
#ifdef USE_HEADER_KEYS
|
|
if (matrixSslLoadRsaKeysMem(keys, (unsigned char *)RSACERT, RSA_SIZE,
|
|
(unsigned char *)RSAKEY, RSAKEY_SIZE,
|
|
(unsigned char *)RSACA, RSACA_SIZE) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* USE_HEADER_KEYS */
|
|
}
|
|
#endif /* !USE_ONLY_PSK_CIPHER_SUITE */
|
|
#endif /* USE_RSA */
|
|
|
|
#ifdef REQUIRE_DH_PARAMS
|
|
if (spec->type == CS_DHE_RSA || spec->type == CS_DH_ANON ||
|
|
spec->type == CS_DHE_PSK) {
|
|
#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS)
|
|
matrixSslLoadDhParams(keys, dhParamFile);
|
|
#endif
|
|
#ifdef USE_HEADER_KEYS
|
|
matrixSslLoadDhParamsMem(keys, DHPARAM, DH_SIZE);
|
|
#endif
|
|
}
|
|
#endif /* REQUIRE_DH_PARAMS */
|
|
|
|
#ifdef USE_PSK_CIPHER_SUITE
|
|
if (spec->type == CS_PSK || spec->type == CS_DHE_PSK) {
|
|
int rc;
|
|
for (rc = 0; rc < PSK_HEADER_TABLE_COUNT; rc++) {
|
|
matrixSslLoadPsk(keys,
|
|
PSK_HEADER_TABLE[rc].key, sizeof(PSK_HEADER_TABLE[rc].key),
|
|
PSK_HEADER_TABLE[rc].id, sizeof(PSK_HEADER_TABLE[rc].id));
|
|
}
|
|
}
|
|
#endif /* USE_PSK_CIPHER_SUITE */
|
|
}
|
|
#ifdef ENABLE_PERF_TIMING
|
|
conn->hsTime = 0;
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
/*
|
|
Create a new SSL session for the new socket and register the
|
|
user certificate validator. No client auth first time through
|
|
*/
|
|
#ifdef USE_SERVER_SIDE_SSL
|
|
if (matrixSslNewServerSession(&ssl, conn->keys, NULL, &options) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
conn->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
conn->ssl = ssl;
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
|
|
static int32 initializeClient(sslConn_t *conn, uint16_t cipherSuite,
|
|
sslSessionId_t *sid)
|
|
{
|
|
ssl_t *ssl;
|
|
sslKeys_t *keys;
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psTime_t start, end;
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
sslSessOpts_t options;
|
|
const sslCipherSpec_t *spec;
|
|
|
|
memset(&options, 0x0, sizeof(sslSessOpts_t));
|
|
options.versionFlag = g_versionFlag;
|
|
#ifdef TEST_RESUMPTIONS_WITH_SESSION_TICKETS
|
|
options.ticketResumption = 1;
|
|
#endif
|
|
|
|
if (conn->keys == NULL) {
|
|
if ((spec = sslGetDefinedCipherSpec(cipherSuite)) == NULL) {
|
|
return PS_FAIL;
|
|
}
|
|
if (matrixSslNewKeys(&keys, NULL) < PS_SUCCESS) {
|
|
return PS_MEM_FAIL;
|
|
}
|
|
conn->keys = keys;
|
|
|
|
#ifdef USE_ECC_CIPHER_SUITE
|
|
if (spec->type == CS_ECDHE_ECDSA || spec->type == CS_ECDHE_RSA) {
|
|
/* For ephemeral ECC keys, define the ephemeral size here,
|
|
otherwise it will default to the largest. We choose the size
|
|
based on the size set for the ECDSA key (even in RSA case). */
|
|
switch (ECC_SIZE) {
|
|
case EC192_SIZE:
|
|
options.ecFlags = SSL_OPT_SECP192R1;
|
|
break;
|
|
case EC224_SIZE:
|
|
options.ecFlags = SSL_OPT_SECP224R1;
|
|
break;
|
|
case EC256_SIZE:
|
|
options.ecFlags = SSL_OPT_SECP256R1;
|
|
break;
|
|
case EC384_SIZE:
|
|
options.ecFlags = SSL_OPT_SECP384R1;
|
|
break;
|
|
case EC521_SIZE:
|
|
options.ecFlags = SSL_OPT_SECP521R1;
|
|
break;
|
|
}
|
|
}
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
if (spec->type == CS_ECDH_ECDSA || spec->type == CS_ECDHE_ECDSA) {
|
|
#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS)
|
|
if (matrixSslLoadEcKeys(keys, clnEcCertFile, clnEcKeyFile, NULL,
|
|
svrEcCAfile) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */
|
|
|
|
#ifdef USE_HEADER_KEYS
|
|
if (matrixSslLoadEcKeysMem(keys, ECC, ECC_SIZE,
|
|
ECCKEY, ECCKEY_SIZE,
|
|
ECCCA, ECCCA_SIZE) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* USE_HEADER_KEYS */
|
|
}
|
|
|
|
#ifdef USE_RSA
|
|
/* ECDH_RSA suites have different cert pair. */
|
|
if (spec->type == CS_ECDH_RSA) {
|
|
#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS)
|
|
if (matrixSslLoadEcKeys(keys, clnEcRsaCertFile, clnEcRsaKeyFile,
|
|
NULL, svrEcRsaCAfile) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */
|
|
|
|
#ifdef USE_HEADER_KEYS
|
|
#if 0
|
|
if (matrixSslLoadEcKeysMem(keys, ECDHRSA521, sizeof(ECDHRSA521),
|
|
ECDHRSA521KEY, sizeof(ECDHRSA521KEY),
|
|
ECDHRSA1024CA, sizeof(ECDHRSA1024CA)) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif
|
|
#endif /* USE_HEADER_KEYS */
|
|
}
|
|
#endif /* USE_RSA */
|
|
#endif /* USE_ONLY_PSK_CIPHER_SUITE */
|
|
#endif /* USE_ECC */
|
|
|
|
#ifdef USE_RSA
|
|
#ifndef USE_ONLY_PSK_CIPHER_SUITE
|
|
if (spec->type == CS_RSA || spec->type == CS_DHE_RSA ||
|
|
spec->type == CS_ECDHE_RSA) {
|
|
#if defined(MATRIX_USE_FILE_SYSTEM) && !defined(USE_HEADER_KEYS)
|
|
if (matrixSslLoadRsaKeys(keys, clnCertFile, clnKeyFile, NULL,
|
|
svrCAfile) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* MATRIX_USE_FILE_SYSTEM && !USE_HEADER_KEYS */
|
|
|
|
#ifdef USE_HEADER_KEYS
|
|
if (matrixSslLoadRsaKeysMem(keys, RSACERT, RSA_SIZE,
|
|
RSAKEY, RSAKEY_SIZE, (unsigned char *)RSACA,
|
|
RSACA_SIZE) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
#endif /* USE_HEADER_KEYS */
|
|
}
|
|
#endif /* USE_ONLY_PSK_CIPHER_SUITE */
|
|
#endif /* USE_RSA */
|
|
|
|
#ifdef USE_PSK_CIPHER_SUITE
|
|
if (spec->type == CS_PSK || spec->type == CS_DHE_PSK) {
|
|
matrixSslLoadPsk(keys,
|
|
PSK_HEADER_TABLE[0].key, sizeof(PSK_HEADER_TABLE[0].key),
|
|
PSK_HEADER_TABLE[0].id, sizeof(PSK_HEADER_TABLE[0].id));
|
|
}
|
|
#endif /* USE_PSK_CIPHER_SUITE */
|
|
}
|
|
|
|
conn->ssl = NULL;
|
|
#ifdef ENABLE_PERF_TIMING
|
|
conn->hsTime = 0;
|
|
psGetTime(&start, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
if (matrixSslNewClientSession(&ssl, conn->keys, sid, &cipherSuite,
|
|
1, clnCertChecker, "localhost", NULL, NULL, &options) < 0) {
|
|
return PS_FAILURE;
|
|
}
|
|
|
|
#ifdef ENABLE_PERF_TIMING
|
|
psGetTime(&end, NULL);
|
|
conn->hsTime += psDiffMsecs(start, end, NULL);
|
|
#endif /* ENABLE_PERF_TIMING */
|
|
|
|
conn->ssl = ssl;
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
Delete session and connection
|
|
*/
|
|
static void freeSessionAndConnection(sslConn_t *conn)
|
|
{
|
|
if (conn->ssl != NULL) {
|
|
matrixSslDeleteSession(conn->ssl);
|
|
}
|
|
matrixSslDeleteKeys(conn->keys);
|
|
conn->ssl = NULL;
|
|
conn->keys = NULL;
|
|
}
|
|
|
|
/* Ignoring the CERTIFICATE_EXPIRED alert in the test because it will
|
|
always fail on Windows because there is no implementation for that */
|
|
static int32_t clnCertChecker(ssl_t *ssl, psX509Cert_t *cert, int32_t alert)
|
|
{
|
|
if (alert == SSL_ALERT_CERTIFICATE_EXPIRED) {
|
|
return 0;
|
|
}
|
|
return alert;
|
|
}
|
|
|
|
#ifdef SSL_REHANDSHAKES_ENABLED
|
|
static int32 clnCertCheckerUpdate(ssl_t *ssl, psX509Cert_t *cert, int32 alert)
|
|
{
|
|
if (alert == SSL_ALERT_CERTIFICATE_EXPIRED) {
|
|
return 0;
|
|
}
|
|
return alert;
|
|
}
|
|
#endif /* SSL_REHANDSHAKES_ENABLED */
|
|
|
|
#ifdef USE_CLIENT_AUTH
|
|
static int32 svrCertChecker(ssl_t *ssl, psX509Cert_t *cert, int32 alert)
|
|
{
|
|
if (alert == SSL_ALERT_CERTIFICATE_EXPIRED) {
|
|
return 0;
|
|
}
|
|
return alert;
|
|
}
|
|
#endif /* USE_CLIENT_AUTH */
|
|
|
|
|
|
#ifdef USE_MATRIXSSL_STATS
|
|
static void statCback(void *ssl, void *stat_ptr, int32 type, int32 value)
|
|
{
|
|
//printf("Got stat event %d with value %d\n", type, value);
|
|
}
|
|
#endif
|
|
/******************************************************************************/
|
|
|
|
|