blob: 75d85b130e7f87c6b11092e8ba31d2ee16130f57 [file] [log] [blame]
/* internal.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL is free software; 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.
*
* wolfSSL is distributed in the hope that it will be useful,
* but 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/internal.h>
#include <wolfssl/error-ssl.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/dh.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#ifdef HAVE_LIBZ
#include "zlib.h"
#endif
#ifdef HAVE_NTRU
#include "ntru_crypto.h"
#endif
#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST)
#ifdef FREESCALE_MQX
#include <fio.h>
#else
#include <stdio.h>
#endif
#endif
#ifdef __sun
#include <sys/filio.h>
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifdef _MSC_VER
/* disable for while(0) cases at the .c level for now */
#pragma warning(disable:4127)
#endif
#if defined(WOLFSSL_CALLBACKS) && !defined(LARGE_STATIC_BUFFERS)
#error \
WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#endif
#if defined(HAVE_SECURE_RENEGOTIATION) && defined(HAVE_RENEGOTIATION_INDICATION)
#error Cannot use both secure-renegotiation and renegotiation-indication
#endif
static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
const byte* input, int inSz, int type);
#ifndef NO_WOLFSSL_CLIENT
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*,
word32);
static int DoServerHello(WOLFSSL* ssl, const byte* input, word32*, word32);
static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*,
word32);
#ifndef NO_CERTS
static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*,
word32);
#endif
#ifdef HAVE_SESSION_TICKET
static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32*,
word32);
#endif
#endif
#ifndef NO_WOLFSSL_SERVER
static int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, word32);
static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32);
#if !defined(NO_RSA) || defined(HAVE_ECC)
static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32);
#endif
#endif
#ifdef WOLFSSL_DTLS
static INLINE int DtlsCheckWindow(DtlsState* state);
static INLINE int DtlsUpdateWindow(DtlsState* state);
#endif
typedef enum {
doProcessInit = 0,
#ifndef NO_WOLFSSL_SERVER
runProcessOldClientHello,
#endif
getRecordLayerHeader,
getData,
runProcessingOneMessage
} processReply;
#ifndef NO_OLD_TLS
static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
int content, int verify);
#endif
#ifndef NO_CERTS
static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes);
#endif
static void PickHashSigAlgo(WOLFSSL* ssl,
const byte* hashSigAlgo, word32 hashSigAlgoSz);
#ifndef WOLFSSL_HAVE_MIN
#define WOLFSSL_HAVE_MIN
static INLINE word32 min(word32 a, word32 b)
{
return a > b ? b : a;
}
#endif /* WOLFSSL_HAVE_MIN */
int IsTLS(const WOLFSSL* ssl)
{
if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
return 1;
return 0;
}
int IsAtLeastTLSv1_2(const WOLFSSL* ssl)
{
if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
return 1;
if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR)
return 1;
return 0;
}
#ifdef HAVE_NTRU
static byte GetEntropy(ENTROPY_CMD cmd, byte* out)
{
/* TODO: add locking? */
static RNG rng;
if (cmd == INIT)
return (wc_InitRng(&rng) == 0) ? 1 : 0;
if (out == NULL)
return 0;
if (cmd == GET_BYTE_OF_ENTROPY)
return (wc_RNG_GenerateBlock(&rng, out, 1) == 0) ? 1 : 0;
if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) {
*out = 1;
return 1;
}
return 0;
}
#endif /* HAVE_NTRU */
/* used by ssl.c too */
void c32to24(word32 in, word24 out)
{
out[0] = (in >> 16) & 0xff;
out[1] = (in >> 8) & 0xff;
out[2] = in & 0xff;
}
#ifdef WOLFSSL_DTLS
static INLINE void c32to48(word32 in, byte out[6])
{
out[0] = 0;
out[1] = 0;
out[2] = (in >> 24) & 0xff;
out[3] = (in >> 16) & 0xff;
out[4] = (in >> 8) & 0xff;
out[5] = in & 0xff;
}
#endif /* WOLFSSL_DTLS */
/* convert 16 bit integer to opaque */
static INLINE void c16toa(word16 u16, byte* c)
{
c[0] = (u16 >> 8) & 0xff;
c[1] = u16 & 0xff;
}
#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
|| defined(HAVE_AESGCM)
/* convert 32 bit integer to opaque */
static INLINE void c32toa(word32 u32, byte* c)
{
c[0] = (u32 >> 24) & 0xff;
c[1] = (u32 >> 16) & 0xff;
c[2] = (u32 >> 8) & 0xff;
c[3] = u32 & 0xff;
}
#endif
/* convert a 24 bit integer into a 32 bit one */
static INLINE void c24to32(const word24 u24, word32* u32)
{
*u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
}
/* convert opaque to 16 bit integer */
static INLINE void ato16(const byte* c, word16* u16)
{
*u16 = (word16) ((c[0] << 8) | (c[1]));
}
#if defined(WOLFSSL_DTLS) || defined(HAVE_SESSION_TICKET)
/* convert opaque to 32 bit integer */
static INLINE void ato32(const byte* c, word32* u32)
{
*u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}
#endif /* WOLFSSL_DTLS */
#ifdef HAVE_LIBZ
/* alloc user allocs to work with zlib */
static void* myAlloc(void* opaque, unsigned int item, unsigned int size)
{
(void)opaque;
return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
}
static void myFree(void* opaque, void* memory)
{
(void)opaque;
XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
}
/* init zlib comp/decomp streams, 0 on success */
static int InitStreams(WOLFSSL* ssl)
{
ssl->c_stream.zalloc = (alloc_func)myAlloc;
ssl->c_stream.zfree = (free_func)myFree;
ssl->c_stream.opaque = (voidpf)ssl->heap;
if (deflateInit(&ssl->c_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
return ZLIB_INIT_ERROR;
ssl->didStreamInit = 1;
ssl->d_stream.zalloc = (alloc_func)myAlloc;
ssl->d_stream.zfree = (free_func)myFree;
ssl->d_stream.opaque = (voidpf)ssl->heap;
if (inflateInit(&ssl->d_stream) != Z_OK) return ZLIB_INIT_ERROR;
return 0;
}
static void FreeStreams(WOLFSSL* ssl)
{
if (ssl->didStreamInit) {
deflateEnd(&ssl->c_stream);
inflateEnd(&ssl->d_stream);
}
}
/* compress in to out, return out size or error */
static int myCompress(WOLFSSL* ssl, byte* in, int inSz, byte* out, int outSz)
{
int err;
int currTotal = (int)ssl->c_stream.total_out;
ssl->c_stream.next_in = in;
ssl->c_stream.avail_in = inSz;
ssl->c_stream.next_out = out;
ssl->c_stream.avail_out = outSz;
err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR;
return (int)ssl->c_stream.total_out - currTotal;
}
/* decompress in to out, returnn out size or error */
static int myDeCompress(WOLFSSL* ssl, byte* in,int inSz, byte* out,int outSz)
{
int err;
int currTotal = (int)ssl->d_stream.total_out;
ssl->d_stream.next_in = in;
ssl->d_stream.avail_in = inSz;
ssl->d_stream.next_out = out;
ssl->d_stream.avail_out = outSz;
err = inflate(&ssl->d_stream, Z_SYNC_FLUSH);
if (err != Z_OK && err != Z_STREAM_END) return ZLIB_DECOMPRESS_ERROR;
return (int)ssl->d_stream.total_out - currTotal;
}
#endif /* HAVE_LIBZ */
void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv)
{
method->version = pv;
method->side = WOLFSSL_CLIENT_END;
method->downgrade = 0;
}
/* Initialze SSL context, return 0 on success */
int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method)
{
XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX));
ctx->method = method;
ctx->refCount = 1; /* so either CTX_free or SSL_free can release */
ctx->heap = ctx; /* defaults to self */
ctx->timeout = WOLFSSL_SESSION_TIMEOUT;
ctx->minDowngrade = TLSv1_MINOR; /* current default */
if (InitMutex(&ctx->countMutex) < 0) {
WOLFSSL_MSG("Mutex error on CTX init");
return BAD_MUTEX_E;
}
#ifndef NO_DH
ctx->minDhKeySz = MIN_DHKEY_SZ;
#endif
#ifdef HAVE_ECC
ctx->eccTempKeySz = ECDHE_SIZE;
#endif
#ifndef WOLFSSL_USER_IO
ctx->CBIORecv = EmbedReceive;
ctx->CBIOSend = EmbedSend;
#ifdef WOLFSSL_DTLS
if (method->version.major == DTLS_MAJOR) {
ctx->CBIORecv = EmbedReceiveFrom;
ctx->CBIOSend = EmbedSendTo;
ctx->CBIOCookie = EmbedGenerateCookie;
}
#endif
#endif /* WOLFSSL_USER_IO */
#ifdef HAVE_NETX
ctx->CBIORecv = NetX_Receive;
ctx->CBIOSend = NetX_Send;
#endif
#ifdef HAVE_NTRU
if (method->side == WOLFSSL_CLIENT_END)
ctx->haveNTRU = 1; /* always on cliet side */
/* server can turn on by loading key */
#endif
#ifdef HAVE_ECC
if (method->side == WOLFSSL_CLIENT_END) {
ctx->haveECDSAsig = 1; /* always on cliet side */
ctx->haveStaticECC = 1; /* server can turn on by loading key */
}
#endif
#ifdef HAVE_CAVIUM
ctx->devId = NO_CAVIUM_DEVICE;
#endif
#ifndef NO_CERTS
ctx->cm = wolfSSL_CertManagerNew();
if (ctx->cm == NULL) {
WOLFSSL_MSG("Bad Cert Manager New");
return BAD_CERT_MANAGER_ERROR;
}
#endif
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
#endif
return 0;
}
/* In case contexts are held in array and don't want to free actual ctx */
void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
{
XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
if (ctx->suites)
XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES);
#ifndef NO_DH
XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH);
XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
#endif
#ifndef NO_CERTS
XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
XFREE(ctx->certChain.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
wolfSSL_CertManagerFree(ctx->cm);
#endif
#ifdef HAVE_TLS_EXTENSIONS
TLSX_FreeAll(ctx->extensions);
#endif
}
void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
{
int doFree = 0;
if (LockMutex(&ctx->countMutex) != 0) {
WOLFSSL_MSG("Couldn't lock count mutex");
return;
}
ctx->refCount--;
if (ctx->refCount == 0)
doFree = 1;
UnLockMutex(&ctx->countMutex);
if (doFree) {
WOLFSSL_MSG("CTX ref count down to 0, doing full free");
SSL_CtxResourceFree(ctx);
FreeMutex(&ctx->countMutex);
XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
}
else {
(void)ctx;
WOLFSSL_MSG("CTX ref count not 0 yet, no free");
}
}
/* Set cipher pointers to null */
void InitCiphers(WOLFSSL* ssl)
{
#ifdef BUILD_ARC4
ssl->encrypt.arc4 = NULL;
ssl->decrypt.arc4 = NULL;
#endif
#ifdef BUILD_DES3
ssl->encrypt.des3 = NULL;
ssl->decrypt.des3 = NULL;
#endif
#ifdef BUILD_AES
ssl->encrypt.aes = NULL;
ssl->decrypt.aes = NULL;
#endif
#ifdef HAVE_CAMELLIA
ssl->encrypt.cam = NULL;
ssl->decrypt.cam = NULL;
#endif
#ifdef HAVE_HC128
ssl->encrypt.hc128 = NULL;
ssl->decrypt.hc128 = NULL;
#endif
#ifdef BUILD_RABBIT
ssl->encrypt.rabbit = NULL;
ssl->decrypt.rabbit = NULL;
#endif
#ifdef HAVE_CHACHA
ssl->encrypt.chacha = NULL;
ssl->decrypt.chacha = NULL;
#endif
#ifdef HAVE_POLY1305
ssl->auth.poly1305 = NULL;
#endif
ssl->encrypt.setup = 0;
ssl->decrypt.setup = 0;
#ifdef HAVE_ONE_TIME_AUTH
ssl->auth.setup = 0;
#endif
}
/* Free ciphers */
void FreeCiphers(WOLFSSL* ssl)
{
(void)ssl;
#ifdef BUILD_ARC4
#ifdef HAVE_CAVIUM
if (ssl->devId != NO_CAVIUM_DEVICE) {
wc_Arc4FreeCavium(ssl->encrypt.arc4);
wc_Arc4FreeCavium(ssl->decrypt.arc4);
}
#endif
XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef BUILD_DES3
#ifdef HAVE_CAVIUM
if (ssl->devId != NO_CAVIUM_DEVICE) {
wc_Des3_FreeCavium(ssl->encrypt.des3);
wc_Des3_FreeCavium(ssl->decrypt.des3);
}
#endif
XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef BUILD_AES
#ifdef HAVE_CAVIUM
if (ssl->devId != NO_CAVIUM_DEVICE) {
wc_AesFreeCavium(ssl->encrypt.aes);
wc_AesFreeCavium(ssl->decrypt.aes);
}
#endif
XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef HAVE_CAMELLIA
XFREE(ssl->encrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef HAVE_HC128
XFREE(ssl->encrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef BUILD_RABBIT
XFREE(ssl->encrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef HAVE_CHACHA
XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef HAVE_POLY1305
XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
}
void InitCipherSpecs(CipherSpecs* cs)
{
cs->bulk_cipher_algorithm = INVALID_BYTE;
cs->cipher_type = INVALID_BYTE;
cs->mac_algorithm = INVALID_BYTE;
cs->kea = INVALID_BYTE;
cs->sig_algo = INVALID_BYTE;
cs->hash_size = 0;
cs->static_ecdh = 0;
cs->key_size = 0;
cs->iv_size = 0;
cs->block_size = 0;
}
static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig,
int haveRSAsig, int haveAnon)
{
int idx = 0;
if (haveECDSAsig) {
#ifdef WOLFSSL_SHA512
suites->hashSigAlgo[idx++] = sha512_mac;
suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
#endif
#ifdef WOLFSSL_SHA384
suites->hashSigAlgo[idx++] = sha384_mac;
suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
#endif
#ifndef NO_SHA256
suites->hashSigAlgo[idx++] = sha256_mac;
suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
#endif
#ifndef NO_SHA
suites->hashSigAlgo[idx++] = sha_mac;
suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
#endif
}
if (haveRSAsig) {
#ifdef WOLFSSL_SHA512
suites->hashSigAlgo[idx++] = sha512_mac;
suites->hashSigAlgo[idx++] = rsa_sa_algo;
#endif
#ifdef WOLFSSL_SHA384
suites->hashSigAlgo[idx++] = sha384_mac;
suites->hashSigAlgo[idx++] = rsa_sa_algo;
#endif
#ifndef NO_SHA256
suites->hashSigAlgo[idx++] = sha256_mac;
suites->hashSigAlgo[idx++] = rsa_sa_algo;
#endif
#ifndef NO_SHA
suites->hashSigAlgo[idx++] = sha_mac;
suites->hashSigAlgo[idx++] = rsa_sa_algo;
#endif
}
if (haveAnon) {
#ifdef HAVE_ANON
suites->hashSigAlgo[idx++] = sha_mac;
suites->hashSigAlgo[idx++] = anonymous_sa_algo;
#endif
}
suites->hashSigAlgoSz = (word16)idx;
}
void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
word16 havePSK, word16 haveDH, word16 haveNTRU,
word16 haveECDSAsig, word16 haveStaticECC, int side)
{
word16 idx = 0;
int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR;
int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR;
int haveRSAsig = 1;
(void)tls; /* shut up compiler */
(void)tls1_2;
(void)haveDH;
(void)havePSK;
(void)haveNTRU;
(void)haveStaticECC;
if (suites == NULL) {
WOLFSSL_MSG("InitSuites pointer error");
return;
}
if (suites->setSuites)
return; /* trust user settings, don't override */
if (side == WOLFSSL_SERVER_END && haveStaticECC) {
haveRSA = 0; /* can't do RSA with ECDSA key */
(void)haveRSA; /* some builds won't read */
}
if (side == WOLFSSL_SERVER_END && haveECDSAsig) {
haveRSAsig = 0; /* can't have RSA sig if signed by ECDSA */
(void)haveRSAsig; /* non ecc builds won't read */
}
#ifdef WOLFSSL_DTLS
if (pv.major == DTLS_MAJOR) {
tls = 1;
tls1_2 = pv.minor <= DTLSv1_2_MINOR;
}
#endif
#ifdef HAVE_RENEGOTIATION_INDICATION
if (side == WOLFSSL_CLIENT_END) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
}
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
if (tls && haveNTRU && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
if (tls && haveNTRU && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
if (tls && haveNTRU && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveNTRU && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveECDSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveECDSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveDH && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveDH && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
if (tls1_2 && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
if (tls1_2 && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
if (tls1_2 && haveECDSAsig) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
if (tls && haveRSA) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
if (tls && haveRSA) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveRSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveECDSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
if (tls1_2 && haveRSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
if (tls1_2 && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
if (tls1_2 && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
if (tls1_2 && haveECDSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
if (tls && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
if (tls && haveECDSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
if (tls && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
if (tls && haveECDSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
if (tls && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
if (tls && haveECDSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveECDSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
if (tls && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
if (tls && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
if (tls1_2 && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
if (tls1_2 && haveECDSAsig) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
if (tls1_2 && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CCM_8;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
if (tls1_2 && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CCM_8;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
if (tls && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
if (tls && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
if (tls && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
if (tls && haveDH && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
if (tls && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA384;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
if (tls && haveDH && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
if (tls && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
if (tls && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
if (tls && haveDH && havePSK) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CCM;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
if (tls && haveDH && havePSK) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CCM;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
if (tls && havePSK) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
if (tls && havePSK) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
if (tls && havePSK) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM_8;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
if (tls && havePSK) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM_8;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
if (tls && haveDH && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
if (tls && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA384;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
if (tls && haveDH && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
if (tls && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
if (tls && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
if (haveRSA ) {
suites->suites[idx++] = 0;
suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
if (haveRSA ) {
suites->suites[idx++] = 0;
suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
if (haveRSA ) {
suites->suites[idx++] = 0;
suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_HC_128_MD5;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_HC_128_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_HC_128_B2B256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_B2B256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_B2B256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
if (tls && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_WITH_RSA_CAMELLIA_256_CBC_SHA
if (tls && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
if (tls && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
if (tls && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
if (tls && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256;
}
#endif
suites->suiteSz = idx;
InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0);
}
#ifndef NO_CERTS
void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag)
{
(void)dynamicFlag;
if (name != NULL) {
name->name = name->staticName;
name->dynamicName = 0;
#ifdef OPENSSL_EXTRA
XMEMSET(&name->fullName, 0, sizeof(DecodedName));
#endif /* OPENSSL_EXTRA */
}
}
void FreeX509Name(WOLFSSL_X509_NAME* name)
{
if (name != NULL) {
if (name->dynamicName)
XFREE(name->name, NULL, DYNAMIC_TYPE_SUBJECT_CN);
#ifdef OPENSSL_EXTRA
if (name->fullName.fullName != NULL)
XFREE(name->fullName.fullName, NULL, DYNAMIC_TYPE_X509);
#endif /* OPENSSL_EXTRA */
}
}
/* Initialize wolfSSL X509 type */
void InitX509(WOLFSSL_X509* x509, int dynamicFlag)
{
InitX509Name(&x509->issuer, 0);
InitX509Name(&x509->subject, 0);
x509->version = 0;
x509->pubKey.buffer = NULL;
x509->sig.buffer = NULL;
x509->derCert.buffer = NULL;
x509->altNames = NULL;
x509->altNamesNext = NULL;
x509->dynamicMemory = (byte)dynamicFlag;
x509->isCa = 0;
#ifdef HAVE_ECC
x509->pkCurveOID = 0;
#endif /* HAVE_ECC */
#ifdef OPENSSL_EXTRA
x509->pathLength = 0;
x509->basicConstSet = 0;
x509->basicConstCrit = 0;
x509->basicConstPlSet = 0;
x509->subjAltNameSet = 0;
x509->subjAltNameCrit = 0;
x509->authKeyIdSet = 0;
x509->authKeyIdCrit = 0;
x509->authKeyId = NULL;
x509->authKeyIdSz = 0;
x509->subjKeyIdSet = 0;
x509->subjKeyIdCrit = 0;
x509->subjKeyId = NULL;
x509->subjKeyIdSz = 0;
x509->keyUsageSet = 0;
x509->keyUsageCrit = 0;
x509->keyUsage = 0;
#ifdef WOLFSSL_SEP
x509->certPolicySet = 0;
x509->certPolicyCrit = 0;
#endif /* WOLFSSL_SEP */
#endif /* OPENSSL_EXTRA */
}
/* Free wolfSSL X509 type */
void FreeX509(WOLFSSL_X509* x509)
{
if (x509 == NULL)
return;
FreeX509Name(&x509->issuer);
FreeX509Name(&x509->subject);
if (x509->pubKey.buffer)
XFREE(x509->pubKey.buffer, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
XFREE(x509->derCert.buffer, NULL, DYNAMIC_TYPE_SUBJECT_CN);
XFREE(x509->sig.buffer, NULL, DYNAMIC_TYPE_SIGNATURE);
#ifdef OPENSSL_EXTRA
XFREE(x509->authKeyId, NULL, 0);
XFREE(x509->subjKeyId, NULL, 0);
#endif /* OPENSSL_EXTRA */
if (x509->altNames)
FreeAltNames(x509->altNames, NULL);
if (x509->dynamicMemory)
XFREE(x509, NULL, DYNAMIC_TYPE_X509);
}
#endif /* NO_CERTS */
/* init everything to 0, NULL, default values before calling anything that may
fail so that desctructor has a "good" state to cleanup */
int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
{
int ret;
byte haveRSA = 0;
byte havePSK = 0;
byte haveAnon = 0;
(void) haveAnon;
XMEMSET(ssl, 0, sizeof(WOLFSSL));
ssl->ctx = ctx; /* only for passing to calls, options could change */
ssl->version = ctx->method->version;
#ifndef NO_RSA
haveRSA = 1;
#endif
ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
#ifdef KEEP_PEER_CERT
InitX509(&ssl->peerCert, 0);
#endif
#ifdef HAVE_ECC
ssl->eccTempKeySz = ctx->eccTempKeySz;
ssl->pkCurveOID = ctx->pkCurveOID;
#endif
ssl->timeout = ctx->timeout;
ssl->rfd = -1; /* set to invalid descriptor */
ssl->wfd = -1;
ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */
ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */
#ifdef HAVE_NETX
ssl->IOCB_ReadCtx = &ssl->nxCtx; /* default NetX IO ctx, same for read */
ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */
#endif
#ifdef WOLFSSL_DTLS
ssl->dtls_expected_rx = MAX_MTU;
#endif
ssl->verifyCallback = ctx->verifyCallback;
ssl->options.side = ctx->method->side;
ssl->options.downgrade = ctx->method->downgrade;
ssl->options.minDowngrade = ctx->minDowngrade;
if (ssl->options.side == WOLFSSL_SERVER_END)
ssl->options.haveDH = ctx->haveDH;
ssl->options.haveNTRU = ctx->haveNTRU;
ssl->options.haveECDSAsig = ctx->haveECDSAsig;
ssl->options.haveStaticECC = ctx->haveStaticECC;
#ifndef NO_PSK
havePSK = ctx->havePSK;
ssl->options.havePSK = ctx->havePSK;
ssl->options.client_psk_cb = ctx->client_psk_cb;
ssl->options.server_psk_cb = ctx->server_psk_cb;
#endif /* NO_PSK */
#ifdef HAVE_ANON
haveAnon = ctx->haveAnon;
ssl->options.haveAnon = ctx->haveAnon;
#endif
ssl->options.serverState = NULL_STATE;
ssl->options.clientState = NULL_STATE;
ssl->options.connectState = CONNECT_BEGIN;
ssl->options.acceptState = ACCEPT_BEGIN;
ssl->options.handShakeState = NULL_STATE;
ssl->options.processReply = doProcessInit;
#ifndef NO_DH
ssl->options.minDhKeySz = ctx->minDhKeySz;
#endif
#ifdef WOLFSSL_DTLS
ssl->dtls_timeout_init = DTLS_TIMEOUT_INIT;
ssl->dtls_timeout_max = DTLS_TIMEOUT_MAX;
ssl->dtls_timeout = ssl->dtls_timeout_init;
#endif
ssl->options.sessionCacheOff = ctx->sessionCacheOff;
ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
ssl->options.verifyPeer = ctx->verifyPeer;
ssl->options.verifyNone = ctx->verifyNone;
ssl->options.failNoCert = ctx->failNoCert;
ssl->options.sendVerify = ctx->sendVerify;
#ifndef NO_OLD_TLS
ssl->hmac = SSL_hmac; /* default to SSLv3 */
#else
ssl->hmac = TLS_hmac;
#endif
ssl->heap = ctx->heap; /* defaults to self */
ssl->options.dtls = ssl->version.major == DTLS_MAJOR;
ssl->options.partialWrite = ctx->partialWrite;
ssl->options.quietShutdown = ctx->quietShutdown;
ssl->options.groupMessages = ctx->groupMessages;
#ifndef NO_DH
if (ssl->options.side == WOLFSSL_SERVER_END) {
ssl->buffers.serverDH_P = ctx->serverDH_P;
ssl->buffers.serverDH_G = ctx->serverDH_G;
}
#endif
#ifndef NO_CERTS
/* ctx still owns certificate, certChain, key, dh, and cm */
ssl->buffers.certificate = ctx->certificate;
ssl->buffers.certChain = ctx->certChain;
ssl->buffers.key = ctx->privateKey;
#endif
#ifdef WOLFSSL_DTLS
ssl->buffers.dtlsCtx.fd = -1;
#endif
ssl->cipher.ssl = ssl;
#ifdef HAVE_CAVIUM
ssl->devId = ctx->devId;
#endif
#ifdef HAVE_TLS_EXTENSIONS
#ifdef HAVE_MAX_FRAGMENT
ssl->max_fragment = MAX_RECORD_SIZE;
#endif
#endif
/* default alert state (none) */
ssl->alert_history.last_rx.code = -1;
ssl->alert_history.last_rx.level = -1;
ssl->alert_history.last_tx.code = -1;
ssl->alert_history.last_tx.level = -1;
InitCiphers(ssl);
InitCipherSpecs(&ssl->specs);
/* all done with init, now can return errors, call other stuff */
/* hsHashes */
ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap,
DYNAMIC_TYPE_HASHES);
if (ssl->hsHashes == NULL) {
WOLFSSL_MSG("HS_Hashes Memory error");
return MEMORY_E;
}
#ifndef NO_OLD_TLS
#ifndef NO_MD5
wc_InitMd5(&ssl->hsHashes->hashMd5);
#endif
#ifndef NO_SHA
ret = wc_InitSha(&ssl->hsHashes->hashSha);
if (ret != 0) {
return ret;
}
#endif
#endif
#ifndef NO_SHA256
ret = wc_InitSha256(&ssl->hsHashes->hashSha256);
if (ret != 0) {
return ret;
}
#endif
#ifdef WOLFSSL_SHA384
ret = wc_InitSha384(&ssl->hsHashes->hashSha384);
if (ret != 0) {
return ret;
}
#endif
#ifdef WOLFSSL_SHA512
ret = wc_InitSha512(&ssl->hsHashes->hashSha512);
if (ret != 0) {
return ret;
}
#endif
/* increment CTX reference count */
if (LockMutex(&ctx->countMutex) != 0) {
WOLFSSL_MSG("Couldn't lock CTX count mutex");
return BAD_MUTEX_E;
}
ctx->refCount++;
UnLockMutex(&ctx->countMutex);
/* arrays */
ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
DYNAMIC_TYPE_ARRAYS);
if (ssl->arrays == NULL) {
WOLFSSL_MSG("Arrays Memory error");
return MEMORY_E;
}
XMEMSET(ssl->arrays, 0, sizeof(Arrays));
#ifndef NO_PSK
if (ctx->server_hint[0]) { /* set in CTX */
XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, MAX_PSK_ID_LEN);
ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0';
}
#endif /* NO_PSK */
/* RNG */
ssl->rng = (RNG*)XMALLOC(sizeof(RNG), ssl->heap, DYNAMIC_TYPE_RNG);
if (ssl->rng == NULL) {
WOLFSSL_MSG("RNG Memory error");
return MEMORY_E;
}
if ( (ret = wc_InitRng(ssl->rng)) != 0) {
WOLFSSL_MSG("RNG Init error");
return ret;
}
/* suites */
ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
DYNAMIC_TYPE_SUITES);
if (ssl->suites == NULL) {
WOLFSSL_MSG("Suites Memory error");
return MEMORY_E;
}
if (ctx->suites)
*ssl->suites = *ctx->suites;
else
XMEMSET(ssl->suites, 0, sizeof(Suites));
#ifndef NO_CERTS
/* make sure server has cert and key unless using PSK or Anon */
if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon)
if (!ssl->buffers.certificate.buffer || !ssl->buffers.key.buffer) {
WOLFSSL_MSG("Server missing certificate and/or private key");
return NO_PRIVATE_KEY;
}
#endif
#ifdef HAVE_SECRET_CALLBACK
ssl->sessionSecretCb = NULL;
ssl->sessionSecretCtx = NULL;
#endif
/* make sure server has DH parms, and add PSK if there, add NTRU too */
if (ssl->options.side == WOLFSSL_SERVER_END)
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
ssl->options.haveDH, ssl->options.haveNTRU,
ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
ssl->options.side);
else
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE,
ssl->options.haveNTRU, ssl->options.haveECDSAsig,
ssl->options.haveStaticECC, ssl->options.side);
return 0;
}
/* free use of temporary arrays */
void FreeArrays(WOLFSSL* ssl, int keep)
{
if (ssl->arrays && keep) {
/* keeps session id for user retrieval */
XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN);
ssl->session.sessionIDSz = ssl->arrays->sessionIDSz;
}
XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->arrays = NULL;
}
/* In case holding SSL object in array and don't want to free actual ssl */
void SSL_ResourceFree(WOLFSSL* ssl)
{
/* Note: any resources used during the handshake should be released in the
* function FreeHandshakeResources(). Be careful with the special cases
* like the RNG which may optionally be kept for the whole session. (For
* example with the RNG, it isn't used beyond the handshake except when
* using stream ciphers where it is retained. */
FreeCiphers(ssl);
FreeArrays(ssl, 0);
wc_FreeRng(ssl->rng);
XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES);
XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
#ifndef NO_DH
XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
/* parameters (p,g) may be owned by ctx */
if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) {
XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
}
#endif
#ifndef NO_CERTS
if (ssl->buffers.weOwnCert)
XFREE(ssl->buffers.certificate.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
if (ssl->buffers.weOwnCertChain)
XFREE(ssl->buffers.certChain.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
if (ssl->buffers.weOwnKey)
XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY);
#endif
#ifndef NO_RSA
if (ssl->peerRsaKey) {
wc_FreeRsaKey(ssl->peerRsaKey);
XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA);
}
#endif
if (ssl->buffers.inputBuffer.dynamicFlag)
ShrinkInputBuffer(ssl, FORCED_FREE);
if (ssl->buffers.outputBuffer.dynamicFlag)
ShrinkOutputBuffer(ssl);
#ifdef WOLFSSL_DTLS
if (ssl->dtls_pool != NULL) {
DtlsPoolReset(ssl);
XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_NONE);
}
if (ssl->dtls_msg_list != NULL) {
DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap);
ssl->dtls_msg_list = NULL;
}
XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
ssl->buffers.dtlsCtx.peer.sa = NULL;
#endif
#if defined(KEEP_PEER_CERT) || defined(GOAHEAD_WS)
FreeX509(&ssl->peerCert);
#endif
#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
wolfSSL_BIO_free(ssl->biord);
if (ssl->biord != ssl->biowr) /* in case same as write */
wolfSSL_BIO_free(ssl->biowr);
#endif
#ifdef HAVE_LIBZ
FreeStreams(ssl);
#endif
#ifdef HAVE_ECC
if (ssl->peerEccKey) {
if (ssl->peerEccKeyPresent)
wc_ecc_free(ssl->peerEccKey);
XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
}
if (ssl->peerEccDsaKey) {
if (ssl->peerEccDsaKeyPresent)
wc_ecc_free(ssl->peerEccDsaKey);
XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC);
}
if (ssl->eccTempKey) {
if (ssl->eccTempKeyPresent)
wc_ecc_free(ssl->eccTempKey);
XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC);
}
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
#endif /* HAVE_ECC */
#ifndef NO_RSA
XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
#endif /* NO_RSA */
#endif /* HAVE_PK_CALLBACKS */
#ifdef HAVE_TLS_EXTENSIONS
TLSX_FreeAll(ssl->extensions);
#endif
#ifdef HAVE_NETX
if (ssl->nxCtx.nxPacket)
nx_packet_release(ssl->nxCtx.nxPacket);
#endif
}
#ifdef WOLFSSL_TI_HASH
static void HashFinal(WOLFSSL * ssl) {
byte dummyHash[32] ;
#ifndef NO_MD5
wc_Md5Final(&(ssl->hsHashes->hashMd5), dummyHash) ;
#endif
#ifndef NO_SHA
wc_ShaFinal(&(ssl->hsHashes->hashSha), dummyHash) ;
#endif
#ifndef NO_SHA256
wc_Sha256Final(&(ssl->hsHashes->hashSha256), dummyHash) ;
#endif
}
#else
#define HashFinal(ssl)
#endif
/* Free any handshake resources no longer needed */
void FreeHandshakeResources(WOLFSSL* ssl)
{
HashFinal(ssl) ;
#ifdef HAVE_SECURE_RENEGOTIATION
if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
WOLFSSL_MSG("Secure Renegotiation needs to retain handshake resources");
return;
}
#endif
/* input buffer */
if (ssl->buffers.inputBuffer.dynamicFlag)
ShrinkInputBuffer(ssl, NO_FORCED_FREE);
/* suites */
XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
ssl->suites = NULL;
/* hsHashes */
XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES);
ssl->hsHashes = NULL;
/* RNG */
if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) {
wc_FreeRng(ssl->rng);
XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
ssl->rng = NULL;
}
#ifdef WOLFSSL_DTLS
/* DTLS_POOL */
if (ssl->options.dtls && ssl->dtls_pool != NULL) {
DtlsPoolReset(ssl);
XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
ssl->dtls_pool = NULL;
}
#endif
/* arrays */
if (ssl->options.saveArrays == 0)
FreeArrays(ssl, 1);
#ifndef NO_RSA
/* peerRsaKey */
if (ssl->peerRsaKey) {
wc_FreeRsaKey(ssl->peerRsaKey);
XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA);
ssl->peerRsaKey = NULL;
}
#endif
#ifdef HAVE_ECC
if (ssl->peerEccKey)
{
if (ssl->peerEccKeyPresent) {
wc_ecc_free(ssl->peerEccKey);
ssl->peerEccKeyPresent = 0;
}
XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
ssl->peerEccKey = NULL;
}
if (ssl->peerEccDsaKey)
{
if (ssl->peerEccDsaKeyPresent) {
wc_ecc_free(ssl->peerEccDsaKey);
ssl->peerEccDsaKeyPresent = 0;
}
XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC);
ssl->peerEccDsaKey = NULL;
}
if (ssl->eccTempKey)
{
if (ssl->eccTempKeyPresent) {
wc_ecc_free(ssl->eccTempKey);
ssl->eccTempKeyPresent = 0;
}
XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC);
ssl->eccTempKey = NULL;
}
#endif
#ifndef NO_DH
XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
ssl->buffers.serverDH_Priv.buffer = NULL;
XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
ssl->buffers.serverDH_Pub.buffer = NULL;
/* parameters (p,g) may be owned by ctx */
if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) {
XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
ssl->buffers.serverDH_G.buffer = NULL;
XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
ssl->buffers.serverDH_P.buffer = NULL;
}
#endif
#ifndef NO_CERTS
if (ssl->buffers.weOwnCert) {
XFREE(ssl->buffers.certificate.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
ssl->buffers.certificate.buffer = NULL;
}
if (ssl->buffers.weOwnCertChain) {
XFREE(ssl->buffers.certChain.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
ssl->buffers.certChain.buffer = NULL;
}
if (ssl->buffers.weOwnKey) {
XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY);
ssl->buffers.key.buffer = NULL;
}
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
ssl->buffers.peerEccDsaKey.buffer = NULL;
#endif /* HAVE_ECC */
#ifndef NO_RSA
XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
ssl->buffers.peerRsaKey.buffer = NULL;
#endif /* NO_RSA */
#endif /* HAVE_PK_CALLBACKS */
}
void FreeSSL(WOLFSSL* ssl)
{
FreeSSL_Ctx(ssl->ctx); /* will decrement and free underyling CTX if 0 */
SSL_ResourceFree(ssl);
XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL);
}
#ifdef WOLFSSL_DTLS
int DtlsPoolInit(WOLFSSL* ssl)
{
if (ssl->dtls_pool == NULL) {
DtlsPool *pool = (DtlsPool*)XMALLOC(sizeof(DtlsPool),
ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
if (pool == NULL) {
WOLFSSL_MSG("DTLS Buffer Pool Memory error");
return MEMORY_E;
}
else {
int i;
for (i = 0; i < DTLS_POOL_SZ; i++) {
pool->buf[i].length = 0;
pool->buf[i].buffer = NULL;
}
pool->used = 0;
ssl->dtls_pool = pool;
}
}
return 0;
}
int DtlsPoolSave(WOLFSSL* ssl, const byte *src, int sz)
{
DtlsPool *pool = ssl->dtls_pool;
if (pool != NULL && pool->used < DTLS_POOL_SZ) {
buffer *pBuf = &pool->buf[pool->used];
pBuf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
if (pBuf->buffer == NULL) {
WOLFSSL_MSG("DTLS Buffer Memory error");
return MEMORY_ERROR;
}
XMEMCPY(pBuf->buffer, src, sz);
pBuf->length = (word32)sz;
pool->used++;
}
return 0;
}
void DtlsPoolReset(WOLFSSL* ssl)
{
DtlsPool *pool = ssl->dtls_pool;
if (pool != NULL) {
buffer *pBuf;
int i, used;
used = pool->used;
for (i = 0, pBuf = &pool->buf[0]; i < used; i++, pBuf++) {
XFREE(pBuf->buffer, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
pBuf->buffer = NULL;
pBuf->length = 0;
}
pool->used = 0;
}
ssl->dtls_timeout = ssl->dtls_timeout_init;
}
int DtlsPoolTimeout(WOLFSSL* ssl)
{
int result = -1;
if (ssl->dtls_timeout < ssl->dtls_timeout_max) {
ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER;
result = 0;
}
return result;
}
int DtlsPoolSend(WOLFSSL* ssl)
{
int ret;
DtlsPool *pool = ssl->dtls_pool;
if (pool != NULL && pool->used > 0) {
int i;
for (i = 0; i < pool->used; i++) {
int sendResult;
buffer* buf = &pool->buf[i];
DtlsRecordLayerHeader* dtls = (DtlsRecordLayerHeader*)buf->buffer;
word16 message_epoch;
ato16(dtls->epoch, &message_epoch);
if (message_epoch == ssl->keys.dtls_epoch) {
/* Increment record sequence number on retransmitted handshake
* messages */
c32to48(ssl->keys.dtls_sequence_number, dtls->sequence_number);
ssl->keys.dtls_sequence_number++;
}
else {
/* The Finished message is sent with the next epoch, keep its
* sequence number */
}
if ((ret = CheckAvailableSize(ssl, buf->length)) != 0)
return ret;
XMEMCPY(ssl->buffers.outputBuffer.buffer, buf->buffer, buf->length);
ssl->buffers.outputBuffer.idx = 0;
ssl->buffers.outputBuffer.length = buf->length;
sendResult = SendBuffered(ssl);
if (sendResult < 0) {
return sendResult;
}
}
}
return 0;
}
/* functions for managing DTLS datagram reordering */
/* Need to allocate space for the handshake message header. The hashing
* routines assume the message pointer is still within the buffer that
* has the headers, and will include those headers in the hash. The store
* routines need to take that into account as well. New will allocate
* extra space for the headers. */
DtlsMsg* DtlsMsgNew(word32 sz, void* heap)
{
DtlsMsg* msg = NULL;
msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG);
if (msg != NULL) {
msg->buf = (byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ,
heap, DYNAMIC_TYPE_NONE);
if (msg->buf != NULL) {
msg->next = NULL;
msg->seq = 0;
msg->sz = sz;
msg->fragSz = 0;
msg->msg = msg->buf + DTLS_HANDSHAKE_HEADER_SZ;
}
else {
XFREE(msg, heap, DYNAMIC_TYPE_DTLS_MSG);
msg = NULL;
}
}
return msg;
}
void DtlsMsgDelete(DtlsMsg* item, void* heap)
{
(void)heap;
if (item != NULL) {
if (item->buf != NULL)
XFREE(item->buf, heap, DYNAMIC_TYPE_NONE);
XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG);
}
}
void DtlsMsgListDelete(DtlsMsg* head, void* heap)
{
DtlsMsg* next;
while (head) {
next = head->next;
DtlsMsgDelete(head, heap);
head = next;
}
}
void DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type,
word32 fragOffset, word32 fragSz)
{
if (msg != NULL && data != NULL && msg->fragSz <= msg->sz &&
fragOffset <= msg->sz && (fragOffset + fragSz) <= msg->sz) {
msg->seq = seq;
msg->type = type;
msg->fragSz += fragSz;
/* If fragOffset is zero, this is either a full message that is out
* of order, or the first fragment of a fragmented message. Copy the
* handshake message header with the message data. Zero length messages
* like Server Hello Done should be saved as well. */
if (fragOffset == 0)
XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ,
fragSz + DTLS_HANDSHAKE_HEADER_SZ);
else {
/* If fragOffet is non-zero, this is an additional fragment that
* needs to be copied to its location in the message buffer. Also
* copy the total size of the message over the fragment size. The
* hash routines look at a defragmented message if it had actually
* come across as a single handshake message. */
XMEMCPY(msg->msg + fragOffset, data, fragSz);
}
c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ);
}
}
DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq)
{
while (head != NULL && head->seq != seq) {
head = head->next;
}
return head;
}
DtlsMsg* DtlsMsgStore(DtlsMsg* head, word32 seq, const byte* data,
word32 dataSz, byte type, word32 fragOffset, word32 fragSz, void* heap)
{
/* See if seq exists in the list. If it isn't in the list, make
* a new item of size dataSz, copy fragSz bytes from data to msg->msg
* starting at offset fragOffset, and add fragSz to msg->fragSz. If
* the seq is in the list and it isn't full, copy fragSz bytes from
* data to msg->msg starting at offset fragOffset, and add fragSz to
* msg->fragSz. The new item should be inserted into the list in its
* proper position.
*
* 1. Find seq in list, or where seq should go in list. If seq not in
* list, create new item and insert into list. Either case, keep
* pointer to item.
* 2. If msg->fragSz + fragSz < sz, copy data to msg->msg at offset
* fragOffset. Add fragSz to msg->fragSz.
*/
if (head != NULL) {
DtlsMsg* cur = DtlsMsgFind(head, seq);
if (cur == NULL) {
cur = DtlsMsgNew(dataSz, heap);
if (cur != NULL) {
DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz);
head = DtlsMsgInsert(head, cur);
}
}
else {
DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz);
}
}
else {
head = DtlsMsgNew(dataSz, heap);
DtlsMsgSet(head, seq, data, type, fragOffset, fragSz);
}
return head;
}
/* DtlsMsgInsert() is an in-order insert. */
DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item)
{
if (head == NULL || item->seq < head->seq) {
item->next = head;
head = item;
}
else if (head->next == NULL) {
head->next = item;
}
else {
DtlsMsg* cur = head->next;
DtlsMsg* prev = head;
while (cur) {
if (item->seq < cur->seq) {
item->next = cur;
prev->next = item;
break;
}
prev = cur;
cur = cur->next;
}
if (cur == NULL) {
prev->next = item;
}
}
return head;
}
#endif /* WOLFSSL_DTLS */
#ifndef NO_OLD_TLS
ProtocolVersion MakeSSLv3(void)
{
ProtocolVersion pv;
pv.major = SSLv3_MAJOR;
pv.minor = SSLv3_MINOR;
return pv;
}
#endif /* NO_OLD_TLS */
#ifdef WOLFSSL_DTLS
ProtocolVersion MakeDTLSv1(void)
{
ProtocolVersion pv;
pv.major = DTLS_MAJOR;
pv.minor = DTLS_MINOR;
return pv;
}
ProtocolVersion MakeDTLSv1_2(void)
{
ProtocolVersion pv;
pv.major = DTLS_MAJOR;
pv.minor = DTLSv1_2_MINOR;
return pv;
}
#endif /* WOLFSSL_DTLS */
#ifdef USE_WINDOWS_API
word32 LowResTimer(void)
{
static int init = 0;
static LARGE_INTEGER freq;
LARGE_INTEGER count;
if (!init) {
QueryPerformanceFrequency(&freq);
init = 1;
}
QueryPerformanceCounter(&count);
return (word32)(count.QuadPart / freq.QuadPart);
}
#elif defined(HAVE_RTP_SYS)
#include "rtptime.h"
word32 LowResTimer(void)
{
return (word32)rtp_get_system_sec();
}
#elif defined(MICRIUM)
word32 LowResTimer(void)
{
NET_SECURE_OS_TICK clk;
#if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
clk = NetSecure_OS_TimeGet();
#endif
return (word32)clk;
}
#elif defined(MICROCHIP_TCPIP_V5)
word32 LowResTimer(void)
{
return (word32) TickGet();
}
#elif defined(MICROCHIP_TCPIP)
#if defined(MICROCHIP_MPLAB_HARMONY)
#include <system/tmr/sys_tmr.h>
word32 LowResTimer(void)
{
return (word32) SYS_TMR_TickCountGet();
}
#else
word32 LowResTimer(void)
{
return (word32) SYS_TICK_Get();
}
#endif
#elif defined(FREESCALE_MQX)
word32 LowResTimer(void)
{
TIME_STRUCT mqxTime;
_time_get_elapsed(&mqxTime);
return (word32) mqxTime.SECONDS;
}
#elif defined(WOLFSSL_TIRTOS)
word32 LowResTimer(void)
{
return (word32) Seconds_get();
}
#elif defined(USER_TICKS)
#if 0
word32 LowResTimer(void)
{
/*
write your own clock tick function if don't want time(0)
needs second accuracy but doesn't have to correlated to EPOCH
*/
}
#endif
#elif defined(TIME_OVERRIDES)
/* use same asn time overrides unless user wants tick override above */
#ifndef HAVE_TIME_T_TYPE
typedef long time_t;
#endif
extern time_t XTIME(time_t * timer);
word32 LowResTimer(void)
{
return (word32) XTIME(0);
}
#else /* !USE_WINDOWS_API && !HAVE_RTP_SYS && !MICRIUM && !USER_TICKS */
#include <time.h>
word32 LowResTimer(void)
{
return (word32)time(0);
}
#endif /* USE_WINDOWS_API */
/* add output to md5 and sha handshake hashes, exclude record header */
static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
{
const byte* adj = output + RECORD_HEADER_SZ + ivSz;
sz -= RECORD_HEADER_SZ;
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
#endif
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
adj += DTLS_RECORD_EXTRA;
sz -= DTLS_RECORD_EXTRA;
}
#endif
#ifndef NO_OLD_TLS
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
#endif
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
#endif
#endif
if (IsAtLeastTLSv1_2(ssl)) {
int ret;
#ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA384
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA512
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
if (ret != 0)
return ret;
#endif
}
return 0;
}
/* add input to md5 and sha handshake hashes, include handshake header */
static int HashInput(WOLFSSL* ssl, const byte* input, int sz)
{
const byte* adj = input - HANDSHAKE_HEADER_SZ;
sz += HANDSHAKE_HEADER_SZ;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
adj -= DTLS_HANDSHAKE_EXTRA;
sz += DTLS_HANDSHAKE_EXTRA;
}
#endif
#ifndef NO_OLD_TLS
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
#endif
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
#endif
#endif
if (IsAtLeastTLSv1_2(ssl)) {
int ret;
#ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA384
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA512
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
if (ret != 0)
return ret;
#endif
}
return 0;
}
/* add record layer header for message */
static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl)
{
RecordLayerHeader* rl;
/* record layer header */
rl = (RecordLayerHeader*)output;
rl->type = type;
rl->pvMajor = ssl->version.major; /* type and version same in each */
rl->pvMinor = ssl->version.minor;
if (!ssl->options.dtls)
c16toa((word16)length, rl->length);
else {
#ifdef WOLFSSL_DTLS
DtlsRecordLayerHeader* dtls;
/* dtls record layer header extensions */
dtls = (DtlsRecordLayerHeader*)output;
c16toa(ssl->keys.dtls_epoch, dtls->epoch);
c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number);
c16toa((word16)length, dtls->length);
#endif
}
}
/* add handshake header for message */
static void AddHandShakeHeader(byte* output, word32 length, byte type,
WOLFSSL* ssl)
{
HandShakeHeader* hs;
(void)ssl;
/* handshake header */
hs = (HandShakeHeader*)output;
hs->type = type;
c32to24(length, hs->length); /* type and length same for each */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
DtlsHandShakeHeader* dtls;
/* dtls handshake header extensions */
dtls = (DtlsHandShakeHeader*)output;
c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
c32to24(0, dtls->fragment_offset);
c32to24(length, dtls->fragment_length);
}
#endif
}
/* add both headers for handshake message */
static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl)
{
if (!ssl->options.dtls) {
AddRecordHeader(output, length + HANDSHAKE_HEADER_SZ, handshake, ssl);
AddHandShakeHeader(output + RECORD_HEADER_SZ, length, type, ssl);
}
#ifdef WOLFSSL_DTLS
else {
AddRecordHeader(output, length+DTLS_HANDSHAKE_HEADER_SZ, handshake,ssl);
AddHandShakeHeader(output + DTLS_RECORD_HEADER_SZ, length, type, ssl);
}
#endif
}
/* return bytes received, -1 on error */
static int Receive(WOLFSSL* ssl, byte* buf, word32 sz)
{
int recvd;
if (ssl->ctx->CBIORecv == NULL) {
WOLFSSL_MSG("Your IO Recv callback is null, please set");
return -1;
}
retry:
recvd = ssl->ctx->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
if (recvd < 0)
switch (recvd) {
case WOLFSSL_CBIO_ERR_GENERAL: /* general/unknown error */
return -1;
case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */
return WANT_READ;
case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */
#ifdef USE_WINDOWS_API
if (ssl->options.dtls) {
goto retry;
}
#endif
ssl->options.connReset = 1;
return -1;
case WOLFSSL_CBIO_ERR_ISR: /* interrupt */
/* see if we got our timeout */
#ifdef WOLFSSL_CALLBACKS
if (ssl->toInfoOn) {
struct itimerval timeout;
getitimer(ITIMER_REAL, &timeout);
if (timeout.it_value.tv_sec == 0 &&
timeout.it_value.tv_usec == 0) {
XSTRNCPY(ssl->timeoutInfo.timeoutName,
"recv() timeout", MAX_TIMEOUT_NAME_SZ);
WOLFSSL_MSG("Got our timeout");
return WANT_READ;
}
}
#endif
goto retry;
case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* peer closed connection */
ssl->options.isClosed = 1;
return -1;
case WOLFSSL_CBIO_ERR_TIMEOUT:
#ifdef WOLFSSL_DTLS
if (DtlsPoolTimeout(ssl) == 0 && DtlsPoolSend(ssl) == 0)
goto retry;
else
#endif
return -1;
default:
return recvd;
}
return recvd;
}
/* Switch dynamic output buffer back to static, buffer is assumed clear */
void ShrinkOutputBuffer(WOLFSSL* ssl)
{
WOLFSSL_MSG("Shrinking output buffer\n");
XFREE(ssl->buffers.outputBuffer.buffer - ssl->buffers.outputBuffer.offset,
ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
ssl->buffers.outputBuffer.dynamicFlag = 0;
ssl->buffers.outputBuffer.offset = 0;
}
/* Switch dynamic input buffer back to static, keep any remaining input */
/* forced free means cleaning up */
void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
{
int usedLength = ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx;
if (!forcedFree && usedLength > STATIC_BUFFER_LEN)
return;
WOLFSSL_MSG("Shrinking input buffer\n");
if (!forcedFree && usedLength)
XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
usedLength);
XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
ssl->buffers.inputBuffer.dynamicFlag = 0;
ssl->buffers.inputBuffer.offset = 0;
ssl->buffers.inputBuffer.idx = 0;
ssl->buffers.inputBuffer.length = usedLength;
}
int SendBuffered(WOLFSSL* ssl)
{
if (ssl->ctx->CBIOSend == NULL) {
WOLFSSL_MSG("Your IO Send callback is null, please set");
return SOCKET_ERROR_E;
}
while (ssl->buffers.outputBuffer.length > 0) {
int sent = ssl->ctx->CBIOSend(ssl,
(char*)ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.idx,
(int)ssl->buffers.outputBuffer.length,
ssl->IOCB_WriteCtx);
if (sent < 0) {
switch (sent) {