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) {
case WOLFSSL_CBIO_ERR_WANT_WRITE: /* would block */
return WANT_WRITE;
case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */
ssl->options.connReset = 1;
break;
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,
"send() timeout", MAX_TIMEOUT_NAME_SZ);
WOLFSSL_MSG("Got our timeout");
return WANT_WRITE;
}
}
#endif
continue;
case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* epipe / conn closed */
ssl->options.connReset = 1; /* treat same as reset */
break;
default:
return SOCKET_ERROR_E;
}
return SOCKET_ERROR_E;
}
if (sent > (int)ssl->buffers.outputBuffer.length) {
WOLFSSL_MSG("SendBuffered() out of bounds read");
return SEND_OOB_READ_E;
}
ssl->buffers.outputBuffer.idx += sent;
ssl->buffers.outputBuffer.length -= sent;
}
ssl->buffers.outputBuffer.idx = 0;
if (ssl->buffers.outputBuffer.dynamicFlag)
ShrinkOutputBuffer(ssl);
return 0;
}
/* Grow the output buffer */
static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
{
byte* tmp;
byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ :
RECORD_HEADER_SZ;
byte align = WOLFSSL_GENERAL_ALIGNMENT;
/* the encrypted data will be offset from the front of the buffer by
the header, if the user wants encrypted alignment they need
to define their alignment requirement */
if (align) {
while (align < hdrSz)
align *= 2;
}
tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length + align,
ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
WOLFSSL_MSG("growing output buffer\n");
if (!tmp) return MEMORY_E;
if (align)
tmp += align - hdrSz;
if (ssl->buffers.outputBuffer.length)
XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
ssl->buffers.outputBuffer.length);
if (ssl->buffers.outputBuffer.dynamicFlag)
XFREE(ssl->buffers.outputBuffer.buffer -
ssl->buffers.outputBuffer.offset, ssl->heap,
DYNAMIC_TYPE_OUT_BUFFER);
ssl->buffers.outputBuffer.dynamicFlag = 1;
if (align)
ssl->buffers.outputBuffer.offset = align - hdrSz;
else
ssl->buffers.outputBuffer.offset = 0;
ssl->buffers.outputBuffer.buffer = tmp;
ssl->buffers.outputBuffer.bufferSize = size +
ssl->buffers.outputBuffer.length;
return 0;
}
/* Grow the input buffer, should only be to read cert or big app data */
int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
{
byte* tmp;
byte hdrSz = DTLS_RECORD_HEADER_SZ;
byte align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0;
/* the encrypted data will be offset from the front of the buffer by
the dtls record header, if the user wants encrypted alignment they need
to define their alignment requirement. in tls we read record header
to get size of record and put actual data back at front, so don't need */
if (align) {
while (align < hdrSz)
align *= 2;
}
tmp = (byte*) XMALLOC(size + usedLength + align, ssl->heap,
DYNAMIC_TYPE_IN_BUFFER);
WOLFSSL_MSG("growing input buffer\n");
if (!tmp) return MEMORY_E;
if (align)
tmp += align - hdrSz;
if (usedLength)
XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx, usedLength);
if (ssl->buffers.inputBuffer.dynamicFlag)
XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
ssl->heap,DYNAMIC_TYPE_IN_BUFFER);
ssl->buffers.inputBuffer.dynamicFlag = 1;
if (align)
ssl->buffers.inputBuffer.offset = align - hdrSz;
else
ssl->buffers.inputBuffer.offset = 0;
ssl->buffers.inputBuffer.buffer = tmp;
ssl->buffers.inputBuffer.bufferSize = size + usedLength;
ssl->buffers.inputBuffer.idx = 0;
ssl->buffers.inputBuffer.length = usedLength;
return 0;
}
/* check available size into output buffer, make room if needed */
int CheckAvailableSize(WOLFSSL *ssl, int size)
{
if (size < 0) {
WOLFSSL_MSG("CheckAvailableSize() called with negative number");
return BAD_FUNC_ARG;
}
if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length
< (word32)size) {
if (GrowOutputBuffer(ssl, size) < 0)
return MEMORY_E;
}
return 0;
}
/* do all verify and sanity checks on record header */
static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
RecordLayerHeader* rh, word16 *size)
{
if (!ssl->options.dtls) {
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
ssl->fuzzerCb(ssl, input + *inOutIdx, RECORD_HEADER_SZ, FUZZ_HEAD,
ssl->fuzzerCtx);
#endif
XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ);
*inOutIdx += RECORD_HEADER_SZ;
ato16(rh->length, size);
}
else {
#ifdef WOLFSSL_DTLS
/* type and version in same sport */
XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
*inOutIdx += ENUM_LEN + VERSION_SZ;
ato16(input + *inOutIdx, &ssl->keys.dtls_state.curEpoch);
*inOutIdx += 4; /* advance past epoch, skip first 2 seq bytes for now */
ato32(input + *inOutIdx, &ssl->keys.dtls_state.curSeq);
*inOutIdx += 4; /* advance past rest of seq */
ato16(input + *inOutIdx, size);
*inOutIdx += LENGTH_SZ;
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
ssl->fuzzerCb(ssl, input + *inOutIdx - LENGTH_SZ - 8 - ENUM_LEN -
VERSION_SZ, ENUM_LEN + VERSION_SZ + 8 + LENGTH_SZ,
FUZZ_HEAD, ssl->fuzzerCtx);
#endif
#endif
}
/* catch version mismatch */
if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor){
if (ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.acceptState == ACCEPT_BEGIN)
WOLFSSL_MSG("Client attempting to connect with different version");
else if (ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->options.downgrade &&
ssl->options.connectState < FIRST_REPLY_DONE)
WOLFSSL_MSG("Server attempting to accept with different version");
else {
WOLFSSL_MSG("SSL version error");
return VERSION_ERROR; /* only use requested version */
}
}
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
if (DtlsCheckWindow(&ssl->keys.dtls_state) != 1)
return SEQUENCE_ERROR;
}
#endif
/* record layer length check */
#ifdef HAVE_MAX_FRAGMENT
if (*size > (ssl->max_fragment + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) {
SendAlert(ssl, alert_fatal, record_overflow);
return LENGTH_ERROR;
}
#else
if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
return LENGTH_ERROR;
#endif
/* verify record type here as well */
switch (rh->type) {
case handshake:
case change_cipher_spec:
case application_data:
case alert:
break;
case no_type:
default:
WOLFSSL_MSG("Unknown Record Type");
return UNKNOWN_RECORD_TYPE;
}
/* haven't decrypted this record yet */
ssl->keys.decryptedCur = 0;
return 0;
}
static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
byte *type, word32 *size, word32 totalSz)
{
const byte *ptr = input + *inOutIdx;
(void)ssl;
*inOutIdx += HANDSHAKE_HEADER_SZ;
if (*inOutIdx > totalSz)
return BUFFER_E;
*type = ptr[0];
c24to32(&ptr[1], size);
return 0;
}
#ifdef WOLFSSL_DTLS
static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, byte *type, word32 *size,
word32 *fragOffset, word32 *fragSz,
word32 totalSz)
{
word32 idx = *inOutIdx;
*inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA;
if (*inOutIdx > totalSz)
return BUFFER_E;
*type = input[idx++];
c24to32(input + idx, size);
idx += BYTE3_LEN;
ato16(input + idx, &ssl->keys.dtls_peer_handshake_number);
idx += DTLS_HANDSHAKE_SEQ_SZ;
c24to32(input + idx, fragOffset);
idx += DTLS_HANDSHAKE_FRAG_SZ;
c24to32(input + idx, fragSz);
return 0;
}
#endif
#ifndef NO_OLD_TLS
/* fill wi