Files
wolfssl/src/internal.c

16901 lines
524 KiB
C
Raw Normal View History

/* internal.c
2011-02-05 11:14:47 -08:00
*
2015-01-08 09:39:04 -07:00
* Copyright (C) 2006-2015 wolfSSL Inc.
2011-02-05 11:14:47 -08:00
*
2014-12-19 11:27:01 -07:00
* This file is part of wolfSSL. (formerly known as CyaSSL)
2011-02-05 11:14:47 -08:00
*
2014-12-19 11:27:01 -07:00
* wolfSSL is free software; you can redistribute it and/or modify
2011-02-05 11:14:47 -08:00
* 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.
*
2014-12-19 11:27:01 -07:00
* wolfSSL is distributed in the hope that it will be useful,
2011-02-05 11:14:47 -08:00
* 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
2014-04-11 15:58:58 -06:00
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
2011-02-05 11:14:47 -08:00
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
2014-12-19 11:27:01 -07:00
#include <wolfssl/wolfcrypt/settings.h>
2015-09-10 16:24:25 -07:00
#ifndef WOLFCRYPT_ONLY
2014-12-19 11:27:01 -07:00
#include <wolfssl/internal.h>
#include <wolfssl/error-ssl.h>
#include <wolfssl/wolfcrypt/asn.h>
2015-03-27 14:28:05 -07:00
#include <wolfssl/wolfcrypt/dh.h>
2015-02-20 15:51:21 -08:00
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
2011-02-05 11:14:47 -08:00
#ifdef HAVE_LIBZ
#include "zlib.h"
#endif
#ifdef HAVE_NTRU
#include "libntruencrypt/ntru_crypto.h"
2011-02-05 11:14:47 -08:00
#endif
2014-12-19 11:27:01 -07:00
#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST)
#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
#if MQX_USE_IO_OLD
#include <fio.h>
#else
#include <nio.h>
#endif
2012-11-01 11:23:42 -06:00
#else
#include <stdio.h>
#endif
2011-02-05 11:14:47 -08:00
#endif
#ifdef __sun
#include <sys/filio.h>
#endif
2012-11-01 11:23:42 -06:00
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
2011-02-05 11:14:47 -08:00
2015-03-18 10:42:10 -06:00
#ifdef _MSC_VER
/* disable for while(0) cases at the .c level for now */
#pragma warning(disable:4127)
#endif
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#if defined(WOLFSSL_CALLBACKS) && !defined(LARGE_STATIC_BUFFERS)
#error \
2014-12-19 11:27:01 -07:00
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
2014-12-19 11:27:01 -07:00
static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
const byte* input, int inSz, int type, int hashOutput);
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*,
word32);
2014-12-19 11:27:01 -07:00
static int DoServerHello(WOLFSSL* ssl, const byte* input, word32*, word32);
static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*,
word32);
#ifndef NO_CERTS
2014-12-19 11:27:01 -07:00
static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*,
word32);
#endif
#ifdef HAVE_SESSION_TICKET
2014-12-19 11:27:01 -07:00
static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32*,
word32);
#endif
2011-02-05 11:14:47 -08:00
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_SERVER
static int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, word32);
static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32);
2012-10-29 15:39:42 -07:00
#if !defined(NO_RSA) || defined(HAVE_ECC)
2014-12-19 11:27:01 -07:00
static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32);
2012-10-29 15:39:42 -07:00
#endif
#ifdef HAVE_STUNNEL
static int SNI_Callback(WOLFSSL* ssl);
#endif
#ifdef WOLFSSL_DTLS
static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte);
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
static INLINE int DtlsCheckWindow(DtlsState* state);
static INLINE int DtlsUpdateWindow(DtlsState* state);
#endif
2011-02-05 11:14:47 -08:00
typedef enum {
doProcessInit = 0,
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_SERVER
2011-02-05 11:14:47 -08:00
runProcessOldClientHello,
#endif
getRecordLayerHeader,
getData,
runProcessingOneMessage
} processReply;
#ifndef NO_OLD_TLS
2014-12-19 11:27:01 -07:00
static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
2014-03-25 16:01:17 -07:00
int content, int verify);
2011-02-05 11:14:47 -08:00
#endif
#ifndef NO_CERTS
2014-12-19 11:27:01 -07:00
static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes);
#endif
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
static void PickHashSigAlgo(WOLFSSL* ssl,
2013-02-18 14:36:50 -08:00
const byte* hashSigAlgo, word32 hashSigAlgoSz);
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
int QSH_Init(WOLFSSL* ssl);
#endif
#ifndef WOLFSSL_HAVE_MIN
#define WOLFSSL_HAVE_MIN
2011-02-05 11:14:47 -08:00
static INLINE word32 min(word32 a, word32 b)
{
return a > b ? b : a;
}
#endif /* WOLFSSL_HAVE_MIN */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
int IsTLS(const WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
return 1;
return 0;
}
2014-12-19 11:27:01 -07:00
int IsAtLeastTLSv1_2(const WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
return 1;
2013-03-06 23:02:33 -08:00
if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR)
return 1;
2011-02-05 11:14:47 -08:00
return 0;
}
static INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend)
{
(void)isSend;
#ifdef WOLFSSL_DTLS
/* For DTLS, epoch 0 is always not encrypted. */
if (ssl->options.dtls && !isSend && ssl->keys.dtls_state.curEpoch == 0)
return 0;
#endif /* WOLFSSL_DTLS */
return ssl->keys.encryptionOn;
}
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
/* free all structs that where used with QSH */
static int QSH_FreeAll(WOLFSSL* ssl)
{
QSHKey* key = ssl->QSH_Key;
QSHKey* preKey = NULL;
QSHSecret* secret = ssl->QSH_secret;
QSHScheme* list = NULL;
QSHScheme* preList = NULL;
/* free elements in struct */
2015-07-11 12:52:22 -06:00
while (key) {
2015-07-07 09:55:58 -06:00
preKey = key;
if (key->pri.buffer)
XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
if (key->pub.buffer)
XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
key = (QSHKey*)key->next;
/* free struct */
XFREE(preKey, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
}
2015-07-11 12:52:22 -06:00
key = NULL;
2015-07-07 09:55:58 -06:00
/* free all of peers QSH keys */
key = ssl->peerQSHKey;
2015-07-11 12:52:22 -06:00
while (key) {
2015-07-07 09:55:58 -06:00
preKey = key;
if (key->pri.buffer)
XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
if (key->pub.buffer)
XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
key = (QSHKey*)key->next;
/* free struct */
XFREE(preKey, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
}
2015-07-11 12:52:22 -06:00
key = NULL;
2015-07-07 09:55:58 -06:00
/* free secret information */
if (secret) {
/* free up the QSHScheme list in QSHSecret */
if (secret->list)
list = secret->list;
while (list) {
preList = list;
if (list->PK)
XFREE(list->PK, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
list = (QSHScheme*)list->next;
XFREE(preList, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
}
/* free secret buffers */
if (secret->SerSi) {
if (secret->SerSi->buffer)
XFREE(secret->SerSi->buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
XFREE(secret->SerSi, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
}
if (secret->CliSi) {
if (secret->CliSi->buffer)
XFREE(secret->CliSi->buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
}
}
XFREE(secret, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY);
2015-07-11 12:52:22 -06:00
secret = NULL;
2015-07-07 09:55:58 -06:00
return 0;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef HAVE_NTRU
static WC_RNG* rng;
2015-07-07 09:55:58 -06:00
static wolfSSL_Mutex* rngMutex;
2011-02-05 11:14:47 -08:00
static word32 GetEntropy(unsigned char* out, word32 num_bytes)
2011-02-05 11:14:47 -08:00
{
2015-07-07 09:55:58 -06:00
int ret = 0;
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
if (rng == NULL) {
2015-12-01 09:24:44 -07:00
if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), 0,
DYNAMIC_TYPE_TLSX)) == NULL)
2015-07-07 09:55:58 -06:00
return DRBG_OUT_OF_MEMORY;
wc_InitRng(rng);
}
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
if (rngMutex == NULL) {
2015-12-01 09:24:44 -07:00
if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), 0,
2015-07-07 09:55:58 -06:00
DYNAMIC_TYPE_TLSX)) == NULL)
return DRBG_OUT_OF_MEMORY;
InitMutex(rngMutex);
}
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
ret |= LockMutex(rngMutex);
ret |= wc_RNG_GenerateBlock(rng, out, num_bytes);
2015-07-07 09:55:58 -06:00
ret |= UnLockMutex(rngMutex);
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
if (ret != 0)
return DRBG_ENTROPY_FAIL;
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
return DRBG_OK;
2011-02-05 11:14:47 -08:00
}
#endif /* HAVE_NTRU */
2011-04-09 13:08:56 -07:00
/* used by ssl.c too */
void c32to24(word32 in, word24 out)
2011-02-05 11:14:47 -08:00
{
out[0] = (in >> 16) & 0xff;
out[1] = (in >> 8) & 0xff;
out[2] = in & 0xff;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
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;
}
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
/* convert 16 bit integer to opaque */
static INLINE void c16toa(word16 u16, byte* c)
2011-02-05 11:14:47 -08:00
{
c[0] = (u16 >> 8) & 0xff;
c[1] = u16 & 0xff;
}
2014-07-18 14:42:45 -06:00
#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
|| defined(HAVE_AESGCM)
2011-02-05 11:14:47 -08:00
/* 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;
}
2014-07-16 14:40:41 -07:00
#endif
2011-02-05 11:14:47 -08:00
/* 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]));
2011-02-05 11:14:47 -08:00
}
2014-12-19 11:27:01 -07:00
#if defined(WOLFSSL_DTLS) || defined(HAVE_SESSION_TICKET)
2011-02-05 11:14:47 -08:00
/* 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];
}
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
#ifdef HAVE_LIBZ
/* alloc user allocs to work with zlib */
2011-06-09 16:43:03 -07:00
static void* myAlloc(void* opaque, unsigned int item, unsigned int size)
2011-02-05 11:14:47 -08:00
{
2011-06-09 16:43:03 -07:00
(void)opaque;
2011-02-05 11:14:47 -08:00
return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
}
2011-06-09 16:43:03 -07:00
static void myFree(void* opaque, void* memory)
2011-02-05 11:14:47 -08:00
{
2011-06-09 16:43:03 -07:00
(void)opaque;
2011-02-05 11:14:47 -08:00
XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
}
/* init zlib comp/decomp streams, 0 on success */
2014-12-19 11:27:01 -07:00
static int InitStreams(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
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;
2011-02-05 11:14:47 -08:00
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;
}
2014-12-19 11:27:01 -07:00
static void FreeStreams(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
if (ssl->didStreamInit) {
deflateEnd(&ssl->c_stream);
inflateEnd(&ssl->d_stream);
}
}
/* compress in to out, return out size or error */
2014-12-19 11:27:01 -07:00
static int myCompress(WOLFSSL* ssl, byte* in, int inSz, byte* out, int outSz)
2011-02-05 11:14:47 -08:00
{
int err;
2013-01-25 13:06:44 -08:00
int currTotal = (int)ssl->c_stream.total_out;
2011-02-05 11:14:47 -08:00
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;
2013-01-25 13:06:44 -08:00
return (int)ssl->c_stream.total_out - currTotal;
2011-02-05 11:14:47 -08:00
}
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* decompress in to out, returnn out size or error */
2014-12-19 11:27:01 -07:00
static int myDeCompress(WOLFSSL* ssl, byte* in,int inSz, byte* out,int outSz)
2011-02-05 11:14:47 -08:00
{
int err;
2013-01-25 13:06:44 -08:00
int currTotal = (int)ssl->d_stream.total_out;
2011-02-05 11:14:47 -08:00
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;
2013-01-25 13:06:44 -08:00
return (int)ssl->d_stream.total_out - currTotal;
2011-02-05 11:14:47 -08:00
}
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
#endif /* HAVE_LIBZ */
2014-12-19 11:27:01 -07:00
void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv)
2011-02-05 11:14:47 -08:00
{
method->version = pv;
2014-12-19 11:27:01 -07:00
method->side = WOLFSSL_CLIENT_END;
2011-02-05 11:14:47 -08:00
method->downgrade = 0;
}
/* Initialze SSL context, return 0 on success */
2014-12-19 11:27:01 -07:00
int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method)
2011-02-05 11:14:47 -08:00
{
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;
2015-03-13 12:20:39 -07:00
ctx->minDowngrade = TLSv1_MINOR; /* current default */
2011-02-05 11:14:47 -08:00
if (InitMutex(&ctx->countMutex) < 0) {
WOLFSSL_MSG("Mutex error on CTX init");
return BAD_MUTEX_E;
}
2011-02-05 11:14:47 -08:00
#ifndef NO_DH
ctx->minDhKeySz = MIN_DHKEY_SZ;
#endif
#ifdef HAVE_ECC
2015-03-09 09:39:50 -07:00
ctx->eccTempKeySz = ECDHE_SIZE;
#endif
2014-12-19 11:27:01 -07:00
#ifndef WOLFSSL_USER_IO
2011-02-05 11:14:47 -08:00
ctx->CBIORecv = EmbedReceive;
ctx->CBIOSend = EmbedSend;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (method->version.major == DTLS_MAJOR) {
ctx->CBIORecv = EmbedReceiveFrom;
ctx->CBIOSend = EmbedSendTo;
}
#endif
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_USER_IO */
2013-06-24 14:00:48 -07:00
#ifdef HAVE_NETX
ctx->CBIORecv = NetX_Receive;
ctx->CBIOSend = NetX_Send;
2011-02-05 11:14:47 -08:00
#endif
#ifdef HAVE_NTRU
2014-12-19 11:27:01 -07:00
if (method->side == WOLFSSL_CLIENT_END)
2011-02-05 11:14:47 -08:00
ctx->haveNTRU = 1; /* always on cliet side */
/* server can turn on by loading key */
#endif
#ifdef HAVE_ECC
2014-12-19 11:27:01 -07:00
if (method->side == WOLFSSL_CLIENT_END) {
ctx->haveECDSAsig = 1; /* always on cliet side */
2012-05-03 09:57:17 -07:00
ctx->haveStaticECC = 1; /* server can turn on by loading key */
}
2011-02-05 11:14:47 -08:00
#endif
#ifdef HAVE_CAVIUM
2014-10-24 10:33:24 -03:00
ctx->devId = NO_CAVIUM_DEVICE;
#endif
2011-02-05 11:14:47 -08:00
#ifndef NO_CERTS
ctx->cm = wolfSSL_CertManagerNew();
2012-05-03 18:07:31 -07:00
if (ctx->cm == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Bad Cert Manager New");
2012-05-03 18:07:31 -07:00
return BAD_CERT_MANAGER_ERROR;
}
#endif
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
#endif
return 0;
2011-02-05 11:14:47 -08:00
}
/* In case contexts are held in array and don't want to free actual ctx */
2014-12-19 11:27:01 -07:00
void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
2011-02-05 11:14:47 -08:00
{
2015-12-28 19:38:04 -03:00
int i;
(void)i;
XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
if (ctx->suites)
XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES);
2015-03-27 14:28:05 -07:00
#ifndef NO_DH
XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH);
XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
2015-03-27 14:28:05 -07:00
#endif
2015-12-28 19:38:04 -03:00
2015-03-27 14:28:05 -07:00
#ifndef NO_CERTS
2011-02-05 11:14:47 -08:00
XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
2011-04-09 13:08:56 -07:00
XFREE(ctx->certChain.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
2014-12-19 11:27:01 -07:00
wolfSSL_CertManagerFree(ctx->cm);
#endif
2015-12-28 19:38:04 -03:00
2013-05-21 14:37:50 -07:00
#ifdef HAVE_TLS_EXTENSIONS
TLSX_FreeAll(ctx->extensions);
2015-12-28 19:38:04 -03:00
#ifndef NO_WOLFSSL_SERVER
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
if (ctx->certOcspRequest) {
FreeOcspRequest(ctx->certOcspRequest);
XFREE(ctx->certOcspRequest, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
}
2013-05-21 14:37:50 -07:00
#endif
2015-12-28 19:38:04 -03:00
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
for (i = 0; i < MAX_CHAIN_DEPTH; i++) {
if (ctx->chainOcspRequest[i]) {
FreeOcspRequest(ctx->chainOcspRequest[i]);
XFREE(ctx->chainOcspRequest[i], NULL, DYNAMIC_TYPE_OCSP_REQUEST);
}
}
#endif
#endif /* NO_WOLFSSL_SERVER */
#endif /* HAVE_TLS_EXTENSIONS */
2011-02-05 11:14:47 -08:00
}
2014-12-19 11:27:01 -07:00
void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
2011-02-05 11:14:47 -08:00
{
int doFree = 0;
if (LockMutex(&ctx->countMutex) != 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Couldn't lock count mutex");
return;
}
ctx->refCount--;
if (ctx->refCount == 0)
doFree = 1;
UnLockMutex(&ctx->countMutex);
if (doFree) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("CTX ref count down to 0, doing full free");
SSL_CtxResourceFree(ctx);
2013-04-17 13:25:02 -07:00
FreeMutex(&ctx->countMutex);
XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
}
else {
(void)ctx;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("CTX ref count not 0 yet, no free");
}
2011-02-05 11:14:47 -08:00
}
/* Set cipher pointers to null */
2014-12-19 11:27:01 -07:00
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
2013-01-21 10:53:42 -08:00
#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;
2014-07-01 14:16:44 -06:00
#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
#ifdef HAVE_IDEA
ssl->encrypt.idea = NULL;
ssl->decrypt.idea = NULL;
#endif
}
/* Free ciphers */
2014-12-19 11:27:01 -07:00
void FreeCiphers(WOLFSSL* ssl)
{
(void)ssl;
#ifdef BUILD_ARC4
#ifdef HAVE_CAVIUM
if (ssl->devId != NO_CAVIUM_DEVICE) {
2014-12-17 09:58:11 -07:00
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) {
2014-12-29 10:27:03 -07:00
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
2013-10-10 16:50:35 -07:00
#ifdef HAVE_CAMELLIA
2013-01-21 10:53:42 -08:00
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
2014-07-01 14:16:44 -06:00
#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);
2014-07-01 14:16:44 -06:00
#endif
#ifdef HAVE_IDEA
XFREE(ssl->encrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
}
void InitCipherSpecs(CipherSpecs* cs)
{
2012-10-09 16:13:05 -07:00
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;
}
2014-10-24 10:33:24 -03:00
static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig,
int haveRSAsig, int haveAnon)
{
int idx = 0;
2014-10-24 10:33:24 -03:00
if (haveECDSAsig) {
#ifdef WOLFSSL_SHA512
suites->hashSigAlgo[idx++] = sha512_mac;
suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
#endif
2014-12-19 11:27:01 -07:00
#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
2014-12-19 11:27:01 -07:00
#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)
2011-02-05 11:14:47 -08:00
{
word16 idx = 0;
2011-03-04 11:13:28 -08:00
int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR;
int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR;
int dtls = 0;
int haveRSAsig = 1;
2011-02-05 11:14:47 -08:00
(void)tls; /* shut up compiler */
(void)tls1_2;
(void)dtls;
2011-04-27 17:31:08 -07:00
(void)haveDH;
(void)havePSK;
(void)haveNTRU;
2012-05-17 17:44:54 -07:00
(void)haveStaticECC;
2011-02-05 11:14:47 -08:00
if (suites == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("InitSuites pointer error");
2014-10-24 10:33:24 -03:00
return;
}
2011-02-05 11:14:47 -08:00
if (suites->setSuites)
return; /* trust user settings, don't override */
2014-12-19 11:27:01 -07:00
if (side == WOLFSSL_SERVER_END && haveStaticECC) {
haveRSA = 0; /* can't do RSA with ECDSA key */
2013-12-11 15:47:40 -08:00
(void)haveRSA; /* some builds won't read */
}
2014-12-19 11:27:01 -07:00
if (side == WOLFSSL_SERVER_END && haveECDSAsig) {
2012-09-04 10:48:26 -07:00
haveRSAsig = 0; /* can't have RSA sig if signed by ECDSA */
(void)haveRSAsig; /* non ecc builds won't read */
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2013-03-06 23:02:33 -08:00
if (pv.major == DTLS_MAJOR) {
dtls = 1;
2013-03-06 23:02:33 -08:00
tls = 1;
2016-01-05 14:19:46 -07:00
/* May be dead assignments dependant upon configuration */
(void) dtls;
(void) tls;
2016-01-05 14:32:45 -07:00
tls1_2 = pv.minor <= DTLSv1_2_MINOR;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef HAVE_RENEGOTIATION_INDICATION
2014-12-19 11:27:01 -07:00
if (side == WOLFSSL_CLIENT_END) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
}
#endif
2015-07-07 09:55:58 -06:00
#ifdef BUILD_TLS_QSH
2015-07-11 12:52:22 -06:00
if (tls) {
2015-07-07 09:55:58 -06:00
suites->suites[idx++] = QSH_BYTE;
suites->suites[idx++] = TLS_QSH;
2011-02-05 11:14:47 -08:00
}
#endif
2015-07-11 12:52:22 -06:00
#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 (!dtls && tls && haveNTRU && haveRSA) {
2015-07-11 12:52:22 -06:00
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
2015-03-27 11:12:42 -07:00
#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
2015-03-27 11:22:42 -07:00
#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 (tls1_2 && haveRSA) {
2015-03-27 11:22:42 -07:00
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 (tls1_2 && haveRSA) {
2015-03-27 11:22:42 -07:00
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
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
2013-03-22 11:30:12 -07:00
if (tls && haveECDSAsig) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
}
#endif
2012-05-03 08:18:59 -07:00
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
if (tls && haveECDSAsig && haveStaticECC) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2012-05-03 08:18:59 -07:00
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
2013-03-22 11:30:12 -07:00
if (tls && haveECDSAsig) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
}
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
if (tls && haveECDSAsig && haveStaticECC) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2012-05-03 09:57:17 -07:00
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
if (!dtls && tls && haveECDSAsig) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
}
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
if (!dtls && tls && haveECDSAsig && haveStaticECC) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2012-05-03 09:57:17 -07:00
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
2013-03-22 11:30:12 -07:00
if (tls && haveECDSAsig) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveECDSAsig && haveStaticECC) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2012-05-03 09:57:17 -07:00
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
}
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSAsig && haveStaticECC) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2012-05-03 09:57:17 -07:00
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
}
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSAsig && haveStaticECC) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2012-05-03 09:57:17 -07:00
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
if (!dtls && tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA;
}
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
if (!dtls && tls && haveRSAsig && haveStaticECC) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2012-05-03 09:57:17 -07:00
suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveRSAsig && haveStaticECC) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2012-05-03 09:57:17 -07:00
suites->suites[idx++] = TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
if (tls1_2 && haveECDSAsig) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2013-03-22 11:30:12 -07:00
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
}
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
if (tls1_2 && haveECDSAsig) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2013-03-22 11:30:12 -07:00
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8;
}
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
2013-01-15 15:20:30 -08:00
if (tls1_2 && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2013-03-22 11:30:12 -07:00
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CCM_8;
2013-01-15 15:20:30 -08:00
}
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
2013-01-15 15:20:30 -08:00
if (tls1_2 && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2013-03-22 11:30:12 -07:00
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CCM_8;
2013-01-15 15:20:30 -08:00
}
#endif
2011-04-26 09:32:18 -07:00
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
if (tls1_2 && haveDH && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-04-26 09:32:18 -07:00
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) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-04-26 09:32:18 -07:00
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
if (tls && haveDH && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-02-05 11:14:47 -08:00
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) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
}
#endif
2011-03-04 11:13:28 -08:00
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
if (tls1_2 && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-03-04 11:13:28 -08:00
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-03-04 11:13:28 -08:00
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
if (tls && havePSK) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-02-05 11:14:47 -08:00
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) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA256;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
if (tls && havePSK) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-02-05 11:14:47 -08:00
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
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
if (tls && havePSK) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2013-03-22 11:30:12 -07:00
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM_8;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
if (tls && havePSK) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = ECC_BYTE;
2013-03-22 11:30:12 -07:00
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
2013-03-20 09:18:05 -07:00
if (tls && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256;
}
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
2013-03-20 09:18:05 -07:00
if (tls && havePSK) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
if (!dtls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
if (!dtls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
if (haveRSA ) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2011-02-05 11:14:47 -08:00
suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
2013-10-24 12:10:09 -07:00
#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
if (!dtls && tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-10-24 12:10:09 -07:00
suites->suites[idx++] = TLS_RSA_WITH_HC_128_MD5;
2011-02-05 11:14:47 -08:00
}
#endif
2014-10-24 10:33:24 -03:00
2013-10-24 12:10:09 -07:00
#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
if (!dtls && tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-10-24 12:10:09 -07:00
suites->suites[idx++] = TLS_RSA_WITH_HC_128_SHA;
2011-02-05 11:14:47 -08:00
}
#endif
2013-10-24 12:10:09 -07:00
#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
if (!dtls && tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-10-24 12:10:09 -07:00
suites->suites[idx++] = TLS_RSA_WITH_HC_128_B2B256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
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) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_B2B256;
}
#endif
2013-10-24 11:52:21 -07:00
#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
if (!dtls && tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-10-24 11:52:21 -07:00
suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA;
2011-02-05 11:14:47 -08:00
}
#endif
2013-01-21 10:53:42 -08:00
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-01-21 10:53:42 -08:00
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) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-01-21 10:53:42 -08:00
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-01-21 10:53:42 -08:00
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) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-01-21 10:53:42 -08:00
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-01-21 10:53:42 -08:00
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) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-01-21 10:53:42 -08:00
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
if (tls && haveRSA) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-01-21 10:53:42 -08:00
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) {
2014-10-24 10:33:24 -03:00
suites->suites[idx++] = 0;
2013-01-21 10:53:42 -08:00
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
if (haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = SSL_RSA_WITH_IDEA_CBC_SHA;
}
#endif
2011-02-05 11:14:47 -08:00
suites->suiteSz = idx;
2014-10-24 10:33:24 -03:00
InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0);
2011-02-05 11:14:47 -08:00
}
#ifndef NO_CERTS
2014-12-19 11:27:01 -07:00
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 */
}
}
2014-12-19 11:27:01 -07:00
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 */
}
}
2014-12-19 11:27:01 -07:00
/* 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;
2013-11-06 11:49:49 -08:00
x509->sig.buffer = NULL;
x509->derCert.buffer = NULL;
x509->altNames = NULL;
x509->altNamesNext = NULL;
2013-04-24 13:35:28 -07:00
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;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SEP
x509->certPolicySet = 0;
x509->certPolicyCrit = 0;
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_SEP */
#endif /* OPENSSL_EXTRA */
}
2014-12-19 11:27:01 -07:00
/* 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
2015-11-19 10:20:28 -08:00
XFREE(x509->authKeyId, NULL, DYNAMIC_TYPE_X509_EXT);
XFREE(x509->subjKeyId, NULL, DYNAMIC_TYPE_X509_EXT);
#endif /* OPENSSL_EXTRA */
if (x509->altNames)
FreeAltNames(x509->altNames, NULL);
if (x509->dynamicMemory)
XFREE(x509, NULL, DYNAMIC_TYPE_X509);
}
#ifndef NO_RSA
/* Verify RSA signature, 0 on success */
int VerifyRsaSign(const byte* sig, word32 sigSz,
const byte* plain, word32 plainSz, RsaKey* key)
{
#ifdef WOLFSSL_SMALL_STACK
byte* verifySig = NULL;
#else
byte verifySig[ENCRYPT_LEN];
#endif
byte* out = NULL; /* inline result */
int ret;
WOLFSSL_ENTER("VerifyRsaSign");
if (sig == NULL || plain == NULL || key == NULL) {
WOLFSSL_MSG("Null pointer input");
return BAD_FUNC_ARG;
}
if (sigSz > ENCRYPT_LEN) {
WOLFSSL_MSG("Signature buffer too big");
return BUFFER_E;
}
#ifdef WOLFSSL_SMALL_STACK
verifySig = (byte*)XMALLOC(ENCRYPT_LEN, NULL,
DYNAMIC_TYPE_SIGNATURE);
if (verifySig == NULL)
return MEMORY_ERROR;
#endif
XMEMCPY(verifySig, sig, sigSz);
ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key);
if (ret != (int)plainSz || !out || XMEMCMP(plain, out, plainSz) != 0) {
WOLFSSL_MSG("RSA Signature verification failed");
ret = RSA_SIGN_FAULT;
} else {
ret = 0; /* RSA reset */
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(verifySig, NULL, DYNAMIC_TYPE_SIGNATURE);
#endif
return ret;
}
#endif /* NO_RSA */
#endif /* NO_CERTS */
/* This function inherits a WOLFSSL_CTX's fields into an SSL object.
It is used during initialization and to switch an ssl's CTX with
wolfSSL_Set_SSL_CTX. Requires ssl->suites alloc and ssl-arrays with PSK
SSL_SUCCESS return value on success */
int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
2011-02-05 11:14:47 -08:00
{
2015-09-15 12:13:11 -07:00
byte havePSK = 0;
byte haveAnon = 0;
byte haveRSA = 0;
byte newSSL = ssl->ctx == NULL;
(void) haveAnon; /* Squash unused var warnings */
if(!ssl || !ctx || ssl->suites == NULL)
return BAD_FUNC_ARG;
#ifndef NO_PSK
if (ctx->server_hint[0] && ssl->arrays == NULL) {
return BAD_FUNC_ARG; /* needed for copy below */
}
#endif
2011-02-05 11:14:47 -08:00
2012-10-29 15:39:42 -07:00
#ifndef NO_RSA
haveRSA = 1;
#endif
#ifndef NO_PSK
havePSK = ctx->havePSK;
#endif /* NO_PSK */
#ifdef HAVE_ANON
haveAnon = ctx->haveAnon;
#endif /* HAVE_ANON*/
2014-10-24 10:33:24 -03:00
/* decrement previous CTX reference count if exists.
* This should only happen if switching ctxs!*/
if (!newSSL) {
WOLFSSL_MSG("freeing old ctx to decrement reference count. Switching ctx.");
wolfSSL_CTX_free(ssl->ctx);
}
2011-02-05 11:14:47 -08:00
/* 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);
ssl->ctx = ctx; /* only for passing to calls, options could change */
ssl->version = ctx->method->version;
#ifdef HAVE_ECC
ssl->eccTempKeySz = ctx->eccTempKeySz;
2014-01-14 14:20:34 -03:00
ssl->pkCurveOID = ctx->pkCurveOID;
#endif
ssl->timeout = ctx->timeout;
2012-10-29 15:39:42 -07:00
ssl->verifyCallback = ctx->verifyCallback;
2011-02-05 11:14:47 -08:00
ssl->options.side = ctx->method->side;
ssl->options.downgrade = ctx->method->downgrade;
2015-03-13 12:20:39 -07:00
ssl->options.minDowngrade = ctx->minDowngrade;
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_SERVER_END)
ssl->options.haveDH = ctx->haveDH;
ssl->options.haveNTRU = ctx->haveNTRU;
ssl->options.haveECDSAsig = ctx->haveECDSAsig;
2012-05-03 08:18:59 -07:00
ssl->options.haveStaticECC = ctx->haveStaticECC;
2011-02-05 11:14:47 -08:00
#ifndef NO_PSK
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
ssl->options.haveAnon = ctx->haveAnon;
#endif
#ifndef NO_DH
ssl->options.minDhKeySz = ctx->minDhKeySz;
#endif
2011-02-05 11:14:47 -08:00
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;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
ssl->heap = ctx->heap; /* defaults to self */
ssl->options.partialWrite = ctx->partialWrite;
ssl->options.quietShutdown = ctx->quietShutdown;
ssl->options.groupMessages = ctx->groupMessages;
2011-02-05 11:14:47 -08:00
2015-03-27 14:28:05 -07:00
#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
2012-05-03 18:07:31 -07:00
/* ctx still owns certificate, certChain, key, dh, and cm */
2011-02-05 11:14:47 -08:00
ssl->buffers.certificate = ctx->certificate;
2011-04-09 13:08:56 -07:00
ssl->buffers.certChain = ctx->certChain;
2011-02-05 11:14:47 -08:00
ssl->buffers.key = ctx->privateKey;
#endif
2011-02-05 11:14:47 -08:00
#ifdef HAVE_CAVIUM
ssl->devId = ctx->devId;
#endif
#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 */
if (ctx->suites)
*ssl->suites = *ctx->suites;
else
XMEMSET(ssl->suites, 0, sizeof(Suites));
/* 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);
#ifndef NO_CERTS
/* make sure server has cert and key unless using PSK or Anon
* This should be true even if just switching ssl ctx */
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
return SSL_SUCCESS;
}
/* init everything to 0, NULL, default values before calling anything that may
fail so that desctructor has a "good" state to cleanup
0 on success */
int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
{
int ret;
XMEMSET(ssl, 0, sizeof(WOLFSSL));
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
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->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;
2014-12-19 11:27:01 -07:00
#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
#ifndef NO_OLD_TLS
ssl->hmac = SSL_hmac; /* default to SSLv3 */
#else
ssl->hmac = TLS_hmac;
#endif
#ifdef WOLFSSL_DTLS
ssl->buffers.dtlsCtx.fd = -1;
#endif
ssl->cipher.ssl = ssl;
2013-05-21 14:37:50 -07:00
#ifdef HAVE_TLS_EXTENSIONS
#ifdef HAVE_MAX_FRAGMENT
ssl->max_fragment = MAX_RECORD_SIZE;
#endif
#ifdef HAVE_ALPN
ssl->alpn_client_list = NULL;
#endif
#endif
2013-03-11 12:28:17 -07:00
/* 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);
2013-02-26 09:00:46 -08:00
InitCipherSpecs(&ssl->specs);
/* all done with init, now can return errors, call other stuff */
/* 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));
/* suites */
ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
DYNAMIC_TYPE_SUITES);
if (ssl->suites == NULL) {
WOLFSSL_MSG("Suites Memory error");
return MEMORY_E;
}
/* Initialize SSL with the appropriate fields from it's ctx */
/* requires valid arrays and suites */
if((ret = SetSSL_CTX(ssl, ctx)) != SSL_SUCCESS)
return ret;
ssl->options.dtls = ssl->version.major == DTLS_MAJOR;
/* 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
2014-12-19 11:27:01 -07:00
#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
2012-09-14 21:19:06 -07:00
/* RNG */
ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap, DYNAMIC_TYPE_RNG);
if (ssl->rng == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("RNG Memory error");
return MEMORY_E;
}
2015-01-01 07:33:07 -07:00
if ( (ret = wc_InitRng(ssl->rng)) != 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("RNG Init error");
return ret;
}
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
if (ret != 0) {
WOLFSSL_MSG("DTLS Cookie Secret error");
return ret;
}
}
#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
#ifdef HAVE_SECRET_CALLBACK
ssl->sessionSecretCb = NULL;
ssl->sessionSecretCtx = NULL;
#endif
2011-02-05 11:14:47 -08:00
return 0;
}
2012-09-14 21:19:06 -07:00
/* free use of temporary arrays */
2014-12-19 11:27:01 -07:00
void FreeArrays(WOLFSSL* ssl, int keep)
2012-09-14 21:19:06 -07:00
{
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;
2012-09-14 21:19:06 -07:00
}
if (ssl->arrays) {
XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->arrays->pendingMsg = NULL;
}
XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_CERT);
2012-09-14 21:19:06 -07:00
ssl->arrays = NULL;
}
2011-02-05 11:14:47 -08:00
/* In case holding SSL object in array and don't want to free actual ssl */
2014-12-19 11:27:01 -07:00
void SSL_ResourceFree(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
2014-11-06 16:07:05 -08:00
/* 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);
2012-09-14 21:19:06 -07:00
FreeArrays(ssl, 0);
2015-01-01 07:33:07 -07:00
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);
2015-03-27 14:28:05 -07:00
#ifndef NO_DH
2011-02-05 11:14:47 -08:00
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 */
2014-12-19 11:27:01 -07:00
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);
}
2015-03-27 14:28:05 -07:00
#endif
#ifndef NO_CERTS
2011-04-04 17:42:50 -07:00
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);
2011-04-04 17:42:50 -07:00
if (ssl->buffers.weOwnKey)
XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY);
#endif
2012-10-29 15:39:42 -07:00
#ifndef NO_RSA
2012-09-14 21:19:06 -07:00
if (ssl->peerRsaKey) {
wc_FreeRsaKey(ssl->peerRsaKey);
2012-09-14 21:19:06 -07:00
XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA);
}
2012-10-29 15:39:42 -07:00
#endif
2011-02-05 11:14:47 -08:00
if (ssl->buffers.inputBuffer.dynamicFlag)
ShrinkInputBuffer(ssl, FORCED_FREE);
if (ssl->buffers.outputBuffer.dynamicFlag)
ShrinkOutputBuffer(ssl);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2015-09-04 11:36:50 -07:00
DtlsPoolDelete(ssl);
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;
2015-09-14 17:13:16 -07:00
#ifndef NO_WOLFSSL_SERVER
XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap,
DYNAMIC_TYPE_COOKIE_PWD);
#endif
2015-09-14 17:13:16 -07:00
#endif /* WOLFSSL_DTLS */
#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
2015-12-02 14:40:32 -08:00
if (ssl->biord != ssl->biowr) /* only free write if different */
2014-12-19 11:27:01 -07:00
wolfSSL_BIO_free(ssl->biowr);
2015-12-02 14:40:32 -08:00
wolfSSL_BIO_free(ssl->biord); /* always free read bio */
2011-02-05 11:14:47 -08:00
#endif
#ifdef HAVE_LIBZ
FreeStreams(ssl);
#endif
#ifdef HAVE_ECC
if (ssl->peerEccKey) {
if (ssl->peerEccKeyPresent)
2014-12-30 15:14:27 -07:00
wc_ecc_free(ssl->peerEccKey);
XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
}
if (ssl->peerEccDsaKey) {
if (ssl->peerEccDsaKeyPresent)
2014-12-30 15:14:27 -07:00
wc_ecc_free(ssl->peerEccDsaKey);
XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC);
}
if (ssl->eccTempKey) {
if (ssl->eccTempKeyPresent)
2014-12-30 15:14:27 -07:00
wc_ecc_free(ssl->eccTempKey);
XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC);
}
2011-02-05 11:14:47 -08:00
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
#endif /* HAVE_ECC */
2014-10-24 10:33:24 -03:00
#ifndef NO_RSA
XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
#endif /* NO_RSA */
#endif /* HAVE_PK_CALLBACKS */
2013-05-21 14:37:50 -07:00
#ifdef HAVE_TLS_EXTENSIONS
TLSX_FreeAll(ssl->extensions);
#ifdef HAVE_ALPN
if (ssl->alpn_client_list != NULL) {
XFREE(ssl->alpn_client_list, NULL, DYNAMIC_TYPE_TMP_BUFFER);
ssl->alpn_client_list = NULL;
}
2013-05-21 14:37:50 -07:00
#endif
#endif /* HAVE_TLS_EXTENSIONS */
2013-06-26 11:03:54 -07:00
#ifdef HAVE_NETX
if (ssl->nxCtx.nxPacket)
nx_packet_release(ssl->nxCtx.nxPacket);
#endif
2015-12-02 14:40:32 -08:00
#if defined(KEEP_PEER_CERT) || defined(GOAHEAD_WS)
FreeX509(&(ssl->peerCert)); /* clang thinks this frees ssl itslef */
#endif
2011-02-05 11:14:47 -08:00
}
#ifdef WOLFSSL_TI_HASH
static void HashFinal(WOLFSSL * ssl) {
2015-06-18 14:25:48 +09:00
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
2011-02-05 11:14:47 -08:00
/* Free any handshake resources no longer needed */
2014-12-19 11:27:01 -07:00
void FreeHandshakeResources(WOLFSSL* ssl)
{
HashFinal(ssl) ;
#ifdef HAVE_SECURE_RENEGOTIATION
if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
2014-12-19 11:27:01 -07:00
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) {
2015-01-01 07:33:07 -07:00
wc_FreeRng(ssl->rng);
XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
ssl->rng = NULL;
}
2012-09-14 09:35:34 -07:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
/* DTLS_POOL */
2015-09-04 11:36:50 -07:00
if (ssl->options.dtls) {
DtlsPoolDelete(ssl);
DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap);
ssl->dtls_msg_list = NULL;
2012-09-14 09:35:34 -07:00
}
#endif
2012-09-14 21:19:06 -07:00
/* arrays */
if (ssl->options.saveArrays == 0)
2012-09-14 21:19:06 -07:00
FreeArrays(ssl, 1);
2012-10-29 15:39:42 -07:00
#ifndef NO_RSA
2012-09-14 21:19:06 -07:00
/* peerRsaKey */
if (ssl->peerRsaKey) {
wc_FreeRsaKey(ssl->peerRsaKey);
2012-09-14 21:19:06 -07:00
XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA);
ssl->peerRsaKey = NULL;
}
2012-10-29 15:39:42 -07:00
#endif
#ifdef HAVE_ECC
if (ssl->peerEccKey)
{
if (ssl->peerEccKeyPresent) {
2014-12-30 15:14:27 -07:00
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) {
2014-12-30 15:14:27 -07:00
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) {
2014-12-30 15:14:27 -07:00
wc_ecc_free(ssl->eccTempKey);
ssl->eccTempKeyPresent = 0;
}
XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC);
ssl->eccTempKey = NULL;
}
#endif
2015-03-27 14:28:05 -07:00
#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;
}
2015-03-27 14:28:05 -07:00
#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 */
2014-10-24 10:33:24 -03:00
#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 */
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
QSH_FreeAll(ssl);
#endif
}
2014-12-19 11:27:01 -07:00
void FreeSSL(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
FreeSSL_Ctx(ssl->ctx); /* will decrement and free underyling CTX if 0 */
2011-02-05 11:14:47 -08:00
SSL_ResourceFree(ssl);
XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL);
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
2014-12-19 11:27:01 -07:00
int DtlsPoolInit(WOLFSSL* ssl)
2012-09-14 09:35:34 -07:00
{
if (ssl->dtls_pool == NULL) {
DtlsPool *pool = (DtlsPool*)XMALLOC(sizeof(DtlsPool),
ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
if (pool == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("DTLS Buffer Pool Memory error");
2012-09-14 09:35:34 -07:00
return MEMORY_E;
}
else {
int i;
2014-10-24 10:33:24 -03:00
2012-09-14 09:35:34 -07:00
for (i = 0; i < DTLS_POOL_SZ; i++) {
pool->buf[i].length = 0;
pool->buf[i].buffer = NULL;
2012-09-14 09:35:34 -07:00
}
pool->used = 0;
ssl->dtls_pool = pool;
}
}
return 0;
}
2014-12-19 11:27:01 -07:00
int DtlsPoolSave(WOLFSSL* ssl, const byte *src, int sz)
2012-09-14 09:35:34 -07:00
{
DtlsPool *pool = ssl->dtls_pool;
if (pool != NULL && pool->used < DTLS_POOL_SZ) {
buffer *pBuf = &pool->buf[pool->used];
2014-06-15 17:26:18 -07:00
pBuf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
if (pBuf->buffer == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("DTLS Buffer Memory error");
return MEMORY_ERROR;
}
XMEMCPY(pBuf->buffer, src, sz);
pool->epoch[pool->used] = ssl->keys.dtls_epoch;
pBuf->length = (word32)sz;
2012-09-14 09:35:34 -07:00
pool->used++;
}
return 0;
2012-09-14 09:35:34 -07:00
}
2014-12-19 11:27:01 -07:00
void DtlsPoolReset(WOLFSSL* ssl)
2012-09-14 09:35:34 -07:00
{
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++) {
2014-06-15 17:26:18 -07:00
XFREE(pBuf->buffer, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
pBuf->buffer = NULL;
pBuf->length = 0;
}
pool->used = 0;
2012-09-14 09:35:34 -07:00
}
ssl->dtls_timeout = ssl->dtls_timeout_init;
2012-09-14 09:35:34 -07:00
}
2015-09-04 11:36:50 -07:00
void DtlsPoolDelete(WOLFSSL* ssl)
{
if (ssl->dtls_pool != NULL) {
DtlsPoolReset(ssl);
XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
ssl->dtls_pool = NULL;
}
}
2014-12-19 11:27:01 -07:00
int DtlsPoolTimeout(WOLFSSL* ssl)
2012-09-14 19:30:50 -07:00
{
int result = -1;
if (ssl->dtls_timeout < ssl->dtls_timeout_max) {
ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER;
2012-09-14 19:30:50 -07:00
result = 0;
}
return result;
}
2014-12-19 11:27:01 -07:00
int DtlsPoolSend(WOLFSSL* ssl)
2012-09-14 09:35:34 -07:00
{
DtlsPool* pool = ssl->dtls_pool;
2012-09-14 09:35:34 -07:00
if (pool != NULL && pool->used > 0) {
int ret = 0;
int i;
buffer* buf;
2012-09-14 09:35:34 -07:00
for (i = 0, buf = pool->buf; i < pool->used; i++, buf++) {
if (pool->epoch[i] == 0) {
DtlsRecordLayerHeader* dtls;
word32* seqNumber;
dtls = (DtlsRecordLayerHeader*)buf->buffer;
seqNumber = (ssl->keys.dtls_epoch == 0) ?
&ssl->keys.dtls_sequence_number :
&ssl->keys.dtls_prev_sequence_number;
c32to48((*seqNumber)++, dtls->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;
}
else if (pool->epoch[i] == ssl->keys.dtls_epoch) {
byte* input;
byte* output;
int inputSz, sendSz;
input = buf->buffer;
inputSz = buf->length;
sendSz = inputSz + MAX_MSG_EXTRA;
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
handshake, 0);
if (sendSz < 0)
return BUILD_MSG_ERROR;
2012-09-14 09:35:34 -07:00
ssl->buffers.outputBuffer.length += sendSz;
}
ret = SendBuffered(ssl);
if (ret < 0) {
return ret;
2012-09-14 09:35:34 -07:00
}
}
}
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;
2014-10-24 10:33:24 -03:00
msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG);
if (msg != NULL) {
XMEMSET(msg, 0, sizeof(DtlsMsg));
msg->buf = (byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ,
heap, DYNAMIC_TYPE_DTLS_BUFFER);
if (msg->buf != NULL) {
msg->sz = sz;
msg->type = no_shake;
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) {
DtlsFrag* cur = item->fragList;
while (cur != NULL) {
DtlsFrag* next = cur->next;
XFREE(cur, heap, DYNAMIC_TYPE_DTLS_FRAG);
cur = next;
}
if (item->buf != NULL)
XFREE(item->buf, heap, DYNAMIC_TYPE_DTLS_BUFFER);
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;
}
}
/* Create a DTLS Fragment from *begin - end, adjust new *begin and bytesLeft */
static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data,
byte* buf, word32* bytesLeft, void* heap)
{
DtlsFrag* newFrag;
word32 added = end - *begin + 1;
newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap,
DYNAMIC_TYPE_DTLS_FRAG);
if (newFrag != NULL) {
newFrag->next = NULL;
newFrag->begin = *begin;
newFrag->end = end;
XMEMCPY(buf + *begin, data, added);
*bytesLeft -= added;
*begin = newFrag->end + 1;
}
return newFrag;
}
int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type,
word32 fragOffset, word32 fragSz, void* heap)
{
if (msg != NULL && data != NULL && msg->fragSz <= msg->sz &&
(fragOffset + fragSz) <= msg->sz) {
DtlsFrag* cur = msg->fragList;
DtlsFrag* prev = cur;
DtlsFrag* newFrag;
word32 bytesLeft = fragSz; /* could be overlapping fragment */
word32 startOffset = fragOffset;
word32 added;
msg->seq = seq;
msg->type = type;
if (fragOffset == 0) {
XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ,
DTLS_HANDSHAKE_HEADER_SZ);
c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ);
}
/* if no mesage data, just return */
if (fragSz == 0)
return 0;
/* if list is empty add full fragment to front */
if (cur == NULL) {
newFrag = CreateFragment(&fragOffset, fragOffset + fragSz - 1, data,
msg->msg, &bytesLeft, heap);
if (newFrag == NULL)
return MEMORY_E;
msg->fragSz = fragSz;
msg->fragList = newFrag;
return 0;
}
/* add to front if before current front, up to next->begin */
if (fragOffset < cur->begin) {
word32 end = fragOffset + fragSz - 1;
if (end >= cur->begin)
end = cur->begin - 1;
added = end - fragOffset + 1;
newFrag = CreateFragment(&fragOffset, end, data, msg->msg,
&bytesLeft, heap);
if (newFrag == NULL)
return MEMORY_E;
msg->fragSz += added;
newFrag->next = cur;
msg->fragList = newFrag;
}
/* while we have bytes left, try to find a gap to fill */
while (bytesLeft > 0) {
/* get previous packet in list */
while (cur && (fragOffset >= cur->begin)) {
prev = cur;
cur = cur->next;
}
/* don't add duplicate data */
if (prev->end >= fragOffset) {
if ( (fragOffset + bytesLeft - 1) <= prev->end)
return 0;
fragOffset = prev->end + 1;
bytesLeft = startOffset + fragSz - fragOffset;
}
if (cur == NULL)
/* we're at the end */
added = bytesLeft;
else
/* we're in between two frames */
added = min(bytesLeft, cur->begin - fragOffset);
/* data already there */
if (added == 0)
continue;
newFrag = CreateFragment(&fragOffset, fragOffset + added - 1,
data + fragOffset - startOffset,
msg->msg, &bytesLeft, heap);
if (newFrag == NULL)
return MEMORY_E;
msg->fragSz += added;
newFrag->next = prev->next;
prev->next = newFrag;
}
}
return 0;
}
DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq)
{
while (head != NULL && head->seq != seq) {
head = head->next;
}
return head;
}
2014-10-24 10:33:24 -03:00
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. Insertions take into account data already in the list
* in case there are overlaps in the handshake message due to retransmit
* messages. 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. Copy the data from the message to the stored message where it
* belongs without overlaps.
*/
if (head != NULL) {
DtlsMsg* cur = DtlsMsgFind(head, seq);
if (cur == NULL) {
cur = DtlsMsgNew(dataSz, heap);
if (cur != NULL) {
if (DtlsMsgSet(cur, seq, data, type,
fragOffset, fragSz, heap) < 0) {
DtlsMsgDelete(cur, heap);
return head;
}
head = DtlsMsgInsert(head, cur);
}
}
else {
/* If this fails, the data is just dropped. */
DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz, heap);
}
}
else {
head = DtlsMsgNew(dataSz, heap);
if (DtlsMsgSet(head, seq, data, type, fragOffset, fragSz, heap) < 0) {
DtlsMsgDelete(head, heap);
return NULL;
}
}
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;
}
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_DTLS */
2012-09-14 09:35:34 -07:00
2015-08-12 16:39:13 -07:00
#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
2012-09-14 09:35:34 -07:00
2011-02-05 11:14:47 -08:00
ProtocolVersion MakeSSLv3(void)
{
ProtocolVersion pv;
pv.major = SSLv3_MAJOR;
pv.minor = SSLv3_MINOR;
return pv;
}
2015-08-12 16:39:13 -07:00
#endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
ProtocolVersion MakeDTLSv1(void)
{
ProtocolVersion pv;
pv.major = DTLS_MAJOR;
pv.minor = DTLS_MINOR;
return pv;
}
2013-03-06 23:02:33 -08:00
ProtocolVersion MakeDTLSv1_2(void)
{
ProtocolVersion pv;
pv.major = DTLS_MAJOR;
pv.minor = DTLSv1_2_MINOR;
return pv;
}
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
2014-10-24 10:33:24 -03:00
#ifdef USE_WINDOWS_API
2011-02-05 11:14:47 -08:00
2013-04-22 10:52:38 -07:00
word32 LowResTimer(void)
2011-02-05 11:14:47 -08:00
{
static int init = 0;
static LARGE_INTEGER freq;
LARGE_INTEGER count;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
if (!init) {
QueryPerformanceFrequency(&freq);
init = 1;
}
QueryPerformanceCounter(&count);
2013-04-22 10:52:38 -07:00
return (word32)(count.QuadPart / freq.QuadPart);
2011-02-05 11:14:47 -08:00
}
#elif defined(HAVE_RTP_SYS)
2011-02-05 11:14:47 -08:00
#include "rtptime.h"
word32 LowResTimer(void)
{
return (word32)rtp_get_system_sec();
}
#elif defined(MICRIUM)
word32 LowResTimer(void)
{
NET_SECURE_OS_TICK clk = 0;
2011-02-05 11:14:47 -08:00
#if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
clk = NetSecure_OS_TimeGet();
#endif
return (word32)clk;
}
2013-04-10 09:16:11 -06:00
#elif defined(MICROCHIP_TCPIP_V5)
2013-04-10 09:16:11 -06:00
word32 LowResTimer(void)
{
2015-12-28 13:58:01 -07:00
return (word32) (TickGet() / TICKS_PER_SECOND);
2013-04-10 09:16:11 -06:00
}
#elif defined(MICROCHIP_TCPIP)
2014-04-01 13:49:30 -07:00
#if defined(MICROCHIP_MPLAB_HARMONY)
#include <system/tmr/sys_tmr.h>
word32 LowResTimer(void)
{
2015-12-28 13:58:01 -07:00
return (word32) (SYS_TMR_TickCountGet() /
SYS_TMR_TickCounterFrequencyGet());
2014-04-01 13:49:30 -07:00
}
#else
word32 LowResTimer(void)
{
2015-12-28 13:58:01 -07:00
return (word32) (SYS_TICK_Get() / SYS_TICK_TicksPerSecondGet());
2014-04-01 13:49:30 -07:00
}
#endif
#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
2013-09-24 20:12:48 -06:00
word32 LowResTimer(void)
{
TIME_STRUCT mqxTime;
_time_get_elapsed(&mqxTime);
return (word32) mqxTime.SECONDS;
}
#elif defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS)
#include "fsl_pit_driver.h"
word32 LowResTimer(void)
{
return PIT_DRV_GetUs();
}
2014-12-19 11:27:01 -07:00
#elif defined(WOLFSSL_TIRTOS)
word32 LowResTimer(void)
{
return (word32) Seconds_get();
}
2011-02-05 11:14:47 -08:00
#elif defined(USER_TICKS)
#if 0
2011-02-05 11:14:47 -08:00
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 */
2011-02-05 11:14:47 -08:00
#include <time.h>
word32 LowResTimer(void)
{
2014-10-24 10:33:24 -03:00
return (word32)time(0);
2011-02-05 11:14:47 -08:00
}
#endif /* USE_WINDOWS_API */
#ifndef NO_CERTS
static int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz)
{
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
#endif
#ifndef NO_OLD_TLS
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz);
#endif
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz);
#endif
#endif
if (IsAtLeastTLSv1_2(ssl)) {
int ret;
#ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA384
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA512
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz);
if (ret != 0)
return ret;
#endif
}
return 0;
}
#endif /* NO_CERTS */
2011-02-05 11:14:47 -08:00
/* add output to md5 and sha handshake hashes, exclude record header */
2014-12-19 11:27:01 -07:00
static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
2011-02-05 11:14:47 -08:00
{
2011-05-25 10:25:05 -07:00
const byte* adj = output + RECORD_HEADER_SZ + ivSz;
2011-02-05 11:14:47 -08:00
sz -= RECORD_HEADER_SZ;
2014-10-24 10:33:24 -03:00
2014-08-11 16:29:19 -06:00
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
2014-08-12 16:25:58 -06:00
ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
2014-08-11 16:29:19 -06:00
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls) {
2011-05-25 10:25:05 -07:00
adj += DTLS_RECORD_EXTRA;
sz -= DTLS_RECORD_EXTRA;
2011-02-05 11:14:47 -08:00
}
#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;
2011-02-28 12:21:06 -08:00
#ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
if (ret != 0)
return ret;
2011-02-28 12:21:06 -08:00
#endif
2014-12-19 11:27:01 -07:00
#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;
2011-02-05 11:14:47 -08:00
}
/* add input to md5 and sha handshake hashes, include handshake header */
2014-12-19 11:27:01 -07:00
static int HashInput(WOLFSSL* ssl, const byte* input, int sz)
2011-02-05 11:14:47 -08:00
{
2011-05-25 10:25:05 -07:00
const byte* adj = input - HANDSHAKE_HEADER_SZ;
2011-02-05 11:14:47 -08:00
sz += HANDSHAKE_HEADER_SZ;
2014-10-24 10:33:24 -03:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls) {
2011-05-25 10:25:05 -07:00
adj -= DTLS_HANDSHAKE_EXTRA;
sz += DTLS_HANDSHAKE_EXTRA;
2011-02-05 11:14:47 -08:00
}
#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;
2011-02-28 12:21:06 -08:00
#ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
if (ret != 0)
return ret;
2011-02-28 12:21:06 -08:00
#endif
2014-12-19 11:27:01 -07:00
#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;
2011-02-05 11:14:47 -08:00
}
/* add record layer header for message */
2014-12-19 11:27:01 -07:00
static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
RecordLayerHeader* rl;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* 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;
2011-02-05 11:14:47 -08:00
#ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE
if (ssl->options.side == WOLFSSL_CLIENT_END
&& ssl->options.connectState == CONNECT_BEGIN
&& !ssl->options.resuming)
rl->pvMinor = ssl->options.downgrade ? ssl->options.minDowngrade
: ssl->version.minor;
#endif
2011-02-05 11:14:47 -08:00
if (!ssl->options.dtls)
c16toa((word16)length, rl->length);
else {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
DtlsRecordLayerHeader* dtls;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* 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,
word32 fragOffset, word32 fragLength,
byte type, WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
HandShakeHeader* hs;
(void)fragOffset;
(void)fragLength;
2011-04-27 17:31:08 -07:00
(void)ssl;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* handshake header */
hs = (HandShakeHeader*)output;
hs->type = type;
c32to24(length, hs->length); /* type and length same for each */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls) {
DtlsHandShakeHeader* dtls;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* dtls handshake header extensions */
dtls = (DtlsHandShakeHeader*)output;
c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
c32to24(fragOffset, dtls->fragment_offset);
c32to24(fragLength, dtls->fragment_length);
2011-02-05 11:14:47 -08:00
}
#endif
}
/* add both headers for handshake message */
2014-12-19 11:27:01 -07:00
static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
word32 lengthAdj = HANDSHAKE_HEADER_SZ;
word32 outputAdj = RECORD_HEADER_SZ;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
lengthAdj += DTLS_HANDSHAKE_EXTRA;
outputAdj += DTLS_RECORD_EXTRA;
2011-02-05 11:14:47 -08:00
}
#endif
AddRecordHeader(output, length + lengthAdj, handshake, ssl);
AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
}
#ifndef NO_CERTS
static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
word32 length, byte type, WOLFSSL* ssl)
{
word32 lengthAdj = HANDSHAKE_HEADER_SZ;
word32 outputAdj = RECORD_HEADER_SZ;
(void)fragSz;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
lengthAdj += DTLS_HANDSHAKE_EXTRA;
outputAdj += DTLS_RECORD_EXTRA;
2011-02-05 11:14:47 -08:00
}
#endif
AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl);
AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl);
2011-02-05 11:14:47 -08:00
}
#endif /* NO_CERTS */
2011-02-05 11:14:47 -08:00
2011-04-25 09:24:21 -07:00
/* return bytes received, -1 on error */
2014-12-19 11:27:01 -07:00
static int Receive(WOLFSSL* ssl, byte* buf, word32 sz)
2011-02-05 11:14:47 -08:00
{
int recvd;
if (ssl->ctx->CBIORecv == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Your IO Recv callback is null, please set");
return -1;
}
2011-02-05 11:14:47 -08:00
retry:
recvd = ssl->ctx->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
2011-02-05 11:14:47 -08:00
if (recvd < 0)
switch (recvd) {
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_GENERAL: /* general/unknown error */
2011-02-05 11:14:47 -08:00
return -1;
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */
2011-02-05 11:14:47 -08:00
return WANT_READ;
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */
2012-09-21 16:36:48 -07:00
#ifdef USE_WINDOWS_API
if (ssl->options.dtls) {
2012-10-03 15:29:28 -07:00
goto retry;
2012-09-21 16:36:48 -07:00
}
#endif
2011-02-05 11:14:47 -08:00
ssl->options.connReset = 1;
return -1;
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_ISR: /* interrupt */
2011-02-05 11:14:47 -08:00
/* see if we got our timeout */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->toInfoOn) {
struct itimerval timeout;
getitimer(ITIMER_REAL, &timeout);
2014-10-24 10:33:24 -03:00
if (timeout.it_value.tv_sec == 0 &&
2011-02-05 11:14:47 -08:00
timeout.it_value.tv_usec == 0) {
XSTRNCPY(ssl->timeoutInfo.timeoutName,
"recv() timeout", MAX_TIMEOUT_NAME_SZ);
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Got our timeout");
2011-04-25 09:24:21 -07:00
return WANT_READ;
2011-02-05 11:14:47 -08:00
}
}
#endif
goto retry;
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* peer closed connection */
2011-02-05 11:14:47 -08:00
ssl->options.isClosed = 1;
return -1;
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_TIMEOUT:
#ifdef WOLFSSL_DTLS
2012-09-14 19:30:50 -07:00
if (DtlsPoolTimeout(ssl) == 0 && DtlsPoolSend(ssl) == 0)
goto retry;
else
2012-09-14 09:35:34 -07:00
#endif
return -1;
default:
return recvd;
2011-02-05 11:14:47 -08:00
}
return recvd;
}
/* Switch dynamic output buffer back to static, buffer is assumed clear */
2014-12-19 11:27:01 -07:00
void ShrinkOutputBuffer(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Shrinking output buffer\n");
XFREE(ssl->buffers.outputBuffer.buffer - ssl->buffers.outputBuffer.offset,
ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
2011-02-05 11:14:47 -08:00
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;
2011-02-05 11:14:47 -08:00
}
/* Switch dynamic input buffer back to static, keep any remaining input */
/* forced free means cleaning up */
2014-12-19 11:27:01 -07:00
void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
2011-02-05 11:14:47 -08:00
{
int usedLength = ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx;
if (!forcedFree && usedLength > STATIC_BUFFER_LEN)
return;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Shrinking input buffer\n");
2011-02-05 11:14:47 -08:00
if (!forcedFree && usedLength)
XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
usedLength);
2013-03-27 16:58:27 -07:00
XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
2011-02-05 11:14:47 -08:00
ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
ssl->buffers.inputBuffer.dynamicFlag = 0;
2013-03-27 16:58:27 -07:00
ssl->buffers.inputBuffer.offset = 0;
2011-02-05 11:14:47 -08:00
ssl->buffers.inputBuffer.idx = 0;
ssl->buffers.inputBuffer.length = usedLength;
}
2014-12-19 11:27:01 -07:00
int SendBuffered(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
if (ssl->ctx->CBIOSend == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Your IO Send callback is null, please set");
return SOCKET_ERROR_E;
}
2011-02-05 11:14:47 -08:00
while (ssl->buffers.outputBuffer.length > 0) {
int sent = ssl->ctx->CBIOSend(ssl,
(char*)ssl->buffers.outputBuffer.buffer +
2011-02-05 11:14:47 -08:00
ssl->buffers.outputBuffer.idx,
(int)ssl->buffers.outputBuffer.length,
ssl->IOCB_WriteCtx);
if (sent < 0) {
switch (sent) {
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_WANT_WRITE: /* would block */
2011-02-05 11:14:47 -08:00
return WANT_WRITE;
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */
2011-02-05 11:14:47 -08:00
ssl->options.connReset = 1;
break;
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_ISR: /* interrupt */
2011-02-05 11:14:47 -08:00
/* see if we got our timeout */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->toInfoOn) {
struct itimerval timeout;
getitimer(ITIMER_REAL, &timeout);
2014-10-24 10:33:24 -03:00
if (timeout.it_value.tv_sec == 0 &&
2011-02-05 11:14:47 -08:00
timeout.it_value.tv_usec == 0) {
XSTRNCPY(ssl->timeoutInfo.timeoutName,
"send() timeout", MAX_TIMEOUT_NAME_SZ);
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Got our timeout");
2011-02-05 11:14:47 -08:00
return WANT_WRITE;
}
}
#endif
continue;
2014-12-19 11:27:01 -07:00
case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* epipe / conn closed */
ssl->options.connReset = 1; /* treat same as reset */
2011-02-05 11:14:47 -08:00
break;
default:
return SOCKET_ERROR_E;
2011-02-05 11:14:47 -08:00
}
return SOCKET_ERROR_E;
}
if (sent > (int)ssl->buffers.outputBuffer.length) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("SendBuffered() out of bounds read");
return SEND_OOB_READ_E;
}
2011-02-05 11:14:47 -08:00
ssl->buffers.outputBuffer.idx += sent;
ssl->buffers.outputBuffer.length -= sent;
}
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
ssl->buffers.outputBuffer.idx = 0;
if (ssl->buffers.outputBuffer.dynamicFlag)
ShrinkOutputBuffer(ssl);
return 0;
}
/* Grow the output buffer */
2014-12-19 11:27:01 -07:00
static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
2011-02-05 11:14:47 -08:00
{
byte* tmp;
2013-03-27 16:58:27 -07:00
byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ :
2014-10-24 10:33:24 -03:00
RECORD_HEADER_SZ;
2014-12-19 11:27:01 -07:00
byte align = WOLFSSL_GENERAL_ALIGNMENT;
/* the encrypted data will be offset from the front of the buffer by
2013-03-27 16:58:27 -07:00
the header, if the user wants encrypted alignment they need
to define their alignment requirement */
2013-03-27 16:58:27 -07:00
if (align) {
while (align < hdrSz)
align *= 2;
}
tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length + align,
ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("growing output buffer\n");
2014-10-24 10:33:24 -03:00
if (!tmp) return MEMORY_E;
if (align)
2013-03-27 16:58:27 -07:00
tmp += align - hdrSz;
2011-02-05 11:14:47 -08:00
if (ssl->buffers.outputBuffer.length)
XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
ssl->buffers.outputBuffer.length);
if (ssl->buffers.outputBuffer.dynamicFlag)
2013-03-27 16:58:27 -07:00
XFREE(ssl->buffers.outputBuffer.buffer -
ssl->buffers.outputBuffer.offset, ssl->heap,
2011-02-05 11:14:47 -08:00
DYNAMIC_TYPE_OUT_BUFFER);
ssl->buffers.outputBuffer.dynamicFlag = 1;
if (align)
2013-03-27 16:58:27 -07:00
ssl->buffers.outputBuffer.offset = align - hdrSz;
else
ssl->buffers.outputBuffer.offset = 0;
2011-02-05 11:14:47 -08:00
ssl->buffers.outputBuffer.buffer = tmp;
ssl->buffers.outputBuffer.bufferSize = size +
2014-10-24 10:33:24 -03:00
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
return 0;
}
/* Grow the input buffer, should only be to read cert or big app data */
2014-12-19 11:27:01 -07:00
int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
2011-02-05 11:14:47 -08:00
{
2013-03-27 16:58:27 -07:00
byte* tmp;
byte hdrSz = DTLS_RECORD_HEADER_SZ;
2014-12-19 11:27:01 -07:00
byte align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0;
2013-03-27 16:58:27 -07:00
/* 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);
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("growing input buffer\n");
2014-10-24 10:33:24 -03:00
if (!tmp) return MEMORY_E;
2013-03-27 16:58:27 -07:00
if (align)
tmp += align - hdrSz;
2011-02-05 11:14:47 -08:00
if (usedLength)
XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx, usedLength);
if (ssl->buffers.inputBuffer.dynamicFlag)
2013-03-27 16:58:27 -07:00
XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
ssl->heap,DYNAMIC_TYPE_IN_BUFFER);
2011-02-05 11:14:47 -08:00
ssl->buffers.inputBuffer.dynamicFlag = 1;
2013-03-27 16:58:27 -07:00
if (align)
ssl->buffers.inputBuffer.offset = align - hdrSz;
else
ssl->buffers.inputBuffer.offset = 0;
2011-02-05 11:14:47 -08:00
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 */
2014-12-19 11:27:01 -07:00
int CheckAvailableSize(WOLFSSL *ssl, int size)
2011-02-05 11:14:47 -08:00
{
if (size < 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("CheckAvailableSize() called with negative number");
return BAD_FUNC_ARG;
}
2011-02-05 11:14:47 -08:00
if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length
< (word32)size) {
if (GrowOutputBuffer(ssl, size) < 0)
return MEMORY_E;
2011-02-05 11:14:47 -08:00
}
2011-02-05 11:14:47 -08:00
return 0;
}
2011-02-05 11:14:47 -08:00
/* do all verify and sanity checks on record header */
2014-12-19 11:27:01 -07:00
static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
2011-02-05 11:14:47 -08:00
RecordLayerHeader* rh, word16 *size)
{
if (!ssl->options.dtls) {
2014-08-12 11:56:20 -06:00
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
2014-08-12 16:25:58 -06:00
ssl->fuzzerCb(ssl, input + *inOutIdx, RECORD_HEADER_SZ, FUZZ_HEAD,
ssl->fuzzerCtx);
2014-08-12 11:56:20 -06:00
#endif
2011-02-05 11:14:47 -08:00
XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ);
*inOutIdx += RECORD_HEADER_SZ;
ato16(rh->length, size);
}
else {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
/* 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);
2012-08-23 15:50:56 -07:00
*inOutIdx += 4; /* advance past epoch, skip first 2 seq bytes for now */
ato32(input + *inOutIdx, &ssl->keys.dtls_state.curSeq);
2011-02-05 11:14:47 -08:00
*inOutIdx += 4; /* advance past rest of seq */
ato16(input + *inOutIdx, size);
*inOutIdx += LENGTH_SZ;
2014-08-12 11:56:20 -06:00
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
2014-08-12 16:25:58 -06:00
ssl->fuzzerCb(ssl, input + *inOutIdx - LENGTH_SZ - 8 - ENUM_LEN -
VERSION_SZ, ENUM_LEN + VERSION_SZ + 8 + LENGTH_SZ,
FUZZ_HEAD, ssl->fuzzerCtx);
2014-08-12 11:56:20 -06:00
#endif
2011-02-05 11:14:47 -08:00
#endif
}
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls &&
(!DtlsCheckWindow(&ssl->keys.dtls_state) ||
(ssl->options.handShakeDone && ssl->keys.dtls_state.curEpoch == 0))) {
return SEQUENCE_ERROR;
}
#endif
2011-02-05 11:14:47 -08:00
/* catch version mismatch */
if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor){
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE)
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Client attempting to connect with different version");
else if (ssl->options.side == WOLFSSL_CLIENT_END &&
2013-08-09 17:27:15 -07:00
ssl->options.downgrade &&
ssl->options.connectState < FIRST_REPLY_DONE)
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Server attempting to accept with different version");
else if (ssl->options.dtls
&& (ssl->options.acceptState == ACCEPT_BEGIN
|| ssl->options.acceptState == CLIENT_HELLO_SENT))
/* Do not check version until Server Hello or Hello Again (2) */
WOLFSSL_MSG("Use version for formatting only in DTLS till ");
2011-04-25 09:24:21 -07:00
else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("SSL version error");
2011-02-05 11:14:47 -08:00
return VERSION_ERROR; /* only use requested version */
2011-04-25 09:24:21 -07:00
}
2011-02-05 11:14:47 -08:00
}
2011-02-05 11:14:47 -08:00
/* 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
2011-02-05 11:14:47 -08:00
if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
return LENGTH_ERROR;
#endif
2011-02-05 11:14:47 -08:00
/* verify record type here as well */
switch (rh->type) {
2011-02-05 11:14:47 -08:00
case handshake:
case change_cipher_spec:
case application_data:
case alert:
break;
2011-04-27 17:31:08 -07:00
case no_type:
2011-02-05 11:14:47 -08:00
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Unknown Record Type");
2011-02-05 11:14:47 -08:00
return UNKNOWN_RECORD_TYPE;
}
2015-12-01 13:32:00 -08:00
/* haven't decrypted this record yet */
ssl->keys.decryptedCur = 0;
2011-02-05 11:14:47 -08:00
return 0;
}
2014-12-19 11:27:01 -07:00
static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
2014-12-01 08:58:52 -08:00
byte *type, word32 *size, word32 totalSz)
2011-02-05 11:14:47 -08:00
{
const byte *ptr = input + *inOutIdx;
2011-04-27 17:31:08 -07:00
(void)ssl;
2014-12-01 08:58:52 -08:00
2011-02-05 11:14:47 -08:00
*inOutIdx += HANDSHAKE_HEADER_SZ;
2014-12-01 08:58:52 -08:00
if (*inOutIdx > totalSz)
return BUFFER_E;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
*type = ptr[0];
c24to32(&ptr[1], size);
return 0;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
2014-12-01 08:58:52 -08:00
word32* inOutIdx, byte *type, word32 *size,
word32 *fragOffset, word32 *fragSz,
word32 totalSz)
{
word32 idx = *inOutIdx;
*inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA;
2014-12-01 08:58:52 -08:00
if (*inOutIdx > totalSz)
return BUFFER_E;
2014-10-24 10:33:24 -03:00
*type = input[idx++];
c24to32(input + idx, size);
idx += BYTE3_LEN;
2012-09-14 19:30:50 -07:00
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
2011-02-05 11:14:47 -08:00
#ifndef NO_OLD_TLS
2011-02-05 11:14:47 -08:00
/* fill with MD5 pad size since biggest required */
2014-10-24 10:33:24 -03:00
static const byte PAD1[PAD_MD5] =
2011-02-05 11:14:47 -08:00
{ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
};
static const byte PAD2[PAD_MD5] =
{ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
};
/* calculate MD5 hash for finished */
2015-06-18 14:25:48 +09:00
#ifdef WOLFSSL_TI_HASH
#include <wolfssl/wolfcrypt/hash.h>
#endif
2014-12-19 11:27:01 -07:00
static void BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
2011-02-05 11:14:47 -08:00
{
2015-06-18 14:25:48 +09:00
2011-02-05 11:14:47 -08:00
byte md5_result[MD5_DIGEST_SIZE];
2015-06-18 14:25:48 +09:00
#ifdef WOLFSSL_SMALL_STACK
Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
#else
Md5 md5[1];
Md5 md5_2[1];
#endif
2014-10-24 10:33:24 -03:00
/* make md5 inner */
2015-06-18 14:25:48 +09:00
md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */
wc_Md5Update(&ssl->hsHashes->hashMd5, sender, SIZEOF_SENDER);
wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN);
wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5);
wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result);
2015-06-18 14:25:48 +09:00
wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */
2011-02-05 11:14:47 -08:00
/* make md5 outer */
2015-06-18 14:25:48 +09:00
wc_InitMd5(md5_2) ;
wc_Md5Update(md5_2, ssl->arrays->masterSecret,SECRET_LEN);
wc_Md5Update(md5_2, PAD2, PAD_MD5);
wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE);
wc_Md5Final(md5_2, hashes->md5);
#ifdef WOLFSSL_SMALL_STACK
XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2011-02-05 11:14:47 -08:00
}
/* calculate SHA hash for finished */
2014-12-19 11:27:01 -07:00
static void BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
2011-02-05 11:14:47 -08:00
{
byte sha_result[SHA_DIGEST_SIZE];
2015-06-18 14:25:48 +09:00
#ifdef WOLFSSL_SMALL_STACK
Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
#else
Sha sha[1];
Sha sha2[1] ;
#endif
2011-02-05 11:14:47 -08:00
/* make sha inner */
2015-06-18 14:25:48 +09:00
sha[0] = ssl->hsHashes->hashSha ; /* Save current position */
wc_ShaUpdate(&ssl->hsHashes->hashSha, sender, SIZEOF_SENDER);
wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN);
wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA);
wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result);
2015-06-18 14:25:48 +09:00
wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */
2011-02-05 11:14:47 -08:00
/* make sha outer */
2015-06-18 14:25:48 +09:00
wc_InitSha(sha2) ;
wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN);
wc_ShaUpdate(sha2, PAD2, PAD_SHA);
wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE);
wc_ShaFinal(sha2, hashes->sha);
2011-02-05 11:14:47 -08:00
2015-06-18 14:25:48 +09:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2011-02-05 11:14:47 -08:00
2015-06-18 14:25:48 +09:00
}
#endif
2011-02-05 11:14:47 -08:00
/* Finished doesn't support SHA512, not SHA512 cipher suites yet */
2014-12-19 11:27:01 -07:00
static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
2011-02-05 11:14:47 -08:00
{
int ret = 0;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
#ifdef WOLFSSL_SHA384
Sha384* sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#else
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
Sha384 sha384[1];
#endif
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (ssl == NULL
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
|| sha384 == NULL
2014-10-24 10:33:24 -03:00
#endif
) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2014-10-24 10:33:24 -03:00
return MEMORY_E;
}
#endif
2011-02-05 11:14:47 -08:00
/* store current states, building requires get_digest which resets state */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
sha384[0] = ssl->hsHashes->hashSha384;
#endif
2013-05-09 15:33:37 -07:00
#ifndef NO_TLS
if (ssl->options.tls) {
2014-03-27 15:43:54 -07:00
ret = BuildTlsFinished(ssl, hashes, sender);
2013-05-09 15:33:37 -07:00
}
#endif
#ifndef NO_OLD_TLS
2013-05-09 15:33:37 -07:00
if (!ssl->options.tls) {
2011-02-05 11:14:47 -08:00
BuildMD5(ssl, hashes, sender);
BuildSHA(ssl, hashes, sender);
}
#endif
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* restore */
if (IsAtLeastTLSv1_2(ssl)) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
ssl->hsHashes->hashSha384 = sha384[0];
2013-02-18 14:36:50 -08:00
#endif
}
2014-03-27 15:43:54 -07:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
#ifdef WOLFSSL_SHA384
XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#endif
2014-03-27 15:43:54 -07:00
return ret;
2011-02-05 11:14:47 -08:00
}
/* cipher requirements */
enum {
REQUIRES_RSA,
REQUIRES_DHE,
REQUIRES_ECC_DSA,
REQUIRES_ECC_STATIC,
REQUIRES_PSK,
REQUIRES_NTRU,
REQUIRES_RSA_SIG
};
/* Does this cipher suite (first, second) have the requirement
an ephemeral key exchange will still require the key for signing
the key exchange so ECHDE_RSA requires an rsa key thus rsa_kea */
static int CipherRequires(byte first, byte second, int requirement)
{
2014-10-24 10:33:24 -03:00
2014-07-10 11:18:49 -06:00
if (first == CHACHA_BYTE) {
2014-10-24 10:33:24 -03:00
2014-07-10 11:18:49 -06:00
switch (second) {
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
2014-07-10 11:18:49 -06:00
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
2014-07-10 11:18:49 -06:00
}
}
/* ECC extensions */
if (first == ECC_BYTE) {
switch (second) {
#ifndef NO_RSA
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
2014-03-27 10:35:57 -06:00
break;
#ifndef NO_DES3
case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
#endif
#ifndef NO_RC4
case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDH_RSA_WITH_RC4_128_SHA :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
#endif
#endif /* NO_RSA */
#ifndef NO_DES3
case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
#endif
#ifndef NO_RC4
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
#endif
#ifndef NO_RSA
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
#endif
2013-04-17 09:37:57 -07:00
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
2013-04-17 09:37:57 -07:00
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
2013-04-17 09:37:57 -07:00
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
2013-04-17 09:37:57 -07:00
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
2013-04-17 09:37:57 -07:00
break;
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
2013-04-17 09:37:57 -07:00
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
2013-04-17 09:37:57 -07:00
case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
#ifndef NO_RSA
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == REQUIRES_ECC_STATIC)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
case TLS_RSA_WITH_AES_128_CCM_8 :
case TLS_RSA_WITH_AES_256_CCM_8 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
break;
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
if (requirement == REQUIRES_RSA_SIG)
return 1;
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
#endif
2013-11-06 11:49:49 -08:00
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
if (requirement == REQUIRES_ECC_DSA)
return 1;
if (requirement == REQUIRES_ECC_STATIC)
return 1;
break;
case TLS_PSK_WITH_AES_128_CCM:
case TLS_PSK_WITH_AES_256_CCM:
case TLS_PSK_WITH_AES_128_CCM_8:
case TLS_PSK_WITH_AES_256_CCM_8:
if (requirement == REQUIRES_PSK)
return 1;
break;
case TLS_DHE_PSK_WITH_AES_128_CCM:
case TLS_DHE_PSK_WITH_AES_256_CCM:
if (requirement == REQUIRES_PSK)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Unsupported cipher suite, CipherRequires ECC");
return 0;
} /* switch */
} /* if */
if (first != ECC_BYTE && first != CHACHA_BYTE) { /* normal suites */
switch (second) {
#ifndef NO_RSA
case SSL_RSA_WITH_RC4_128_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
case SSL_RSA_WITH_RC4_128_MD5 :
if (requirement == REQUIRES_RSA)
return 1;
break;
case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
2015-07-11 12:52:22 -06:00
case TLS_NTRU_RSA_WITH_RC4_128_SHA :
if (requirement == REQUIRES_NTRU)
return 1;
break;
case TLS_RSA_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_RSA_WITH_AES_128_CBC_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
2015-07-11 12:52:22 -06:00
case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
if (requirement == REQUIRES_NTRU)
return 1;
break;
case TLS_RSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
2011-02-05 11:14:47 -08:00
2015-07-11 12:52:22 -06:00
case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_NTRU)
return 1;
break;
case TLS_RSA_WITH_AES_256_CBC_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_RSA_WITH_NULL_SHA :
case TLS_RSA_WITH_NULL_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
2015-07-11 12:52:22 -06:00
case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_NTRU)
return 1;
break;
case SSL_RSA_WITH_IDEA_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
#endif
2011-04-04 17:42:50 -07:00
case TLS_PSK_WITH_AES_128_GCM_SHA256 :
case TLS_PSK_WITH_AES_256_GCM_SHA384 :
case TLS_PSK_WITH_AES_128_CBC_SHA256 :
case TLS_PSK_WITH_AES_256_CBC_SHA384 :
case TLS_PSK_WITH_AES_128_CBC_SHA :
case TLS_PSK_WITH_AES_256_CBC_SHA :
case TLS_PSK_WITH_NULL_SHA384 :
case TLS_PSK_WITH_NULL_SHA256 :
case TLS_PSK_WITH_NULL_SHA :
if (requirement == REQUIRES_PSK)
return 1;
break;
case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
case TLS_DHE_PSK_WITH_NULL_SHA384 :
case TLS_DHE_PSK_WITH_NULL_SHA256 :
if (requirement == REQUIRES_DHE)
return 1;
if (requirement == REQUIRES_PSK)
return 1;
break;
2011-02-05 11:14:47 -08:00
#ifndef NO_RSA
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
case TLS_RSA_WITH_HC_128_MD5 :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_RSA_WITH_HC_128_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_RSA_WITH_HC_128_B2B256:
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_RSA_WITH_AES_128_CBC_B2B256:
case TLS_RSA_WITH_AES_256_CBC_B2B256:
if (requirement == REQUIRES_RSA)
return 1;
break;
2011-02-05 11:14:47 -08:00
case TLS_RSA_WITH_RABBIT_SHA :
if (requirement == REQUIRES_RSA)
return 1;
break;
2012-05-24 12:45:10 -07:00
case TLS_RSA_WITH_AES_128_GCM_SHA256 :
case TLS_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == REQUIRES_RSA)
return 1;
break;
2012-05-24 12:45:10 -07:00
case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA :
case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA :
case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_RSA_SIG)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
#endif
#ifdef HAVE_ANON
case TLS_DH_anon_WITH_AES_128_CBC_SHA :
if (requirement == REQUIRES_DHE)
return 1;
break;
#endif
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Unsupported cipher suite, CipherRequires");
return 0;
} /* switch */
} /* if ECC / Normal suites else */
return 0;
}
2011-02-05 11:14:47 -08:00
#ifndef NO_CERTS
/* Match names with wildcards, each wildcard can represent a single name
component or fragment but not mulitple names, i.e.,
*.z.com matches y.z.com but not x.y.z.com
2012-05-02 14:45:30 -07:00
return 1 on success */
static int MatchDomainName(const char* pattern, int len, const char* str)
{
char p, s;
2012-05-16 17:04:56 -07:00
if (pattern == NULL || str == NULL || len <= 0)
return 0;
while (len > 0) {
p = (char)XTOLOWER((unsigned char)*pattern++);
if (p == 0)
break;
2012-05-16 17:04:56 -07:00
if (p == '*') {
while (--len > 0 &&
(p = (char)XTOLOWER((unsigned char)*pattern++)) == '*')
;
2011-02-05 11:14:47 -08:00
if (len == 0)
p = '\0';
while ( (s = (char)XTOLOWER((unsigned char) *str)) != '\0') {
if (s == p)
break;
if (s == '.')
return 0;
str++;
}
}
else {
if (p != (char)XTOLOWER((unsigned char) *str))
return 0;
}
if (*str != '\0')
str++;
2011-02-05 11:14:47 -08:00
if (len > 0)
len--;
}
2011-02-05 11:14:47 -08:00
return *str == '\0';
}
2011-02-05 11:14:47 -08:00
/* try to find an altName match to domain, return 1 on success */
static int CheckAltNames(DecodedCert* dCert, char* domain)
{
int match = 0;
DNS_entry* altName = NULL;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Checking AltNames");
2011-02-05 11:14:47 -08:00
if (dCert)
altName = dCert->altNames;
while (altName) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" individual AltName check");
if (MatchDomainName(altName->name,(int)XSTRLEN(altName->name), domain)){
match = 1;
break;
}
altName = altName->next;
}
2011-02-05 11:14:47 -08:00
return match;
2011-02-05 11:14:47 -08:00
}
#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
2011-02-05 11:14:47 -08:00
/* Copy parts X509 needs from Decoded cert, 0 on success */
2014-12-19 11:27:01 -07:00
int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
{
2014-03-25 16:01:17 -07:00
int ret = 0;
if (x509 == NULL || dCert == NULL)
return BAD_FUNC_ARG;
x509->version = dCert->version + 1;
XSTRNCPY(x509->issuer.name, dCert->issuer, ASN_NAME_MAX);
x509->issuer.name[ASN_NAME_MAX - 1] = '\0';
x509->issuer.sz = (int)XSTRLEN(x509->issuer.name) + 1;
#ifdef OPENSSL_EXTRA
if (dCert->issuerName.fullName != NULL) {
XMEMCPY(&x509->issuer.fullName,
&dCert->issuerName, sizeof(DecodedName));
x509->issuer.fullName.fullName = (char*)XMALLOC(
dCert->issuerName.fullNameLen, NULL, DYNAMIC_TYPE_X509);
if (x509->issuer.fullName.fullName != NULL)
XMEMCPY(x509->issuer.fullName.fullName,
dCert->issuerName.fullName, dCert->issuerName.fullNameLen);
}
#endif /* OPENSSL_EXTRA */
XSTRNCPY(x509->subject.name, dCert->subject, ASN_NAME_MAX);
x509->subject.name[ASN_NAME_MAX - 1] = '\0';
x509->subject.sz = (int)XSTRLEN(x509->subject.name) + 1;
#ifdef OPENSSL_EXTRA
if (dCert->subjectName.fullName != NULL) {
XMEMCPY(&x509->subject.fullName,
&dCert->subjectName, sizeof(DecodedName));
x509->subject.fullName.fullName = (char*)XMALLOC(
dCert->subjectName.fullNameLen, NULL, DYNAMIC_TYPE_X509);
if (x509->subject.fullName.fullName != NULL)
XMEMCPY(x509->subject.fullName.fullName,
dCert->subjectName.fullName, dCert->subjectName.fullNameLen);
}
#endif /* OPENSSL_EXTRA */
XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE);
x509->serialSz = dCert->serialSz;
if (dCert->subjectCNLen < ASN_NAME_MAX) {
XMEMCPY(x509->subjectCN, dCert->subjectCN, dCert->subjectCNLen);
x509->subjectCN[dCert->subjectCNLen] = '\0';
}
else
x509->subjectCN[0] = '\0';
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SEP
{
int minSz = min(dCert->deviceTypeSz, EXTERNAL_SERIAL_SIZE);
if (minSz > 0) {
x509->deviceTypeSz = minSz;
XMEMCPY(x509->deviceType, dCert->deviceType, minSz);
}
else
x509->deviceTypeSz = 0;
minSz = min(dCert->hwTypeSz, EXTERNAL_SERIAL_SIZE);
if (minSz != 0) {
x509->hwTypeSz = minSz;
XMEMCPY(x509->hwType, dCert->hwType, minSz);
}
else
x509->hwTypeSz = 0;
minSz = min(dCert->hwSerialNumSz, EXTERNAL_SERIAL_SIZE);
if (minSz != 0) {
x509->hwSerialNumSz = minSz;
XMEMCPY(x509->hwSerialNum, dCert->hwSerialNum, minSz);
}
else
x509->hwSerialNumSz = 0;
}
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_SEP */
{
int minSz = min(dCert->beforeDateLen, MAX_DATE_SZ);
if (minSz != 0) {
x509->notBeforeSz = minSz;
XMEMCPY(x509->notBefore, dCert->beforeDate, minSz);
}
else
x509->notBeforeSz = 0;
minSz = min(dCert->afterDateLen, MAX_DATE_SZ);
if (minSz != 0) {
x509->notAfterSz = minSz;
XMEMCPY(x509->notAfter, dCert->afterDate, minSz);
}
else
x509->notAfterSz = 0;
}
2011-02-05 11:14:47 -08:00
if (dCert->publicKey != NULL && dCert->pubKeySize != 0) {
x509->pubKey.buffer = (byte*)XMALLOC(
dCert->pubKeySize, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
if (x509->pubKey.buffer != NULL) {
x509->pubKeyOID = dCert->keyOID;
x509->pubKey.length = dCert->pubKeySize;
XMEMCPY(x509->pubKey.buffer, dCert->publicKey, dCert->pubKeySize);
}
else
ret = MEMORY_E;
}
if (dCert->signature != NULL && dCert->sigLength != 0) {
x509->sig.buffer = (byte*)XMALLOC(
dCert->sigLength, NULL, DYNAMIC_TYPE_SIGNATURE);
if (x509->sig.buffer == NULL) {
ret = MEMORY_E;
}
else {
XMEMCPY(x509->sig.buffer, dCert->signature, dCert->sigLength);
x509->sig.length = dCert->sigLength;
x509->sigOID = dCert->signatureOID;
2011-04-25 09:24:21 -07:00
}
2011-02-05 11:14:47 -08:00
}
/* store cert for potential retrieval */
x509->derCert.buffer = (byte*)XMALLOC(dCert->maxIdx, NULL,
DYNAMIC_TYPE_CERT);
if (x509->derCert.buffer == NULL) {
ret = MEMORY_E;
}
else {
XMEMCPY(x509->derCert.buffer, dCert->source, dCert->maxIdx);
x509->derCert.length = dCert->maxIdx;
}
x509->altNames = dCert->altNames;
dCert->weOwnAltNames = 0;
x509->altNamesNext = x509->altNames; /* index hint */
x509->isCa = dCert->isCA;
#ifdef OPENSSL_EXTRA
x509->pathLength = dCert->pathLength;
x509->keyUsage = dCert->extKeyUsage;
x509->basicConstSet = dCert->extBasicConstSet;
x509->basicConstCrit = dCert->extBasicConstCrit;
x509->basicConstPlSet = dCert->extBasicConstPlSet;
x509->subjAltNameSet = dCert->extSubjAltNameSet;
x509->subjAltNameCrit = dCert->extSubjAltNameCrit;
x509->authKeyIdSet = dCert->extAuthKeyIdSet;
x509->authKeyIdCrit = dCert->extAuthKeyIdCrit;
if (dCert->extAuthKeyIdSrc != NULL && dCert->extAuthKeyIdSz != 0) {
2015-11-19 10:20:28 -08:00
x509->authKeyId = (byte*)XMALLOC(dCert->extAuthKeyIdSz, NULL,
DYNAMIC_TYPE_X509_EXT);
if (x509->authKeyId != NULL) {
XMEMCPY(x509->authKeyId,
dCert->extAuthKeyIdSrc, dCert->extAuthKeyIdSz);
x509->authKeyIdSz = dCert->extAuthKeyIdSz;
}
else
ret = MEMORY_E;
2011-02-05 11:14:47 -08:00
}
x509->subjKeyIdSet = dCert->extSubjKeyIdSet;
x509->subjKeyIdCrit = dCert->extSubjKeyIdCrit;
if (dCert->extSubjKeyIdSrc != NULL && dCert->extSubjKeyIdSz != 0) {
2015-11-19 10:20:28 -08:00
x509->subjKeyId = (byte*)XMALLOC(dCert->extSubjKeyIdSz, NULL,
DYNAMIC_TYPE_X509_EXT);
if (x509->subjKeyId != NULL) {
XMEMCPY(x509->subjKeyId,
dCert->extSubjKeyIdSrc, dCert->extSubjKeyIdSz);
x509->subjKeyIdSz = dCert->extSubjKeyIdSz;
}
else
ret = MEMORY_E;
2011-02-05 11:14:47 -08:00
}
x509->keyUsageSet = dCert->extKeyUsageSet;
x509->keyUsageCrit = dCert->extKeyUsageCrit;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SEP
x509->certPolicySet = dCert->extCertPolicySet;
x509->certPolicyCrit = dCert->extCertPolicyCrit;
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_SEP */
#endif /* OPENSSL_EXTRA */
#ifdef HAVE_ECC
x509->pkCurveOID = dCert->pkCurveOID;
#endif /* HAVE_ECC */
2011-02-05 11:14:47 -08:00
return ret;
2011-02-05 11:14:47 -08:00
}
#endif /* KEEP_PEER_CERT || SESSION_CERTS */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 size)
2011-02-05 11:14:47 -08:00
{
word32 listSz;
word32 begin = *inOutIdx;
int ret = 0;
int anyError = 0;
int totalCerts = 0; /* number of certs in certs buffer */
int count;
buffer certs[MAX_CHAIN_DEPTH];
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
char* domain = NULL;
DecodedCert* dCert = NULL;
2014-12-19 11:27:01 -07:00
WOLFSSL_X509_STORE_CTX* store = NULL;
#else
char domain[ASN_NAME_MAX];
DecodedCert dCert[1];
2014-12-19 11:27:01 -07:00
WOLFSSL_X509_STORE_CTX store[1];
2014-10-24 10:33:24 -03:00
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo);
#endif
if ((*inOutIdx - begin) + OPAQUE24_LEN > size)
return BUFFER_ERROR;
c24to32(input + *inOutIdx, &listSz);
*inOutIdx += OPAQUE24_LEN;
if (listSz > MAX_RECORD_SIZE)
return BUFFER_E;
2011-02-05 11:14:47 -08:00
if ((*inOutIdx - begin) + listSz != size)
return BUFFER_ERROR;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Loading peer's cert chain");
/* first put cert chain into buffer so can verify top down
we're sent bottom up */
while (listSz) {
word32 certSz;
if (totalCerts >= MAX_CHAIN_DEPTH)
return MAX_CHAIN_ERROR;
if ((*inOutIdx - begin) + OPAQUE24_LEN > size)
return BUFFER_ERROR;
c24to32(input + *inOutIdx, &certSz);
*inOutIdx += OPAQUE24_LEN;
2011-02-05 11:14:47 -08:00
if ((*inOutIdx - begin) + certSz > size)
return BUFFER_ERROR;
certs[totalCerts].length = certSz;
certs[totalCerts].buffer = input + *inOutIdx;
2011-02-05 11:14:47 -08:00
#ifdef SESSION_CERTS
if (ssl->session.chain.count < MAX_CHAIN_DEPTH &&
certSz < MAX_X509_SIZE) {
ssl->session.chain.certs[ssl->session.chain.count].length = certSz;
XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer,
input + *inOutIdx, certSz);
ssl->session.chain.count++;
} else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Couldn't store chain cert for session");
}
#endif
2011-02-05 11:14:47 -08:00
*inOutIdx += certSz;
listSz -= certSz + CERT_HEADER_SZ;
2011-02-05 11:14:47 -08:00
totalCerts++;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" Put another cert into chain");
}
2011-02-05 11:14:47 -08:00
count = totalCerts;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (dCert == NULL)
return MEMORY_E;
#endif
/* verify up to peer's first */
while (count > 1) {
buffer myCert = certs[count - 1];
byte* subjectHash;
InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap);
ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone,
ssl->ctx->cm);
#ifndef NO_SKID
subjectHash = dCert->extSubjKeyId;
#else
subjectHash = dCert->subjectHash;
2011-02-05 11:14:47 -08:00
#endif
if (ret == 0 && dCert->isCA == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Chain cert is not a CA, not adding as one");
}
else if (ret == 0 && ssl->options.verifyNone) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Chain cert not verified by option, not adding as CA");
}
else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) {
buffer add;
add.length = myCert.length;
add.buffer = (byte*)XMALLOC(myCert.length, ssl->heap,
DYNAMIC_TYPE_CA);
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Adding CA from chain");
2011-02-05 11:14:47 -08:00
if (add.buffer == NULL)
return MEMORY_E;
XMEMCPY(add.buffer, myCert.buffer, myCert.length);
2011-02-05 11:14:47 -08:00
/* already verified above */
ret = AddCA(ssl->ctx->cm, add, WOLFSSL_CHAIN_CA, 0);
if (ret == 1) ret = 0; /* SSL_SUCCESS for external */
}
else if (ret != 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Failed to verify CA from chain");
}
else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verified CA from chain and already had it");
}
2011-02-05 11:14:47 -08:00
#if defined(HAVE_OCSP) || defined(HAVE_CRL)
if (ret == 0) {
int doCrlLookup = 1;
2015-12-28 19:38:04 -03:00
#ifdef HAVE_OCSP
2015-12-28 19:38:04 -03:00
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
if (ssl->status_request_v2)
ret = TLSX_CSR2_InitRequests(ssl->extensions, dCert, 0);
else /* skips OCSP and force CRL check */
#endif
if (ssl->ctx->cm->ocspEnabled && ssl->ctx->cm->ocspCheckAll) {
WOLFSSL_MSG("Doing Non Leaf OCSP check");
2015-12-28 19:38:04 -03:00
ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL);
doCrlLookup = (ret == OCSP_CERT_UNKNOWN);
if (ret != 0) {
doCrlLookup = 0;
WOLFSSL_MSG("\tOCSP Lookup not ok");
}
}
#endif /* HAVE_OCSP */
#ifdef HAVE_CRL
2015-12-28 19:38:04 -03:00
if (ret == 0 && doCrlLookup && ssl->ctx->cm->crlEnabled
&& ssl->ctx->cm->crlCheckAll) {
WOLFSSL_MSG("Doing Non Leaf CRL check");
ret = CheckCertCRL(ssl->ctx->cm->crl, dCert);
2011-02-05 11:14:47 -08:00
if (ret != 0) {
WOLFSSL_MSG("\tCRL check not ok");
}
}
2015-11-02 15:51:01 -03:00
#else
(void)doCrlLookup;
#endif /* HAVE_CRL */
}
#endif /* HAVE_OCSP || HAVE_CRL */
2011-02-05 11:14:47 -08:00
if (ret != 0 && anyError == 0)
anyError = ret; /* save error from last time */
FreeDecodedCert(dCert);
count--;
2011-02-05 11:14:47 -08:00
}
/* peer's, may not have one if blank client cert sent by TLSv1.2 */
if (count) {
buffer myCert = certs[0];
int fatal = 0;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verifying Peer's cert");
InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap);
ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone,
ssl->ctx->cm);
if (ret == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verified Peer's cert");
fatal = 0;
}
else if (ret == ASN_PARSE_E) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Got Peer cert ASN PARSE ERROR, fatal");
fatal = 1;
}
else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Failed to verify Peer's cert");
if (ssl->verifyCallback) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("\tCallback override available, will continue");
fatal = 0;
}
else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("\tNo callback override available, fatal");
fatal = 1;
}
}
#ifdef HAVE_SECURE_RENEGOTIATION
if (fatal == 0 && ssl->secure_renegotiation
&& ssl->secure_renegotiation->enabled) {
if (IsEncryptionOn(ssl, 0)) {
/* compare against previous time */
if (XMEMCMP(dCert->subjectHash,
ssl->secure_renegotiation->subject_hash,
SHA_DIGEST_SIZE) != 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Peer sent different cert during scr, fatal");
fatal = 1;
ret = SCR_DIFFERENT_CERT_E;
}
}
/* cache peer's hash */
if (fatal == 0) {
XMEMCPY(ssl->secure_renegotiation->subject_hash,
dCert->subjectHash, SHA_DIGEST_SIZE);
}
}
#endif
#if defined(HAVE_OCSP) || defined(HAVE_CRL)
if (fatal == 0) {
2015-11-02 15:51:01 -03:00
int doLookup = 1;
if (ssl->options.side == WOLFSSL_CLIENT_END) {
2015-12-28 19:38:04 -03:00
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
2015-11-02 15:51:01 -03:00
if (ssl->status_request) {
fatal = TLSX_CSR_InitRequest(ssl->extensions, dCert);
doLookup = 0;
}
#endif
2015-12-28 19:38:04 -03:00
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
if (ssl->status_request_v2) {
fatal = TLSX_CSR2_InitRequests(ssl->extensions, dCert, 1);
doLookup = 0;
}
#endif
}
2015-11-02 15:51:01 -03:00
#ifdef HAVE_OCSP
2015-11-02 15:51:01 -03:00
if (doLookup && ssl->ctx->cm->ocspEnabled) {
WOLFSSL_MSG("Doing Leaf OCSP check");
2015-12-28 19:38:04 -03:00
ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL);
2015-11-02 15:51:01 -03:00
doLookup = (ret == OCSP_CERT_UNKNOWN);
if (ret != 0) {
WOLFSSL_MSG("\tOCSP Lookup not ok");
fatal = 0;
}
}
#endif /* HAVE_OCSP */
#ifdef HAVE_CRL
2015-11-02 15:51:01 -03:00
if (doLookup && ssl->ctx->cm->crlEnabled) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Doing Leaf CRL check");
ret = CheckCertCRL(ssl->ctx->cm->crl, dCert);
if (ret != 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("\tCRL check not ok");
fatal = 0;
}
}
#endif /* HAVE_CRL */
2015-11-02 15:51:01 -03:00
(void)doLookup;
}
#endif /* HAVE_OCSP || HAVE_CRL */
#ifdef KEEP_PEER_CERT
2015-11-02 15:51:01 -03:00
if (fatal == 0) {
/* set X509 format for peer cert even if fatal */
int copyRet = CopyDecodedToX509(&ssl->peerCert, dCert);
if (copyRet == MEMORY_E)
fatal = 1;
}
#endif
#ifndef IGNORE_KEY_EXTENSIONS
if (dCert->extKeyUsageSet) {
if ((ssl->specs.kea == rsa_kea) &&
(dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) {
ret = KEYUSE_ENCIPHER_E;
}
if ((ssl->specs.sig_algo == rsa_sa_algo ||
(ssl->specs.sig_algo == ecc_dsa_sa_algo &&
!ssl->specs.static_ecdh)) &&
(dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("KeyUse Digital Sig not set");
ret = KEYUSE_SIGNATURE_E;
}
}
if (dCert->extExtKeyUsageSet) {
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_CLIENT_END) {
if ((dCert->extExtKeyUsage &
(EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("ExtKeyUse Server Auth not set");
ret = EXTKEYUSE_AUTH_E;
}
}
else {
if ((dCert->extExtKeyUsage &
(EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("ExtKeyUse Client Auth not set");
ret = EXTKEYUSE_AUTH_E;
}
}
}
#endif /* IGNORE_KEY_EXTENSIONS */
if (fatal) {
FreeDecodedCert(dCert);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
ssl->error = ret;
return ret;
}
ssl->options.havePeerCert = 1;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
domain = (char*)XMALLOC(ASN_NAME_MAX, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (domain == NULL) {
FreeDecodedCert(dCert);
XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
/* store for callback use */
if (dCert->subjectCNLen < ASN_NAME_MAX) {
XMEMCPY(domain, dCert->subjectCN, dCert->subjectCNLen);
domain[dCert->subjectCNLen] = '\0';
}
else
domain[0] = '\0';
if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen,
(char*)ssl->buffers.domainName.buffer) == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("DomainName match on common name failed");
if (CheckAltNames(dCert,
(char*)ssl->buffers.domainName.buffer) == 0 ) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("DomainName match on alt names failed too");
ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */
}
}
}
/* decode peer key */
switch (dCert->keyOID) {
#ifndef NO_RSA
case RSAk:
{
word32 idx = 0;
int keyRet = 0;
if (ssl->peerRsaKey == NULL) {
ssl->peerRsaKey = (RsaKey*)XMALLOC(sizeof(RsaKey),
ssl->heap, DYNAMIC_TYPE_RSA);
if (ssl->peerRsaKey == NULL) {
WOLFSSL_MSG("PeerRsaKey Memory error");
keyRet = MEMORY_E;
} else {
keyRet = wc_InitRsaKey(ssl->peerRsaKey,
ssl->ctx->heap);
}
} else if (ssl->peerRsaKeyPresent) {
/* don't leak on reuse */
wc_FreeRsaKey(ssl->peerRsaKey);
ssl->peerRsaKeyPresent = 0;
keyRet = wc_InitRsaKey(ssl->peerRsaKey, ssl->heap);
}
if (keyRet != 0 || wc_RsaPublicKeyDecode(dCert->publicKey,
&idx, ssl->peerRsaKey, dCert->pubKeySize) != 0) {
ret = PEER_KEY_ERROR;
}
else {
ssl->peerRsaKeyPresent = 1;
#ifdef HAVE_PK_CALLBACKS
#ifndef NO_RSA
ssl->buffers.peerRsaKey.buffer =
2014-12-04 17:16:39 -08:00
(byte*)XMALLOC(dCert->pubKeySize,
ssl->heap, DYNAMIC_TYPE_RSA);
if (ssl->buffers.peerRsaKey.buffer == NULL)
ret = MEMORY_ERROR;
else {
XMEMCPY(ssl->buffers.peerRsaKey.buffer,
dCert->publicKey, dCert->pubKeySize);
ssl->buffers.peerRsaKey.length =
dCert->pubKeySize;
}
#endif /* NO_RSA */
#endif /*HAVE_PK_CALLBACKS */
}
}
break;
#endif /* NO_RSA */
2015-07-11 12:52:22 -06:00
#ifdef HAVE_NTRU
case NTRUk:
{
if (dCert->pubKeySize > sizeof(ssl->peerNtruKey)) {
ret = PEER_KEY_ERROR;
}
else {
XMEMCPY(ssl->peerNtruKey, dCert->publicKey,
dCert->pubKeySize);
ssl->peerNtruKeyLen = (word16)dCert->pubKeySize;
ssl->peerNtruKeyPresent = 1;
}
}
break;
#endif /* HAVE_NTRU */
#ifdef HAVE_ECC
case ECDSAk:
{
if (ssl->peerEccDsaKey == NULL) {
/* alloc/init on demand */
ssl->peerEccDsaKey = (ecc_key*)XMALLOC(sizeof(ecc_key),
ssl->ctx->heap, DYNAMIC_TYPE_ECC);
if (ssl->peerEccDsaKey == NULL) {
WOLFSSL_MSG("PeerEccDsaKey Memory error");
return MEMORY_E;
}
wc_ecc_init(ssl->peerEccDsaKey);
} else if (ssl->peerEccDsaKeyPresent) {
/* don't leak on reuse */
2014-12-30 15:14:27 -07:00
wc_ecc_free(ssl->peerEccDsaKey);
ssl->peerEccDsaKeyPresent = 0;
2014-12-30 15:14:27 -07:00
wc_ecc_init(ssl->peerEccDsaKey);
}
2014-12-30 15:14:27 -07:00
if (wc_ecc_import_x963(dCert->publicKey, dCert->pubKeySize,
ssl->peerEccDsaKey) != 0) {
ret = PEER_KEY_ERROR;
}
else {
ssl->peerEccDsaKeyPresent = 1;
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ssl->buffers.peerEccDsaKey.buffer =
2014-12-04 17:16:39 -08:00
(byte*)XMALLOC(dCert->pubKeySize,
ssl->heap, DYNAMIC_TYPE_ECC);
if (ssl->buffers.peerEccDsaKey.buffer == NULL)
ret = MEMORY_ERROR;
else {
XMEMCPY(ssl->buffers.peerEccDsaKey.buffer,
dCert->publicKey, dCert->pubKeySize);
ssl->buffers.peerEccDsaKey.length =
dCert->pubKeySize;
}
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
}
}
break;
#endif /* HAVE_ECC */
default:
break;
}
FreeDecodedCert(dCert);
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2014-12-19 11:27:01 -07:00
store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX),
NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (store == NULL) {
XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
if (anyError != 0 && ret == 0)
ret = anyError;
if (ret != 0) {
if (!ssl->options.verifyNone) {
int why = bad_certificate;
if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E)
why = certificate_expired;
if (ssl->verifyCallback) {
int ok;
store->error = ret;
store->error_depth = totalCerts;
store->discardSessionCerts = 0;
store->domain = domain;
store->userCtx = ssl->verifyCbCtx;
#ifdef KEEP_PEER_CERT
store->current_cert = &ssl->peerCert;
#else
store->current_cert = NULL;
#endif
2015-07-14 14:56:26 -06:00
#if defined(HAVE_FORTRESS) || defined(HAVE_STUNNEL)
store->ex_data = ssl;
#endif
ok = ssl->verifyCallback(0, store);
if (ok) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verify callback overriding error!");
ret = 0;
}
#ifdef SESSION_CERTS
if (store->discardSessionCerts) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verify callback requested discard sess certs");
ssl->session.chain.count = 0;
}
#endif
}
if (ret != 0) {
SendAlert(ssl, alert_fatal, why); /* try to send */
ssl->options.isClosed = 1;
}
}
ssl->error = ret;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_ALWAYS_VERIFY_CB
else {
if (ssl->verifyCallback) {
int ok;
store->error = ret;
store->error_depth = totalCerts;
store->discardSessionCerts = 0;
store->domain = domain;
store->userCtx = ssl->verifyCbCtx;
#ifdef KEEP_PEER_CERT
store->current_cert = &ssl->peerCert;
#endif
store->ex_data = ssl;
ok = ssl->verifyCallback(1, store);
if (!ok) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verify callback overriding valid certificate!");
ret = -1;
SendAlert(ssl, alert_fatal, bad_certificate);
ssl->options.isClosed = 1;
}
#ifdef SESSION_CERTS
if (store->discardSessionCerts) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verify callback requested discard sess certs");
ssl->session.chain.count = 0;
}
#endif
}
}
#endif
if (ssl->options.verifyNone &&
(ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Ignoring CRL problem based on verify setting");
ret = ssl->error = 0;
}
2014-12-19 11:27:01 -07:00
if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END)
ssl->options.serverState = SERVER_CERT_COMPLETE;
if (IsEncryptionOn(ssl, 0)) {
*inOutIdx += ssl->keys.padSz;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(store, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
2015-11-02 15:51:01 -03:00
static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 size)
{
int ret = 0;
byte status_type;
word32 status_length;
if (size < ENUM_LEN + OPAQUE24_LEN)
return BUFFER_ERROR;
status_type = input[(*inOutIdx)++];
c24to32(input + *inOutIdx, &status_length);
*inOutIdx += OPAQUE24_LEN;
if (size != ENUM_LEN + OPAQUE24_LEN + status_length)
return BUFFER_ERROR;
switch (status_type) {
2015-12-28 19:38:04 -03:00
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2015-11-02 15:51:01 -03:00
2015-12-28 19:38:04 -03:00
/* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */
case WOLFSSL_CSR2_OCSP: {
OcspRequest* request;
#ifdef WOLFSSL_SMALL_STACK
CertStatus* status;
OcspResponse* response;
#else
CertStatus status[1];
OcspResponse response[1];
#endif
2015-11-02 15:51:01 -03:00
do {
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (ssl->status_request) {
2015-12-28 19:38:04 -03:00
request = TLSX_CSR_GetRequest(ssl->extensions);
2015-11-02 15:51:01 -03:00
ssl->status_request = 0;
break;
}
#endif
2015-12-28 19:38:04 -03:00
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
if (ssl->status_request_v2) {
request = TLSX_CSR2_GetRequest(ssl->extensions,
status_type, 0);
ssl->status_request_v2 = 0;
break;
}
#endif
2015-11-02 15:51:01 -03:00
return BUFFER_ERROR;
} while(0);
2015-12-28 19:38:04 -03:00
if (request == NULL)
return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */
#ifdef WOLFSSL_SMALL_STACK
status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
2015-11-02 15:51:01 -03:00
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-28 19:38:04 -03:00
response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
2015-11-02 15:51:01 -03:00
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-28 19:38:04 -03:00
if (status == NULL || response == NULL) {
if (status)
XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (response)
XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2015-11-02 15:51:01 -03:00
2015-12-28 19:38:04 -03:00
return MEMORY_ERROR;
}
#endif
2015-11-02 15:51:01 -03:00
InitOcspResponse(response, status, input +*inOutIdx, status_length);
2015-12-28 19:38:04 -03:00
if ((OcspResponseDecode(response, ssl->ctx->cm) != 0)
|| (response->responseStatus != OCSP_SUCCESSFUL)
|| (response->status->status != CERT_GOOD)
|| (CompareOcspReqResp(request, response) != 0))
ret = BAD_CERTIFICATE_STATUS_ERROR;
2015-11-02 15:51:01 -03:00
*inOutIdx += status_length;
2015-12-28 19:38:04 -03:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
break;
#endif
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
case WOLFSSL_CSR2_OCSP_MULTI: {
OcspRequest* request;
word32 list_length = status_length;
byte index = 0;
#ifdef WOLFSSL_SMALL_STACK
CertStatus* status;
OcspResponse* response;
#else
CertStatus status[1];
OcspResponse response[1];
#endif
do {
if (ssl->status_request_v2) {
ssl->status_request_v2 = 0;
break;
}
return BUFFER_ERROR;
} while(0);
#ifdef WOLFSSL_SMALL_STACK
status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (status == NULL || response == NULL) {
if (status)
XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (response)
XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_ERROR;
}
#endif
while (list_length && ret == 0) {
if (OPAQUE24_LEN > list_length) {
ret = BUFFER_ERROR;
break;
}
c24to32(input + *inOutIdx, &status_length);
*inOutIdx += OPAQUE24_LEN;
list_length -= OPAQUE24_LEN;
if (status_length > list_length) {
ret = BUFFER_ERROR;
break;
}
if (status_length) {
InitOcspResponse(response, status, input +*inOutIdx,
status_length);
if ((OcspResponseDecode(response, ssl->ctx->cm) != 0)
|| (response->responseStatus != OCSP_SUCCESSFUL)
|| (response->status->status != CERT_GOOD))
ret = BAD_CERTIFICATE_STATUS_ERROR;
while (ret == 0) {
request = TLSX_CSR2_GetRequest(ssl->extensions,
status_type, index++);
if (request == NULL)
ret = BAD_CERTIFICATE_STATUS_ERROR;
else if (CompareOcspReqResp(request, response) == 0)
break;
else if (index == 1) /* server cert must be OK */
ret = BAD_CERTIFICATE_STATUS_ERROR;
}
*inOutIdx += status_length;
list_length -= status_length;
}
}
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
ssl->status_request_v2 = 0;
#endif
#ifdef WOLFSSL_SMALL_STACK
XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2015-11-02 15:51:01 -03:00
}
break;
2015-12-28 19:38:04 -03:00
2015-11-02 15:51:01 -03:00
#endif
default:
ret = BUFFER_ERROR;
}
if (ret != 0)
SendAlert(ssl, alert_fatal, bad_certificate_status_response);
return ret;
}
#endif /* !NO_CERTS */
2014-12-19 11:27:01 -07:00
static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32 size, word32 totalSz)
{
(void)input;
if (size) /* must be 0 */
return BUFFER_ERROR;
if (IsEncryptionOn(ssl, 0)) {
/* access beyond input + size should be checked against totalSz */
if (*inOutIdx + ssl->keys.padSz > totalSz)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz;
}
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_SERVER_END) {
SendAlert(ssl, alert_fatal, unexpected_message); /* try */
return FATAL_ERROR;
}
2014-09-29 14:48:49 -07:00
#ifdef HAVE_SECURE_RENEGOTIATION
else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
ssl->secure_renegotiation->startScr = 1;
return 0;
}
#endif
else {
return SendAlert(ssl, alert_warning, no_renegotiation);
2014-09-29 14:48:49 -07:00
}
}
2014-12-19 11:27:01 -07:00
int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
word32 totalSz, int sniff)
{
word32 finishedSz = (ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ);
if (finishedSz != size)
return BUFFER_ERROR;
2014-09-16 11:51:13 -07:00
/* check against totalSz */
if (*inOutIdx + size + ssl->keys.padSz > totalSz)
return BUFFER_E;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
#endif
if (sniff == NO_SNIFF) {
if (XMEMCMP(input + *inOutIdx, &ssl->hsHashes->verifyHashes,size) != 0){
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verify finished error on hashes");
return VERIFY_FINISHED_ERROR;
}
}
#ifdef HAVE_SECURE_RENEGOTIATION
2014-09-16 17:26:57 -07:00
if (ssl->secure_renegotiation) {
2014-09-16 11:51:13 -07:00
/* save peer's state */
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_CLIENT_END)
2014-09-16 17:26:57 -07:00
XMEMCPY(ssl->secure_renegotiation->server_verify_data,
input + *inOutIdx, TLS_FINISHED_SZ);
2014-09-16 11:51:13 -07:00
else
2014-09-16 17:26:57 -07:00
XMEMCPY(ssl->secure_renegotiation->client_verify_data,
input + *inOutIdx, TLS_FINISHED_SZ);
2014-09-16 11:51:13 -07:00
}
#endif
/* force input exhaustion at ProcessReply consuming padSz */
*inOutIdx += size + ssl->keys.padSz;
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
if (!ssl->options.resuming) {
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
}
}
else {
ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
if (ssl->options.resuming) {
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
}
}
return 0;
2011-02-05 11:14:47 -08:00
}
/* Make sure no duplicates, no fast forward, or other problems; 0 on success */
2014-12-19 11:27:01 -07:00
static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
{
/* verify not a duplicate, mark received, check state */
switch (type) {
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
case hello_request:
if (ssl->msgsReceived.got_hello_request) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate HelloRequest received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_hello_request = 1;
break;
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_SERVER
case client_hello:
if (ssl->msgsReceived.got_client_hello) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate ClientHello received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_client_hello = 1;
break;
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
case server_hello:
if (ssl->msgsReceived.got_server_hello) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate ServerHello received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_server_hello = 1;
break;
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
case hello_verify_request:
if (ssl->msgsReceived.got_hello_verify_request) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate HelloVerifyRequest received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_hello_verify_request = 1;
break;
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
case session_ticket:
if (ssl->msgsReceived.got_session_ticket) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate SessionTicket received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_session_ticket = 1;
break;
#endif
case certificate:
if (ssl->msgsReceived.got_certificate) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate Certificate received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_certificate = 1;
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
if (ssl->options.side == WOLFSSL_CLIENT_END) {
if ( ssl->msgsReceived.got_server_hello == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No ServerHello before Cert");
return OUT_OF_ORDER_E;
}
}
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_SERVER
if (ssl->options.side == WOLFSSL_SERVER_END) {
if ( ssl->msgsReceived.got_client_hello == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No ClientHello before Cert");
return OUT_OF_ORDER_E;
}
}
#endif
break;
2015-11-02 15:51:01 -03:00
#ifndef NO_WOLFSSL_CLIENT
case certificate_status:
if (ssl->msgsReceived.got_certificate_status) {
WOLFSSL_MSG("Duplicate CertificateSatatus received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_certificate_status = 1;
if (ssl->msgsReceived.got_certificate == 0) {
WOLFSSL_MSG("No Certificate before CertificateStatus");
return OUT_OF_ORDER_E;
}
if (ssl->msgsReceived.got_server_key_exchange != 0) {
WOLFSSL_MSG("CertificateStatus after ServerKeyExchange");
return OUT_OF_ORDER_E;
}
break;
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
case server_key_exchange:
if (ssl->msgsReceived.got_server_key_exchange) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate ServerKeyExchange received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_server_key_exchange = 1;
2015-11-02 15:51:01 -03:00
if (ssl->msgsReceived.got_server_hello == 0) {
WOLFSSL_MSG("No ServerHello before ServerKeyExchange");
return OUT_OF_ORDER_E;
}
2015-11-02 15:51:01 -03:00
if (ssl->msgsReceived.got_certificate_status == 0) {
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (ssl->status_request) {
int ret;
WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0)
return ret;
}
2015-12-28 19:38:04 -03:00
#endif
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
if (ssl->status_request_v2) {
int ret;
WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
if ((ret = TLSX_CSR2_ForceRequest(ssl)) != 0)
return ret;
}
2015-11-02 15:51:01 -03:00
#endif
}
break;
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
case certificate_request:
if (ssl->msgsReceived.got_certificate_request) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate CertificateRequest received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_certificate_request = 1;
break;
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
case server_hello_done:
if (ssl->msgsReceived.got_server_hello_done) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate ServerHelloDone received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_server_hello_done = 1;
if (ssl->msgsReceived.got_certificate == 0) {
if (ssl->specs.kea == psk_kea ||
ssl->specs.kea == dhe_psk_kea ||
ssl->options.usingAnon_cipher) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No Cert required");
} else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No Certificate before ServerHelloDone");
return OUT_OF_ORDER_E;
}
}
if (ssl->msgsReceived.got_server_key_exchange == 0) {
2015-07-30 16:45:31 -07:00
int pskNoServerHint = 0; /* not required in this case */
#ifndef NO_PSK
if (ssl->specs.kea == psk_kea &&
ssl->arrays->server_hint[0] == 0)
pskNoServerHint = 1;
#endif
if (ssl->specs.static_ecdh == 1 ||
ssl->specs.kea == rsa_kea ||
2015-07-30 16:45:31 -07:00
ssl->specs.kea == ntru_kea ||
pskNoServerHint) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No KeyExchange required");
} else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No ServerKeyExchange before ServerDone");
return OUT_OF_ORDER_E;
}
}
break;
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_SERVER
case certificate_verify:
if (ssl->msgsReceived.got_certificate_verify) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate CertificateVerify received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_certificate_verify = 1;
if ( ssl->msgsReceived.got_certificate == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No Cert before CertVerify");
return OUT_OF_ORDER_E;
}
break;
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_SERVER
case client_key_exchange:
if (ssl->msgsReceived.got_client_key_exchange) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate ClientKeyExchange received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_client_key_exchange = 1;
if (ssl->msgsReceived.got_client_hello == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No ClientHello before ClientKeyExchange");
return OUT_OF_ORDER_E;
}
break;
#endif
case finished:
if (ssl->msgsReceived.got_finished) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate Finished received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_finished = 1;
if (ssl->msgsReceived.got_change_cipher == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Finished received before ChangeCipher");
return NO_CHANGE_CIPHER_E;
}
break;
case change_cipher_hs:
if (ssl->msgsReceived.got_change_cipher) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Duplicate ChangeCipher received");
return DUPLICATE_MSG_E;
}
ssl->msgsReceived.got_change_cipher = 1;
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (!ssl->options.resuming &&
ssl->msgsReceived.got_server_hello_done == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No ServerHelloDone before ChangeCipher");
return OUT_OF_ORDER_E;
}
}
#endif
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_SERVER
if (ssl->options.side == WOLFSSL_SERVER_END) {
if (!ssl->options.resuming &&
ssl->msgsReceived.got_client_key_exchange == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("No ClientKeyExchange before ChangeCipher");
return OUT_OF_ORDER_E;
}
}
#endif
break;
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Unknown message type");
return SANITY_MSG_E;
}
return 0;
}
2014-12-19 11:27:01 -07:00
static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
byte type, word32 size, word32 totalSz)
{
int ret = 0;
(void)totalSz;
2014-12-19 11:27:01 -07:00
WOLFSSL_ENTER("DoHandShakeMsgType");
/* make sure can read the message */
if (*inOutIdx + size > totalSz)
return INCOMPLETE_DATA;
/* sanity check msg received */
if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Sanity Check on handshake message type received failed");
return ret;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
/* add name later, add on record and handshake header part back on */
if (ssl->toInfoOn) {
int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
AddPacketInfo(0, &ssl->timeoutInfo, input + *inOutIdx - add,
size + add, ssl->heap);
AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
}
#endif
if (ssl->options.handShakeState == HANDSHAKE_DONE && type != hello_request){
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("HandShake message after handshake complete");
SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E;
}
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls == 0 &&
ssl->options.serverState == NULL_STATE && type != server_hello) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("First server message not server hello");
SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E;
}
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls &&
type == server_hello_done &&
ssl->options.serverState < SERVER_HELLO_COMPLETE) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Server hello done received before server hello in DTLS");
SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E;
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.clientState == NULL_STATE && type != client_hello) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("First client message not client hello");
SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E;
}
2011-02-05 11:14:47 -08:00
/* above checks handshake state */
/* hello_request not hashed */
/* Also, skip hashing the client_hello message here for DTLS. It will be
* hashed later if the DTLS cookie is correct. */
if (type != hello_request && !(ssl->options.dtls && type == client_hello)) {
ret = HashInput(ssl, input + *inOutIdx, size);
if (ret != 0) return ret;
}
2011-02-05 11:14:47 -08:00
switch (type) {
case hello_request:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing hello request");
ret = DoHelloRequest(ssl, input, inOutIdx, size, totalSz);
break;
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
case hello_verify_request:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing hello verify request");
ret = DoHelloVerifyRequest(ssl, input,inOutIdx, size);
break;
case server_hello:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing server hello");
ret = DoServerHello(ssl, input, inOutIdx, size);
break;
#ifndef NO_CERTS
case certificate_request:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing certificate request");
ret = DoCertificateRequest(ssl, input, inOutIdx, size);
break;
#endif
2013-01-15 15:20:30 -08:00
case server_key_exchange:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing server key exchange");
ret = DoServerKeyExchange(ssl, input, inOutIdx, size);
break;
#ifdef HAVE_SESSION_TICKET
case session_ticket:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing session ticket");
ret = DoSessionTicket(ssl, input, inOutIdx, size);
break;
#endif /* HAVE_SESSION_TICKET */
#endif
2013-01-15 15:20:30 -08:00
#ifndef NO_CERTS
case certificate:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing certificate");
2015-11-02 15:51:01 -03:00
ret = DoCertificate(ssl, input, inOutIdx, size);
break;
case certificate_status:
WOLFSSL_MSG("processing certificate status");
ret = DoCertificateStatus(ssl, input, inOutIdx, size);
break;
#endif
2013-01-15 15:20:30 -08:00
case server_hello_done:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing server hello done");
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddLateName("ServerHelloDone", &ssl->timeoutInfo);
#endif
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
if (IsEncryptionOn(ssl, 0)) {
*inOutIdx += ssl->keys.padSz;
}
if (ssl->options.resuming) {
WOLFSSL_MSG("Not resuming as thought");
ssl->options.resuming = 0;
}
break;
case finished:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing finished");
ret = DoFinished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF);
break;
2013-01-21 10:53:42 -08:00
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_SERVER
case client_hello:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing client hello");
ret = DoClientHello(ssl, input, inOutIdx, size);
break;
2011-02-05 11:14:47 -08:00
case client_key_exchange:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing client key exchange");
ret = DoClientKeyExchange(ssl, input, inOutIdx, size);
break;
#if !defined(NO_RSA) || defined(HAVE_ECC)
case certificate_verify:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("processing certificate verify");
ret = DoCertificateVerify(ssl, input, inOutIdx, size);
break;
#endif /* !NO_RSA || HAVE_ECC */
2014-12-19 11:27:01 -07:00
#endif /* !NO_WOLFSSL_SERVER */
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Unknown handshake message type");
ret = UNKNOWN_HANDSHAKE_TYPE;
break;
2011-02-05 11:14:47 -08:00
}
2014-12-19 11:27:01 -07:00
WOLFSSL_LEAVE("DoHandShakeMsgType()", ret);
return ret;
2011-02-05 11:14:47 -08:00
}
2014-12-19 11:27:01 -07:00
static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 totalSz)
2011-02-05 11:14:47 -08:00
{
int ret = 0;
word32 inputLength;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
WOLFSSL_ENTER("DoHandShakeMsg()");
2011-02-05 11:14:47 -08:00
if (ssl->arrays == NULL) {
byte type;
word32 size;
if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0)
return PARSE_ERROR;
return DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
}
inputLength = ssl->buffers.inputBuffer.length - *inOutIdx;
/* If there is a pending fragmented handshake message,
* pending message size will be non-zero. */
if (ssl->arrays->pendingMsgSz == 0) {
byte type;
word32 size;
if (GetHandShakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0)
return PARSE_ERROR;
/* Cap the maximum size of a handshake message to something reasonable.
* By default is the maximum size of a certificate message assuming
* nine 2048-bit RSA certificates in the chain. */
if (size > MAX_HANDSHAKE_SZ) {
WOLFSSL_MSG("Handshake message too large");
return HANDSHAKE_SIZE_ERROR;
}
/* size is the size of the certificate message payload */
if (inputLength - HANDSHAKE_HEADER_SZ < size) {
ssl->arrays->pendingMsgType = type;
ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
ssl->heap,
DYNAMIC_TYPE_ARRAYS);
if (ssl->arrays->pendingMsg == NULL)
return MEMORY_E;
XMEMCPY(ssl->arrays->pendingMsg,
input + *inOutIdx - HANDSHAKE_HEADER_SZ,
inputLength);
ssl->arrays->pendingMsgOffset = inputLength;
*inOutIdx += inputLength - HANDSHAKE_HEADER_SZ;
return 0;
}
ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
}
else {
if (inputLength + ssl->arrays->pendingMsgOffset
> ssl->arrays->pendingMsgSz) {
return BUFFER_ERROR;
}
else {
XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
input + *inOutIdx, inputLength);
ssl->arrays->pendingMsgOffset += inputLength;
*inOutIdx += inputLength;
}
if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
{
word32 idx = 0;
ret = DoHandShakeMsgType(ssl,
ssl->arrays->pendingMsg
+ HANDSHAKE_HEADER_SZ,
&idx, ssl->arrays->pendingMsgType,
ssl->arrays->pendingMsgSz
- HANDSHAKE_HEADER_SZ,
ssl->arrays->pendingMsgSz);
XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->arrays->pendingMsg = NULL;
ssl->arrays->pendingMsgSz = 0;
}
}
2014-12-19 11:27:01 -07:00
WOLFSSL_LEAVE("DoHandShakeMsg()", ret);
return ret;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
static INLINE int DtlsCheckWindow(DtlsState* state)
{
word32 cur;
word32 next;
DtlsSeq window;
if (state->curEpoch == state->nextEpoch) {
next = state->nextSeq;
window = state->window;
}
else if (state->curEpoch < state->nextEpoch) {
next = state->prevSeq;
window = state->prevWindow;
}
else {
return 0;
}
2013-01-15 15:20:30 -08:00
cur = state->curSeq;
2013-01-15 15:20:30 -08:00
if ((next > DTLS_SEQ_BITS) && (cur < next - DTLS_SEQ_BITS)) {
return 0;
}
else if ((cur < next) && (window & ((DtlsSeq)1 << (next - cur - 1)))) {
return 0;
}
2013-01-15 15:20:30 -08:00
return 1;
}
static INLINE int DtlsUpdateWindow(DtlsState* state)
{
word32 cur;
word32* next;
DtlsSeq* window;
if (state->curEpoch == state->nextEpoch) {
next = &state->nextSeq;
window = &state->window;
}
else {
next = &state->prevSeq;
window = &state->prevWindow;
2011-02-05 11:14:47 -08:00
}
cur = state->curSeq;
if (cur < *next) {
*window |= ((DtlsSeq)1 << (*next - cur - 1));
2012-12-24 15:40:09 -08:00
}
else {
*window <<= (1 + cur - *next);
*window |= 1;
*next = cur + 1;
2012-12-24 15:40:09 -08:00
}
return 1;
2012-12-24 15:40:09 -08:00
}
2014-12-19 11:27:01 -07:00
static int DtlsMsgDrain(WOLFSSL* ssl)
2012-12-27 16:35:43 -08:00
{
DtlsMsg* item = ssl->dtls_msg_list;
int ret = 0;
2012-12-27 16:35:43 -08:00
/* While there is an item in the store list, and it is the expected
* message, and it is complete, and there hasn't been an error in the
* last messge... */
while (item != NULL &&
ssl->keys.dtls_expected_peer_handshake_number == item->seq &&
item->fragSz == item->sz &&
ret == 0) {
word32 idx = 0;
ssl->keys.dtls_expected_peer_handshake_number++;
ret = DoHandShakeMsgType(ssl, item->msg,
&idx, item->type, item->sz, item->sz);
ssl->dtls_msg_list = item->next;
DtlsMsgDelete(item, ssl->heap);
item = ssl->dtls_msg_list;
}
return ret;
2012-12-27 16:35:43 -08:00
}
2014-12-19 11:27:01 -07:00
static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 totalSz)
2012-12-27 16:35:43 -08:00
{
byte type;
word32 size;
word32 fragOffset, fragSz;
int ret = 0;
2012-12-27 16:35:43 -08:00
2014-12-19 11:27:01 -07:00
WOLFSSL_ENTER("DoDtlsHandShakeMsg()");
if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type,
2014-12-01 08:58:52 -08:00
&size, &fragOffset, &fragSz, totalSz) != 0)
return PARSE_ERROR;
2012-12-27 16:35:43 -08:00
if (*inOutIdx + fragSz > totalSz)
return INCOMPLETE_DATA;
/* Check the handshake sequence number first. If out of order,
* add the current message to the list. If the message is in order,
* but it is a fragment, add the current message to the list, then
* check the head of the list to see if it is complete, if so, pop
* it out as the current message. If the message is complete and in
* order, process it. Check the head of the list to see if it is in
* order, if so, process it. (Repeat until list exhausted.) If the
* head is out of order, return for more processing.
*/
if (ssl->keys.dtls_peer_handshake_number >
ssl->keys.dtls_expected_peer_handshake_number) {
/* Current message is out of order. It will get stored in the list.
* Storing also takes care of defragmentation. */
ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list,
ssl->keys.dtls_peer_handshake_number, input + *inOutIdx,
size, type, fragOffset, fragSz, ssl->heap);
*inOutIdx += fragSz;
ret = 0;
}
else if (ssl->keys.dtls_peer_handshake_number <
ssl->keys.dtls_expected_peer_handshake_number) {
/* Already saw this message and processed it. It can be ignored. */
*inOutIdx += fragSz;
if(type == finished )
*inOutIdx += ssl->keys.padSz;
ret = 0;
}
else if (fragSz < size) {
/* Since this branch is in order, but fragmented, dtls_msg_list will be
* pointing to the message with this fragment in it. Check it to see
* if it is completed. */
ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list,
ssl->keys.dtls_peer_handshake_number, input + *inOutIdx,
size, type, fragOffset, fragSz, ssl->heap);
*inOutIdx += fragSz;
ret = 0;
if (ssl->dtls_msg_list != NULL &&
ssl->dtls_msg_list->fragSz >= ssl->dtls_msg_list->sz)
ret = DtlsMsgDrain(ssl);
}
else {
/* This branch is in order next, and a complete message. */
ssl->keys.dtls_expected_peer_handshake_number++;
ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
if (ret == 0 && ssl->dtls_msg_list != NULL)
ret = DtlsMsgDrain(ssl);
}
2014-12-19 11:27:01 -07:00
WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret);
return ret;
2012-12-27 16:35:43 -08:00
}
#endif
2014-07-18 14:42:45 -06:00
#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
|| defined(HAVE_AESGCM)
2014-12-19 11:27:01 -07:00
static INLINE word32 GetSEQIncrement(WOLFSSL* ssl, int verify)
2012-12-27 16:35:43 -08:00
{
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
if (verify)
return ssl->keys.dtls_state.curSeq; /* explicit from peer */
else
return ssl->keys.dtls_sequence_number - 1; /* already incremented */
}
#endif
if (verify)
return ssl->keys.peer_sequence_number++;
else
return ssl->keys.sequence_number++;
2012-12-27 16:35:43 -08:00
}
2014-07-16 14:40:41 -07:00
#endif
2012-12-27 16:35:43 -08:00
#ifdef HAVE_AEAD
2014-12-19 11:27:01 -07:00
static INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
2012-12-27 16:35:43 -08:00
{
int i;
for (i = AEAD_EXP_IV_SZ-1; i >= 0; i--) {
if (++ssl->keys.aead_exp_IV[i]) return;
}
2012-12-27 16:35:43 -08:00
}
2014-07-16 14:55:38 -06:00
#if defined(HAVE_POLY1305) && defined(HAVE_CHACHA)
2014-07-17 15:00:40 -06:00
/*more recent rfc's concatonate input for poly1305 differently*/
2014-12-19 11:27:01 -07:00
static int Poly1305Tag(WOLFSSL* ssl, byte* additional, const byte* out,
2014-07-17 15:00:40 -06:00
byte* cipher, word16 sz, byte* tag)
2014-07-16 14:55:38 -06:00
{
2014-07-17 15:00:40 -06:00
int ret = 0;
int paddingSz = 0;
int msglen = (sz - ssl->specs.aead_mac_size);
word32 keySz = 32;
int blockSz = 16;
2014-07-17 15:00:40 -06:00
byte padding[16];
2014-07-16 14:55:38 -06:00
2014-07-17 15:00:40 -06:00
if (msglen < 0)
return INPUT_CASE_ERROR;
2014-07-16 14:55:38 -06:00
2014-07-17 15:00:40 -06:00
XMEMSET(padding, 0, sizeof(padding));
2014-07-16 14:55:38 -06:00
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0)
2014-07-17 15:00:40 -06:00
return ret;
2014-07-16 14:55:38 -06:00
2015-06-18 14:25:48 +09:00
/* additional input to poly1305 */
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional, blockSz)) != 0)
2014-07-17 15:00:40 -06:00
return ret;
2014-07-16 14:55:38 -06:00
2014-07-17 15:00:40 -06:00
/* cipher input */
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0)
2014-07-17 15:00:40 -06:00
return ret;
2014-07-17 15:33:48 -06:00
/* handle padding for cipher input to make it 16 bytes long */
2014-10-24 10:33:24 -03:00
if (msglen % 16 != 0) {
2014-07-17 15:00:40 -06:00
paddingSz = (16 - (sz - ssl->specs.aead_mac_size) % 16);
if (paddingSz < 0)
return INPUT_CASE_ERROR;
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, paddingSz))
2014-07-17 15:00:40 -06:00
!= 0)
return ret;
}
/* add size of AD and size of cipher to poly input */
XMEMSET(padding, 0, sizeof(padding));
padding[0] = blockSz;
2014-07-17 15:00:40 -06:00
/* 32 bit size of cipher to 64 bit endian */
padding[8] = msglen & 0xff;
padding[9] = (msglen >> 8) & 0xff;
padding[10] = (msglen >>16) & 0xff;
padding[11] = (msglen >>24) & 0xff;
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding)))
2014-07-17 15:00:40 -06:00
!= 0)
return ret;
/* generate tag */
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305Final(ssl->auth.poly1305, tag)) != 0)
2014-07-17 15:00:40 -06:00
return ret;
return ret;
}
2014-07-16 14:55:38 -06:00
2014-07-17 15:33:48 -06:00
/* Used for the older version of creating AEAD tags with Poly1305 */
2014-12-19 11:27:01 -07:00
static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
2014-07-17 15:00:40 -06:00
byte* cipher, word16 sz, byte* tag)
2014-07-16 14:55:38 -06:00
{
2014-07-17 15:00:40 -06:00
int ret = 0;
int msglen = (sz - ssl->specs.aead_mac_size);
word32 keySz = 32;
byte padding[8]; /* used to temporarly store lengths */
2014-07-16 14:55:38 -06:00
#ifdef CHACHA_AEAD_TEST
printf("Using old version of poly1305 input.\n");
#endif
2014-07-17 15:00:40 -06:00
if (msglen < 0)
return INPUT_CASE_ERROR;
2014-07-16 14:55:38 -06:00
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0)
2014-07-17 15:00:40 -06:00
return ret;
2014-07-16 14:55:38 -06:00
2015-06-18 14:25:48 +09:00
/* add TLS compressed length and additional input to poly1305 */
2014-07-17 15:00:40 -06:00
additional[AEAD_AUTH_DATA_SZ - 2] = (msglen >> 8) & 0xff;
additional[AEAD_AUTH_DATA_SZ - 1] = msglen & 0xff;
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional,
2014-07-17 15:00:40 -06:00
AEAD_AUTH_DATA_SZ)) != 0)
return ret;
/* length of additional input plus padding */
XMEMSET(padding, 0, sizeof(padding));
padding[0] = AEAD_AUTH_DATA_SZ;
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding,
2014-07-17 15:00:40 -06:00
sizeof(padding))) != 0)
return ret;
2014-07-16 14:55:38 -06:00
2014-07-17 15:00:40 -06:00
/* add cipher info and then its length */
XMEMSET(padding, 0, sizeof(padding));
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0)
2014-07-17 15:00:40 -06:00
return ret;
/* 32 bit size of cipher to 64 bit endian */
padding[0] = msglen & 0xff;
padding[1] = (msglen >> 8) & 0xff;
padding[2] = (msglen >> 16) & 0xff;
padding[3] = (msglen >> 24) & 0xff;
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding)))
2014-07-17 15:00:40 -06:00
!= 0)
return ret;
/* generate tag */
2014-12-30 10:30:54 -07:00
if ((ret = wc_Poly1305Final(ssl->auth.poly1305, tag)) != 0)
2014-07-17 15:00:40 -06:00
return ret;
2014-07-16 14:55:38 -06:00
2014-07-17 15:00:40 -06:00
return ret;
2014-07-16 14:55:38 -06:00
}
2014-07-17 15:00:40 -06:00
2014-07-17 15:33:48 -06:00
2014-12-19 11:27:01 -07:00
static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
2014-07-17 15:00:40 -06:00
word16 sz)
{
2015-06-18 14:25:48 +09:00
const byte* additionalSrc = input - RECORD_HEADER_SZ;
int ret = 0;
byte tag[POLY1305_AUTH_SZ];
byte additional[CHACHA20_BLOCK_SIZE];
byte nonce[AEAD_NONCE_SZ];
byte cipher[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */
2014-07-24 20:12:10 -07:00
#ifdef CHACHA_AEAD_TEST
int i;
2014-07-24 18:59:39 -06:00
#endif
2015-06-18 14:25:48 +09:00
XMEMSET(tag, 0, sizeof(tag));
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
XMEMSET(cipher, 0, sizeof(cipher));
XMEMSET(additional, 0, CHACHA20_BLOCK_SIZE);
/* get nonce */
c32toa(ssl->keys.sequence_number, nonce + AEAD_IMP_IV_SZ
+ AEAD_SEQ_OFFSET);
/* opaque SEQ number stored for AD */
c32toa(GetSEQIncrement(ssl, 0), additional + AEAD_SEQ_OFFSET);
/* Store the type, version. Unfortunately, they are in
* the input buffer ahead of the plaintext. */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
c16toa(ssl->keys.dtls_epoch, additional);
additionalSrc -= DTLS_HANDSHAKE_EXTRA;
}
#endif
XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3);
#ifdef CHACHA_AEAD_TEST
printf("Encrypt Additional : ");
for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) {
printf("%02x", additional[i]);
}
printf("\n\n");
printf("input before encryption :\n");
for (i = 0; i < sz; i++) {
printf("%02x", input[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n");
#endif
/* set the nonce for chacha and get poly1305 key */
if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0)
return ret;
if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, cipher,
cipher, sizeof(cipher))) != 0)
return ret;
/* encrypt the plain text */
if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out, input,
sz - ssl->specs.aead_mac_size)) != 0)
return ret;
/* get the tag : future use of hmac could go here*/
if (ssl->options.oldPoly == 1) {
if ((ret = Poly1305TagOld(ssl, additional, (const byte* )out,
cipher, sz, tag)) != 0)
return ret;
}
else {
if ((ret = Poly1305Tag(ssl, additional, (const byte* )out,
cipher, sz, tag)) != 0)
return ret;
}
/* append tag to ciphertext */
XMEMCPY(out + sz - ssl->specs.aead_mac_size, tag, sizeof(tag));
AeadIncrementExpIV(ssl);
ForceZero(nonce, AEAD_NONCE_SZ);
#ifdef CHACHA_AEAD_TEST
printf("mac tag :\n");
for (i = 0; i < 16; i++) {
printf("%02x", tag[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n\noutput after encrypt :\n");
for (i = 0; i < sz; i++) {
printf("%02x", out[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n");
#endif
return ret;
2014-07-17 15:00:40 -06:00
}
2014-07-17 15:33:48 -06:00
2014-12-19 11:27:01 -07:00
static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
2014-07-17 15:00:40 -06:00
word16 sz)
{
2015-06-18 14:25:48 +09:00
byte additional[CHACHA20_BLOCK_SIZE];
byte nonce[AEAD_NONCE_SZ];
byte tag[POLY1305_AUTH_SZ];
byte cipher[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
int ret = 0;
2015-06-18 14:25:48 +09:00
XMEMSET(tag, 0, sizeof(tag));
XMEMSET(cipher, 0, sizeof(cipher));
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
XMEMSET(additional, 0, CHACHA20_BLOCK_SIZE);
2014-07-17 15:33:48 -06:00
#ifdef CHACHA_AEAD_TEST
int i;
2015-06-18 14:25:48 +09:00
printf("input before decrypt :\n");
for (i = 0; i < sz; i++) {
printf("%02x", input[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n");
#endif
/* get nonce */
c32toa(ssl->keys.peer_sequence_number, nonce + AEAD_IMP_IV_SZ
+ AEAD_SEQ_OFFSET);
/* sequence number field is 64-bits, we only use 32-bits */
c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET);
/* get AD info */
additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
/* Store the type, version. */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
c16toa(ssl->keys.dtls_state.curEpoch, additional);
#endif
#ifdef CHACHA_AEAD_TEST
printf("Decrypt Additional : ");
for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) {
printf("%02x", additional[i]);
}
printf("\n\n");
#endif
/* set nonce and get poly1305 key */
if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0)
return ret;
if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, cipher,
cipher, sizeof(cipher))) != 0)
return ret;
/* get the tag : future use of hmac could go here*/
if (ssl->options.oldPoly == 1) {
if ((ret = Poly1305TagOld(ssl, additional, input, cipher,
sz, tag)) != 0)
return ret;
}
else {
if ((ret = Poly1305Tag(ssl, additional, input, cipher,
sz, tag)) != 0)
return ret;
}
/* check mac sent along with packet */
if (ConstantCompare(input + sz - ssl->specs.aead_mac_size, tag,
ssl->specs.aead_mac_size) != 0) {
2015-06-18 14:25:48 +09:00
WOLFSSL_MSG("Mac did not match");
SendAlert(ssl, alert_fatal, bad_record_mac);
ForceZero(nonce, AEAD_NONCE_SZ);
return VERIFY_MAC_ERROR;
}
/* if mac was good decrypt message */
if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain, input,
sz - ssl->specs.aead_mac_size)) != 0)
return ret;
#ifdef CHACHA_AEAD_TEST
printf("plain after decrypt :\n");
for (i = 0; i < sz; i++) {
printf("%02x", plain[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n");
#endif
return ret;
2014-07-17 15:00:40 -06:00
}
#endif /* HAVE_CHACHA && HAVE_POLY1305 */
#endif /* HAVE_AEAD */
2012-12-27 16:35:43 -08:00
2014-12-19 11:27:01 -07:00
static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz)
2012-12-27 16:35:43 -08:00
{
int ret = 0;
(void)out;
(void)input;
(void)sz;
2012-12-27 16:35:43 -08:00
if (ssl->encrypt.setup == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Encrypt ciphers not setup");
return ENCRYPT_ERROR;
}
2012-12-27 16:35:43 -08:00
2014-08-11 16:29:19 -06:00
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
2014-08-12 16:25:58 -06:00
ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx);
2014-08-11 16:29:19 -06:00
#endif
switch (ssl->specs.bulk_cipher_algorithm) {
#ifdef BUILD_ARC4
2014-12-19 11:27:01 -07:00
case wolfssl_rc4:
2014-12-17 09:58:11 -07:00
wc_Arc4Process(ssl->encrypt.arc4, out, input, sz);
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef BUILD_DES3
2014-12-19 11:27:01 -07:00
case wolfssl_triple_des:
ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz);
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef BUILD_AES
2014-12-19 11:27:01 -07:00
case wolfssl_aes:
ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef BUILD_AESGCM
2014-12-19 11:27:01 -07:00
case wolfssl_aes_gcm:
{
byte additional[AEAD_AUTH_DATA_SZ];
byte nonce[AEAD_NONCE_SZ];
const byte* additionalSrc = input - 5;
2012-12-27 16:35:43 -08:00
XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ);
2012-12-27 16:35:43 -08:00
/* sequence number field is 64-bits, we only use 32-bits */
c32toa(GetSEQIncrement(ssl, 0),
additional + AEAD_SEQ_OFFSET);
2012-12-27 16:35:43 -08:00
/* Store the type, version. Unfortunately, they are in
* the input buffer ahead of the plaintext. */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
c16toa(ssl->keys.dtls_epoch, additional);
additionalSrc -= DTLS_HANDSHAKE_EXTRA;
}
#endif
XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3);
2012-12-27 16:35:43 -08:00
/* Store the length of the plain text minus the explicit
* IV length minus the authentication tag size. */
c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
additional + AEAD_LEN_OFFSET);
XMEMCPY(nonce,
ssl->keys.aead_enc_imp_IV, AEAD_IMP_IV_SZ);
XMEMCPY(nonce + AEAD_IMP_IV_SZ,
ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ);
ret = wc_AesGcmEncrypt(ssl->encrypt.aes,
out + AEAD_EXP_IV_SZ, input + AEAD_EXP_IV_SZ,
sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
nonce, AEAD_NONCE_SZ,
out + sz - ssl->specs.aead_mac_size,
ssl->specs.aead_mac_size,
additional, AEAD_AUTH_DATA_SZ);
AeadIncrementExpIV(ssl);
2015-02-20 15:51:21 -08:00
ForceZero(nonce, AEAD_NONCE_SZ);
}
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef HAVE_AESCCM
2014-12-19 11:27:01 -07:00
case wolfssl_aes_ccm:
{
byte additional[AEAD_AUTH_DATA_SZ];
byte nonce[AEAD_NONCE_SZ];
const byte* additionalSrc = input - 5;
2012-12-27 16:35:43 -08:00
XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ);
2012-12-27 16:35:43 -08:00
/* sequence number field is 64-bits, we only use 32-bits */
c32toa(GetSEQIncrement(ssl, 0),
additional + AEAD_SEQ_OFFSET);
2012-12-27 16:35:43 -08:00
/* Store the type, version. Unfortunately, they are in
* the input buffer ahead of the plaintext. */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
c16toa(ssl->keys.dtls_epoch, additional);
additionalSrc -= DTLS_HANDSHAKE_EXTRA;
}
#endif
XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3);
2012-12-27 16:35:43 -08:00
/* Store the length of the plain text minus the explicit
* IV length minus the authentication tag size. */
c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
additional + AEAD_LEN_OFFSET);
XMEMCPY(nonce,
ssl->keys.aead_enc_imp_IV, AEAD_IMP_IV_SZ);
XMEMCPY(nonce + AEAD_IMP_IV_SZ,
ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ);
2015-10-02 11:40:47 -06:00
ret = wc_AesCcmEncrypt(ssl->encrypt.aes,
out + AEAD_EXP_IV_SZ, input + AEAD_EXP_IV_SZ,
sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
nonce, AEAD_NONCE_SZ,
out + sz - ssl->specs.aead_mac_size,
ssl->specs.aead_mac_size,
additional, AEAD_AUTH_DATA_SZ);
AeadIncrementExpIV(ssl);
2015-02-20 15:51:21 -08:00
ForceZero(nonce, AEAD_NONCE_SZ);
}
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef HAVE_CAMELLIA
2014-12-19 11:27:01 -07:00
case wolfssl_camellia:
2014-12-30 11:00:18 -07:00
wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz);
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef HAVE_HC128
2014-12-19 11:27:01 -07:00
case wolfssl_hc128:
ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz);
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef BUILD_RABBIT
2014-12-19 11:27:01 -07:00
case wolfssl_rabbit:
ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz);
break;
#endif
2012-12-27 16:35:43 -08:00
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
2014-12-19 11:27:01 -07:00
case wolfssl_chacha:
ret = ChachaAEADEncrypt(ssl, out, input, sz);
break;
2014-07-01 14:16:44 -06:00
#endif
#ifdef HAVE_NULL_CIPHER
2014-12-19 11:27:01 -07:00
case wolfssl_cipher_null:
if (input != out) {
XMEMMOVE(out, input, sz);
}
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef HAVE_IDEA
case wolfssl_idea:
ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz);
break;
#endif
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("wolfSSL Encrypt programming error");
ret = ENCRYPT_ERROR;
2012-12-27 16:35:43 -08:00
}
return ret;
2012-12-27 16:35:43 -08:00
}
2014-12-19 11:27:01 -07:00
static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
word16 sz)
{
int ret = 0;
(void)plain;
(void)input;
(void)sz;
2012-12-27 16:35:43 -08:00
if (ssl->decrypt.setup == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Decrypt ciphers not setup");
return DECRYPT_ERROR;
}
2012-12-27 16:35:43 -08:00
switch (ssl->specs.bulk_cipher_algorithm) {
#ifdef BUILD_ARC4
2014-12-19 11:27:01 -07:00
case wolfssl_rc4:
2014-12-17 09:58:11 -07:00
wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz);
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef BUILD_DES3
2014-12-19 11:27:01 -07:00
case wolfssl_triple_des:
ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef BUILD_AES
2014-12-19 11:27:01 -07:00
case wolfssl_aes:
ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef BUILD_AESGCM
2014-12-19 11:27:01 -07:00
case wolfssl_aes_gcm:
{
byte additional[AEAD_AUTH_DATA_SZ];
byte nonce[AEAD_NONCE_SZ];
2012-12-27 16:35:43 -08:00
XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ);
2012-12-27 16:35:43 -08:00
/* sequence number field is 64-bits, we only use 32-bits */
c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET);
2012-12-27 16:35:43 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
c16toa(ssl->keys.dtls_state.curEpoch, additional);
#endif
2012-12-27 16:35:43 -08:00
additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
2012-12-27 16:35:43 -08:00
c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
additional + AEAD_LEN_OFFSET);
XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AEAD_IMP_IV_SZ);
XMEMCPY(nonce + AEAD_IMP_IV_SZ, input, AEAD_EXP_IV_SZ);
2014-12-29 10:27:03 -07:00
if (wc_AesGcmDecrypt(ssl->decrypt.aes,
plain + AEAD_EXP_IV_SZ,
input + AEAD_EXP_IV_SZ,
sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
nonce, AEAD_NONCE_SZ,
input + sz - ssl->specs.aead_mac_size,
ssl->specs.aead_mac_size,
additional, AEAD_AUTH_DATA_SZ) < 0) {
SendAlert(ssl, alert_fatal, bad_record_mac);
ret = VERIFY_MAC_ERROR;
}
2015-02-20 15:51:21 -08:00
ForceZero(nonce, AEAD_NONCE_SZ);
}
break;
#endif
2012-12-27 16:35:43 -08:00
#ifdef HAVE_AESCCM
2014-12-19 11:27:01 -07:00
case wolfssl_aes_ccm:
{
byte additional[AEAD_AUTH_DATA_SZ];
byte nonce[AEAD_NONCE_SZ];
2012-12-27 16:35:43 -08:00
XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ);
2012-12-27 16:35:43 -08:00
/* sequence number field is 64-bits, we only use 32-bits */
c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET);
2012-12-27 16:35:43 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
c16toa(ssl->keys.dtls_state.curEpoch, additional);
#endif
2012-12-27 16:35:43 -08:00
additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
2012-12-27 16:35:43 -08:00
c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
additional + AEAD_LEN_OFFSET);
XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AEAD_IMP_IV_SZ);
XMEMCPY(nonce + AEAD_IMP_IV_SZ, input, AEAD_EXP_IV_SZ);
2014-12-29 10:27:03 -07:00
if (wc_AesCcmDecrypt(ssl->decrypt.aes,
plain + AEAD_EXP_IV_SZ,
input + AEAD_EXP_IV_SZ,
sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size,
nonce, AEAD_NONCE_SZ,
input + sz - ssl->specs.aead_mac_size,
ssl->specs.aead_mac_size,
additional, AEAD_AUTH_DATA_SZ) < 0) {
SendAlert(ssl, alert_fatal, bad_record_mac);
ret = VERIFY_MAC_ERROR;
}
2015-02-20 15:51:21 -08:00
ForceZero(nonce, AEAD_NONCE_SZ);
}
break;
#endif
#ifdef HAVE_CAMELLIA
2014-12-19 11:27:01 -07:00
case wolfssl_camellia:
2014-12-30 14:13:57 -07:00
wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz);
break;
#endif
#ifdef HAVE_HC128
2014-12-19 11:27:01 -07:00
case wolfssl_hc128:
ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz);
break;
#endif
#ifdef BUILD_RABBIT
2014-12-19 11:27:01 -07:00
case wolfssl_rabbit:
ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz);
break;
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
2014-12-19 11:27:01 -07:00
case wolfssl_chacha:
ret = ChachaAEADDecrypt(ssl, plain, input, sz);
break;
2014-07-01 14:16:44 -06:00
#endif
#ifdef HAVE_NULL_CIPHER
2014-12-19 11:27:01 -07:00
case wolfssl_cipher_null:
if (input != plain) {
XMEMMOVE(plain, input, sz);
}
break;
#endif
2014-10-24 10:33:24 -03:00
#ifdef HAVE_IDEA
case wolfssl_idea:
ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz);
break;
#endif
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("wolfSSL Decrypt programming error");
ret = DECRYPT_ERROR;
}
return ret;
2012-12-27 16:35:43 -08:00
}
/* check cipher text size for sanity */
2014-12-19 11:27:01 -07:00
static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
2011-02-05 11:14:47 -08:00
{
#ifdef HAVE_TRUNCATED_HMAC
word32 minLength = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ
: ssl->specs.hash_size;
#else
word32 minLength = ssl->specs.hash_size; /* covers stream */
2011-02-05 11:14:47 -08:00
#endif
if (ssl->specs.cipher_type == block) {
if (encryptSz % ssl->specs.block_size) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Block ciphertext not block size");
return SANITY_CIPHER_E;
}
minLength++; /* pad byte */
if (ssl->specs.block_size > minLength)
minLength = ssl->specs.block_size;
2011-02-05 11:14:47 -08:00
if (ssl->options.tls1_1)
minLength += ssl->specs.block_size; /* explicit IV */
2011-02-05 11:14:47 -08:00
}
2012-12-27 16:35:43 -08:00
else if (ssl->specs.cipher_type == aead) {
2014-07-18 14:42:45 -06:00
minLength = ssl->specs.aead_mac_size; /* authTag size */
2014-12-19 11:27:01 -07:00
if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
2014-07-18 14:42:45 -06:00
minLength += AEAD_EXP_IV_SZ; /* explicit IV */
}
2011-02-05 11:14:47 -08:00
if (encryptSz < minLength) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Ciphertext not minimum size");
return SANITY_CIPHER_E;
2011-04-25 09:24:21 -07:00
}
2011-02-05 11:14:47 -08:00
return 0;
}
2011-02-05 11:14:47 -08:00
#ifndef NO_OLD_TLS
2011-02-05 11:14:47 -08:00
static INLINE void Md5Rounds(int rounds, const byte* data, int sz)
{
Md5 md5;
int i;
2011-02-05 11:14:47 -08:00
2015-01-01 07:33:07 -07:00
wc_InitMd5(&md5);
for (i = 0; i < rounds; i++)
2015-01-01 07:33:07 -07:00
wc_Md5Update(&md5, data, sz);
2015-08-15 16:51:23 +09:00
wc_Md5Free(&md5) ; /* in case needed to release resources */
2011-02-05 11:14:47 -08:00
}
/* do a dummy sha round */
static INLINE void ShaRounds(int rounds, const byte* data, int sz)
2011-02-05 11:14:47 -08:00
{
Sha sha;
int i;
2011-02-05 11:14:47 -08:00
wc_InitSha(&sha); /* no error check on purpose, dummy round */
for (i = 0; i < rounds; i++)
wc_ShaUpdate(&sha, data, sz);
2015-08-15 16:51:23 +09:00
wc_ShaFree(&sha) ; /* in case needed to release resources */
}
#endif
2011-02-05 11:14:47 -08:00
#ifndef NO_SHA256
2011-02-05 11:14:47 -08:00
static INLINE void Sha256Rounds(int rounds, const byte* data, int sz)
{
Sha256 sha256;
int i;
wc_InitSha256(&sha256); /* no error check on purpose, dummy round */
for (i = 0; i < rounds; i++) {
wc_Sha256Update(&sha256, data, sz);
/* no error check on purpose, dummy round */
}
2015-08-15 16:51:23 +09:00
wc_Sha256Free(&sha256) ; /* in case needed to release resources */
2011-02-05 11:14:47 -08:00
}
#endif
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
static INLINE void Sha384Rounds(int rounds, const byte* data, int sz)
{
Sha384 sha384;
int i;
2011-02-05 11:14:47 -08:00
2015-01-01 07:33:07 -07:00
wc_InitSha384(&sha384); /* no error check on purpose, dummy round */
2011-02-05 11:14:47 -08:00
for (i = 0; i < rounds; i++) {
2015-01-01 07:33:07 -07:00
wc_Sha384Update(&sha384, data, sz);
/* no error check on purpose, dummy round */
}
2015-08-15 16:51:23 +09:00
wc_Sha384Free(&sha384) ; /* in case needed to release resources */
2011-02-05 11:14:47 -08:00
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA512
static INLINE void Sha512Rounds(int rounds, const byte* data, int sz)
{
Sha512 sha512;
int i;
2015-01-01 07:33:07 -07:00
wc_InitSha512(&sha512); /* no error check on purpose, dummy round */
for (i = 0; i < rounds; i++) {
2015-01-01 07:33:07 -07:00
wc_Sha512Update(&sha512, data, sz);
/* no error check on purpose, dummy round */
}
2015-08-15 16:51:23 +09:00
wc_Sha512Free(&sha512) ; /* in case needed to release resources */
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_RIPEMD
static INLINE void RmdRounds(int rounds, const byte* data, int sz)
2011-02-05 11:14:47 -08:00
{
RipeMd ripemd;
int i;
2015-01-06 10:36:35 -07:00
wc_InitRipeMd(&ripemd);
for (i = 0; i < rounds; i++)
2015-01-06 10:36:35 -07:00
wc_RipeMdUpdate(&ripemd, data, sz);
}
#endif
/* Do dummy rounds */
static INLINE void DoRounds(int type, int rounds, const byte* data, int sz)
{
switch (type) {
2014-10-24 10:33:24 -03:00
case no_mac :
break;
#ifndef NO_OLD_TLS
#ifndef NO_MD5
case md5_mac :
Md5Rounds(rounds, data, sz);
break;
2011-02-05 11:14:47 -08:00
#endif
#ifndef NO_SHA
case sha_mac :
ShaRounds(rounds, data, sz);
break;
#endif
#endif
#ifndef NO_SHA256
case sha256_mac :
Sha256Rounds(rounds, data, sz);
break;
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
case sha384_mac :
Sha384Rounds(rounds, data, sz);
break;
#endif
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA512
case sha512_mac :
Sha512Rounds(rounds, data, sz);
break;
#endif
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_RIPEMD
case rmd_mac :
RmdRounds(rounds, data, sz);
break;
#endif
2011-02-05 11:14:47 -08:00
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Bad round type");
break;
}
}
2011-02-05 11:14:47 -08:00
/* do number of compression rounds on dummy data */
2014-12-19 11:27:01 -07:00
static INLINE void CompressRounds(WOLFSSL* ssl, int rounds, const byte* dummy)
{
if (rounds)
DoRounds(ssl->specs.mac_algorithm, rounds, dummy, COMPRESS_LOWER);
}
2011-02-05 11:14:47 -08:00
/* check all length bytes for the pad value, return 0 on success */
2015-06-05 09:42:10 -07:00
static int PadCheck(const byte* a, byte pad, int length)
{
int i;
2015-06-05 09:42:10 -07:00
int compareSum = 0;
2011-02-05 11:14:47 -08:00
for (i = 0; i < length; i++) {
2015-06-05 09:42:10 -07:00
compareSum |= a[i] ^ pad;
}
2011-02-05 11:14:47 -08:00
2015-06-05 09:42:10 -07:00
return compareSum;
}
2011-02-05 11:14:47 -08:00
/* get compression extra rounds */
static INLINE int GetRounds(int pLen, int padLen, int t)
{
int roundL1 = 1; /* round up flags */
int roundL2 = 1;
2011-02-05 11:14:47 -08:00
int L1 = COMPRESS_CONSTANT + pLen - t;
int L2 = COMPRESS_CONSTANT + pLen - padLen - 1 - t;
2011-02-05 11:14:47 -08:00
L1 -= COMPRESS_UPPER;
L2 -= COMPRESS_UPPER;
if ( (L1 % COMPRESS_LOWER) == 0)
roundL1 = 0;
if ( (L2 % COMPRESS_LOWER) == 0)
roundL2 = 0;
L1 /= COMPRESS_LOWER;
L2 /= COMPRESS_LOWER;
L1 += roundL1;
L2 += roundL2;
2011-02-05 11:14:47 -08:00
return L1 - L2;
}
2011-02-05 11:14:47 -08:00
/* timing resistant pad/verify check, return 0 on success */
2014-12-19 11:27:01 -07:00
static int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t,
int pLen, int content)
{
byte verify[MAX_DIGEST_SIZE];
byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0};
byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy;
int ret = 0;
2011-02-05 11:14:47 -08:00
2015-06-10 15:24:24 -07:00
(void)dmy;
if ( (t + padLen + 1) > pLen) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Plain Len not long enough for pad/mac");
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE);
ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */
ConstantCompare(verify, input + pLen - t, t);
return VERIFY_MAC_ERROR;
}
if (PadCheck(input + pLen - (padLen + 1), (byte)padLen, padLen + 1) != 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("PadCheck failed");
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1);
ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */
ConstantCompare(verify, input + pLen - t, t);
2011-02-05 11:14:47 -08:00
return VERIFY_MAC_ERROR;
}
2011-02-05 11:14:47 -08:00
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1);
ret = ssl->hmac(ssl, verify, input, pLen - padLen - 1 - t, content, 1);
2011-02-05 11:14:47 -08:00
CompressRounds(ssl, GetRounds(pLen, padLen, t), dummy);
2011-02-05 11:14:47 -08:00
if (ConstantCompare(verify, input + (pLen - padLen - 1 - t), t) != 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verify MAC compare failed");
return VERIFY_MAC_ERROR;
}
2011-02-05 11:14:47 -08:00
if (ret != 0)
return VERIFY_MAC_ERROR;
return 0;
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
{
word32 msgSz = ssl->keys.encryptSz;
word32 idx = *inOutIdx;
int dataSz;
int ivExtra = 0;
byte* rawData = input + idx; /* keep current for hmac */
#ifdef HAVE_LIBZ
byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
#endif
2014-02-24 11:15:22 -08:00
if (ssl->options.handShakeDone == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Received App data before a handshake completed");
SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E;
}
if (ssl->specs.cipher_type == block) {
if (ssl->options.tls1_1)
ivExtra = ssl->specs.block_size;
}
else if (ssl->specs.cipher_type == aead) {
2014-12-19 11:27:01 -07:00
if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
2014-07-17 15:00:40 -06:00
ivExtra = AEAD_EXP_IV_SZ;
2011-02-05 11:14:47 -08:00
}
dataSz = msgSz - ivExtra - ssl->keys.padSz;
if (dataSz < 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("App data buffer error, malicious input?");
return BUFFER_ERROR;
}
2011-02-05 11:14:47 -08:00
/* read data */
if (dataSz) {
int rawSz = dataSz; /* keep raw size for idx adjustment */
2011-02-05 11:14:47 -08:00
#ifdef HAVE_LIBZ
if (ssl->options.usingCompression) {
dataSz = myDeCompress(ssl, rawData, dataSz, decomp, sizeof(decomp));
if (dataSz < 0) return dataSz;
2011-02-05 11:14:47 -08:00
}
#endif
idx += rawSz;
2011-02-05 11:14:47 -08:00
ssl->buffers.clearOutputBuffer.buffer = rawData;
ssl->buffers.clearOutputBuffer.length = dataSz;
}
2011-02-05 11:14:47 -08:00
idx += ssl->keys.padSz;
2011-02-05 11:14:47 -08:00
#ifdef HAVE_LIBZ
/* decompress could be bigger, overwrite after verify */
if (ssl->options.usingCompression)
XMEMMOVE(rawData, decomp, dataSz);
#endif
2011-02-05 11:14:47 -08:00
*inOutIdx = idx;
return 0;
}
/* process alert, return level */
2014-12-19 11:27:01 -07:00
static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type,
word32 totalSz)
{
byte level;
byte code;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
AddPacketName("Alert", &ssl->handShakeInfo);
2011-02-05 11:14:47 -08:00
if (ssl->toInfoOn)
/* add record header back on to info + 2 byte level, data */
AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx -
RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap);
2011-02-05 11:14:47 -08:00
#endif
/* make sure can read the message */
if (*inOutIdx + ALERT_SIZE > totalSz)
return BUFFER_E;
level = input[(*inOutIdx)++];
code = input[(*inOutIdx)++];
ssl->alert_history.last_rx.code = code;
ssl->alert_history.last_rx.level = level;
*type = code;
if (level == alert_fatal) {
ssl->options.isClosed = 1; /* Don't send close_notify */
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Got alert");
if (*type == close_notify) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" close notify");
ssl->options.closeNotify = 1;
}
2015-02-11 09:37:54 -07:00
WOLFSSL_ERROR(*type);
if (IsEncryptionOn(ssl, 0)) {
if (*inOutIdx + ssl->keys.padSz > totalSz)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz;
}
2011-02-05 11:14:47 -08:00
return level;
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
static int GetInputData(WOLFSSL *ssl, word32 size)
{
int in;
int inSz;
int maxLength;
int usedLength;
int dtlsExtra = 0;
2011-02-05 11:14:47 -08:00
2014-10-24 10:33:24 -03:00
/* check max input length */
usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx;
maxLength = ssl->buffers.inputBuffer.bufferSize - usedLength;
inSz = (int)(size - usedLength); /* from last partial read */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
if (size < ssl->dtls_expected_rx)
dtlsExtra = (int)(ssl->dtls_expected_rx - size);
2014-10-24 10:33:24 -03:00
inSz = ssl->dtls_expected_rx;
2011-02-05 11:14:47 -08:00
}
#endif
2014-10-24 10:33:24 -03:00
if (inSz > maxLength) {
if (GrowInputBuffer(ssl, size + dtlsExtra, usedLength) < 0)
return MEMORY_E;
2011-02-05 11:14:47 -08:00
}
2014-10-24 10:33:24 -03:00
if (inSz <= 0)
return BUFFER_ERROR;
2014-10-24 10:33:24 -03:00
/* Put buffer data at start if not there */
if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
XMEMMOVE(ssl->buffers.inputBuffer.buffer,
ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
usedLength);
2014-10-24 10:33:24 -03:00
/* remove processed data */
ssl->buffers.inputBuffer.idx = 0;
ssl->buffers.inputBuffer.length = usedLength;
2014-10-24 10:33:24 -03:00
/* read data from network */
do {
2014-10-24 10:33:24 -03:00
in = Receive(ssl,
ssl->buffers.inputBuffer.buffer +
2014-10-24 10:33:24 -03:00
ssl->buffers.inputBuffer.length,
inSz);
if (in == -1)
return SOCKET_ERROR_E;
2014-10-24 10:33:24 -03:00
if (in == WANT_READ)
return WANT_READ;
2011-02-05 11:14:47 -08:00
if (in > inSz)
return RECV_OVERFLOW_E;
2014-10-24 10:33:24 -03:00
ssl->buffers.inputBuffer.length += in;
inSz -= in;
2011-02-05 11:14:47 -08:00
} while (ssl->buffers.inputBuffer.length < size);
2011-02-05 11:14:47 -08:00
return 0;
2011-02-05 11:14:47 -08:00
}
2014-12-19 11:27:01 -07:00
static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
int content, word32* padSz)
2011-02-05 11:14:47 -08:00
{
int ivExtra = 0;
int ret;
word32 pad = 0;
word32 padByte = 0;
#ifdef HAVE_TRUNCATED_HMAC
word32 digestSz = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ
: ssl->specs.hash_size;
#else
word32 digestSz = ssl->specs.hash_size;
#endif
byte verify[MAX_DIGEST_SIZE];
2011-02-05 11:14:47 -08:00
if (ssl->specs.cipher_type == block) {
if (ssl->options.tls1_1)
ivExtra = ssl->specs.block_size;
pad = *(input + msgSz - ivExtra - 1);
padByte = 1;
2011-02-05 11:14:47 -08:00
if (ssl->options.tls) {
ret = TimingPadVerify(ssl, input, pad, digestSz, msgSz - ivExtra,
content);
if (ret != 0)
return ret;
}
else { /* sslv3, some implementations have bad padding, but don't
2014-10-24 10:33:24 -03:00
* allow bad read */
int badPadLen = 0;
byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0};
byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy;
2015-06-10 15:24:24 -07:00
(void)dmy;
if (pad > (msgSz - digestSz - 1)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Plain Len not long enough for pad/mac");
pad = 0; /* no bad read */
badPadLen = 1;
}
PadCheck(dummy, (byte)pad, MAX_PAD_SIZE); /* timing only */
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1,
content, 1);
if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
digestSz) != 0)
return VERIFY_MAC_ERROR;
if (ret != 0 || badPadLen)
return VERIFY_MAC_ERROR;
2013-02-18 14:36:50 -08:00
}
2011-02-05 11:14:47 -08:00
}
else if (ssl->specs.cipher_type == stream) {
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, content, 1);
if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){
return VERIFY_MAC_ERROR;
}
if (ret != 0)
return VERIFY_MAC_ERROR;
2011-02-05 11:14:47 -08:00
}
if (ssl->specs.cipher_type == aead) {
*padSz = ssl->specs.aead_mac_size;
}
else {
*padSz = digestSz + pad + padByte;
2013-02-18 14:36:50 -08:00
}
return 0;
2011-02-05 11:14:47 -08:00
}
2011-02-05 11:14:47 -08:00
/* process input requests, return 0 is done, 1 is call again to complete, and
negative number is error */
2014-12-19 11:27:01 -07:00
int ProcessReply(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
int ret = 0, type, readSz;
int atomicUser = 0;
word32 startIdx = 0;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
int used;
2011-02-05 11:14:47 -08:00
#endif
2013-08-09 17:27:15 -07:00
#ifdef ATOMIC_USER
if (ssl->ctx->DecryptVerifyCb)
2013-08-09 17:27:15 -07:00
atomicUser = 1;
#endif
if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE){
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("ProcessReply retry in error state, not allowed");
return ssl->error;
2011-02-05 11:14:47 -08:00
}
for (;;) {
switch (ssl->options.processReply) {
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
/* in the WOLFSSL_SERVER case, get the first byte for detecting
* old client hello */
case doProcessInit:
2014-10-24 10:33:24 -03:00
readSz = RECORD_HEADER_SZ;
2014-10-24 10:33:24 -03:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
readSz = DTLS_RECORD_HEADER_SZ;
#endif
/* get header or return error */
if (!ssl->options.dtls) {
if ((ret = GetInputData(ssl, readSz)) < 0)
return ret;
} else {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
/* read ahead may already have header */
used = ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx;
if (used < readSz)
if ((ret = GetInputData(ssl, readSz)) < 0)
return ret;
#endif
}
#ifdef OLD_HELLO_ALLOWED
2013-08-09 17:27:15 -07:00
/* see if sending SSLv2 client hello */
2014-12-19 11:27:01 -07:00
if ( ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.clientState == NULL_STATE &&
ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
!= handshake) {
byte b0, b1;
ssl->options.processReply = runProcessOldClientHello;
2011-02-05 11:14:47 -08:00
/* sanity checks before getting size at front */
if (ssl->buffers.inputBuffer.buffer[
ssl->buffers.inputBuffer.idx + 2] != OLD_HELLO_ID) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Not a valid old client hello");
return PARSE_ERROR;
}
if (ssl->buffers.inputBuffer.buffer[
ssl->buffers.inputBuffer.idx + 3] != SSLv3_MAJOR &&
ssl->buffers.inputBuffer.buffer[
ssl->buffers.inputBuffer.idx + 3] != DTLS_MAJOR) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Not a valid version in old client hello");
return PARSE_ERROR;
}
/* how many bytes need ProcessOldClientHello */
b0 =
ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
b1 =
ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
ssl->curSize = (word16)(((b0 & 0x7f) << 8) | b1);
}
else {
ssl->options.processReply = getRecordLayerHeader;
continue;
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
/* in the WOLFSSL_SERVER case, run the old client hello */
2014-10-24 10:33:24 -03:00
case runProcessOldClientHello:
2011-02-05 11:14:47 -08:00
/* get sz bytes or return error */
if (!ssl->options.dtls) {
if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
return ret;
} else {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
/* read ahead may already have */
used = ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx;
if (used < ssl->curSize)
if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
return ret;
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_DTLS */
}
2011-02-05 11:14:47 -08:00
ret = ProcessOldClientHello(ssl, ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx,
ssl->curSize);
if (ret < 0)
return ret;
else if (ssl->buffers.inputBuffer.idx ==
ssl->buffers.inputBuffer.length) {
ssl->options.processReply = doProcessInit;
return 0;
}
2011-02-05 11:14:47 -08:00
#endif /* OLD_HELLO_ALLOWED */
/* get the record layer header */
case getRecordLayerHeader:
2011-02-05 11:14:47 -08:00
ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
&ssl->curRL, &ssl->curSize);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls && ret == SEQUENCE_ERROR) {
WOLFSSL_MSG("Silently dropping out of order DTLS message");
ssl->options.processReply = doProcessInit;
ssl->buffers.inputBuffer.length = 0;
ssl->buffers.inputBuffer.idx = 0;
continue;
}
#endif
if (ret != 0)
return ret;
2011-02-05 11:14:47 -08:00
ssl->options.processReply = getData;
2011-02-05 11:14:47 -08:00
/* retrieve record layer data */
case getData:
2011-02-05 11:14:47 -08:00
/* get sz bytes or return error */
if (!ssl->options.dtls) {
if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
return ret;
} else {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
/* read ahead may already have */
used = ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx;
if (used < ssl->curSize)
if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
return ret;
#endif
}
2014-10-24 10:33:24 -03:00
ssl->options.processReply = runProcessingOneMessage;
startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */
/* the record layer is here */
case runProcessingOneMessage:
2015-12-01 13:32:00 -08:00
if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0)
{
ret = SanityCheckCipherText(ssl, ssl->curSize);
if (ret < 0)
return ret;
2011-02-05 11:14:47 -08:00
if (atomicUser) {
#ifdef ATOMIC_USER
ret = ssl->ctx->DecryptVerifyCb(ssl,
2014-10-24 10:33:24 -03:00
ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx,
ssl->curSize, ssl->curRL.type, 1,
&ssl->keys.padSz, ssl->DecryptVerifyCtx);
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
/* go past TLSv1.1 IV */
2014-07-17 15:00:40 -06:00
if (ssl->specs.cipher_type == aead &&
2014-12-19 11:27:01 -07:00
ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
ssl->buffers.inputBuffer.idx += AEAD_EXP_IV_SZ;
#endif /* ATOMIC_USER */
}
else {
2014-10-24 10:33:24 -03:00
ret = Decrypt(ssl, ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx,
ssl->curSize);
if (ret < 0) {
WOLFSSL_MSG("Decrypt failed");
2014-12-19 11:27:01 -07:00
WOLFSSL_ERROR(ret);
return DECRYPT_ERROR;
}
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
/* go past TLSv1.1 IV */
2014-07-17 15:00:40 -06:00
if (ssl->specs.cipher_type == aead &&
2014-12-19 11:27:01 -07:00
ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
ssl->buffers.inputBuffer.idx += AEAD_EXP_IV_SZ;
2011-02-05 11:14:47 -08:00
ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx,
ssl->curSize, ssl->curRL.type,
&ssl->keys.padSz);
}
if (ret < 0) {
WOLFSSL_MSG("VerifyMac failed");
2014-12-19 11:27:01 -07:00
WOLFSSL_ERROR(ret);
return DECRYPT_ERROR;
}
ssl->keys.encryptSz = ssl->curSize;
2015-12-01 13:32:00 -08:00
ssl->keys.decryptedCur = 1;
}
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
DtlsUpdateWindow(&ssl->keys.dtls_state);
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_DTLS */
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("received record layer msg");
2011-04-09 13:08:56 -07:00
switch (ssl->curRL.type) {
case handshake :
/* debugging in DoHandShakeMsg */
if (!ssl->options.dtls) {
2014-10-24 10:33:24 -03:00
ret = DoHandShakeMsg(ssl,
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.length);
}
else {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2014-10-24 10:33:24 -03:00
ret = DoDtlsHandShakeMsg(ssl,
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.length);
#endif
}
if (ret != 0)
return ret;
break;
case change_cipher_spec:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("got CHANGE CIPHER SPEC");
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
AddPacketName("ChangeCipher", &ssl->handShakeInfo);
/* add record header back on info */
if (ssl->toInfoOn) {
AddPacketInfo("ChangeCipher", &ssl->timeoutInfo,
ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ,
1 + RECORD_HEADER_SZ, ssl->heap);
AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
}
#endif
/* Check for duplicate CCS message in DTLS mode.
* DTLS allows for duplicate messages, and it should be
* skipped. */
if (ssl->options.dtls &&
ssl->msgsReceived.got_change_cipher) {
WOLFSSL_MSG("Duplicate ChangeCipher msg");
if (ssl->curSize != 1) {
WOLFSSL_MSG("Malicious or corrupted"
" duplicate ChangeCipher msg");
return LENGTH_ERROR;
}
ssl->buffers.inputBuffer.idx++;
break;
}
ret = SanityCheckMsgReceived(ssl, change_cipher_hs);
if (ret != 0)
return ret;
#ifdef HAVE_SESSION_TICKET
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->expect_session_ticket) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Expected session ticket missing");
return SESSION_TICKET_EXPECT_E;
}
#endif
if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) {
ssl->buffers.inputBuffer.idx += ssl->keys.padSz;
2015-03-18 10:42:10 -06:00
ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx;
}
if (ssl->curSize != 1) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Malicious or corrupted ChangeCipher msg");
return LENGTH_ERROR;
}
#ifndef NO_CERTS
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.verifyPeer &&
ssl->options.havePeerCert)
if (!ssl->options.havePeerVerify) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("client didn't send cert verify");
return NO_PEER_VERIFY;
}
#endif
ssl->buffers.inputBuffer.idx++;
ssl->keys.encryptionOn = 1;
/* setup decrypt keys for following messages */
if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
return ret;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
DtlsPoolReset(ssl);
ssl->keys.dtls_state.nextEpoch++;
ssl->keys.dtls_state.nextSeq = 0;
}
#endif
#ifdef HAVE_LIBZ
if (ssl->options.usingCompression)
if ( (ret = InitStreams(ssl)) != 0)
return ret;
#endif
ret = BuildFinished(ssl, &ssl->hsHashes->verifyHashes,
ssl->options.side == WOLFSSL_CLIENT_END ?
server : client);
if (ret != 0)
return ret;
break;
case application_data:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("got app DATA");
if ((ret = DoApplicationData(ssl,
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx))
!= 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_ERROR(ret);
return ret;
}
break;
case alert:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("got ALERT!");
ret = DoAlert(ssl, ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx, &type,
ssl->buffers.inputBuffer.length);
if (ret == alert_fatal)
return FATAL_ERROR;
else if (ret < 0)
return ret;
/* catch warnings that are handled as errors */
if (type == close_notify)
return ssl->error = ZERO_RETURN;
2014-10-24 10:33:24 -03:00
if (type == decrypt_error)
return FATAL_ERROR;
break;
2014-10-24 10:33:24 -03:00
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_ERROR(UNKNOWN_RECORD_TYPE);
return UNKNOWN_RECORD_TYPE;
}
ssl->options.processReply = doProcessInit;
/* input exhausted? */
if (ssl->buffers.inputBuffer.idx == ssl->buffers.inputBuffer.length)
return 0;
/* more messages per record */
else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("More messages in record");
#ifdef WOLFSSL_DTLS
/* read-ahead but dtls doesn't bundle messages per record */
if (ssl->options.dtls) {
ssl->options.processReply = doProcessInit;
continue;
}
#endif
ssl->options.processReply = runProcessingOneMessage;
2014-09-30 11:52:21 -07:00
if (IsEncryptionOn(ssl, 0)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Bundled encrypted messages, remove middle pad");
2014-09-30 11:52:21 -07:00
ssl->buffers.inputBuffer.idx -= ssl->keys.padSz;
}
continue;
}
/* more records */
else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("More records in input");
ssl->options.processReply = doProcessInit;
continue;
}
default:
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Bad process input state, programming error");
return INPUT_CASE_ERROR;
2011-04-09 13:08:56 -07:00
}
2011-02-05 11:14:47 -08:00
}
}
2014-12-19 11:27:01 -07:00
int SendChangeCipher(WOLFSSL* ssl)
{
byte *output;
int sendSz = RECORD_HEADER_SZ + ENUM_LEN;
int idx = RECORD_HEADER_SZ;
int ret;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls) {
sendSz += DTLS_RECORD_EXTRA;
idx += DTLS_RECORD_EXTRA;
2011-02-05 11:14:47 -08:00
}
#endif
/* are we in scr */
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
sendSz += MAX_MSG_EXTRA;
}
/* check for avalaible size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
2011-02-05 11:14:47 -08:00
return ret;
/* get ouput buffer */
2014-10-24 10:33:24 -03:00
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
AddRecordHeader(output, 1, change_cipher_spec, ssl);
2011-02-05 11:14:47 -08:00
output[idx] = 1; /* turn it on */
2011-04-09 13:08:56 -07:00
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
byte input[ENUM_LEN];
int inputSz = ENUM_LEN;
input[0] = 1; /* turn it on */
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
change_cipher_spec, 0);
if (sendSz < 0)
return sendSz;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return ret;
2012-09-14 09:35:34 -07:00
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("ChangeCipher", &ssl->handShakeInfo);
2011-02-05 11:14:47 -08:00
if (ssl->toInfoOn)
AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, output, sendSz,
2011-02-05 11:14:47 -08:00
ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
if (ssl->options.groupMessages)
return 0;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
else if (ssl->options.dtls) {
/* If using DTLS, force the ChangeCipherSpec message to be in the
* same datagram as the finished message. */
return 0;
}
#endif
else
return SendBuffered(ssl);
2011-02-05 11:14:47 -08:00
}
#ifndef NO_OLD_TLS
2014-12-19 11:27:01 -07:00
static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
int content, int verify)
2011-02-05 11:14:47 -08:00
{
byte result[MAX_DIGEST_SIZE];
word32 digestSz = ssl->specs.hash_size; /* actual sizes */
word32 padSz = ssl->specs.pad_size;
int ret = 0;
2011-02-05 11:14:47 -08:00
Md5 md5;
Sha sha;
2011-02-05 11:14:47 -08:00
/* data */
byte seq[SEQ_SZ];
byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */
2014-12-19 11:27:01 -07:00
const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify);
2014-10-24 10:33:24 -03:00
2014-08-11 16:29:19 -06:00
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
2014-08-12 16:25:58 -06:00
ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
2014-08-11 16:29:19 -06:00
#endif
XMEMSET(seq, 0, SEQ_SZ);
conLen[0] = (byte)content;
c16toa((word16)sz, &conLen[ENUM_LEN]);
c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
2011-02-05 11:14:47 -08:00
if (ssl->specs.mac_algorithm == md5_mac) {
2015-01-01 07:33:07 -07:00
wc_InitMd5(&md5);
/* inner */
2015-01-01 07:33:07 -07:00
wc_Md5Update(&md5, macSecret, digestSz);
wc_Md5Update(&md5, PAD1, padSz);
wc_Md5Update(&md5, seq, SEQ_SZ);
wc_Md5Update(&md5, conLen, sizeof(conLen));
/* in buffer */
2015-01-01 07:33:07 -07:00
wc_Md5Update(&md5, in, sz);
wc_Md5Final(&md5, result);
/* outer */
2015-01-01 07:33:07 -07:00
wc_Md5Update(&md5, macSecret, digestSz);
wc_Md5Update(&md5, PAD2, padSz);
wc_Md5Update(&md5, result, digestSz);
wc_Md5Final(&md5, digest);
}
else {
2015-01-01 07:33:07 -07:00
ret = wc_InitSha(&sha);
if (ret != 0)
return ret;
/* inner */
2015-01-01 07:33:07 -07:00
wc_ShaUpdate(&sha, macSecret, digestSz);
wc_ShaUpdate(&sha, PAD1, padSz);
wc_ShaUpdate(&sha, seq, SEQ_SZ);
wc_ShaUpdate(&sha, conLen, sizeof(conLen));
/* in buffer */
2015-01-01 07:33:07 -07:00
wc_ShaUpdate(&sha, in, sz);
wc_ShaFinal(&sha, result);
/* outer */
2015-01-01 07:33:07 -07:00
wc_ShaUpdate(&sha, macSecret, digestSz);
wc_ShaUpdate(&sha, PAD2, padSz);
wc_ShaUpdate(&sha, result, digestSz);
wc_ShaFinal(&sha, digest);
2011-02-28 12:21:06 -08:00
}
return 0;
}
2011-02-28 12:21:06 -08:00
#ifndef NO_CERTS
2014-12-19 11:27:01 -07:00
static void BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest)
{
byte md5_result[MD5_DIGEST_SIZE];
2011-02-05 11:14:47 -08:00
2015-06-18 14:25:48 +09:00
#ifdef WOLFSSL_SMALL_STACK
Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
#else
Md5 md5[1];
Md5 md5_2[1];
#endif
/* make md5 inner */
2015-06-18 14:25:48 +09:00
md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */
wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN);
wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5);
2015-06-18 14:25:48 +09:00
wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result);
wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */
/* make md5 outer */
2015-06-18 14:25:48 +09:00
wc_InitMd5(md5_2) ;
wc_Md5Update(md5_2, ssl->arrays->masterSecret, SECRET_LEN);
wc_Md5Update(md5_2, PAD2, PAD_MD5);
wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE);
2011-02-05 11:14:47 -08:00
2015-06-18 14:25:48 +09:00
wc_Md5Final(md5_2, digest);
#ifdef WOLFSSL_SMALL_STACK
XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2011-02-05 11:14:47 -08:00
}
2014-12-19 11:27:01 -07:00
static void BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest)
2011-02-05 11:14:47 -08:00
{
byte sha_result[SHA_DIGEST_SIZE];
2014-10-24 10:33:24 -03:00
2015-06-18 14:25:48 +09:00
#ifdef WOLFSSL_SMALL_STACK
Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
#else
Sha sha[1];
Sha sha2[1];
#endif
/* make sha inner */
2015-06-18 14:25:48 +09:00
sha[0] = ssl->hsHashes->hashSha ; /* Save current position */
wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN);
wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA);
2015-06-18 14:25:48 +09:00
wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result);
wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */
2011-02-05 11:14:47 -08:00
/* make sha outer */
2015-06-18 14:25:48 +09:00
wc_InitSha(sha2) ;
wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN);
wc_ShaUpdate(sha2, PAD2, PAD_SHA);
wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE);
wc_ShaFinal(sha2, digest);
#ifdef WOLFSSL_SMALL_STACK
XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2011-02-05 11:14:47 -08:00
}
#endif /* NO_CERTS */
#endif /* NO_OLD_TLS */
2011-02-05 11:14:47 -08:00
#ifndef NO_CERTS
2014-12-19 11:27:01 -07:00
static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes)
{
/* store current states, building requires get_digest which resets state */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
Sha384 sha384 = ssl->hsHashes->hashSha384;
#endif
#ifdef WOLFSSL_SHA512
Sha512 sha512 = ssl->hsHashes->hashSha512;
#endif
2014-10-24 10:33:24 -03:00
if (ssl->options.tls) {
#if ! defined( NO_OLD_TLS )
2015-05-21 13:42:02 +09:00
wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5);
wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha);
2011-02-05 11:14:47 -08:00
#endif
if (IsAtLeastTLSv1_2(ssl)) {
int ret;
2011-02-05 11:14:47 -08:00
#ifndef NO_SHA256
2015-05-21 13:42:02 +09:00
ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,hashes->sha256);
if (ret != 0)
return ret;
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
ret = wc_Sha384Final(&ssl->hsHashes->hashSha384,hashes->sha384);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA512
ret = wc_Sha512Final(&ssl->hsHashes->hashSha512,hashes->sha512);
if (ret != 0)
return ret;
#endif
2011-02-05 11:14:47 -08:00
}
}
#if ! defined( NO_OLD_TLS )
else {
BuildMD5_CertVerify(ssl, hashes->md5);
BuildSHA_CertVerify(ssl, hashes->sha);
}
2014-10-24 10:33:24 -03:00
/* restore */
2011-02-05 11:14:47 -08:00
#endif
if (IsAtLeastTLSv1_2(ssl)) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
ssl->hsHashes->hashSha384 = sha384;
#endif
#ifdef WOLFSSL_SHA512
ssl->hsHashes->hashSha512 = sha512;
#endif
}
2011-02-05 11:14:47 -08:00
return 0;
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_LEANPSK */
2011-02-05 11:14:47 -08:00
/* Build SSL Message, encrypted */
2014-12-19 11:27:01 -07:00
static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
const byte* input, int inSz, int type, int hashOutput)
{
#ifdef HAVE_TRUNCATED_HMAC
word32 digestSz = min(ssl->specs.hash_size,
ssl->truncated_hmac ? TRUNCATED_HMAC_SZ : ssl->specs.hash_size);
#else
word32 digestSz = ssl->specs.hash_size;
2011-02-05 11:14:47 -08:00
#endif
2014-10-24 10:33:24 -03:00
word32 sz = RECORD_HEADER_SZ + inSz + digestSz;
word32 pad = 0, i;
word32 idx = RECORD_HEADER_SZ;
word32 ivSz = 0; /* TLSv1.1 IV */
word32 headerSz = RECORD_HEADER_SZ;
word16 size;
byte iv[AES_BLOCK_SIZE]; /* max size */
int ret = 0;
int atomicUser = 0;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
sz += DTLS_RECORD_EXTRA;
2014-10-24 10:33:24 -03:00
idx += DTLS_RECORD_EXTRA;
headerSz += DTLS_RECORD_EXTRA;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef ATOMIC_USER
if (ssl->ctx->MacEncryptCb)
atomicUser = 1;
#endif
2011-02-05 11:14:47 -08:00
if (ssl->specs.cipher_type == block) {
word32 blockSz = ssl->specs.block_size;
if (ssl->options.tls1_1) {
ivSz = blockSz;
sz += ivSz;
if (ivSz > (word32)sizeof(iv))
return BUFFER_E;
2015-01-01 07:33:07 -07:00
ret = wc_RNG_GenerateBlock(ssl->rng, iv, ivSz);
if (ret != 0)
return ret;
2011-02-05 11:14:47 -08:00
2011-04-25 09:24:21 -07:00
}
sz += 1; /* pad byte */
pad = (sz - headerSz) % blockSz;
pad = blockSz - pad;
sz += pad;
2011-02-05 11:14:47 -08:00
}
#ifdef HAVE_AEAD
if (ssl->specs.cipher_type == aead) {
2014-12-19 11:27:01 -07:00
if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
2014-07-16 14:55:38 -06:00
ivSz = AEAD_EXP_IV_SZ;
2014-07-17 15:00:40 -06:00
sz += (ivSz + ssl->specs.aead_mac_size - digestSz);
XMEMCPY(iv, ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ);
}
#endif
if (sz > (word32)outSz) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Oops, want to write past output buffer size");
return BUFFER_E;
}
size = (word16)(sz - headerSz); /* include mac and digest */
2014-10-24 10:33:24 -03:00
AddRecordHeader(output, size, (byte)type, ssl);
2011-02-05 11:14:47 -08:00
/* write to output */
if (ivSz) {
XMEMCPY(output + idx, iv, min(ivSz, sizeof(iv)));
idx += ivSz;
}
XMEMCPY(output + idx, input, inSz);
idx += inSz;
2011-02-05 11:14:47 -08:00
if (type == handshake && hashOutput) {
ret = HashOutput(ssl, output, headerSz + inSz, ivSz);
if (ret != 0)
return ret;
}
2011-02-05 11:14:47 -08:00
if (ssl->specs.cipher_type == block) {
word32 tmpIdx = idx + digestSz;
for (i = 0; i <= pad; i++)
output[tmpIdx++] = (byte)pad; /* pad byte gets pad value too */
}
if (atomicUser) { /* User Record Layer Callback handling */
#ifdef ATOMIC_USER
if ( (ret = ssl->ctx->MacEncryptCb(ssl, output + idx,
output + headerSz + ivSz, inSz, type, 0,
output + headerSz, output + headerSz, size,
ssl->MacEncryptCtx)) != 0)
return ret;
#endif
2011-02-05 11:14:47 -08:00
}
2014-10-24 10:33:24 -03:00
else {
if (ssl->specs.cipher_type != aead) {
#ifdef HAVE_TRUNCATED_HMAC
if (ssl->truncated_hmac && ssl->specs.hash_size > digestSz) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* hmac = NULL;
#else
byte hmac[MAX_DIGEST_SIZE];
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (hmac == NULL)
return MEMORY_E;
#endif
2011-02-05 11:14:47 -08:00
ret = ssl->hmac(ssl, hmac, output + headerSz + ivSz, inSz,
type, 0);
XMEMCPY(output + idx, hmac, digestSz);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
} else
#endif
ret = ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz,
type, 0);
2011-02-05 11:14:47 -08:00
}
if (ret != 0)
return ret;
2011-02-05 11:14:47 -08:00
if ( (ret = Encrypt(ssl, output + headerSz, output+headerSz,size)) != 0)
return ret;
2012-11-16 12:16:00 -08:00
}
2011-02-05 11:14:47 -08:00
return sz;
2011-02-05 11:14:47 -08:00
}
2014-12-19 11:27:01 -07:00
int SendFinished(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
int sendSz,
finishedSz = ssl->options.tls ? TLS_FINISHED_SZ :
FINISHED_SZ;
byte input[FINISHED_SZ + DTLS_HANDSHAKE_HEADER_SZ]; /* max */
byte *output;
Hashes* hashes;
int ret;
int headerSz = HANDSHAKE_HEADER_SZ;
int outputSz;
2011-02-05 11:14:47 -08:00
/* setup encrypt keys */
if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
return ret;
/* check for available size */
outputSz = sizeof(input) + MAX_MSG_EXTRA;
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
2011-02-05 11:14:47 -08:00
return ret;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
headerSz += DTLS_HANDSHAKE_EXTRA;
ssl->keys.dtls_epoch++;
ssl->keys.dtls_prev_sequence_number =
ssl->keys.dtls_sequence_number;
ssl->keys.dtls_sequence_number = 0;
}
#endif
2011-02-05 11:14:47 -08:00
/* get ouput buffer */
2014-10-24 10:33:24 -03:00
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
2011-02-05 11:14:47 -08:00
/* make finished hashes */
hashes = (Hashes*)&input[headerSz];
ret = BuildFinished(ssl, hashes,
ssl->options.side == WOLFSSL_CLIENT_END ? client : server);
if (ret != 0) return ret;
#ifdef HAVE_SECURE_RENEGOTIATION
2014-09-16 17:26:57 -07:00
if (ssl->secure_renegotiation) {
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_CLIENT_END)
2014-09-16 17:26:57 -07:00
XMEMCPY(ssl->secure_renegotiation->client_verify_data, hashes,
2014-09-16 11:51:13 -07:00
TLS_FINISHED_SZ);
else
2014-09-16 17:26:57 -07:00
XMEMCPY(ssl->secure_renegotiation->server_verify_data, hashes,
2014-09-16 11:51:13 -07:00
TLS_FINISHED_SZ);
}
#endif
2014-09-16 11:51:13 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, input, headerSz + finishedSz)) != 0)
return ret;
}
#endif
sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz,
handshake, 1);
if (sendSz < 0)
return BUILD_MSG_ERROR;
2011-02-05 11:14:47 -08:00
if (!ssl->options.resuming) {
#ifndef NO_SESSION_CACHE
AddSession(ssl); /* just try */
#endif
if (ssl->options.side == WOLFSSL_SERVER_END) {
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
}
}
else {
2014-12-19 11:27:01 -07:00
if (ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
}
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
2011-02-05 11:14:47 -08:00
if (ssl->toInfoOn)
AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz,
ssl->heap);
2011-02-05 11:14:47 -08:00
#endif
ssl->buffers.outputBuffer.length += sendSz;
return SendBuffered(ssl);
}
#ifndef NO_CERTS
2014-12-19 11:27:01 -07:00
int SendCertificate(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
2015-08-14 15:06:12 -07:00
int ret = 0;
word32 certSz, certChainSz, headerSz, listSz, payloadSz;
word32 length, maxFragment;
2011-02-05 11:14:47 -08:00
if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
return 0; /* not needed */
if (ssl->options.sendVerify == SEND_BLANK_CERT) {
certSz = 0;
certChainSz = 0;
headerSz = CERT_HEADER_SZ;
length = CERT_HEADER_SZ;
listSz = 0;
2011-02-05 11:14:47 -08:00
}
else {
certSz = ssl->buffers.certificate.length;
headerSz = 2 * CERT_HEADER_SZ;
/* list + cert size */
length = certSz + headerSz;
listSz = certSz + CERT_HEADER_SZ;
2011-02-05 11:14:47 -08:00
/* may need to send rest of chain, already has leading size(s) */
if (certSz) {
certChainSz = ssl->buffers.certChain.length;
length += certChainSz;
listSz += certChainSz;
}
2015-08-14 15:06:12 -07:00
else
certChainSz = 0;
}
2011-02-05 11:14:47 -08:00
payloadSz = length;
if (ssl->fragOffset != 0)
length -= (ssl->fragOffset + headerSz);
maxFragment = MAX_RECORD_SIZE;
if (ssl->options.dtls) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ
- DTLS_HANDSHAKE_HEADER_SZ - 100;
#endif /* WOLFSSL_DTLS */
}
2011-02-05 11:14:47 -08:00
#ifdef HAVE_MAX_FRAGMENT
if (ssl->max_fragment != 0 && maxFragment >= ssl->max_fragment)
maxFragment = ssl->max_fragment;
#endif /* HAVE_MAX_FRAGMENT */
2014-09-29 13:38:56 -07:00
while (length > 0 && ret == 0) {
byte* output = NULL;
2015-08-14 15:06:12 -07:00
word32 fragSz = 0;
word32 i = RECORD_HEADER_SZ;
int sendSz = RECORD_HEADER_SZ;
if (!ssl->options.dtls) {
if (ssl->fragOffset == 0) {
if (headerSz + certSz + certChainSz <=
maxFragment - HANDSHAKE_HEADER_SZ) {
2011-02-05 11:14:47 -08:00
fragSz = headerSz + certSz + certChainSz;
}
else {
fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
}
sendSz += fragSz + HANDSHAKE_HEADER_SZ;
i += HANDSHAKE_HEADER_SZ;
}
else {
fragSz = min(length, maxFragment);
sendSz += fragSz;
}
if (IsEncryptionOn(ssl, 1))
sendSz += MAX_MSG_EXTRA;
}
else {
#ifdef WOLFSSL_DTLS
fragSz = min(length, maxFragment);
sendSz += fragSz + DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
+ HANDSHAKE_HEADER_SZ;
i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
+ HANDSHAKE_HEADER_SZ;
#endif
}
2011-02-05 11:14:47 -08:00
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
2011-02-05 11:14:47 -08:00
/* get ouput buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
if (ssl->fragOffset == 0) {
if (!ssl->options.dtls) {
AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
if (!IsEncryptionOn(ssl, 1))
HashOutputRaw(ssl, output + RECORD_HEADER_SZ,
HANDSHAKE_HEADER_SZ);
}
else {
#ifdef WOLFSSL_DTLS
AddHeaders(output, payloadSz, certificate, ssl);
if (!IsEncryptionOn(ssl, 1))
HashOutputRaw(ssl,
output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA,
HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA);
/* Adding the headers increments these, decrement them for
* actual message header. */
ssl->keys.dtls_sequence_number--;
ssl->keys.dtls_handshake_number--;
AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
ssl->keys.dtls_handshake_number--;
#endif /* WOLFSSL_DTLS */
}
/* list total */
c32to24(listSz, output + i);
if (!IsEncryptionOn(ssl, 1))
HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
i += CERT_HEADER_SZ;
length -= CERT_HEADER_SZ;
fragSz -= CERT_HEADER_SZ;
if (certSz) {
c32to24(certSz, output + i);
if (!IsEncryptionOn(ssl, 1))
HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
i += CERT_HEADER_SZ;
length -= CERT_HEADER_SZ;
fragSz -= CERT_HEADER_SZ;
if (!IsEncryptionOn(ssl, 1)) {
HashOutputRaw(ssl, ssl->buffers.certificate.buffer, certSz);
if (certChainSz)
HashOutputRaw(ssl, ssl->buffers.certChain.buffer,
certChainSz);
}
}
}
else {
if (!ssl->options.dtls) {
AddRecordHeader(output, fragSz, handshake, ssl);
}
else {
#ifdef WOLFSSL_DTLS
AddFragHeaders(output, fragSz, ssl->fragOffset + headerSz,
payloadSz, certificate, ssl);
ssl->keys.dtls_handshake_number--;
#endif /* WOLFSSL_DTLS */
}
}
2014-09-29 13:38:56 -07:00
/* member */
if (certSz && ssl->fragOffset < certSz) {
word32 copySz = min(certSz - ssl->fragOffset, fragSz);
XMEMCPY(output + i,
ssl->buffers.certificate.buffer + ssl->fragOffset, copySz);
i += copySz;
ssl->fragOffset += copySz;
length -= copySz;
fragSz -= copySz;
}
if (certChainSz && fragSz) {
word32 copySz = min(certChainSz + certSz - ssl->fragOffset, fragSz);
XMEMCPY(output + i,
ssl->buffers.certChain.buffer + ssl->fragOffset - certSz,
copySz);
i += copySz;
ssl->fragOffset += copySz;
length -= copySz;
}
2014-09-29 13:38:56 -07:00
if (IsEncryptionOn(ssl, 1)) {
2015-12-02 14:40:32 -08:00
byte* input = NULL;
int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */
2014-09-29 13:38:56 -07:00
2015-12-02 14:40:32 -08:00
if (inputSz < 0) {
WOLFSSL_MSG("Send Cert bad inputSz");
return BUFFER_E;
}
if (inputSz > 0) { /* clang thinks could be zero, let's help */
input = (byte*)XMALLOC(inputSz, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (input == NULL)
return MEMORY_E;
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
}
2014-09-29 13:38:56 -07:00
sendSz = BuildMessage(ssl, output,sendSz,input,inputSz,handshake,1);
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
2014-09-29 13:38:56 -07:00
if (sendSz < 0)
return sendSz;
}
2011-02-05 11:14:47 -08:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return ret;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
AddPacketName("Certificate", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz,
ssl->heap);
#endif
2011-02-05 11:14:47 -08:00
ssl->buffers.outputBuffer.length += sendSz;
if (!ssl->options.groupMessages)
ret = SendBuffered(ssl);
}
if (ret != WANT_WRITE) {
/* Clean up the fragment offset. */
ssl->fragOffset = 0;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
ssl->keys.dtls_handshake_number++;
#endif
if (ssl->options.side == WOLFSSL_SERVER_END)
ssl->options.serverState = SERVER_CERT_COMPLETE;
}
return ret;
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
int SendCertificateRequest(WOLFSSL* ssl)
{
byte *output;
int ret;
int sendSz;
word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
2014-10-24 10:33:24 -03:00
int typeTotal = 1; /* only 1 for now */
int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */
2011-02-05 11:14:47 -08:00
if (IsAtLeastTLSv1_2(ssl))
reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
2011-02-05 11:14:47 -08:00
if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
return 0; /* not needed */
2011-02-05 11:14:47 -08:00
sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
}
#endif
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
2011-02-05 11:14:47 -08:00
/* get ouput buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
AddHeaders(output, reqSz, certificate_request, ssl);
2011-02-05 11:14:47 -08:00
/* write to output */
output[i++] = (byte)typeTotal; /* # of types */
#ifdef HAVE_ECC
if (ssl->options.cipherSuite0 == ECC_BYTE &&
ssl->specs.sig_algo == ecc_dsa_sa_algo) {
output[i++] = ecdsa_sign;
} else
#endif /* HAVE_ECC */
{
output[i++] = rsa_sign;
}
2011-02-05 11:14:47 -08:00
/* supported hash/sig */
if (IsAtLeastTLSv1_2(ssl)) {
c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
i += LENGTH_SZ;
2011-04-20 14:40:07 -07:00
XMEMCPY(&output[i],
ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz);
i += ssl->suites->hashSigAlgoSz;
}
2011-02-05 11:14:47 -08:00
c16toa(0, &output[i]); /* auth's */
/* if add more to output, adjust i
i += REQ_HEADER_SZ; */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return ret;
}
#endif
2011-02-05 11:14:47 -08:00
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0)
return ret;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
AddPacketName("CertificateRequest", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output,
sendSz, ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
if (ssl->options.groupMessages)
return 0;
else
return SendBuffered(ssl);
}
2015-12-28 19:38:04 -03:00
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
byte count)
{
byte* output = NULL;
word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
word32 length = ENUM_LEN;
int sendSz = 0;
int ret = 0;
int i = 0;
WOLFSSL_ENTER("BuildCertificateStatus");
switch (type) {
case WOLFSSL_CSR2_OCSP_MULTI:
length += OPAQUE24_LEN;
/* followed by */
case WOLFSSL_CSR2_OCSP:
for (i = 0; i < count; i++)
length += OPAQUE24_LEN + status[i].length;
break;
default:
return 0;
}
sendSz = idx + length;
if (ssl->keys.encryptionOn)
sendSz += MAX_MSG_EXTRA;
if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) {
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
AddHeaders(output, length, certificate_status, ssl);
output[idx++] = type;
if (type == WOLFSSL_CSR2_OCSP_MULTI) {
c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx);
idx += OPAQUE24_LEN;
}
for (i = 0; i < count; i++) {
c32to24(status[i].length, output + idx);
idx += OPAQUE24_LEN;
XMEMCPY(output + idx, status[i].buffer, status[i].length);
idx += status[i].length;
}
if (IsEncryptionOn(ssl, 1)) {
byte* input;
int inputSz = idx - RECORD_HEADER_SZ;
input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (input == NULL)
return MEMORY_E;
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
handshake, 1);
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (sendSz < 0)
ret = sendSz;
}
else
ret = HashOutput(ssl, output, sendSz, 0);
#ifdef WOLFSSL_DTLS
if (ret == 0 && ssl->options.dtls)
2016-01-18 20:46:52 -03:00
ret = DtlsPoolSave(ssl, output, sendSz);
2015-12-28 19:38:04 -03:00
#endif
#ifdef WOLFSSL_CALLBACKS
if (ret == 0 && ssl->hsInfoOn)
AddPacketName("CertificateStatus", &ssl->handShakeInfo);
if (ret == 0 && ssl->toInfoOn)
AddPacketInfo("CertificateStatus", &ssl->timeoutInfo, output,
sendSz, ssl->heap);
#endif
if (ret == 0) {
ssl->buffers.outputBuffer.length += sendSz;
if (!ssl->options.groupMessages)
ret = SendBuffered(ssl);
}
}
WOLFSSL_LEAVE("BuildCertificateStatus", ret);
return ret;
}
#endif
int SendCertificateStatus(WOLFSSL* ssl)
{
int ret = 0;
byte status_type = 0;
WOLFSSL_ENTER("SendCertificateStatus");
(void) ssl;
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
status_type = ssl->status_request;
#endif
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
status_type = status_type ? status_type : ssl->status_request_v2;
#endif
switch (status_type) {
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
/* case WOLFSSL_CSR_OCSP: */
case WOLFSSL_CSR2_OCSP: {
OcspRequest* request = ssl->ctx->certOcspRequest;
buffer response = {NULL, 0};
/* unable to fetch status. skip. */
if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0)
return 0;
if (!request || ssl->buffers.weOwnCert) {
buffer der = ssl->buffers.certificate;
#ifdef WOLFSSL_SMALL_STACK
DecodedCert* cert = NULL;
#else
DecodedCert cert[1];
#endif
/* unable to fetch status. skip. */
if (der.buffer == NULL || der.length == 0)
return 0;
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (cert == NULL)
return MEMORY_E;
#endif
InitDecodedCert(cert, der.buffer, der.length, NULL);
if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY,
ssl->ctx->cm)) != 0) {
WOLFSSL_MSG("ParseCert failed");
}
else {
request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
DYNAMIC_TYPE_OCSP_REQUEST);
if (request == NULL) {
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return MEMORY_E;
}
ret = InitOcspRequest(request, cert, 0);
if (ret != 0) {
XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
}
else if (!ssl->buffers.weOwnCert && 0 == LockMutex(
&ssl->ctx->cm->ocsp_stapling->ocspLock)) {
if (!ssl->ctx->certOcspRequest)
ssl->ctx->certOcspRequest = request;
UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock);
}
}
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
if (ret == 0) {
ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request,
&response);
/* Suppressing, not critical */
if (ret == OCSP_CERT_REVOKED
|| ret == OCSP_CERT_UNKNOWN
|| ret == OCSP_LOOKUP_FAIL)
ret = 0;
if (response.buffer) {
if (ret == 0)
ret = BuildCertificateStatus(ssl, status_type,
&response, 1);
XFREE(response.buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
}
if (request != ssl->ctx->certOcspRequest)
XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
}
break;
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
/* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
#if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2
case WOLFSSL_CSR2_OCSP_MULTI: {
OcspRequest* request = ssl->ctx->certOcspRequest;
buffer responses[1 + MAX_CHAIN_DEPTH];
int i = 0;
ForceZero(responses, sizeof(responses));
/* unable to fetch status. skip. */
if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0)
return 0;
if (!request || ssl->buffers.weOwnCert) {
buffer der = ssl->buffers.certificate;
#ifdef WOLFSSL_SMALL_STACK
DecodedCert* cert = NULL;
#else
DecodedCert cert[1];
#endif
/* unable to fetch status. skip. */
if (der.buffer == NULL || der.length == 0)
return 0;
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (cert == NULL)
return MEMORY_E;
#endif
InitDecodedCert(cert, der.buffer, der.length, NULL);
if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY,
ssl->ctx->cm)) != 0) {
WOLFSSL_MSG("ParseCert failed");
}
else {
request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
DYNAMIC_TYPE_OCSP_REQUEST);
if (request == NULL) {
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return MEMORY_E;
}
ret = InitOcspRequest(request, cert, 0);
if (ret != 0) {
XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
}
else if (!ssl->buffers.weOwnCert && 0 == LockMutex(
&ssl->ctx->cm->ocsp_stapling->ocspLock)) {
if (!ssl->ctx->certOcspRequest)
ssl->ctx->certOcspRequest = request;
UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock);
}
}
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
if (ret == 0) {
ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request,
&responses[0]);
/* Suppressing, not critical */
if (ret == OCSP_CERT_REVOKED
|| ret == OCSP_CERT_UNKNOWN
|| ret == OCSP_LOOKUP_FAIL)
ret = 0;
}
if (request != ssl->ctx->certOcspRequest)
XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
if (ret == 0 && (!ssl->ctx->chainOcspRequest[0]
|| ssl->buffers.weOwnCertChain)) {
buffer der = {NULL, 0};
word32 idx = 0;
#ifdef WOLFSSL_SMALL_STACK
DecodedCert* cert = NULL;
#else
DecodedCert cert[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (cert == NULL)
return MEMORY_E;
#endif
while (idx + OPAQUE24_LEN < ssl->buffers.certChain.length) {
c24to32(ssl->buffers.certChain.buffer + idx, &der.length);
idx += OPAQUE24_LEN;
der.buffer = ssl->buffers.certChain.buffer + idx;
idx += der.length;
if (idx > ssl->buffers.certChain.length)
break;
InitDecodedCert(cert, der.buffer, der.length, NULL);
if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY,
ssl->ctx->cm)) != 0) {
WOLFSSL_MSG("ParseCert failed");
break;
}
else {
request = (OcspRequest*)XMALLOC(sizeof(OcspRequest),
NULL, DYNAMIC_TYPE_OCSP_REQUEST);
if (request == NULL) {
ret = MEMORY_E;
break;
}
ret = InitOcspRequest(request, cert, 0);
if (ret != 0) {
XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
break;
}
else if (!ssl->buffers.weOwnCertChain && 0 ==
LockMutex(
&ssl->ctx->cm->ocsp_stapling->ocspLock)) {
if (!ssl->ctx->chainOcspRequest[i])
ssl->ctx->chainOcspRequest[i] = request;
UnLockMutex(
&ssl->ctx->cm->ocsp_stapling->ocspLock);
}
ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
request, &responses[i + 1]);
/* Suppressing, not critical */
if (ret == OCSP_CERT_REVOKED
|| ret == OCSP_CERT_UNKNOWN
|| ret == OCSP_LOOKUP_FAIL)
ret = 0;
if (request != ssl->ctx->chainOcspRequest[i])
XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
i++;
}
FreeDecodedCert(cert);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
else {
while (ret == 0 &&
NULL != (request = ssl->ctx->chainOcspRequest[i])) {
ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
request, &responses[++i]);
/* Suppressing, not critical */
if (ret == OCSP_CERT_REVOKED
|| ret == OCSP_CERT_UNKNOWN
|| ret == OCSP_LOOKUP_FAIL)
ret = 0;
}
}
if (responses[0].buffer) {
if (ret == 0)
ret = BuildCertificateStatus(ssl, status_type,
responses, i + 1);
for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++)
if (responses[i].buffer)
XFREE(responses[i].buffer, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
}
}
break;
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
default:
break;
}
return ret;
}
#endif /* !NO_CERTS */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
int SendData(WOLFSSL* ssl, const void* data, int sz)
{
int sent = 0, /* plainText size */
sendSz,
ret,
dtlsExtra = 0;
2011-02-05 11:14:47 -08:00
if (ssl->error == WANT_WRITE)
ssl->error = 0;
2011-02-05 11:14:47 -08:00
if (ssl->options.handShakeState != HANDSHAKE_DONE) {
int err;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("handshake not complete, trying to finish");
if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS)
return err;
}
2011-02-05 11:14:47 -08:00
/* last time system socket output buffer was full, try again to send */
if (ssl->buffers.outputBuffer.length > 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("output buffer was full, trying to send again");
if ( (ssl->error = SendBuffered(ssl)) < 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_ERROR(ssl->error);
if (ssl->error == SOCKET_ERROR_E && ssl->options.connReset)
return 0; /* peer reset */
return ssl->error;
}
else {
/* advance sent to previous sent + plain size just sent */
sent = ssl->buffers.prevSent + ssl->buffers.plainSz;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("sent write buffered data");
if (sent > sz) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("error: write() after WANT_WRITE with short size");
return ssl->error = BAD_FUNC_ARG;
}
}
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
dtlsExtra = DTLS_RECORD_EXTRA;
}
#endif
2011-02-05 11:14:47 -08:00
for (;;) {
#ifdef HAVE_MAX_FRAGMENT
int len = min(sz - sent, min(ssl->max_fragment, OUTPUT_RECORD_SIZE));
#else
int len = min(sz - sent, OUTPUT_RECORD_SIZE);
#endif
byte* out;
byte* sendBuffer = (byte*)data + sent; /* may switch on comp */
int buffSz = len; /* may switch on comp */
int outputSz;
#ifdef HAVE_LIBZ
byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
#endif
2011-02-05 11:14:47 -08:00
if (sent == sz) break;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
len = min(len, MAX_UDP_SIZE);
buffSz = len;
}
#endif
2011-02-05 11:14:47 -08:00
/* check for available size */
outputSz = len + COMP_EXTRA + dtlsExtra + MAX_MSG_EXTRA;
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
return ssl->error = ret;
2011-02-05 11:14:47 -08:00
/* get ouput buffer */
out = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
#ifdef HAVE_LIBZ
if (ssl->options.usingCompression) {
buffSz = myCompress(ssl, sendBuffer, buffSz, comp, sizeof(comp));
if (buffSz < 0) {
return buffSz;
}
sendBuffer = comp;
}
#endif
sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz,
application_data, 0);
if (sendSz < 0)
return BUILD_MSG_ERROR;
2011-02-05 11:14:47 -08:00
ssl->buffers.outputBuffer.length += sendSz;
2011-02-05 11:14:47 -08:00
if ( (ret = SendBuffered(ssl)) < 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_ERROR(ret);
/* store for next call if WANT_WRITE or user embedSend() that
doesn't present like WANT_WRITE */
ssl->buffers.plainSz = len;
ssl->buffers.prevSent = sent;
if (ret == SOCKET_ERROR_E && ssl->options.connReset)
return 0; /* peer reset */
return ssl->error = ret;
}
2011-02-05 11:14:47 -08:00
sent += len;
2011-02-05 11:14:47 -08:00
/* only one message per attempt */
if (ssl->options.partialWrite == 1) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Paritial Write on, only sending one record");
break;
}
}
2014-10-24 10:33:24 -03:00
return sent;
}
2011-02-05 11:14:47 -08:00
/* process input data */
2014-12-19 11:27:01 -07:00
int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
{
int size;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
WOLFSSL_ENTER("ReceiveData()");
2011-02-05 11:14:47 -08:00
if (ssl->error == WANT_READ)
ssl->error = 0;
2011-02-05 11:14:47 -08:00
if (ssl->error != 0 && ssl->error != WANT_WRITE) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed");
return ssl->error;
}
2011-02-05 11:14:47 -08:00
if (ssl->options.handShakeState != HANDSHAKE_DONE) {
int err;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Handshake not complete, trying to finish");
if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS)
return err;
}
2011-02-05 11:14:47 -08:00
2014-09-29 14:48:49 -07:00
#ifdef HAVE_SECURE_RENEGOTIATION
startScr:
if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) {
int err;
ssl->secure_renegotiation->startScr = 0; /* only start once */
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Need to start scr, server requested");
if ( (err = wolfSSL_Rehandshake(ssl)) != SSL_SUCCESS)
2014-09-29 14:48:49 -07:00
return err;
}
#endif
while (ssl->buffers.clearOutputBuffer.length == 0) {
if ( (ssl->error = ProcessReply(ssl)) < 0) {
2015-02-11 09:37:54 -07:00
WOLFSSL_ERROR(ssl->error);
if (ssl->error == ZERO_RETURN) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Zero return, no more data coming");
return 0; /* no more data coming */
}
if (ssl->error == SOCKET_ERROR_E) {
if (ssl->options.connReset || ssl->options.isClosed) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Peer reset or closed, connection done");
ssl->error = SOCKET_PEER_CLOSED_E;
WOLFSSL_ERROR(ssl->error);
return 0; /* peer reset or closed */
}
}
return ssl->error;
}
2014-09-29 14:48:49 -07:00
#ifdef HAVE_SECURE_RENEGOTIATION
if (ssl->secure_renegotiation &&
ssl->secure_renegotiation->startScr) {
goto startScr;
}
#endif
}
2011-02-05 11:14:47 -08:00
if (sz < (int)ssl->buffers.clearOutputBuffer.length)
size = sz;
else
size = ssl->buffers.clearOutputBuffer.length;
2011-02-05 11:14:47 -08:00
XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size);
2011-02-05 11:14:47 -08:00
if (peek == 0) {
ssl->buffers.clearOutputBuffer.length -= size;
ssl->buffers.clearOutputBuffer.buffer += size;
}
2014-10-24 10:33:24 -03:00
if (ssl->buffers.clearOutputBuffer.length == 0 &&
ssl->buffers.inputBuffer.dynamicFlag)
ShrinkInputBuffer(ssl, NO_FORCED_FREE);
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
WOLFSSL_LEAVE("ReceiveData()", size);
return size;
}
2011-02-05 11:14:47 -08:00
/* send alert message */
2014-12-19 11:27:01 -07:00
int SendAlert(WOLFSSL* ssl, int severity, int type)
{
byte input[ALERT_SIZE];
byte *output;
int sendSz;
int ret;
int outputSz;
int dtlsExtra = 0;
/* if sendalert is called again for nonbloking */
if (ssl->options.sendAlertState != 0) {
ret = SendBuffered(ssl);
if (ret == 0)
ssl->options.sendAlertState = 0;
return ret;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
2014-10-24 10:33:24 -03:00
dtlsExtra = DTLS_RECORD_EXTRA;
#endif
/* check for available size */
outputSz = ALERT_SIZE + MAX_MSG_EXTRA + dtlsExtra;
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
return ret;
/* get ouput buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
input[0] = (byte)severity;
input[1] = (byte)type;
ssl->alert_history.last_tx.code = type;
ssl->alert_history.last_tx.level = severity;
if (severity == alert_fatal) {
ssl->options.isClosed = 1; /* Don't send close_notify */
}
/* only send encrypted alert if handshake actually complete, otherwise
other side may not be able to handle it */
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE,alert,0);
else {
AddRecordHeader(output, ALERT_SIZE, alert, ssl);
output += RECORD_HEADER_SZ;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
output += DTLS_RECORD_EXTRA;
#endif
XMEMCPY(output, input, ALERT_SIZE);
sendSz = RECORD_HEADER_SZ + ALERT_SIZE;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
sendSz += DTLS_RECORD_EXTRA;
#endif
}
if (sendSz < 0)
return BUILD_MSG_ERROR;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
AddPacketName("Alert", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddPacketInfo("Alert", &ssl->timeoutInfo, output, sendSz,ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
ssl->options.sendAlertState = 1;
return SendBuffered(ssl);
}
2014-12-19 11:27:01 -07:00
const char* wolfSSL_ERR_reason_error_string(unsigned long e)
{
#ifdef NO_ERROR_STRINGS
(void)e;
return "no support for error strings built in";
#else
int error = (int)e;
2014-12-19 11:27:01 -07:00
/* pass to wolfCrypt */
if (error < MAX_CODE_E && error > MIN_CODE_E) {
2014-12-19 11:27:01 -07:00
return wc_GetErrorString(error);
}
switch (error) {
case UNSUPPORTED_SUITE :
return "unsupported cipher suite";
case INPUT_CASE_ERROR :
return "input state error";
case PREFIX_ERROR :
return "bad index to key rounds";
case MEMORY_ERROR :
return "out of memory";
case VERIFY_FINISHED_ERROR :
return "verify problem on finished";
case VERIFY_MAC_ERROR :
return "verify mac problem";
case PARSE_ERROR :
return "parse error on header";
case SIDE_ERROR :
return "wrong client/server type";
case NO_PEER_CERT :
return "peer didn't send cert";
case UNKNOWN_HANDSHAKE_TYPE :
return "weird handshake type";
case SOCKET_ERROR_E :
return "error state on socket";
case SOCKET_NODATA :
return "expected data, not there";
case INCOMPLETE_DATA :
return "don't have enough data to complete task";
case UNKNOWN_RECORD_TYPE :
return "unknown type in record hdr";
case DECRYPT_ERROR :
return "error during decryption";
case FATAL_ERROR :
return "revcd alert fatal error";
case ENCRYPT_ERROR :
return "error during encryption";
case FREAD_ERROR :
return "fread problem";
case NO_PEER_KEY :
return "need peer's key";
case NO_PRIVATE_KEY :
return "need the private key";
case NO_DH_PARAMS :
return "server missing DH params";
case RSA_PRIVATE_ERROR :
return "error during rsa priv op";
case MATCH_SUITE_ERROR :
return "can't match cipher suite";
case BUILD_MSG_ERROR :
return "build message failure";
case BAD_HELLO :
return "client hello malformed";
case DOMAIN_NAME_MISMATCH :
return "peer subject name mismatch";
case WANT_READ :
case SSL_ERROR_WANT_READ :
return "non-blocking socket wants data to be read";
case NOT_READY_ERROR :
return "handshake layer not ready yet, complete first";
case PMS_VERSION_ERROR :
return "premaster secret version mismatch error";
case VERSION_ERROR :
return "record layer version error";
case WANT_WRITE :
case SSL_ERROR_WANT_WRITE :
return "non-blocking socket write buffer full";
case BUFFER_ERROR :
return "malformed buffer input error";
case VERIFY_CERT_ERROR :
return "verify problem on certificate";
case VERIFY_SIGN_ERROR :
return "verify problem based on signature";
case CLIENT_ID_ERROR :
return "psk client identity error";
case SERVER_HINT_ERROR:
return "psk server hint error";
case PSK_KEY_ERROR:
return "psk key callback error";
case NTRU_KEY_ERROR:
return "NTRU key error";
case NTRU_DRBG_ERROR:
return "NTRU drbg error";
case NTRU_ENCRYPT_ERROR:
return "NTRU encrypt error";
case NTRU_DECRYPT_ERROR:
return "NTRU decrypt error";
case ZLIB_INIT_ERROR:
return "zlib init error";
case ZLIB_COMPRESS_ERROR:
return "zlib compress error";
case ZLIB_DECOMPRESS_ERROR:
return "zlib decompress error";
case GETTIME_ERROR:
return "gettimeofday() error";
case GETITIMER_ERROR:
return "getitimer() error";
case SIGACT_ERROR:
return "sigaction() error";
case SETITIMER_ERROR:
return "setitimer() error";
case LENGTH_ERROR:
return "record layer length error";
case PEER_KEY_ERROR:
return "cant decode peer key";
case ZERO_RETURN:
case SSL_ERROR_ZERO_RETURN:
return "peer sent close notify alert";
case ECC_CURVETYPE_ERROR:
return "Bad ECC Curve Type or unsupported";
case ECC_CURVE_ERROR:
return "Bad ECC Curve or unsupported";
case ECC_PEERKEY_ERROR:
return "Bad ECC Peer Key";
case ECC_MAKEKEY_ERROR:
return "ECC Make Key failure";
case ECC_EXPORT_ERROR:
return "ECC Export Key failure";
2011-02-05 11:14:47 -08:00
case ECC_SHARED_ERROR:
return "ECC DHE shared failure";
case NOT_CA_ERROR:
return "Not a CA by basic constraint error";
case BAD_PATH_ERROR:
return "Bad path for opendir error";
2012-05-03 18:07:31 -07:00
case BAD_CERT_MANAGER_ERROR:
return "Bad Cert Manager error";
2012-05-03 18:07:31 -07:00
case OCSP_CERT_REVOKED:
return "OCSP Cert revoked";
2012-05-16 17:04:56 -07:00
case CRL_CERT_REVOKED:
return "CRL Cert revoked";
2012-05-16 17:04:56 -07:00
case CRL_MISSING:
return "CRL missing, not loaded";
2012-05-16 17:04:56 -07:00
case MONITOR_SETUP_E:
return "CRL monitor setup error";
2012-05-22 17:25:15 -07:00
case THREAD_CREATE_E:
return "Thread creation problem";
2012-05-22 17:25:15 -07:00
2012-05-22 15:52:08 -07:00
case OCSP_NEED_URL:
return "OCSP need URL";
2012-05-22 15:52:08 -07:00
case OCSP_CERT_UNKNOWN:
return "OCSP Cert unknown";
2012-05-22 15:52:08 -07:00
case OCSP_LOOKUP_FAIL:
return "OCSP Responder lookup fail";
2012-05-22 15:52:08 -07:00
case MAX_CHAIN_ERROR:
return "Maximum Chain Depth Exceeded";
2012-08-08 16:56:19 -07:00
case COOKIE_ERROR:
return "DTLS Cookie Error";
2012-08-08 16:56:19 -07:00
2012-08-23 15:50:56 -07:00
case SEQUENCE_ERROR:
return "DTLS Sequence Error";
2012-08-23 15:50:56 -07:00
case SUITES_ERROR:
return "Suites Pointer Error";
2012-09-17 17:25:38 -07:00
case SSL_NO_PEM_HEADER:
return "No PEM Header Error";
2012-09-17 17:25:38 -07:00
case OUT_OF_ORDER_E:
return "Out of order message, fatal";
case BAD_KEA_TYPE_E:
return "Bad KEA type found";
2012-12-24 15:40:09 -08:00
case SANITY_CIPHER_E:
return "Sanity check on ciphertext failed";
2012-12-24 15:40:09 -08:00
case RECV_OVERFLOW_E:
return "Receive callback returned more than requested";
case GEN_COOKIE_E:
return "Generate Cookie Error";
case NO_PEER_VERIFY:
return "Need peer certificate verify Error";
2013-04-24 11:10:23 -07:00
case FWRITE_ERROR:
return "fwrite Error";
2013-04-24 11:10:23 -07:00
case CACHE_MATCH_ERROR:
return "Cache restore header match Error";
2013-05-21 14:37:50 -07:00
case UNKNOWN_SNI_HOST_NAME_E:
return "Unrecognized host name Error";
2013-05-21 14:37:50 -07:00
2016-01-27 09:50:20 -07:00
case UNKNOWN_MAX_FRAG_LEN_E:
return "Unrecognized max frag len Error";
case KEYUSE_SIGNATURE_E:
return "Key Use digitalSignature not set Error";
case KEYUSE_ENCIPHER_E:
return "Key Use keyEncipherment not set Error";
case EXTKEYUSE_AUTH_E:
return "Ext Key Use server/client auth not set Error";
case SEND_OOB_READ_E:
return "Send Callback Out of Bounds Read Error";
2014-09-16 18:56:32 -07:00
case SECURE_RENEGOTIATION_E:
return "Invalid Renegotiation Error";
case SESSION_TICKET_LEN_E:
return "Session Ticket Too Long Error";
case SESSION_TICKET_EXPECT_E:
return "Session Ticket Error";
case SCR_DIFFERENT_CERT_E:
return "Peer sent different cert during SCR";
case SESSION_SECRET_CB_E:
return "Session Secret Callback Error";
case NO_CHANGE_CIPHER_E:
return "Finished received from peer before Change Cipher Error";
case SANITY_MSG_E:
return "Sanity Check on message order Error";
case DUPLICATE_MSG_E:
return "Duplicate HandShake message Error";
case SNI_UNSUPPORTED:
return "Protocol version does not support SNI Error";
case SOCKET_PEER_CLOSED_E:
return "Peer closed underlying transport Error";
case BAD_TICKET_KEY_CB_SZ:
return "Bad user session ticket key callback Size Error";
case BAD_TICKET_MSG_SZ:
return "Bad session ticket message Size Error";
case BAD_TICKET_ENCRYPT:
return "Bad user ticket callback encrypt Error";
case DH_KEY_SIZE_E:
return "DH key too small Error";
case SNI_ABSENT_ERROR:
return "No Server Name Indication extension Error";
case RSA_SIGN_FAULT:
return "RSA Signature Fault Error";
2015-11-02 15:51:01 -03:00
case HANDSHAKE_SIZE_ERROR:
return "Handshake message too large Error";
case UNKNOWN_ALPN_PROTOCOL_NAME_E:
return "Unrecognized protocol name Error";
2015-11-02 15:51:01 -03:00
case BAD_CERTIFICATE_STATUS_ERROR:
return "Bad Certificate Status Message Error";
case OCSP_INVALID_STATUS:
return "Invalid OCSP Status Error";
2011-02-05 11:14:47 -08:00
default :
return "unknown error number";
2011-02-05 11:14:47 -08:00
}
#endif /* NO_ERROR_STRINGS */
}
void SetErrorString(int error, char* str)
{
2014-12-19 11:27:01 -07:00
XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ);
}
2011-02-05 11:14:47 -08:00
/* be sure to add to cipher_name_idx too !!!! */
2014-10-24 10:33:24 -03:00
static const char* const cipher_names[] =
2011-02-05 11:14:47 -08:00
{
#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
"RC4-SHA",
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
"RC4-MD5",
#endif
#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
"DES-CBC3-SHA",
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
"AES128-SHA",
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
"AES256-SHA",
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
"NULL-SHA",
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
"NULL-SHA256",
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
"DHE-RSA-AES128-SHA",
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
"DHE-RSA-AES256-SHA",
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
"DHE-PSK-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
"DHE-PSK-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
"PSK-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
"PSK-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
"DHE-PSK-AES256-CBC-SHA384",
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
"DHE-PSK-AES128-CBC-SHA256",
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
"PSK-AES256-CBC-SHA384",
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
"PSK-AES128-CBC-SHA256",
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
"PSK-AES128-CBC-SHA",
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
"PSK-AES256-CBC-SHA",
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
"DHE-PSK-AES128-CCM",
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
"DHE-PSK-AES256-CCM",
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
"PSK-AES128-CCM",
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
"PSK-AES256-CCM",
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
"PSK-AES128-CCM-8",
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
"PSK-AES256-CCM-8",
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
"DHE-PSK-NULL-SHA384",
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
"DHE-PSK-NULL-SHA256",
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
"PSK-NULL-SHA384",
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
"PSK-NULL-SHA256",
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
"PSK-NULL-SHA",
#endif
2013-10-24 12:10:09 -07:00
#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
2011-02-05 11:14:47 -08:00
"HC128-MD5",
#endif
2014-10-24 10:33:24 -03:00
2013-10-24 12:10:09 -07:00
#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
2011-02-05 11:14:47 -08:00
"HC128-SHA",
#endif
2013-10-24 12:10:09 -07:00
#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
"HC128-B2B256",
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
"AES128-B2B256",
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
"AES256-B2B256",
#endif
2013-10-24 11:52:21 -07:00
#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
2011-02-05 11:14:47 -08:00
"RABBIT-SHA",
#endif
2015-07-11 12:52:22 -06:00
#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
"NTRU-RC4-SHA",
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
"NTRU-DES-CBC3-SHA",
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
"NTRU-AES128-SHA",
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
"NTRU-AES256-SHA",
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
"AES128-CCM-8",
2013-01-15 15:20:30 -08:00
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
"AES256-CCM-8",
2013-01-15 15:20:30 -08:00
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
"ECDHE-ECDSA-AES128-CCM-8",
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
"ECDHE-ECDSA-AES256-CCM-8",
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
"ECDHE-RSA-AES128-SHA",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
"ECDHE-RSA-AES256-SHA",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
"ECDHE-ECDSA-AES128-SHA",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
"ECDHE-ECDSA-AES256-SHA",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
"ECDHE-RSA-RC4-SHA",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
"ECDHE-RSA-DES-CBC3-SHA",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
"ECDHE-ECDSA-RC4-SHA",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
"ECDHE-ECDSA-DES-CBC3-SHA",
#endif
2011-03-04 11:13:28 -08:00
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
"AES128-SHA256",
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
"AES256-SHA256",
#endif
2011-04-26 09:32:18 -07:00
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
"DHE-RSA-AES128-SHA256",
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
2012-05-03 08:18:59 -07:00
"DHE-RSA-AES256-SHA256",
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
"ECDH-RSA-AES128-SHA",
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
"ECDH-RSA-AES256-SHA",
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
"ECDH-ECDSA-AES128-SHA",
2011-04-26 09:32:18 -07:00
#endif
2012-05-03 09:57:17 -07:00
2012-05-03 08:18:59 -07:00
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
2012-05-03 09:57:17 -07:00
"ECDH-ECDSA-AES256-SHA",
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
"ECDH-RSA-RC4-SHA",
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
"ECDH-RSA-DES-CBC3-SHA",
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
"ECDH-ECDSA-RC4-SHA",
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
"ECDH-ECDSA-DES-CBC3-SHA",
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
"AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
"AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
"DHE-RSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
"DHE-RSA-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
"ECDHE-RSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
"ECDHE-RSA-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
"ECDHE-ECDSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
"ECDHE-ECDSA-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
"ECDH-RSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
2012-06-28 23:09:13 -07:00
"ECDH-RSA-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
"ECDH-ECDSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
2013-01-21 10:53:42 -08:00
"ECDH-ECDSA-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
"CAMELLIA128-SHA",
2013-01-21 10:53:42 -08:00
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
"DHE-RSA-CAMELLIA128-SHA",
2013-01-21 10:53:42 -08:00
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
"CAMELLIA256-SHA",
2013-01-21 10:53:42 -08:00
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
"DHE-RSA-CAMELLIA256-SHA",
2013-01-21 10:53:42 -08:00
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
"CAMELLIA128-SHA256",
2013-01-21 10:53:42 -08:00
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
"DHE-RSA-CAMELLIA128-SHA256",
2013-01-21 10:53:42 -08:00
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
"CAMELLIA256-SHA256",
2013-01-21 10:53:42 -08:00
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
"DHE-RSA-CAMELLIA256-SHA256",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
"ECDHE-RSA-AES128-SHA256",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
"ECDHE-ECDSA-AES128-SHA256",
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
"ECDH-RSA-AES128-SHA256",
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
"ECDH-ECDSA-AES128-SHA256",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
"ECDHE-RSA-AES256-SHA384",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
"ECDHE-ECDSA-AES256-SHA384",
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
"ECDH-RSA-AES256-SHA384",
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
"ECDH-ECDSA-AES256-SHA384",
2011-04-26 09:32:18 -07:00
#endif
2012-05-03 08:18:59 -07:00
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
2014-07-17 15:00:40 -06:00
"ECDHE-RSA-CHACHA20-POLY1305",
2014-07-01 14:16:44 -06:00
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
2014-07-17 15:00:40 -06:00
"ECDHE-ECDSA-CHACHA20-POLY1305",
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
2014-07-17 15:00:40 -06:00
"DHE-RSA-CHACHA20-POLY1305",
#endif
#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
"ADH-AES128-SHA",
#endif
2015-07-07 09:55:58 -06:00
#ifdef BUILD_TLS_QSH
"QSH",
#endif
#ifdef HAVE_RENEGOTIATION_INDICATION
"RENEGOTIATION-INFO",
#endif
#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
"IDEA-CBC-SHA",
#endif
2011-02-05 11:14:47 -08:00
};
/* cipher suite number that matches above name table */
2014-03-02 11:06:41 -08:00
static int cipher_name_idx[] =
2011-02-05 11:14:47 -08:00
{
#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
SSL_RSA_WITH_RC4_128_SHA,
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
SSL_RSA_WITH_RC4_128_MD5,
#endif
#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
2014-10-24 10:33:24 -03:00
TLS_RSA_WITH_AES_128_CBC_SHA,
2011-02-05 11:14:47 -08:00
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA,
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
TLS_RSA_WITH_NULL_SHA,
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
TLS_RSA_WITH_NULL_SHA256,
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
2014-10-24 10:33:24 -03:00
TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
2011-02-05 11:14:47 -08:00
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
TLS_PSK_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
TLS_PSK_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
TLS_PSK_WITH_AES_256_CBC_SHA384,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
2014-10-24 10:33:24 -03:00
TLS_PSK_WITH_AES_128_CBC_SHA256,
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
2014-10-24 10:33:24 -03:00
TLS_PSK_WITH_AES_128_CBC_SHA,
2011-02-05 11:14:47 -08:00
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
TLS_PSK_WITH_AES_256_CBC_SHA,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
TLS_DHE_PSK_WITH_AES_128_CCM,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
TLS_DHE_PSK_WITH_AES_256_CCM,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
TLS_PSK_WITH_AES_128_CCM,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
TLS_PSK_WITH_AES_256_CCM,
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
TLS_PSK_WITH_AES_128_CCM_8,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
TLS_PSK_WITH_AES_256_CCM_8,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
TLS_DHE_PSK_WITH_NULL_SHA384,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
TLS_DHE_PSK_WITH_NULL_SHA256,
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
TLS_PSK_WITH_NULL_SHA384,
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
TLS_PSK_WITH_NULL_SHA256,
#endif
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
TLS_PSK_WITH_NULL_SHA,
#endif
2013-10-24 12:10:09 -07:00
#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
2014-10-24 10:33:24 -03:00
TLS_RSA_WITH_HC_128_MD5,
2011-02-05 11:14:47 -08:00
#endif
2013-10-24 12:10:09 -07:00
#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
2014-10-24 10:33:24 -03:00
TLS_RSA_WITH_HC_128_SHA,
2011-02-05 11:14:47 -08:00
#endif
2013-10-24 12:10:09 -07:00
#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
TLS_RSA_WITH_HC_128_B2B256,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
TLS_RSA_WITH_AES_128_CBC_B2B256,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
TLS_RSA_WITH_AES_256_CBC_B2B256,
#endif
2013-10-24 11:52:21 -07:00
#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
2014-10-24 10:33:24 -03:00
TLS_RSA_WITH_RABBIT_SHA,
2011-02-05 11:14:47 -08:00
#endif
2015-07-11 12:52:22 -06:00
#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
TLS_NTRU_RSA_WITH_RC4_128_SHA,
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA,
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
TLS_NTRU_RSA_WITH_AES_128_CBC_SHA,
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
TLS_NTRU_RSA_WITH_AES_256_CBC_SHA,
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
TLS_RSA_WITH_AES_128_CCM_8,
2013-01-15 15:20:30 -08:00
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
TLS_RSA_WITH_AES_256_CCM_8,
2013-01-15 15:20:30 -08:00
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
#endif
2013-03-22 11:30:12 -07:00
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
#endif
2011-02-05 11:14:47 -08:00
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
2014-10-24 10:33:24 -03:00
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
2011-02-05 11:14:47 -08:00
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
2014-10-24 10:33:24 -03:00
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
2011-02-05 11:14:47 -08:00
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
2014-10-24 10:33:24 -03:00
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
2011-02-05 11:14:47 -08:00
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
2014-10-24 10:33:24 -03:00
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
2011-02-05 11:14:47 -08:00
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
2014-10-24 10:33:24 -03:00
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
2011-02-05 11:14:47 -08:00
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
2014-10-24 10:33:24 -03:00
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
2011-02-05 11:14:47 -08:00
#endif
2011-03-04 11:13:28 -08:00
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
2014-10-24 10:33:24 -03:00
TLS_RSA_WITH_AES_128_CBC_SHA256,
2011-03-04 11:13:28 -08:00
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256,
#endif
2011-04-26 09:32:18 -07:00
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
2014-10-24 10:33:24 -03:00
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
2011-04-26 09:32:18 -07:00
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
2012-05-03 08:18:59 -07:00
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
#endif
2012-05-03 08:18:59 -07:00
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
2012-05-03 09:57:17 -07:00
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
TLS_ECDH_RSA_WITH_RC4_128_SHA,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
2011-04-26 09:32:18 -07:00
#endif
2012-05-03 09:57:17 -07:00
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
#endif
2012-06-28 23:09:13 -07:00
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
2013-01-21 10:53:42 -08:00
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
2011-04-26 09:32:18 -07:00
#endif
2012-05-03 08:18:59 -07:00
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
2014-07-01 14:16:44 -06:00
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
#endif
#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
TLS_DH_anon_WITH_AES_128_CBC_SHA,
#endif
2015-07-07 09:55:58 -06:00
#ifdef BUILD_TLS_QSH
TLS_QSH,
#endif
#ifdef HAVE_RENEGOTIATION_INDICATION
TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
#endif
#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
SSL_RSA_WITH_IDEA_CBC_SHA,
#endif
2011-02-05 11:14:47 -08:00
};
/* returns the cipher_names array */
const char* const* GetCipherNames(void)
{
return cipher_names;
}
2014-08-15 10:56:38 -07:00
/* returns the size of the cipher_names array */
int GetCipherNamesSize(void)
{
2014-08-15 10:56:38 -07:00
return (int)(sizeof(cipher_names) / sizeof(char*));
}
2014-08-15 10:56:38 -07:00
/**
Set the enabled cipher suites.
2011-02-05 11:14:47 -08:00
@param [out] suites Suites structure.
@param [in] list List of cipher suites, only supports full name from
cipher_name[] delimited by ':'.
2011-02-05 11:14:47 -08:00
@return true on success, else false.
*/
int SetCipherList(Suites* suites, const char* list)
{
int ret = 0;
int idx = 0;
int haveRSAsig = 0;
int haveECDSAsig = 0;
int haveAnon = 0;
const int suiteSz = GetCipherNamesSize();
char* next = (char*)list;
if (suites == NULL || list == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("SetCipherList parameter error");
return 0;
}
2014-10-24 10:33:24 -03:00
if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0)
2014-12-19 11:27:01 -07:00
return 1; /* wolfSSL defualt */
2011-02-05 11:14:47 -08:00
do {
char* current = next;
char name[MAX_SUITE_NAME + 1];
int i;
word32 length;
2011-02-05 11:14:47 -08:00
next = XSTRSTR(next, ":");
length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /* last */
: (word32)(next - current));
2011-02-05 11:14:47 -08:00
XSTRNCPY(name, current, length);
name[(length == sizeof(name)) ? length - 1 : length] = 0;
2011-02-05 11:14:47 -08:00
for (i = 0; i < suiteSz; i++) {
2011-02-05 11:14:47 -08:00
if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) {
suites->suites[idx++] = (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE
2015-07-07 09:55:58 -06:00
: (XSTRSTR(name, "QSH")) ? QSH_BYTE
: (XSTRSTR(name, "EC")) ? ECC_BYTE
: (XSTRSTR(name, "CCM")) ? ECC_BYTE
: 0x00; /* normal */
suites->suites[idx++] = (byte)cipher_name_idx[i];
2011-02-05 11:14:47 -08:00
/* The suites are either ECDSA, RSA, PSK, or Anon. The RSA
* suites don't necessarily have RSA in the name. */
if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA"))
haveECDSAsig = 1;
else if (XSTRSTR(name, "ADH"))
haveAnon = 1;
else if ((haveRSAsig == 0) && (XSTRSTR(name, "PSK") == NULL))
haveRSAsig = 1;
2013-02-18 14:36:50 -08:00
ret = 1; /* found at least one */
2011-02-05 11:14:47 -08:00
break;
}
}
2011-02-05 11:14:47 -08:00
}
while (next++); /* ++ needed to skip ':' */
2011-02-05 11:14:47 -08:00
if (ret) {
suites->setSuites = 1;
suites->suiteSz = (word16)idx;
InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon);
2011-02-05 11:14:47 -08:00
}
return ret;
}
2014-12-19 11:27:01 -07:00
static void PickHashSigAlgo(WOLFSSL* ssl,
const byte* hashSigAlgo, word32 hashSigAlgoSz)
{
word32 i;
ssl->suites->sigAlgo = ssl->specs.sig_algo;
ssl->suites->hashAlgo = sha_mac;
2014-12-01 08:58:52 -08:00
/* i+1 since peek a byte ahead for type */
for (i = 0; (i+1) < hashSigAlgoSz; i += 2) {
if (hashSigAlgo[i+1] == ssl->specs.sig_algo) {
if (hashSigAlgo[i] == sha_mac) {
break;
}
#ifndef NO_SHA256
else if (hashSigAlgo[i] == sha256_mac) {
ssl->suites->hashAlgo = sha256_mac;
break;
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
else if (hashSigAlgo[i] == sha384_mac) {
ssl->suites->hashAlgo = sha384_mac;
break;
}
#endif
#ifdef WOLFSSL_SHA512
else if (hashSigAlgo[i] == sha512_mac) {
ssl->suites->hashAlgo = sha512_mac;
break;
}
#endif
}
}
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
/* Initialisze HandShakeInfo */
void InitHandShakeInfo(HandShakeInfo* info)
{
int i;
info->cipherName[0] = 0;
for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
info->packetNames[i][0] = 0;
info->numberPackets = 0;
info->negotiationError = 0;
}
/* Set Final HandShakeInfo parameters */
2014-12-19 11:27:01 -07:00
void FinishHandShakeInfo(HandShakeInfo* info, const WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
int i;
2014-10-24 10:33:24 -03:00
int sz = sizeof(cipher_name_idx)/sizeof(int);
2011-02-05 11:14:47 -08:00
for (i = 0; i < sz; i++)
if (ssl->options.cipherSuite == (byte)cipher_name_idx[i]) {
if (ssl->options.cipherSuite0 == ECC_BYTE)
continue; /* ECC suites at end */
XSTRNCPY(info->cipherName, cipher_names[i], MAX_CIPHERNAME_SZ);
break;
}
/* error max and min are negative numbers */
if (ssl->error <= MIN_PARAM_ERR && ssl->error >= MAX_PARAM_ERR)
info->negotiationError = ssl->error;
}
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* Add name to info packet names, increase packet name count */
void AddPacketName(const char* name, HandShakeInfo* info)
{
if (info->numberPackets < MAX_PACKETS_HANDSHAKE) {
XSTRNCPY(info->packetNames[info->numberPackets++], name,
MAX_PACKETNAME_SZ);
}
2014-10-24 10:33:24 -03:00
}
2011-02-05 11:14:47 -08:00
/* Initialisze TimeoutInfo */
void InitTimeoutInfo(TimeoutInfo* info)
{
int i;
info->timeoutName[0] = 0;
info->flags = 0;
for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) {
info->packets[i].packetName[0] = 0;
info->packets[i].timestamp.tv_sec = 0;
info->packets[i].timestamp.tv_usec = 0;
info->packets[i].bufferValue = 0;
info->packets[i].valueSz = 0;
}
info->numberPackets = 0;
info->timeoutValue.tv_sec = 0;
info->timeoutValue.tv_usec = 0;
}
/* Free TimeoutInfo */
void FreeTimeoutInfo(TimeoutInfo* info, void* heap)
{
int i;
(void)heap;
2011-02-05 11:14:47 -08:00
for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
if (info->packets[i].bufferValue) {
XFREE(info->packets[i].bufferValue, heap, DYNAMIC_TYPE_INFO);
info->packets[i].bufferValue = 0;
}
}
/* Add PacketInfo to TimeoutInfo */
void AddPacketInfo(const char* name, TimeoutInfo* info, const byte* data,
int sz, void* heap)
{
if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) {
Timeval currTime;
/* may add name after */
if (name)
XSTRNCPY(info->packets[info->numberPackets].packetName, name,
MAX_PACKETNAME_SZ);
/* add data, put in buffer if bigger than static buffer */
info->packets[info->numberPackets].valueSz = sz;
if (sz < MAX_VALUE_SZ)
XMEMCPY(info->packets[info->numberPackets].value, data, sz);
else {
info->packets[info->numberPackets].bufferValue =
XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
if (!info->packets[info->numberPackets].bufferValue)
/* let next alloc catch, just don't fill, not fatal here */
info->packets[info->numberPackets].valueSz = 0;
else
XMEMCPY(info->packets[info->numberPackets].bufferValue,
data, sz);
}
gettimeofday(&currTime, 0);
info->packets[info->numberPackets].timestamp.tv_sec =
currTime.tv_sec;
info->packets[info->numberPackets].timestamp.tv_usec =
currTime.tv_usec;
info->numberPackets++;
}
}
/* Add packet name to previsouly added packet info */
void AddLateName(const char* name, TimeoutInfo* info)
{
/* make sure we have a valid previous one */
if (info->numberPackets > 0 && info->numberPackets <
MAX_PACKETS_HANDSHAKE) {
XSTRNCPY(info->packets[info->numberPackets - 1].packetName, name,
MAX_PACKETNAME_SZ);
}
}
/* Add record header to previsouly added packet info */
void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
{
/* make sure we have a valid previous one */
if (info->numberPackets > 0 && info->numberPackets <
MAX_PACKETS_HANDSHAKE) {
if (info->packets[info->numberPackets - 1].bufferValue)
XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
RECORD_HEADER_SZ);
else
XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
RECORD_HEADER_SZ);
}
}
2014-12-19 11:27:01 -07:00
#endif /* WOLFSSL_CALLBACKS */
2011-02-05 11:14:47 -08:00
/* client only parts */
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_CLIENT
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
int SendClientHello(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
byte *output;
word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
int sendSz;
int idSz = ssl->options.resuming
? ssl->session.sessionIDSz
: 0;
2011-02-05 11:14:47 -08:00
int ret;
if (ssl->suites == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Bad suites pointer in SendClientHello");
return SUITES_ERROR;
2014-10-24 10:33:24 -03:00
}
#ifdef HAVE_SESSION_TICKET
if (ssl->options.resuming && ssl->session.ticketLen > 0) {
SessionTicket* ticket;
ticket = TLSX_SessionTicket_Create(0,
ssl->session.ticket, ssl->session.ticketLen);
if (ticket == NULL) return MEMORY_E;
ret = TLSX_UseSessionTicket(&ssl->extensions, ticket);
if (ret != SSL_SUCCESS) return ret;
idSz = 0;
}
#endif
length = VERSION_SZ + RAN_LEN
2014-10-24 10:33:24 -03:00
+ idSz + ENUM_LEN
+ ssl->suites->suiteSz + SUITE_LEN
+ COMP_LEN + ENUM_LEN;
2013-05-21 14:37:50 -07:00
#ifdef HAVE_TLS_EXTENSIONS
2015-07-07 09:55:58 -06:00
/* auto populate extensions supported unless user defined */
if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0)
return ret;
#ifdef HAVE_QSH
if (QSH_Init(ssl) != 0)
return MEMORY_E;
#endif
2013-05-21 14:37:50 -07:00
length += TLSX_GetRequestSize(ssl);
#else
2013-02-18 14:36:50 -08:00
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) {
length += ssl->suites->hashSigAlgoSz + HELLO_EXT_SZ;
}
2013-05-21 14:37:50 -07:00
#endif
2011-02-05 11:14:47 -08:00
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls) {
length += ENUM_LEN; /* cookie */
2012-09-14 21:19:06 -07:00
if (ssl->arrays->cookieSz != 0) length += ssl->arrays->cookieSz;
2011-02-05 11:14:47 -08:00
sendSz = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
}
#endif
if (IsEncryptionOn(ssl, 1))
sendSz += MAX_MSG_EXTRA;
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
2011-02-05 11:14:47 -08:00
return ret;
/* get ouput buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
AddHeaders(output, length, client_hello, ssl);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
DtlsRecordLayerHeader* rh = (DtlsRecordLayerHeader*)output;
rh->pvMajor = DTLS_MAJOR;
rh->pvMinor = DTLS_MINOR;
}
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
/* client hello, first version */
output[idx++] = ssl->version.major;
output[idx++] = ssl->version.minor;
2011-02-05 11:14:47 -08:00
ssl->chVersion = ssl->version; /* store in case changed */
/* then random */
if (ssl->options.connectState == CONNECT_BEGIN) {
2015-01-01 07:33:07 -07:00
ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN);
if (ret != 0)
return ret;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* store random */
2012-09-14 21:19:06 -07:00
XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN);
2011-02-05 11:14:47 -08:00
} else {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
/* send same random on hello again */
2012-09-14 21:19:06 -07:00
XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN);
2011-02-05 11:14:47 -08:00
#endif
}
idx += RAN_LEN;
/* then session id */
output[idx++] = (byte)idSz;
2011-02-05 11:14:47 -08:00
if (idSz) {
XMEMCPY(output + idx, ssl->session.sessionID,
ssl->session.sessionIDSz);
idx += ssl->session.sessionIDSz;
2011-02-05 11:14:47 -08:00
}
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* then DTLS cookie */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls) {
2012-09-14 21:19:06 -07:00
byte cookieSz = ssl->arrays->cookieSz;
output[idx++] = cookieSz;
if (cookieSz) {
2012-09-14 21:19:06 -07:00
XMEMCPY(&output[idx], ssl->arrays->cookie, cookieSz);
idx += cookieSz;
}
2011-02-05 11:14:47 -08:00
}
#endif
/* then cipher suites */
c16toa(ssl->suites->suiteSz, output + idx);
2011-02-05 11:14:47 -08:00
idx += 2;
XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz);
idx += ssl->suites->suiteSz;
2011-02-05 11:14:47 -08:00
/* last, compression */
output[idx++] = COMP_LEN;
if (ssl->options.usingCompression)
output[idx++] = ZLIB_COMPRESSION;
else
output[idx++] = NO_COMPRESSION;
2013-05-21 14:37:50 -07:00
#ifdef HAVE_TLS_EXTENSIONS
idx += TLSX_WriteRequest(ssl, output + idx);
(void)idx; /* suppress analyzer warning, keep idx current */
#else
2013-02-18 14:36:50 -08:00
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
{
2013-02-18 14:36:50 -08:00
int i;
/* add in the extensions length */
2015-12-21 16:11:02 -07:00
c16toa((word16)(HELLO_EXT_LEN + ssl->suites->hashSigAlgoSz),
output + idx);
idx += 2;
c16toa(HELLO_EXT_SIG_ALGO, output + idx);
idx += 2;
2015-12-21 16:11:02 -07:00
c16toa((word16)(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz),
output+idx);
idx += 2;
2013-02-18 14:36:50 -08:00
c16toa(ssl->suites->hashSigAlgoSz, output + idx);
idx += 2;
2013-02-18 14:36:50 -08:00
for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) {
output[idx] = ssl->suites->hashSigAlgo[i];
}
}
2013-05-21 14:37:50 -07:00
#endif
if (IsEncryptionOn(ssl, 1)) {
byte* input;
int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */
input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (input == NULL)
return MEMORY_E;
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
sendSz = BuildMessage(ssl, output,sendSz,input,inputSz,handshake,1);
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (sendSz < 0)
return sendSz;
} else {
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0)
return ret;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return ret;
2012-09-14 09:35:34 -07:00
}
#endif
2011-02-05 11:14:47 -08:00
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz,
ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
return SendBuffered(ssl);
}
2014-12-19 11:27:01 -07:00
static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 size)
2011-02-05 11:14:47 -08:00
{
ProtocolVersion pv;
byte cookieSz;
word32 begin = *inOutIdx;
2014-10-24 10:33:24 -03:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn) AddPacketName("HelloVerifyRequest",
&ssl->handShakeInfo);
if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
2012-09-14 09:35:34 -07:00
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
if (ssl->options.dtls) {
DtlsPoolReset(ssl);
}
2011-02-05 11:14:47 -08:00
#endif
2014-10-24 10:33:24 -03:00
if ((*inOutIdx - begin) + OPAQUE16_LEN + OPAQUE8_LEN > size)
return BUFFER_ERROR;
XMEMCPY(&pv, input + *inOutIdx, OPAQUE16_LEN);
*inOutIdx += OPAQUE16_LEN;
if (pv.major != DTLS_MAJOR ||
(pv.minor != DTLS_MINOR && pv.minor != DTLSv1_2_MINOR))
return VERSION_ERROR;
2011-02-05 11:14:47 -08:00
cookieSz = input[(*inOutIdx)++];
2014-10-24 10:33:24 -03:00
if (cookieSz) {
if ((*inOutIdx - begin) + cookieSz > size)
return BUFFER_ERROR;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (cookieSz <= MAX_COOKIE_LEN) {
2012-09-14 21:19:06 -07:00
XMEMCPY(ssl->arrays->cookie, input + *inOutIdx, cookieSz);
ssl->arrays->cookieSz = cookieSz;
}
#endif
*inOutIdx += cookieSz;
}
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
return 0;
}
2014-12-19 11:27:01 -07:00
static INLINE int DSH_CheckSessionId(WOLFSSL* ssl)
{
int ret = 0;
#ifdef HAVE_SECRET_CALLBACK
/* If a session secret callback exists, we are using that
* key instead of the saved session key. */
ret = ret || (ssl->sessionSecretCb != NULL);
#endif
#ifdef HAVE_SESSION_TICKET
/* server may send blank ticket which may not be expected to indicate
* exisiting one ok but will also be sending a new one */
ret = ret || (ssl->session.ticketLen > 0);
#endif
ret = ret ||
(ssl->options.haveSessionId && XMEMCMP(ssl->arrays->sessionID,
ssl->session.sessionID, ID_LEN) == 0);
return ret;
}
2014-12-19 11:27:01 -07:00
static int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32 helloSz)
2011-02-05 11:14:47 -08:00
{
2014-09-30 12:55:15 -07:00
byte cs0; /* cipher suite bytes 0, 1 */
byte cs1;
2011-02-05 11:14:47 -08:00
ProtocolVersion pv;
byte compression;
word32 i = *inOutIdx;
word32 begin = i;
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
#endif
/* protocol version, random and session id length check */
2015-02-20 12:38:29 -08:00
if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
/* protocol version */
XMEMCPY(&pv, input + i, OPAQUE16_LEN);
i += OPAQUE16_LEN;
if (pv.minor > ssl->version.minor) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Server using higher version, fatal error");
return VERSION_ERROR;
}
else if (pv.minor < ssl->version.minor) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("server using lower version");
if (!ssl->options.downgrade) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" no downgrade allowed, fatal error");
return VERSION_ERROR;
}
if (pv.minor < ssl->options.minDowngrade) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" version below minimum allowed, fatal error");
return VERSION_ERROR;
}
2014-10-01 09:44:24 -07:00
#ifdef HAVE_SECURE_RENEGOTIATION
if (ssl->secure_renegotiation &&
ssl->secure_renegotiation->enabled &&
ssl->options.handShakeDone) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Server changed version during scr");
2014-10-01 09:44:24 -07:00
return VERSION_ERROR;
}
#endif
if (pv.minor == SSLv3_MINOR) {
/* turn off tls */
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" downgrading to SSLv3");
ssl->options.tls = 0;
ssl->options.tls1_1 = 0;
ssl->version.minor = SSLv3_MINOR;
}
else if (pv.minor == TLSv1_MINOR) {
/* turn off tls 1.1+ */
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" downgrading to TLSv1");
ssl->options.tls1_1 = 0;
ssl->version.minor = TLSv1_MINOR;
}
else if (pv.minor == TLSv1_1_MINOR) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" downgrading to TLSv1.1");
ssl->version.minor = TLSv1_1_MINOR;
}
}
/* random */
2012-09-14 21:19:06 -07:00
XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
2011-02-05 11:14:47 -08:00
i += RAN_LEN;
/* session id */
ssl->arrays->sessionIDSz = input[i++];
if (ssl->arrays->sessionIDSz > ID_LEN) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Invalid session ID size");
ssl->arrays->sessionIDSz = 0;
return BUFFER_ERROR;
2011-02-05 11:14:47 -08:00
}
else if (ssl->arrays->sessionIDSz) {
if ((i - begin) + ssl->arrays->sessionIDSz > helloSz)
return BUFFER_ERROR;
XMEMCPY(ssl->arrays->sessionID, input + i,
ssl->arrays->sessionIDSz);
i += ssl->arrays->sessionIDSz;
2012-05-17 10:55:42 -07:00
ssl->options.haveSessionId = 1;
2011-02-05 11:14:47 -08:00
}
2014-10-24 10:33:24 -03:00
/* suite and compression */
if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
2014-09-30 12:55:15 -07:00
cs0 = input[i++];
cs1 = input[i++];
#ifdef HAVE_SECURE_RENEGOTIATION
if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
ssl->options.handShakeDone) {
if (ssl->options.cipherSuite0 != cs0 ||
ssl->options.cipherSuite != cs1) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Server changed cipher suite during scr");
2014-09-30 12:55:15 -07:00
return MATCH_SUITE_ERROR;
}
}
#endif
ssl->options.cipherSuite0 = cs0;
ssl->options.cipherSuite = cs1;
2011-02-05 11:14:47 -08:00
compression = input[i++];
2011-04-25 09:24:21 -07:00
if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Server refused compression, turning off");
2011-02-05 11:14:47 -08:00
ssl->options.usingCompression = 0; /* turn off if server refused */
2011-04-25 09:24:21 -07:00
}
*inOutIdx = i;
2015-07-07 09:55:58 -06:00
2013-05-21 14:37:50 -07:00
if ( (i - begin) < helloSz) {
#ifdef HAVE_TLS_EXTENSIONS
2014-06-25 11:52:37 -03:00
if (TLSX_SupportExtensions(ssl)) {
int ret = 0;
2013-05-21 14:37:50 -07:00
word16 totalExtSz;
if ((i - begin) + OPAQUE16_LEN > helloSz)
return BUFFER_ERROR;
2013-05-21 14:37:50 -07:00
ato16(&input[i], &totalExtSz);
i += OPAQUE16_LEN;
if ((i - begin) + totalExtSz > helloSz)
return BUFFER_ERROR;
2013-05-21 14:37:50 -07:00
if ((ret = TLSX_Parse(ssl, (byte *) input + i,
totalExtSz, 0, NULL)))
2013-05-21 14:37:50 -07:00
return ret;
i += totalExtSz;
*inOutIdx = i;
}
else
#endif
*inOutIdx = begin + helloSz; /* skip extensions */
2013-05-21 14:37:50 -07:00
}
2011-02-05 11:14:47 -08:00
ssl->options.serverState = SERVER_HELLO_COMPLETE;
if (IsEncryptionOn(ssl, 0)) {
2014-09-26 10:47:57 -07:00
*inOutIdx += ssl->keys.padSz;
}
#ifdef HAVE_SECRET_CALLBACK
if (ssl->sessionSecretCb != NULL) {
int secretSz = SECRET_LEN, ret;
ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret,
&secretSz, ssl->sessionSecretCtx);
if (ret != 0 || secretSz != SECRET_LEN)
return SESSION_SECRET_CB_E;
}
#endif /* HAVE_SECRET_CALLBACK */
2011-02-05 11:14:47 -08:00
if (ssl->options.resuming) {
if (DSH_CheckSessionId(ssl)) {
2011-02-05 11:14:47 -08:00
if (SetCipherSpecs(ssl) == 0) {
int ret = -1;
2012-09-14 21:19:06 -07:00
XMEMCPY(ssl->arrays->masterSecret,
ssl->session.masterSecret, SECRET_LEN);
2013-05-09 15:33:37 -07:00
#ifdef NO_OLD_TLS
2011-02-28 12:21:06 -08:00
ret = DeriveTlsKeys(ssl);
2013-05-09 15:33:37 -07:00
#else
#ifndef NO_TLS
if (ssl->options.tls)
ret = DeriveTlsKeys(ssl);
#endif
if (!ssl->options.tls)
ret = DeriveKeys(ssl);
#endif
2011-02-05 11:14:47 -08:00
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
2011-02-28 12:21:06 -08:00
return ret;
2011-02-05 11:14:47 -08:00
}
2012-05-17 07:55:25 -07:00
else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Unsupported cipher suite, DoServerHello");
2011-02-05 11:14:47 -08:00
return UNSUPPORTED_SUITE;
2012-05-17 07:55:25 -07:00
}
2011-02-05 11:14:47 -08:00
}
2011-04-25 09:24:21 -07:00
else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Server denied resumption attempt");
2011-02-05 11:14:47 -08:00
ssl->options.resuming = 0; /* server denied resumption try */
2011-04-25 09:24:21 -07:00
}
2011-02-05 11:14:47 -08:00
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
if (ssl->options.dtls) {
DtlsPoolReset(ssl);
}
#endif
2011-02-05 11:14:47 -08:00
return SetCipherSpecs(ssl);
}
/* Make sure client setup is valid for this suite, true on success */
2014-12-19 11:27:01 -07:00
int VerifyClientSuite(WOLFSSL* ssl)
{
int havePSK = 0;
byte first = ssl->options.cipherSuite0;
byte second = ssl->options.cipherSuite;
2014-12-19 11:27:01 -07:00
WOLFSSL_ENTER("VerifyClientSuite");
#ifndef NO_PSK
havePSK = ssl->options.havePSK;
#endif
if (CipherRequires(first, second, REQUIRES_PSK)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Requires PSK");
if (havePSK == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Don't have PSK");
return 0;
}
}
return 1; /* success */
}
#ifndef NO_CERTS
2011-02-05 11:14:47 -08:00
/* just read in and ignore for now TODO: */
2014-12-19 11:27:01 -07:00
static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*
inOutIdx, word32 size)
2011-02-05 11:14:47 -08:00
{
word16 len;
word32 begin = *inOutIdx;
2014-10-24 10:33:24 -03:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn)
AddPacketName("CertificateRequest", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddLateName("CertificateRequest", &ssl->timeoutInfo);
#endif
if ((*inOutIdx - begin) + OPAQUE8_LEN > size)
return BUFFER_ERROR;
2011-02-05 11:14:47 -08:00
len = input[(*inOutIdx)++];
if ((*inOutIdx - begin) + len > size)
return BUFFER_ERROR;
2011-02-05 11:14:47 -08:00
/* types, read in here */
*inOutIdx += len;
/* signature and hash signature algorithm */
2011-02-28 12:21:06 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
ato16(input + *inOutIdx, &len);
*inOutIdx += OPAQUE16_LEN;
if ((*inOutIdx - begin) + len > size)
return BUFFER_ERROR;
PickHashSigAlgo(ssl, input + *inOutIdx, len);
2013-02-18 14:36:50 -08:00
*inOutIdx += len;
2011-02-28 12:21:06 -08:00
}
2011-02-05 11:14:47 -08:00
/* authorities */
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
ato16(input + *inOutIdx, &len);
*inOutIdx += OPAQUE16_LEN;
if ((*inOutIdx - begin) + len > size)
return BUFFER_ERROR;
2011-02-05 11:14:47 -08:00
while (len) {
word16 dnSz;
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
ato16(input + *inOutIdx, &dnSz);
*inOutIdx += OPAQUE16_LEN;
if ((*inOutIdx - begin) + dnSz > size)
return BUFFER_ERROR;
*inOutIdx += dnSz;
len -= OPAQUE16_LEN + dnSz;
2011-02-05 11:14:47 -08:00
}
/* don't send client cert or cert verify if user hasn't provided
cert and private key */
if (ssl->buffers.certificate.buffer && ssl->buffers.key.buffer)
ssl->options.sendVerify = SEND_CERT;
else if (IsTLS(ssl))
2011-02-05 11:14:47 -08:00
ssl->options.sendVerify = SEND_BLANK_CERT;
if (IsEncryptionOn(ssl, 0))
2014-09-30 11:52:21 -07:00
*inOutIdx += ssl->keys.padSz;
2011-02-05 11:14:47 -08:00
return 0;
}
#endif /* !NO_CERTS */
2011-02-05 11:14:47 -08:00
2015-03-18 14:12:23 -07:00
#ifdef HAVE_ECC
static int CheckCurveId(int oid)
{
int ret = 0;
switch (oid) {
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
case WOLFSSL_ECC_SECP160R1:
#endif
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
case WOLFSSL_ECC_SECP192R1:
#endif
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
case WOLFSSL_ECC_SECP224R1:
#endif
#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
case WOLFSSL_ECC_SECP256R1:
#endif
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
case WOLFSSL_ECC_SECP384R1:
#endif
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
case WOLFSSL_ECC_SECP521R1:
#endif
break;
default:
ret = -1;
}
return ret;
}
#endif /* HAVE_ECC */
2014-12-19 11:27:01 -07:00
static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 size)
2011-02-05 11:14:47 -08:00
{
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
word16 name;
2015-09-15 17:46:45 -06:00
int qshSz;
2015-07-07 09:55:58 -06:00
#endif
word16 length = 0;
word32 begin = *inOutIdx;
2014-03-25 16:01:17 -07:00
int ret = 0;
2014-12-04 13:30:30 -08:00
#define ERROR_OUT(err, eLabel) do { ret = err; goto eLabel; } while(0)
2011-02-05 11:14:47 -08:00
(void)length; /* shut up compiler warnings */
(void)begin;
2011-04-27 17:31:08 -07:00
(void)ssl;
(void)input;
(void)size;
2014-03-25 16:01:17 -07:00
(void)ret;
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn)
AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
#endif
2015-12-03 12:37:49 -08:00
switch (ssl->specs.kea)
{
2011-02-05 11:14:47 -08:00
#ifndef NO_PSK
2015-12-03 12:37:49 -08:00
case psk_kea:
{
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx,
min(length, MAX_PSK_ID_LEN));
ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0;
*inOutIdx += length;
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
/* QSH extensions */
#ifdef HAVE_QSH
if (ssl->peerQSHKeyPresent) {
/* extension name */
ato16(input + *inOutIdx, &name);
*inOutIdx += OPAQUE16_LEN;
2015-11-02 15:51:01 -03:00
if (name == TLSX_QUANTUM_SAFE_HYBRID) {
2015-09-15 17:46:45 -06:00
/* if qshSz is larger than 0 it is the length of buffer
used */
if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx,
2015-12-03 12:37:49 -08:00
size, 0)) < 0) {
2015-09-15 17:46:45 -06:00
return qshSz;
2015-12-03 12:37:49 -08:00
}
2015-09-15 17:46:45 -06:00
*inOutIdx += qshSz;
2015-07-07 09:55:58 -06:00
}
else {
/* unknown extension sent server ignored
handshake */
return BUFFER_ERROR;
}
}
#endif
2011-02-05 11:14:47 -08:00
return 0;
}
#endif
#ifndef NO_DH
2015-12-03 12:37:49 -08:00
case diffie_hellman_kea:
2011-02-05 11:14:47 -08:00
{
2015-12-03 12:37:49 -08:00
/* p */
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
}
2015-12-03 12:37:49 -08:00
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
}
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
if (length < ssl->options.minDhKeySz) {
WOLFSSL_MSG("Server using a DH key that is too small");
SendAlert(ssl, alert_fatal, handshake_failure);
return DH_KEY_SIZE_E;
}
2015-12-03 12:37:49 -08:00
ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_P.buffer) {
ssl->buffers.serverDH_P.length = length;
}
else {
return MEMORY_ERROR;
}
2015-12-03 12:37:49 -08:00
XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length);
*inOutIdx += length;
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
ssl->options.dhKeySz = length;
2015-12-03 12:37:49 -08:00
/* g */
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
}
2015-12-03 12:37:49 -08:00
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
}
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap,
DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_G.buffer) {
ssl->buffers.serverDH_G.length = length;
}
else {
return MEMORY_ERROR;
}
2015-12-03 12:37:49 -08:00
XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length);
*inOutIdx += length;
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
/* pub */
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
}
2015-12-03 12:37:49 -08:00
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
}
2011-02-05 11:14:47 -08:00
2016-01-18 20:48:12 -03:00
ssl->buffers.serverDH_Pub.buffer =
2015-12-03 12:37:49 -08:00
(byte*) XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_Pub.buffer) {
ssl->buffers.serverDH_Pub.length = length;
}
else {
return MEMORY_ERROR;
}
2016-01-18 20:48:12 -03:00
XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx,
2015-12-03 12:37:49 -08:00
length);
*inOutIdx += length;
break;
2011-02-05 11:14:47 -08:00
} /* dh_kea */
#endif /* NO_DH */
2011-02-05 11:14:47 -08:00
#ifdef HAVE_ECC
2015-12-03 12:37:49 -08:00
case ecc_diffie_hellman_kea:
2011-02-05 11:14:47 -08:00
{
2015-12-03 12:37:49 -08:00
byte b;
2016-01-18 20:48:12 -03:00
if ((*inOutIdx - begin) + ENUM_LEN + OPAQUE16_LEN +
2015-12-03 12:37:49 -08:00
OPAQUE8_LEN > size) {
return BUFFER_ERROR;
}
2015-12-03 12:37:49 -08:00
b = input[(*inOutIdx)++];
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
if (b != named_curve) {
return ECC_CURVETYPE_ERROR;
}
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
*inOutIdx += 1; /* curve type, eat leading 0 */
b = input[(*inOutIdx)++];
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
if (CheckCurveId(b) != 0) {
return ECC_CURVE_ERROR;
}
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
length = input[(*inOutIdx)++];
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
}
2011-02-05 11:14:47 -08:00
if (ssl->peerEccKey == NULL) {
2015-12-03 12:37:49 -08:00
/* alloc/init on demand */
ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key),
ssl->ctx->heap, DYNAMIC_TYPE_ECC);
if (ssl->peerEccKey == NULL) {
WOLFSSL_MSG("PeerEccKey Memory error");
return MEMORY_E;
}
wc_ecc_init(ssl->peerEccKey);
} else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */
wc_ecc_free(ssl->peerEccKey);
ssl->peerEccKeyPresent = 0;
wc_ecc_init(ssl->peerEccKey);
}
2016-01-18 20:48:12 -03:00
if (wc_ecc_import_x963(input + *inOutIdx, length,
2015-12-03 12:37:49 -08:00
ssl->peerEccKey) != 0) {
return ECC_PEERKEY_ERROR;
}
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
*inOutIdx += length;
ssl->peerEccKeyPresent = 1;
break;
2011-02-05 11:14:47 -08:00
}
#endif /* HAVE_ECC */
#if !defined(NO_DH) && !defined(NO_PSK)
2015-12-03 12:37:49 -08:00
case dhe_psk_kea:
{
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx,
2015-12-03 12:37:49 -08:00
min(length, MAX_PSK_ID_LEN));
ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0;
*inOutIdx += length;
/* p */
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
if (length < ssl->options.minDhKeySz) {
WOLFSSL_MSG("Server using a DH key that is too small");
SendAlert(ssl, alert_fatal, handshake_failure);
return DH_KEY_SIZE_E;
}
2016-01-18 20:48:12 -03:00
ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_P.buffer) {
ssl->buffers.serverDH_P.length = length;
2015-12-03 12:37:49 -08:00
}
else {
return MEMORY_ERROR;
2015-12-03 12:37:49 -08:00
}
XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length);
*inOutIdx += length;
ssl->options.dhKeySz = length;
/* g */
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap,
DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_G.buffer) {
ssl->buffers.serverDH_G.length = length;
2015-12-03 12:37:49 -08:00
}
else {
return MEMORY_ERROR;
2015-12-03 12:37:49 -08:00
}
XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length);
*inOutIdx += length;
/* pub */
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap,
DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_Pub.buffer) {
ssl->buffers.serverDH_Pub.length = length;
2015-12-03 12:37:49 -08:00
}
else {
return MEMORY_ERROR;
2015-12-03 12:37:49 -08:00
}
XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx, length);
*inOutIdx += length;
2015-12-03 12:37:49 -08:00
break;
}
#endif /* !NO_DH || !NO_PSK */
2015-12-03 12:37:49 -08:00
} /* switch() */
#if !defined(NO_DH) || defined(HAVE_ECC)
if (!ssl->options.usingAnon_cipher &&
(ssl->specs.kea == ecc_diffie_hellman_kea ||
ssl->specs.kea == diffie_hellman_kea))
2011-02-05 11:14:47 -08:00
{
#ifndef NO_OLD_TLS
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
Md5* md5 = NULL;
Sha* sha = NULL;
#else
Md5 md5[1];
Sha sha[1];
#endif
#endif
#ifndef NO_SHA256
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
Sha256* sha256 = NULL;
byte* hash256 = NULL;
#else
Sha256 sha256[1];
byte hash256[SHA256_DIGEST_SIZE];
#endif
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
#ifdef WOLFSSL_SMALL_STACK
Sha384* sha384 = NULL;
byte* hash384 = NULL;
#else
Sha384 sha384[1];
byte hash384[SHA384_DIGEST_SIZE];
#endif
#endif
#ifdef WOLFSSL_SHA512
#ifdef WOLFSSL_SMALL_STACK
Sha512* sha512 = NULL;
byte* hash512 = NULL;
#else
Sha512 sha512[1];
byte hash512[SHA512_DIGEST_SIZE];
#endif
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* hash = NULL;
byte* messageVerify = NULL;
#else
byte hash[FINISHED_SZ];
byte messageVerify[MAX_DH_SZ];
#endif
byte hashAlgo = sha_mac;
byte sigAlgo = ssl->specs.sig_algo;
word16 verifySz = (word16) (*inOutIdx - begin);
2011-02-05 11:14:47 -08:00
#ifndef NO_OLD_TLS
byte doMd5 = 0;
byte doSha = 0;
#endif
#ifndef NO_SHA256
byte doSha256 = 0;
#endif
#ifdef WOLFSSL_SHA384
byte doSha384 = 0;
#endif
#ifdef WOLFSSL_SHA512
byte doSha512 = 0;
#endif
2015-03-27 14:28:05 -07:00
(void)hash;
2015-03-27 19:20:31 -07:00
(void)sigAlgo;
(void)hashAlgo;
2015-03-27 14:28:05 -07:00
2011-02-05 11:14:47 -08:00
/* save message for hash verify */
2015-12-03 12:37:49 -08:00
if (verifySz > MAX_DH_SZ) {
ERROR_OUT(BUFFER_ERROR, done);
2015-12-03 12:37:49 -08:00
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
messageVerify = (byte*)XMALLOC(MAX_DH_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (messageVerify == NULL) {
ERROR_OUT(MEMORY_E, done);
2015-12-03 12:37:49 -08:00
}
#endif
XMEMCPY(messageVerify, input + begin, verifySz);
2011-02-05 11:14:47 -08:00
2011-02-28 12:21:06 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
byte setHash = 0;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size) {
ERROR_OUT(BUFFER_ERROR, done);
2015-12-03 12:37:49 -08:00
}
hashAlgo = input[(*inOutIdx)++];
sigAlgo = input[(*inOutIdx)++];
switch (hashAlgo) {
case sha512_mac:
#ifdef WOLFSSL_SHA512
doSha512 = 1;
setHash = 1;
#endif
break;
case sha384_mac:
#ifdef WOLFSSL_SHA384
doSha384 = 1;
setHash = 1;
#endif
break;
case sha256_mac:
#ifndef NO_SHA256
doSha256 = 1;
setHash = 1;
#endif
break;
case sha_mac:
#ifndef NO_OLD_TLS
doSha = 1;
setHash = 1;
#endif
break;
default:
ERROR_OUT(ALGO_ID_E, done);
}
if (setHash == 0) {
ERROR_OUT(ALGO_ID_E, done);
}
} else {
/* only using sha and md5 for rsa */
#ifndef NO_OLD_TLS
doSha = 1;
if (sigAlgo == rsa_sa_algo) {
doMd5 = 1;
}
#else
ERROR_OUT(ALGO_ID_E, done);
#endif
2011-02-28 12:21:06 -08:00
}
2011-02-05 11:14:47 -08:00
/* signature */
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
ERROR_OUT(BUFFER_ERROR, done);
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
ERROR_OUT(BUFFER_ERROR, done);
2015-12-03 12:37:49 -08:00
}
/* inOutIdx updated at the end of the function */
2011-02-05 11:14:47 -08:00
/* verify signature */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
hash = (byte*)XMALLOC(FINISHED_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (hash == NULL) {
ERROR_OUT(MEMORY_E, done);
2015-12-03 12:37:49 -08:00
}
#endif
#ifndef NO_OLD_TLS
2011-02-05 11:14:47 -08:00
/* md5 */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (doMd5) {
md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (md5 == NULL) {
ERROR_OUT(MEMORY_E, done);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doMd5) {
wc_InitMd5(md5);
wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN);
wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN);
wc_Md5Update(md5, messageVerify, verifySz);
wc_Md5Final(md5, hash);
}
2011-02-05 11:14:47 -08:00
/* sha */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (doSha) {
sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha == NULL) {
ERROR_OUT(MEMORY_E, done);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha) {
ret = wc_InitSha(sha);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
goto done;
}
wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN);
wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN);
wc_ShaUpdate(sha, messageVerify, verifySz);
wc_ShaFinal(sha, hash + MD5_DIGEST_SIZE);
}
#endif
#ifndef NO_SHA256
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (doSha256) {
sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha256 == NULL || hash256 == NULL) {
ERROR_OUT(MEMORY_E, done);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha256) {
if (!(ret = wc_InitSha256(sha256))
&& !(ret = wc_Sha256Update(sha256, ssl->arrays->clientRandom,
RAN_LEN))
&& !(ret = wc_Sha256Update(sha256, ssl->arrays->serverRandom,
RAN_LEN))
2015-12-03 12:37:49 -08:00
&& !(ret = wc_Sha256Update(sha256, messageVerify, verifySz))) {
ret = wc_Sha256Final(sha256, hash256);
2015-12-03 12:37:49 -08:00
}
if (ret != 0) {
goto done;
}
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
#ifdef WOLFSSL_SMALL_STACK
if (doSha384) {
sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha384 == NULL || hash384 == NULL) {
ERROR_OUT(MEMORY_E, done);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha384) {
if (!(ret = wc_InitSha384(sha384))
&& !(ret = wc_Sha384Update(sha384, ssl->arrays->clientRandom,
RAN_LEN))
&& !(ret = wc_Sha384Update(sha384, ssl->arrays->serverRandom,
RAN_LEN))
2015-12-03 12:37:49 -08:00
&& !(ret = wc_Sha384Update(sha384, messageVerify, verifySz))) {
ret = wc_Sha384Final(sha384, hash384);
2015-12-03 12:37:49 -08:00
}
if (ret != 0) {
goto done;
}
}
#endif
2013-02-18 14:36:50 -08:00
#ifdef WOLFSSL_SHA512
#ifdef WOLFSSL_SMALL_STACK
if (doSha512) {
sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha512 == NULL || hash512 == NULL) {
ERROR_OUT(MEMORY_E, done);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha512) {
if (!(ret = wc_InitSha512(sha512))
&& !(ret = wc_Sha512Update(sha512, ssl->arrays->clientRandom,
RAN_LEN))
&& !(ret = wc_Sha512Update(sha512, ssl->arrays->serverRandom,
RAN_LEN))
2015-12-03 12:37:49 -08:00
&& !(ret = wc_Sha512Update(sha512, messageVerify, verifySz))) {
ret = wc_Sha512Final(sha512, hash512);
2015-12-03 12:37:49 -08:00
}
if (ret != 0) {
goto done;
}
}
#endif
2015-12-03 12:37:49 -08:00
switch (sigAlgo)
{
#ifndef NO_RSA
2011-02-05 11:14:47 -08:00
/* rsa */
2015-12-03 12:37:49 -08:00
case rsa_sa_algo:
2011-02-05 11:14:47 -08:00
{
byte* out = NULL;
byte doUserRsa = 0;
word32 verifiedSz = 0;
#ifdef HAVE_PK_CALLBACKS
if (ssl->ctx->RsaVerifyCb)
doUserRsa = 1;
#endif /*HAVE_PK_CALLBACKS */
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
if (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent) {
ERROR_OUT(NO_PEER_KEY, done);
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
if (doUserRsa) {
#ifdef HAVE_PK_CALLBACKS
2014-10-24 10:33:24 -03:00
verifiedSz = ssl->ctx->RsaVerifyCb(ssl,
(byte *)input + *inOutIdx,
2014-10-24 10:33:24 -03:00
length, &out,
ssl->buffers.peerRsaKey.buffer,
ssl->buffers.peerRsaKey.length,
ssl->RsaVerifyCtx);
#endif /*HAVE_PK_CALLBACKS */
}
2015-12-03 12:37:49 -08:00
else {
verifiedSz = wc_RsaSSL_VerifyInline((byte *)input + *inOutIdx,
length, &out, ssl->peerRsaKey);
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
word32 encSigSz;
#ifndef NO_OLD_TLS
2013-02-18 14:36:50 -08:00
byte* digest = &hash[MD5_DIGEST_SIZE];
int typeH = SHAh;
int digestSz = SHA_DIGEST_SIZE;
#else
byte* digest = hash256;
int typeH = SHA256h;
int digestSz = SHA256_DIGEST_SIZE;
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* encodedSig = NULL;
#else
byte encodedSig[MAX_ENCODED_SIG_SZ];
#endif
2013-02-18 14:36:50 -08:00
if (hashAlgo == sha_mac) {
#ifndef NO_SHA
digest = &hash[MD5_DIGEST_SIZE];
typeH = SHAh;
digestSz = SHA_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha256_mac) {
2013-02-18 14:36:50 -08:00
#ifndef NO_SHA256
digest = hash256;
typeH = SHA256h;
digestSz = SHA256_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha384_mac) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
2013-02-18 14:36:50 -08:00
digest = hash384;
typeH = SHA384h;
digestSz = SHA384_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha512_mac) {
#ifdef WOLFSSL_SHA512
digest = hash512;
typeH = SHA512h;
digestSz = SHA512_DIGEST_SIZE;
#endif
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (encodedSig == NULL) {
ERROR_OUT(MEMORY_E, done);
2015-12-03 12:37:49 -08:00
}
#endif
2015-12-03 12:37:49 -08:00
if (digest == NULL) {
ERROR_OUT(ALGO_ID_E, done);
2015-12-03 12:37:49 -08:00
}
encSigSz = wc_EncodeSignature(encodedSig, digest, digestSz,
typeH);
if (encSigSz != verifiedSz || !out || XMEMCMP(out, encodedSig,
2015-12-03 12:37:49 -08:00
min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) {
ret = VERIFY_SIGN_ERROR;
2015-12-03 12:37:49 -08:00
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2015-12-03 12:37:49 -08:00
if (ret != 0) {
goto done;
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
}
else if (verifiedSz != FINISHED_SZ || !out || XMEMCMP(out,
2015-12-03 12:37:49 -08:00
hash, FINISHED_SZ) != 0) {
ERROR_OUT(VERIFY_SIGN_ERROR, done);
2015-12-03 12:37:49 -08:00
}
break;
}
#endif
2011-02-05 11:14:47 -08:00
#ifdef HAVE_ECC
/* ecdsa */
2016-01-18 20:48:12 -03:00
case ecc_dsa_sa_algo:
2015-12-03 12:37:49 -08:00
{
2014-03-25 16:01:17 -07:00
int verify = 0;
#ifndef NO_OLD_TLS
2013-02-18 14:36:50 -08:00
byte* digest = &hash[MD5_DIGEST_SIZE];
word32 digestSz = SHA_DIGEST_SIZE;
#else
byte* digest = hash256;
word32 digestSz = SHA256_DIGEST_SIZE;
#endif
byte doUserEcc = 0;
#ifdef HAVE_PK_CALLBACKS
2015-12-03 12:37:49 -08:00
if (ssl->ctx->EccVerifyCb) {
doUserEcc = 1;
2015-12-03 12:37:49 -08:00
}
#endif
if (!ssl->peerEccDsaKeyPresent)
ERROR_OUT(NO_PEER_KEY, done);
2011-02-05 11:14:47 -08:00
2013-02-18 14:36:50 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
if (hashAlgo == sha_mac) {
#ifndef NO_SHA
digest = &hash[MD5_DIGEST_SIZE];
digestSz = SHA_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha256_mac) {
2013-02-18 14:36:50 -08:00
#ifndef NO_SHA256
digest = hash256;
digestSz = SHA256_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha384_mac) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
2013-02-18 14:36:50 -08:00
digest = hash384;
digestSz = SHA384_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha512_mac) {
#ifdef WOLFSSL_SHA512
digest = hash512;
digestSz = SHA512_DIGEST_SIZE;
#endif
}
2013-02-18 14:36:50 -08:00
}
if (doUserEcc) {
#ifdef HAVE_PK_CALLBACKS
ret = ssl->ctx->EccVerifyCb(ssl, input + *inOutIdx, length,
digest, digestSz,
ssl->buffers.peerEccDsaKey.buffer,
ssl->buffers.peerEccDsaKey.length,
&verify, ssl->EccVerifyCtx);
#endif
}
else {
2014-12-30 15:14:27 -07:00
ret = wc_ecc_verify_hash(input + *inOutIdx, length,
digest, digestSz, &verify, ssl->peerEccDsaKey);
}
2015-12-03 12:37:49 -08:00
if (ret != 0 || verify == 0) {
ERROR_OUT(VERIFY_SIGN_ERROR, done);
2015-12-03 12:37:49 -08:00
}
break;
2011-02-05 11:14:47 -08:00
}
#endif /* HAVE_ECC */
2015-12-03 12:37:49 -08:00
default:
ERROR_OUT(ALGO_ID_E, done);
2015-12-03 12:37:49 -08:00
} /* switch (sigAlgo) */
2011-02-05 11:14:47 -08:00
/* signature length */
*inOutIdx += length;
2011-02-05 11:14:47 -08:00
ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
done:
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
#ifndef NO_OLD_TLS
XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifndef NO_SHA256
XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef WOLFSSL_SHA512
XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2015-12-03 12:37:49 -08:00
if (ret != 0) {
return ret;
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
}
2014-09-26 10:27:14 -07:00
if (IsEncryptionOn(ssl, 0)) {
2014-09-26 10:27:14 -07:00
*inOutIdx += ssl->keys.padSz;
}
2015-07-07 09:55:58 -06:00
/* QSH extensions */
#ifdef HAVE_QSH
if (ssl->peerQSHKeyPresent) {
/* extension name */
ato16(input + *inOutIdx, &name);
*inOutIdx += OPAQUE16_LEN;
2015-11-02 15:51:01 -03:00
if (name == TLSX_QUANTUM_SAFE_HYBRID) {
2015-09-15 17:46:45 -06:00
/* if qshSz is larger than 0 it is the length of buffer used */
if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx,
2015-12-03 12:37:49 -08:00
size, 0)) < 0) {
2015-09-15 17:46:45 -06:00
return qshSz;
2015-12-03 12:37:49 -08:00
}
2015-09-15 17:46:45 -06:00
*inOutIdx += qshSz;
2015-07-07 09:55:58 -06:00
}
else {
/* unknown extension sent server ignored
handshake */
return BUFFER_ERROR;
}
}
#endif
return 0;
#else /* !NO_DH or HAVE_ECC */
return NOT_COMPILED_IN; /* not supported by build */
#endif /* !NO_DH or HAVE_ECC */
#undef ERROR_OUT
2011-02-05 11:14:47 -08:00
}
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
#ifdef HAVE_NTRU
/* Encrypt a byte array using ntru
key a struct containing the public key to use
bufIn array to be encrypted
inSz size of bufIn array
bufOut cipher text out
outSz will be set to the new size of cipher text
*/
static int NtruSecretEncrypt(QSHKey* key, byte* bufIn, word32 inSz,
byte* bufOut, word16* outSz)
{
int ret;
DRBG_HANDLE drbg;
/* sanity checks on input arguments */
if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
return BAD_FUNC_ARG;
if (key->pub.buffer == NULL)
return BAD_FUNC_ARG;
switch (key->name) {
case WOLFSSL_NTRU_EESS439:
case WOLFSSL_NTRU_EESS593:
case WOLFSSL_NTRU_EESS743:
break;
default:
WOLFSSL_MSG("Unknown QSH encryption key!");
return -1;
}
/* set up ntru drbg */
ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
2015-07-07 09:55:58 -06:00
if (ret != DRBG_OK)
return NTRU_DRBG_ERROR;
/* encrypt the byte array */
ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length, key->pub.buffer,
inSz, bufIn, outSz, bufOut);
ntru_crypto_drbg_uninstantiate(drbg);
if (ret != NTRU_OK)
return NTRU_ENCRYPT_ERROR;
return ret;
}
/* Decrypt a byte array using ntru
key a struct containing the private key to use
bufIn array to be decrypted
inSz size of bufIn array
bufOut plain text out
outSz will be set to the new size of plain text
*/
static int NtruSecretDecrypt(QSHKey* key, byte* bufIn, word32 inSz,
byte* bufOut, word16* outSz)
{
int ret;
DRBG_HANDLE drbg;
/* sanity checks on input arguments */
if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
return BAD_FUNC_ARG;
if (key->pri.buffer == NULL)
return BAD_FUNC_ARG;
switch (key->name) {
case WOLFSSL_NTRU_EESS439:
case WOLFSSL_NTRU_EESS593:
case WOLFSSL_NTRU_EESS743:
break;
default:
WOLFSSL_MSG("Unknown QSH decryption key!");
return -1;
}
/* set up drbg */
ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
2015-07-07 09:55:58 -06:00
if (ret != DRBG_OK)
return NTRU_DRBG_ERROR;
/* decrypt cipher text */
ret = ntru_crypto_ntru_decrypt(key->pri.length, key->pri.buffer,
inSz, bufIn, outSz, bufOut);
ntru_crypto_drbg_uninstantiate(drbg);
if (ret != NTRU_OK)
return NTRU_ENCRYPT_ERROR;
return ret;
}
#endif /* HAVE_NTRU */
int QSH_Init(WOLFSSL* ssl)
{
/* check so not initialising twice when running DTLS */
if (ssl->QSH_secret != NULL)
return 0;
/* malloc memory for holding generated secret information */
2015-12-01 09:24:44 -07:00
if ((ssl->QSH_secret = (QSHSecret*)XMALLOC(sizeof(QSHSecret), NULL,
DYNAMIC_TYPE_TMP_BUFFER)) == NULL)
2015-07-07 09:55:58 -06:00
return MEMORY_E;
ssl->QSH_secret->CliSi = (buffer*)XMALLOC(sizeof(buffer), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (ssl->QSH_secret->CliSi == NULL)
return MEMORY_E;
ssl->QSH_secret->SerSi = (buffer*)XMALLOC(sizeof(buffer), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (ssl->QSH_secret->SerSi == NULL)
return MEMORY_E;
/* initialize variables */
ssl->QSH_secret->list = NULL;
ssl->QSH_secret->CliSi->length = 0;
ssl->QSH_secret->CliSi->buffer = NULL;
ssl->QSH_secret->SerSi->length = 0;
ssl->QSH_secret->SerSi->buffer = NULL;
return 0;
}
static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn,
byte* out, word32* szOut)
{
int ret = 0;
word16 size = *szOut;
WOLFSSL_MSG("Encrypting QSH key material");
switch (key->name) {
#ifdef HAVE_NTRU
case WOLFSSL_NTRU_EESS439:
case WOLFSSL_NTRU_EESS593:
case WOLFSSL_NTRU_EESS743:
ret = NtruSecretEncrypt(key, in, szIn, out, &size);
break;
#endif
default:
WOLFSSL_MSG("Unknown QSH encryption key!");
return -1;
}
*szOut = size;
return ret;
}
/* Decrypt using Quantum Safe Handshake algorithms */
int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn,
byte* out, word16* szOut)
{
int ret = 0;
word16 size = *szOut;
WOLFSSL_MSG("Decrypting QSH key material");
switch (key->name) {
#ifdef HAVE_NTRU
case WOLFSSL_NTRU_EESS439:
case WOLFSSL_NTRU_EESS593:
case WOLFSSL_NTRU_EESS743:
ret = NtruSecretDecrypt(key, in, szIn, out, &size);
break;
#endif
default:
WOLFSSL_MSG("Unknown QSH decryption key!");
return -1;
}
*szOut = size;
return ret;
}
/* Get the max cipher text for corresponding encryption scheme
(encrypting 48 or max plain text whichever is smaller)
*/
static word32 QSH_MaxSecret(QSHKey* key)
{
byte isNtru = 0;
word16 inSz = 48;
word16 outSz;
DRBG_HANDLE drbg = 0;
byte bufIn[48];
int ret = 0;
if (key == NULL || key->pub.length == 0)
return 0;
switch(key->name) {
#ifdef HAVE_NTRU
case WOLFSSL_NTRU_EESS439:
isNtru = 1;
break;
case WOLFSSL_NTRU_EESS593:
isNtru = 1;
break;
case WOLFSSL_NTRU_EESS743:
isNtru = 1;
break;
#endif
default:
WOLFSSL_MSG("Unknown QSH encryption scheme size!");
return 0;
}
if (isNtru) {
ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
2015-07-07 09:55:58 -06:00
if (ret != DRBG_OK)
return NTRU_DRBG_ERROR;
ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length,
key->pub.buffer, inSz, bufIn, &outSz, NULL);
if (ret != NTRU_OK) {
return NTRU_ENCRYPT_ERROR;
}
ntru_crypto_drbg_uninstantiate(drbg);
return outSz;
}
return 0;
}
/* Generate the secret byte material for pms
returns length on success and -1 on fail
*/
static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer)
{
int sz = 0;
int plainSz = 48; /* lesser of 48 and max plain text able to encrypt */
int offset = 0;
word32 tmpSz = 0;
buffer* buf;
QSHKey* current = ssl->peerQSHKey;
QSHScheme* schmPre = NULL;
QSHScheme* schm = NULL;
if (ssl == NULL)
return -1;
WOLFSSL_MSG("Generating QSH secret key material");
/* get size of buffer needed */
while (current) {
if (current->pub.length != 0) {
sz += plainSz;
}
current = (QSHKey*)current->next;
}
/* allocate memory for buffer */
if (isServer) {
buf = ssl->QSH_secret->SerSi;
}
else {
buf = ssl->QSH_secret->CliSi;
}
buf->length = sz;
2015-12-01 09:24:44 -07:00
buf->buffer = (byte*)XMALLOC(sz, buf->buffer, DYNAMIC_TYPE_TMP_BUFFER);
2015-07-07 09:55:58 -06:00
if (buf->buffer == NULL) {
WOLFSSL_ERROR(MEMORY_E);
}
/* create secret information */
sz = 0;
current = ssl->peerQSHKey;
while (current) {
2015-12-01 09:24:44 -07:00
schm = (QSHScheme*)XMALLOC(sizeof(QSHScheme), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-07-07 09:55:58 -06:00
if (schm == NULL)
return MEMORY_E;
/* initialize variables */
schm->name = 0;
schm->PK = NULL;
schm->PKLen = 0;
schm->next = NULL;
if (ssl->QSH_secret->list == NULL) {
ssl->QSH_secret->list = schm;
}
else {
if (schmPre)
schmPre->next = schm;
}
tmpSz = QSH_MaxSecret(current);
2015-12-01 09:24:44 -07:00
if ((schm->PK = (byte*)XMALLOC(tmpSz, 0,
DYNAMIC_TYPE_TMP_BUFFER)) == NULL)
2015-07-07 09:55:58 -06:00
return -1;
/* store info for writing extension */
schm->name = current->name;
/* no key to use for encryption */
if (tmpSz == 0) {
current = (QSHKey*)current->next;
continue;
}
if (wc_RNG_GenerateBlock(ssl->rng, buf->buffer + offset, plainSz)
!= 0) {
return -1;
}
if (QSH_Encrypt(current, buf->buffer + offset, plainSz, schm->PK,
&tmpSz) != 0) {
return -1;
}
schm->PKLen = tmpSz;
sz += tmpSz;
offset += plainSz;
schmPre = schm;
current = (QSHKey*)current->next;
}
return sz;
}
static word32 QSH_KeyGetSize(WOLFSSL* ssl)
{
word32 sz = 0;
QSHKey* current = ssl->peerQSHKey;
if (ssl == NULL)
return -1;
sz += OPAQUE16_LEN; /* type of extension ie 0x00 0x18 */
sz += OPAQUE24_LEN;
/* get size of buffer needed */
while (current) {
sz += OPAQUE16_LEN; /* scheme id */
sz += OPAQUE16_LEN; /* encrypted key len*/
sz += QSH_MaxSecret(current);
current = (QSHKey*)current->next;
}
return sz;
}
/* handle QSH key Exchange
return 0 on success
*/
static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer)
{
int ret = 0;
WOLFSSL_ENTER("QSH KeyExchange");
ret = QSH_GenerateSerCliSecret(ssl, isServer);
if (ret < 0)
return MEMORY_E;
return 0;
}
#endif /* HAVE_QSH */
2014-12-19 11:27:01 -07:00
int SendClientKeyExchange(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* encSecret = NULL;
#else
byte encSecret[MAX_ENCRYPT_SZ];
#endif
2011-02-05 11:14:47 -08:00
word32 encSz = 0;
word32 idx = 0;
int ret = 0;
byte doUserRsa = 0;
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
word32 qshSz = 0;
if (ssl->peerQSHKeyPresent) {
qshSz = QSH_KeyGetSize(ssl);
}
#endif
(void)doUserRsa;
#ifdef HAVE_PK_CALLBACKS
#ifndef NO_RSA
if (ssl->ctx->RsaEncCb)
doUserRsa = 1;
#endif /* NO_RSA */
#endif /*HAVE_PK_CALLBACKS */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (encSecret == NULL)
return MEMORY_E;
#endif
2011-02-05 11:14:47 -08:00
2012-10-29 15:39:42 -07:00
switch (ssl->specs.kea) {
#ifndef NO_RSA
case rsa_kea:
2015-01-01 07:33:07 -07:00
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret,
SECRET_LEN);
if (ret != 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
2012-10-29 15:39:42 -07:00
ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
ssl->arrays->preMasterSz = SECRET_LEN;
2011-02-05 11:14:47 -08:00
if (ssl->peerRsaKey == NULL || ssl->peerRsaKeyPresent == 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2012-10-29 15:39:42 -07:00
return NO_PEER_KEY;
}
2011-02-05 11:14:47 -08:00
if (doUserRsa) {
#ifdef HAVE_PK_CALLBACKS
#ifndef NO_RSA
encSz = MAX_ENCRYPT_SZ;
ret = ssl->ctx->RsaEncCb(ssl,
ssl->arrays->preMasterSecret,
SECRET_LEN,
encSecret, &encSz,
ssl->buffers.peerRsaKey.buffer,
ssl->buffers.peerRsaKey.length,
ssl->RsaEncCtx);
#endif /* NO_RSA */
#endif /*HAVE_PK_CALLBACKS */
}
else {
ret = wc_RsaPublicEncrypt(ssl->arrays->preMasterSecret,
SECRET_LEN, encSecret, MAX_ENCRYPT_SZ,
ssl->peerRsaKey, ssl->rng);
if (ret > 0) {
encSz = ret;
ret = 0; /* set success to 0 */
}
2012-10-29 15:39:42 -07:00
}
break;
#endif
#ifndef NO_DH
2012-10-29 15:39:42 -07:00
case diffie_hellman_kea:
{
buffer serverP = ssl->buffers.serverDH_P;
buffer serverG = ssl->buffers.serverDH_G;
buffer serverPub = ssl->buffers.serverDH_Pub;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* priv = NULL;
#else
2012-10-29 15:39:42 -07:00
byte priv[ENCRYPT_LEN];
#endif
2012-10-29 15:39:42 -07:00
word32 privSz = 0;
DhKey key;
if (serverP.buffer == 0 || serverG.buffer == 0 ||
serverPub.buffer == 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2012-10-29 15:39:42 -07:00
return NO_PEER_KEY;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (priv == NULL) {
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
2012-10-29 15:39:42 -07:00
2014-12-30 14:13:57 -07:00
wc_InitDhKey(&key);
ret = wc_DhSetKey(&key, serverP.buffer, serverP.length,
2012-10-29 15:39:42 -07:00
serverG.buffer, serverG.length);
if (ret == 0)
/* for DH, encSecret is Yc, agree is pre-master */
2014-12-30 14:13:57 -07:00
ret = wc_DhGenerateKeyPair(&key, ssl->rng, priv, &privSz,
2012-10-29 15:39:42 -07:00
encSecret, &encSz);
if (ret == 0)
2014-12-30 14:13:57 -07:00
ret = wc_DhAgree(&key, ssl->arrays->preMasterSecret,
2012-10-29 15:39:42 -07:00
&ssl->arrays->preMasterSz, priv, privSz,
serverPub.buffer, serverPub.length);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2014-12-30 14:13:57 -07:00
wc_FreeDhKey(&key);
2012-10-29 15:39:42 -07:00
}
break;
#endif /* NO_DH */
2011-02-05 11:14:47 -08:00
#ifndef NO_PSK
2012-10-29 15:39:42 -07:00
case psk_kea:
{
byte* pms = ssl->arrays->preMasterSecret;
ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
ssl->arrays->server_hint, ssl->arrays->client_identity,
MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
2014-10-24 10:33:24 -03:00
if (ssl->arrays->psk_keySz == 0 ||
ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2012-10-29 15:39:42 -07:00
return PSK_KEY_ERROR;
}
2012-10-29 15:39:42 -07:00
encSz = (word32)XSTRLEN(ssl->arrays->client_identity);
if (encSz > MAX_PSK_ID_LEN) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return CLIENT_ID_ERROR;
}
2012-10-29 15:39:42 -07:00
XMEMCPY(encSecret, ssl->arrays->client_identity, encSz);
/* make psk pre master secret */
/* length of key + length 0s + length of key + key */
c16toa((word16)ssl->arrays->psk_keySz, pms);
pms += 2;
XMEMSET(pms, 0, ssl->arrays->psk_keySz);
pms += ssl->arrays->psk_keySz;
c16toa((word16)ssl->arrays->psk_keySz, pms);
pms += 2;
XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4;
2015-02-20 15:51:21 -08:00
ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
2013-03-20 09:12:00 -07:00
ssl->arrays->psk_keySz = 0; /* No further need */
2012-10-29 15:39:42 -07:00
}
break;
2011-02-05 11:14:47 -08:00
#endif /* NO_PSK */
#if !defined(NO_DH) && !defined(NO_PSK)
case dhe_psk_kea:
{
byte* pms = ssl->arrays->preMasterSecret;
byte* es = encSecret;
buffer serverP = ssl->buffers.serverDH_P;
buffer serverG = ssl->buffers.serverDH_G;
buffer serverPub = ssl->buffers.serverDH_Pub;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* priv = NULL;
#else
byte priv[ENCRYPT_LEN];
#endif
word32 privSz = 0;
word32 pubSz = 0;
word32 esSz = 0;
DhKey key;
if (serverP.buffer == 0 || serverG.buffer == 0 ||
serverPub.buffer == 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return NO_PEER_KEY;
}
ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
ssl->arrays->server_hint, ssl->arrays->client_identity,
MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
if (ssl->arrays->psk_keySz == 0 ||
ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return PSK_KEY_ERROR;
}
esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
if (esSz > MAX_PSK_ID_LEN) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return CLIENT_ID_ERROR;
}
2014-10-24 10:33:24 -03:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (priv == NULL) {
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
2014-06-03 23:11:18 -07:00
c16toa((word16)esSz, es);
es += OPAQUE16_LEN;
XMEMCPY(es, ssl->arrays->client_identity, esSz);
es += esSz;
encSz = esSz + OPAQUE16_LEN;
2014-12-30 14:13:57 -07:00
wc_InitDhKey(&key);
ret = wc_DhSetKey(&key, serverP.buffer, serverP.length,
serverG.buffer, serverG.length);
if (ret == 0)
/* for DH, encSecret is Yc, agree is pre-master */
2014-12-30 14:13:57 -07:00
ret = wc_DhGenerateKeyPair(&key, ssl->rng, priv, &privSz,
es + OPAQUE16_LEN, &pubSz);
if (ret == 0)
2014-12-30 14:13:57 -07:00
ret = wc_DhAgree(&key, pms + OPAQUE16_LEN,
&ssl->arrays->preMasterSz, priv, privSz,
serverPub.buffer, serverPub.length);
2014-12-30 14:13:57 -07:00
wc_FreeDhKey(&key);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
if (ret != 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
c16toa((word16)pubSz, es);
encSz += pubSz + OPAQUE16_LEN;
c16toa((word16)ssl->arrays->preMasterSz, pms);
ssl->arrays->preMasterSz += OPAQUE16_LEN;
pms += ssl->arrays->preMasterSz;
/* make psk pre master secret */
/* length of key + length 0s + length of key + key */
c16toa((word16)ssl->arrays->psk_keySz, pms);
pms += OPAQUE16_LEN;
XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
ssl->arrays->preMasterSz +=
ssl->arrays->psk_keySz + OPAQUE16_LEN;
2015-02-20 15:51:21 -08:00
ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
ssl->arrays->psk_keySz = 0; /* No further need */
}
break;
#endif /* !NO_DH && !NO_PSK */
2015-07-11 12:52:22 -06:00
#ifdef HAVE_NTRU
case ntru_kea:
{
word32 rc;
word16 cipherLen = MAX_ENCRYPT_SZ;
DRBG_HANDLE drbg;
ret = wc_RNG_GenerateBlock(ssl->rng,
ssl->arrays->preMasterSecret, SECRET_LEN);
if (ret != 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
ssl->arrays->preMasterSz = SECRET_LEN;
if (ssl->peerNtruKeyPresent == 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return NO_PEER_KEY;
}
rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
2015-07-11 12:52:22 -06:00
if (rc != DRBG_OK) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return NTRU_DRBG_ERROR;
}
rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen,
ssl->peerNtruKey,
ssl->arrays->preMasterSz,
ssl->arrays->preMasterSecret,
&cipherLen, encSecret);
ntru_crypto_drbg_uninstantiate(drbg);
if (rc != NTRU_OK) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return NTRU_ENCRYPT_ERROR;
}
encSz = cipherLen;
ret = 0;
}
break;
#endif /* HAVE_NTRU */
2011-02-05 11:14:47 -08:00
#ifdef HAVE_ECC
2012-10-29 15:39:42 -07:00
case ecc_diffie_hellman_kea:
{
ecc_key myKey;
2013-12-11 12:03:09 -08:00
ecc_key* peerKey = NULL;
word32 size = MAX_ENCRYPT_SZ;
2012-10-29 15:39:42 -07:00
if (ssl->specs.static_ecdh) {
/* TODO: EccDsa is really fixed Ecc change naming */
if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
!ssl->peerEccDsaKey->dp) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2012-10-29 15:39:42 -07:00
return NO_PEER_KEY;
}
peerKey = ssl->peerEccDsaKey;
2012-10-29 15:39:42 -07:00
}
else {
if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
!ssl->peerEccKey->dp) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2012-10-29 15:39:42 -07:00
return NO_PEER_KEY;
}
peerKey = ssl->peerEccKey;
2012-10-29 15:39:42 -07:00
}
2011-02-05 11:14:47 -08:00
if (peerKey == NULL) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2013-12-11 12:03:09 -08:00
return NO_PEER_KEY;
}
2013-12-11 12:03:09 -08:00
2014-12-30 15:14:27 -07:00
wc_ecc_init(&myKey);
ret = wc_ecc_make_key(ssl->rng, peerKey->dp->size, &myKey);
if (ret != 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2012-10-29 15:39:42 -07:00
return ECC_MAKEKEY_ERROR;
}
2011-02-05 11:14:47 -08:00
2012-10-29 15:39:42 -07:00
/* precede export with 1 byte length */
2014-12-30 15:14:27 -07:00
ret = wc_ecc_export_x963(&myKey, encSecret + 1, &size);
2012-10-29 15:39:42 -07:00
encSecret[0] = (byte)size;
encSz = size + 1;
2011-02-05 11:14:47 -08:00
2012-10-29 15:39:42 -07:00
if (ret != 0)
ret = ECC_EXPORT_ERROR;
else {
size = sizeof(ssl->arrays->preMasterSecret);
2014-12-30 15:14:27 -07:00
ret = wc_ecc_shared_secret(&myKey, peerKey,
2012-10-29 15:39:42 -07:00
ssl->arrays->preMasterSecret, &size);
if (ret != 0)
ret = ECC_SHARED_ERROR;
}
2011-02-05 11:14:47 -08:00
2012-10-29 15:39:42 -07:00
ssl->arrays->preMasterSz = size;
2014-12-30 15:14:27 -07:00
wc_ecc_free(&myKey);
2012-10-29 15:39:42 -07:00
}
break;
2011-02-05 11:14:47 -08:00
#endif /* HAVE_ECC */
2012-10-29 15:39:42 -07:00
default:
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2012-10-29 15:39:42 -07:00
return ALGO_ID_E; /* unsupported kea */
}
2011-02-05 11:14:47 -08:00
if (ret == 0) {
byte *output;
int sendSz;
word32 tlsSz = 0;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea)
tlsSz = 2;
if (ssl->specs.kea == ecc_diffie_hellman_kea ||
ssl->specs.kea == dhe_psk_kea) /* always off */
2011-02-05 11:14:47 -08:00
tlsSz = 0;
sendSz = encSz + tlsSz + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls) {
sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
}
#endif
if (IsEncryptionOn(ssl, 1))
sendSz += MAX_MSG_EXTRA;
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
encSz += qshSz;
sendSz += qshSz;
#endif
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2011-02-05 11:14:47 -08:00
return ret;
}
2011-02-05 11:14:47 -08:00
/* get ouput buffer */
2014-10-24 10:33:24 -03:00
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
if (ssl->peerQSHKeyPresent) {
byte idxSave = idx;
idx = sendSz - qshSz;
if (QSH_KeyExchangeWrite(ssl, 0) != 0)
return MEMORY_E;
/* extension type */
2015-11-02 15:51:01 -03:00
c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx);
2015-07-07 09:55:58 -06:00
idx += OPAQUE16_LEN;
/* write to output and check amount written */
if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx)
> qshSz - OPAQUE16_LEN)
return MEMORY_E;
idx = idxSave;
}
#endif
2011-02-05 11:14:47 -08:00
AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl);
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
if (ssl->peerQSHKeyPresent) {
encSz -= qshSz;
}
#endif
2011-02-05 11:14:47 -08:00
if (tlsSz) {
c16toa((word16)encSz, &output[idx]);
idx += 2;
}
XMEMCPY(output + idx, encSecret, encSz);
idx += encSz;
if (IsEncryptionOn(ssl, 1)) {
byte* input;
int inputSz = idx-RECORD_HEADER_SZ; /* buildmsg adds rechdr */
input = (byte*)XMALLOC(inputSz, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (input == NULL) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return MEMORY_E;
}
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
handshake, 1);
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (sendSz < 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return sendSz;
}
} else {
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
2012-09-14 09:35:34 -07:00
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn)
AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo,
output, sendSz, ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
if (ssl->options.groupMessages)
ret = 0;
else
ret = SendBuffered(ssl);
2011-02-05 11:14:47 -08:00
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2011-02-05 11:14:47 -08:00
if (ret == 0 || ret == WANT_WRITE) {
int tmpRet = MakeMasterSecret(ssl);
if (tmpRet != 0)
ret = tmpRet; /* save WANT_WRITE unless more serious */
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
}
2013-03-20 09:12:00 -07:00
/* No further need for PMS */
2015-02-20 15:51:21 -08:00
ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
2013-03-20 09:12:00 -07:00
ssl->arrays->preMasterSz = 0;
2011-02-05 11:14:47 -08:00
return ret;
}
#ifndef NO_CERTS
2014-12-19 11:27:01 -07:00
int SendCertificateVerify(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
byte *output;
2014-09-29 13:38:56 -07:00
int sendSz = MAX_CERT_VERIFY_SZ, length, ret;
2011-02-05 11:14:47 -08:00
word32 idx = 0;
2012-05-02 10:30:15 -07:00
word32 sigOutSz = 0;
#ifndef NO_RSA
2011-02-05 11:14:47 -08:00
RsaKey key;
2014-04-01 13:08:48 -07:00
int initRsaKey = 0;
#endif
2012-05-02 10:30:15 -07:00
int usingEcc = 0;
#ifdef HAVE_ECC
ecc_key eccKey;
#endif
2011-02-05 11:14:47 -08:00
(void)idx;
2011-02-05 11:14:47 -08:00
if (ssl->options.sendVerify == SEND_BLANK_CERT)
return 0; /* sent blank cert, can't verify */
if (IsEncryptionOn(ssl, 1))
2014-09-29 13:38:56 -07:00
sendSz += MAX_MSG_EXTRA;
/* check for available size */
2014-09-29 13:38:56 -07:00
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
2011-02-05 11:14:47 -08:00
return ret;
/* get ouput buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
if (ret != 0)
return ret;
2011-02-05 11:14:47 -08:00
2012-05-02 10:30:15 -07:00
#ifdef HAVE_ECC
2014-12-30 15:14:27 -07:00
wc_ecc_init(&eccKey);
2012-05-02 10:30:15 -07:00
#endif
#ifndef NO_RSA
ret = wc_InitRsaKey(&key, ssl->heap);
2014-04-01 13:08:48 -07:00
if (ret == 0) initRsaKey = 1;
if (ret == 0)
ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
2014-04-01 13:08:48 -07:00
ssl->buffers.key.length);
2012-05-02 10:30:15 -07:00
if (ret == 0)
sigOutSz = wc_RsaEncryptSize(&key);
2014-10-24 10:33:24 -03:00
else
#endif
{
2012-05-02 10:30:15 -07:00
#ifdef HAVE_ECC
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Trying ECC client cert, RSA didn't work");
2014-10-24 10:33:24 -03:00
idx = 0;
2014-12-30 15:14:27 -07:00
ret = wc_EccPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &eccKey,
2012-05-02 10:30:15 -07:00
ssl->buffers.key.length);
if (ret == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Using ECC client cert");
2012-05-02 10:30:15 -07:00
usingEcc = 1;
2014-10-24 10:33:24 -03:00
sigOutSz = MAX_ENCODED_SIG_SZ;
2012-05-02 10:30:15 -07:00
}
else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Bad client cert type");
2012-05-02 10:30:15 -07:00
}
#endif
}
2011-02-05 11:14:47 -08:00
if (ret == 0) {
byte* verify = (byte*)&output[RECORD_HEADER_SZ +
HANDSHAKE_HEADER_SZ];
#ifndef NO_OLD_TLS
byte* signBuffer = ssl->hsHashes->certHashes.md5;
#else
byte* signBuffer = NULL;
#endif
2013-02-18 14:36:50 -08:00
word32 signSz = FINISHED_SZ;
2011-02-28 12:21:06 -08:00
word32 extraSz = 0; /* tls 1.2 hash/sig */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* encodedSig = NULL;
#else
byte encodedSig[MAX_ENCODED_SIG_SZ];
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (encodedSig == NULL) {
#ifndef NO_RSA
if (initRsaKey)
wc_FreeRsaKey(&key);
#endif
#ifdef HAVE_ECC
2014-12-30 15:14:27 -07:00
wc_ecc_free(&eccKey);
#endif
return MEMORY_E;
}
#endif
2011-02-05 11:14:47 -08:00
(void)encodedSig;
(void)signSz;
(void)signBuffer;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls)
verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
#endif
2012-05-02 10:30:15 -07:00
length = sigOutSz;
2011-02-28 12:21:06 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
2013-02-18 14:36:50 -08:00
verify[0] = ssl->suites->hashAlgo;
2012-05-02 10:30:15 -07:00
verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo;
2011-02-28 12:21:06 -08:00
extraSz = HASH_SIG_SIZE;
}
2011-02-05 11:14:47 -08:00
2012-05-02 10:30:15 -07:00
if (usingEcc) {
#ifdef HAVE_ECC
word32 localSz = MAX_ENCODED_SIG_SZ;
word32 digestSz;
byte* digest;
byte doUserEcc = 0;
#ifndef NO_OLD_TLS
/* old tls default */
digestSz = SHA_DIGEST_SIZE;
digest = ssl->hsHashes->certHashes.sha;
#else
/* new tls default */
digestSz = SHA256_DIGEST_SIZE;
digest = ssl->hsHashes->certHashes.sha256;
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
if (ssl->ctx->EccSignCb)
doUserEcc = 1;
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
2013-02-18 14:36:50 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
if (ssl->suites->hashAlgo == sha_mac) {
#ifndef NO_SHA
digest = ssl->hsHashes->certHashes.sha;
digestSz = SHA_DIGEST_SIZE;
#endif
}
else if (ssl->suites->hashAlgo == sha256_mac) {
2013-02-18 14:36:50 -08:00
#ifndef NO_SHA256
digest = ssl->hsHashes->certHashes.sha256;
2013-02-18 14:36:50 -08:00
digestSz = SHA256_DIGEST_SIZE;
#endif
}
else if (ssl->suites->hashAlgo == sha384_mac) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
digest = ssl->hsHashes->certHashes.sha384;
2013-02-18 14:36:50 -08:00
digestSz = SHA384_DIGEST_SIZE;
#endif
}
else if (ssl->suites->hashAlgo == sha512_mac) {
#ifdef WOLFSSL_SHA512
digest = ssl->hsHashes->certHashes.sha512;
digestSz = SHA512_DIGEST_SIZE;
#endif
}
2013-02-18 14:36:50 -08:00
}
if (doUserEcc) {
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ret = ssl->ctx->EccSignCb(ssl, digest, digestSz,
encodedSig, &localSz,
ssl->buffers.key.buffer,
ssl->buffers.key.length,
ssl->EccSignCtx);
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
}
else {
2014-12-30 15:14:27 -07:00
ret = wc_ecc_sign_hash(digest, digestSz, encodedSig,
&localSz, ssl->rng, &eccKey);
}
if (ret == 0) {
length = localSz;
c16toa((word16)length, verify + extraSz); /* prepend hdr */
XMEMCPY(verify + extraSz + VERIFY_HEADER,encodedSig,length);
}
2012-05-02 10:30:15 -07:00
#endif
2011-02-05 11:14:47 -08:00
}
#ifndef NO_RSA
2012-05-02 10:30:15 -07:00
else {
byte doUserRsa = 0;
#ifdef HAVE_PK_CALLBACKS
if (ssl->ctx->RsaSignCb)
doUserRsa = 1;
#endif /*HAVE_PK_CALLBACKS */
2012-05-02 10:30:15 -07:00
if (IsAtLeastTLSv1_2(ssl)) {
2015-03-18 10:42:10 -06:00
/*
2015-03-18 14:27:07 -07:00
* MSVC Compiler complains because it can not
2015-03-18 10:42:10 -06:00
* guarantee any of the conditionals will succeed in
* assigning a value before wc_EncodeSignature executes.
*/
2015-03-18 14:27:07 -07:00
byte* digest = NULL;
2015-03-18 10:42:10 -06:00
int digestSz = 0;
int typeH = 0;
int didSet = 0;
2013-02-18 14:36:50 -08:00
if (ssl->suites->hashAlgo == sha_mac) {
#ifndef NO_SHA
digest = ssl->hsHashes->certHashes.sha;
typeH = SHAh;
digestSz = SHA_DIGEST_SIZE;
2015-02-20 12:38:29 -08:00
didSet = 1;
#endif
}
else if (ssl->suites->hashAlgo == sha256_mac) {
2013-02-18 14:36:50 -08:00
#ifndef NO_SHA256
digest = ssl->hsHashes->certHashes.sha256;
2013-02-18 14:36:50 -08:00
typeH = SHA256h;
digestSz = SHA256_DIGEST_SIZE;
2015-02-20 12:38:29 -08:00
didSet = 1;
2013-02-18 14:36:50 -08:00
#endif
}
else if (ssl->suites->hashAlgo == sha384_mac) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
digest = ssl->hsHashes->certHashes.sha384;
2013-02-18 14:36:50 -08:00
typeH = SHA384h;
digestSz = SHA384_DIGEST_SIZE;
2015-02-20 12:38:29 -08:00
didSet = 1;
#endif
}
else if (ssl->suites->hashAlgo == sha512_mac) {
#ifdef WOLFSSL_SHA512
digest = ssl->hsHashes->certHashes.sha512;
typeH = SHA512h;
digestSz = SHA512_DIGEST_SIZE;
didSet = 1;
#endif
}
2015-02-20 12:38:29 -08:00
if (didSet == 0) {
/* defaults */
#ifndef NO_OLD_TLS
digest = ssl->hsHashes->certHashes.sha;
2015-02-20 12:38:29 -08:00
digestSz = SHA_DIGEST_SIZE;
typeH = SHAh;
#else
digest = ssl->hsHashes->certHashes.sha256;
2015-02-20 12:38:29 -08:00
digestSz = SHA256_DIGEST_SIZE;
typeH = SHA256h;
2013-02-18 14:36:50 -08:00
#endif
}
2012-05-02 10:30:15 -07:00
2014-12-30 15:14:27 -07:00
signSz = wc_EncodeSignature(encodedSig, digest,digestSz,typeH);
2012-05-02 10:30:15 -07:00
signBuffer = encodedSig;
}
2011-02-05 11:14:47 -08:00
c16toa((word16)length, verify + extraSz); /* prepend hdr */
if (doUserRsa) {
#ifdef HAVE_PK_CALLBACKS
#ifndef NO_RSA
word32 ioLen = ENCRYPT_LEN;
ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz,
verify + extraSz + VERIFY_HEADER,
&ioLen,
ssl->buffers.key.buffer,
ssl->buffers.key.length,
ssl->RsaSignCtx);
#endif /* NO_RSA */
#endif /*HAVE_PK_CALLBACKS */
}
else {
ret = wc_RsaSSL_Sign(signBuffer, signSz, verify + extraSz +
VERIFY_HEADER, ENCRYPT_LEN, &key, ssl->rng);
}
2011-02-05 11:14:47 -08:00
if (ret > 0) {
/* check for signature faults */
ret = VerifyRsaSign(verify + extraSz + VERIFY_HEADER, ret,
signBuffer, signSz, &key);
}
2012-05-02 10:30:15 -07:00
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2012-05-02 10:30:15 -07:00
if (ret == 0) {
2011-02-28 12:21:06 -08:00
AddHeaders(output, length + extraSz + VERIFY_HEADER,
certificate_verify, ssl);
2011-02-05 11:14:47 -08:00
sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length +
2011-02-28 12:21:06 -08:00
extraSz + VERIFY_HEADER;
2014-09-29 13:38:56 -07:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
if (ssl->options.dtls) {
2011-02-05 11:14:47 -08:00
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
2014-09-29 13:38:56 -07:00
}
#endif
if (IsEncryptionOn(ssl, 1)) {
2014-09-29 13:38:56 -07:00
byte* input;
int inputSz = sendSz - RECORD_HEADER_SZ;
/* build msg adds rec hdr */
input = (byte*)XMALLOC(inputSz, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (input == NULL)
ret = MEMORY_E;
else {
XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
sendSz = BuildMessage(ssl, output,
MAX_CERT_VERIFY_SZ +MAX_MSG_EXTRA,
input, inputSz, handshake, 1);
2014-09-29 13:38:56 -07:00
XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (sendSz < 0)
ret = sendSz;
}
} else {
ret = HashOutput(ssl, output, sendSz, 0);
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2014-09-29 13:38:56 -07:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return ret;
2012-09-14 09:35:34 -07:00
}
2011-02-05 11:14:47 -08:00
#endif
}
}
#ifndef NO_RSA
2014-04-01 13:08:48 -07:00
if (initRsaKey)
wc_FreeRsaKey(&key);
#endif
2012-05-02 10:30:15 -07:00
#ifdef HAVE_ECC
2014-12-30 15:14:27 -07:00
wc_ecc_free(&eccKey);
2012-05-02 10:30:15 -07:00
#endif
2011-02-05 11:14:47 -08:00
if (ret == 0) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn)
AddPacketName("CertificateVerify", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddPacketInfo("CertificateVerify", &ssl->timeoutInfo,
output, sendSz, ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
if (ssl->options.groupMessages)
return 0;
else
return SendBuffered(ssl);
2011-02-05 11:14:47 -08:00
}
else
return ret;
}
#endif /* NO_CERTS */
2011-02-05 11:14:47 -08:00
#ifdef HAVE_SESSION_TICKET
2014-12-19 11:27:01 -07:00
int DoSessionTicket(WOLFSSL* ssl,
const byte* input, word32* inOutIdx, word32 size)
{
word32 begin = *inOutIdx;
word32 lifetime;
word16 length;
if (ssl->expect_session_ticket == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Unexpected session ticket");
return SESSION_TICKET_EXPECT_E;
}
if ((*inOutIdx - begin) + OPAQUE32_LEN > size)
return BUFFER_ERROR;
ato32(input + *inOutIdx, &lifetime);
*inOutIdx += OPAQUE32_LEN;
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN;
if (length > sizeof(ssl->session.ticket))
return SESSION_TICKET_LEN_E;
if ((*inOutIdx - begin) + length > size)
return BUFFER_ERROR;
/* If the received ticket including its length is greater than
* a length value, the save it. Otherwise, don't save it. */
if (length > 0) {
XMEMCPY(ssl->session.ticket, input + *inOutIdx, length);
*inOutIdx += length;
ssl->session.ticketLen = length;
ssl->timeout = lifetime;
if (ssl->session_ticket_cb != NULL) {
ssl->session_ticket_cb(ssl,
ssl->session.ticket, ssl->session.ticketLen,
ssl->session_ticket_ctx);
}
/* Create a fake sessionID based on the ticket, this will
* supercede the existing session cache info. */
ssl->options.haveSessionId = 1;
XMEMCPY(ssl->arrays->sessionID,
ssl->session.ticket + length - ID_LEN, ID_LEN);
#ifndef NO_SESSION_CACHE
AddSession(ssl);
#endif
}
else {
ssl->session.ticketLen = 0;
}
if (IsEncryptionOn(ssl, 0)) {
2014-10-02 10:43:06 -07:00
*inOutIdx += ssl->keys.padSz;
}
ssl->expect_session_ticket = 0;
return 0;
}
#endif /* HAVE_SESSION_TICKET */
2014-12-19 11:27:01 -07:00
#endif /* NO_WOLFSSL_CLIENT */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifndef NO_WOLFSSL_SERVER
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
int SendServerHello(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
byte *output;
word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
int sendSz;
int ret;
byte sessIdSz = ID_LEN;
2011-02-05 11:14:47 -08:00
length = VERSION_SZ + RAN_LEN
2014-10-24 10:33:24 -03:00
+ ID_LEN + ENUM_LEN
+ SUITE_LEN
2011-02-05 11:14:47 -08:00
+ ENUM_LEN;
2013-05-21 14:37:50 -07:00
#ifdef HAVE_TLS_EXTENSIONS
length += TLSX_GetResponseSize(ssl);
#ifdef HAVE_SESSION_TICKET
if (ssl->options.useTicket && ssl->arrays->sessionIDSz == 0) {
/* no session id */
length -= ID_LEN;
sessIdSz = 0;
}
#endif /* HAVE_SESSION_TICKET */
2013-05-21 14:37:50 -07:00
#endif
/* check for avalaible size */
if ((ret = CheckAvailableSize(ssl, MAX_HELLO_SZ)) != 0)
2011-02-05 11:14:47 -08:00
return ret;
/* get ouput buffer */
2014-10-24 10:33:24 -03:00
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
/* Server Hello should use the same sequence number as the
* Client Hello. */
ssl->keys.dtls_sequence_number = ssl->keys.dtls_state.curSeq;
idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
}
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
AddHeaders(output, length, server_hello, ssl);
/* now write to output */
/* first version */
output[idx++] = ssl->version.major;
output[idx++] = ssl->version.minor;
2011-02-05 11:14:47 -08:00
/* then random and session id */
if (!ssl->options.resuming) {
/* generate random part and session id */
2016-01-18 20:48:12 -03:00
ret = wc_RNG_GenerateBlock(ssl->rng, output + idx,
RAN_LEN + sizeof(sessIdSz) + sessIdSz);
if (ret != 0)
return ret;
/* store info in SSL for later */
XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
idx += RAN_LEN;
output[idx++] = sessIdSz;
XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz);
}
else {
/* If resuming, use info from SSL */
XMEMCPY(output + idx, ssl->arrays->serverRandom, RAN_LEN);
idx += RAN_LEN;
output[idx++] = sessIdSz;
XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz);
}
idx += sessIdSz;
2011-02-05 11:14:47 -08:00
#ifdef SHOW_SECRETS
{
int j;
printf("server random: ");
for (j = 0; j < RAN_LEN; j++)
2012-09-14 21:19:06 -07:00
printf("%02x", ssl->arrays->serverRandom[j]);
2011-02-05 11:14:47 -08:00
printf("\n");
}
#endif
/* then cipher suite */
2014-10-24 10:33:24 -03:00
output[idx++] = ssl->options.cipherSuite0;
2011-02-05 11:14:47 -08:00
output[idx++] = ssl->options.cipherSuite;
/* then compression */
2011-02-05 11:14:47 -08:00
if (ssl->options.usingCompression)
output[idx++] = ZLIB_COMPRESSION;
else
output[idx++] = NO_COMPRESSION;
2013-05-21 14:37:50 -07:00
/* last, extensions */
2013-05-21 14:37:50 -07:00
#ifdef HAVE_TLS_EXTENSIONS
2014-06-25 11:52:37 -03:00
TLSX_WriteResponse(ssl, output + idx);
2013-05-21 14:37:50 -07:00
#endif
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
ssl->buffers.outputBuffer.length += sendSz;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return ret;
2012-09-14 09:35:34 -07:00
}
#endif
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0)
return ret;
2011-02-05 11:14:47 -08:00
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn)
AddPacketName("ServerHello", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz,
ssl->heap);
#endif
2011-02-05 11:14:47 -08:00
ssl->options.serverState = SERVER_HELLO_COMPLETE;
if (ssl->options.groupMessages)
return 0;
else
return SendBuffered(ssl);
2011-02-05 11:14:47 -08:00
}
#ifdef HAVE_ECC
2011-09-28 13:19:05 -07:00
static byte SetCurveId(int size)
2011-02-05 11:14:47 -08:00
{
switch(size) {
2015-03-18 14:12:23 -07:00
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
2011-02-05 11:14:47 -08:00
case 20:
2015-03-18 14:12:23 -07:00
return WOLFSSL_ECC_SECP160R1;
#endif
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
2011-02-05 11:14:47 -08:00
case 24:
2015-03-18 14:12:23 -07:00
return WOLFSSL_ECC_SECP192R1;
#endif
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
2011-02-05 11:14:47 -08:00
case 28:
2015-03-18 14:12:23 -07:00
return WOLFSSL_ECC_SECP224R1;
#endif
#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
2011-02-05 11:14:47 -08:00
case 32:
2015-03-18 14:12:23 -07:00
return WOLFSSL_ECC_SECP256R1;
#endif
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
2011-02-05 11:14:47 -08:00
case 48:
2015-03-18 14:12:23 -07:00
return WOLFSSL_ECC_SECP384R1;
#endif
#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
2011-02-05 11:14:47 -08:00
case 66:
2015-03-18 14:12:23 -07:00
return WOLFSSL_ECC_SECP521R1;
#endif
2011-02-05 11:14:47 -08:00
default:
return 0;
2014-10-24 10:33:24 -03:00
}
2011-02-05 11:14:47 -08:00
}
#endif /* HAVE_ECC */
2014-12-19 11:27:01 -07:00
int SendServerKeyExchange(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
int ret = 0;
2011-04-27 17:31:08 -07:00
(void)ssl;
2014-12-04 13:30:30 -08:00
#define ERROR_OUT(err, eLabel) do { ret = err; goto eLabel; } while(0)
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
word32 qshSz = 0;
2015-07-11 12:52:22 -06:00
if (ssl->peerQSHKeyPresent && ssl->options.haveQSH) {
2015-07-07 09:55:58 -06:00
qshSz = QSH_KeyGetSize(ssl);
}
#endif
2015-12-03 12:37:49 -08:00
switch(ssl->specs.kea)
{
#ifndef NO_PSK
2015-12-03 12:37:49 -08:00
case psk_kea:
2011-02-05 11:14:47 -08:00
{
byte *output;
word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
int sendSz;
2012-09-14 21:19:06 -07:00
if (ssl->arrays->server_hint[0] == 0) return 0; /* don't send */
2011-02-05 11:14:47 -08:00
/* include size part */
2012-09-14 21:19:06 -07:00
length = (word32)XSTRLEN(ssl->arrays->server_hint);
2015-12-03 12:37:49 -08:00
if (length > MAX_PSK_ID_LEN) {
return SERVER_HINT_ERROR;
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
length += HINT_LEN_SZ;
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
length += qshSz;
sendSz += qshSz;
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
}
#endif
/* check for available size */
2015-12-03 12:37:49 -08:00
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
return ret;
}
2011-02-05 11:14:47 -08:00
/* get ouput buffer */
2014-10-24 10:33:24 -03:00
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
AddHeaders(output, length, server_key_exchange, ssl);
/* key data */
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
c16toa((word16)(length - qshSz - HINT_LEN_SZ), output + idx);
#else
2011-02-05 11:14:47 -08:00
c16toa((word16)(length - HINT_LEN_SZ), output + idx);
2015-07-07 09:55:58 -06:00
#endif
2011-02-05 11:14:47 -08:00
idx += HINT_LEN_SZ;
2012-09-14 21:19:06 -07:00
XMEMCPY(output + idx, ssl->arrays->server_hint,length -HINT_LEN_SZ);
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
if (ssl->peerQSHKeyPresent) {
if (qshSz > 0) {
idx = sendSz - qshSz;
2015-12-03 12:37:49 -08:00
if (QSH_KeyExchangeWrite(ssl, 1) != 0) {
2015-07-07 09:55:58 -06:00
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
2015-07-07 09:55:58 -06:00
/* extension type */
2015-11-02 15:51:01 -03:00
c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx);
2015-07-07 09:55:58 -06:00
idx += OPAQUE16_LEN;
/* write to output and check amount written */
if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx)
2015-12-03 12:37:49 -08:00
> qshSz - OPAQUE16_LEN) {
2015-07-07 09:55:58 -06:00
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
2015-07-07 09:55:58 -06:00
}
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2015-12-03 12:37:49 -08:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) {
return ret;
2015-12-03 12:37:49 -08:00
}
}
#endif
ret = HashOutput(ssl, output, sendSz, 0);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
return ret;
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2015-12-03 12:37:49 -08:00
if (ssl->hsInfoOn) {
AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
2015-12-03 12:37:49 -08:00
}
if (ssl->toInfoOn) {
AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output,
2015-12-03 12:37:49 -08:00
sendSz, ssl->heap);
}
#endif
2011-02-05 11:14:47 -08:00
ssl->buffers.outputBuffer.length += sendSz;
2015-12-03 12:37:49 -08:00
if (ssl->options.groupMessages) {
ret = 0;
2015-12-03 12:37:49 -08:00
}
else {
ret = SendBuffered(ssl);
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
2015-12-03 12:37:49 -08:00
break;
2011-02-05 11:14:47 -08:00
}
#endif /*NO_PSK */
2011-02-05 11:14:47 -08:00
#if !defined(NO_DH) && !defined(NO_PSK)
2015-12-03 12:37:49 -08:00
case dhe_psk_kea:
{
byte *output;
word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
word32 hintLen;
int sendSz;
DhKey dhKey;
if (ssl->buffers.serverDH_P.buffer == NULL ||
2015-12-03 12:37:49 -08:00
ssl->buffers.serverDH_G.buffer == NULL) {
return NO_DH_PARAMS;
2015-12-03 12:37:49 -08:00
}
if (ssl->buffers.serverDH_Pub.buffer == NULL) {
ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_Pub.buffer == NULL) {
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
}
if (ssl->buffers.serverDH_Priv.buffer == NULL) {
ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_Priv.buffer == NULL) {
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
}
2014-12-30 14:13:57 -07:00
wc_InitDhKey(&dhKey);
ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length,
ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length);
2015-12-03 12:37:49 -08:00
if (ret == 0) {
2014-12-30 14:13:57 -07:00
ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng,
ssl->buffers.serverDH_Priv.buffer,
&ssl->buffers.serverDH_Priv.length,
ssl->buffers.serverDH_Pub.buffer,
&ssl->buffers.serverDH_Pub.length);
2015-12-03 12:37:49 -08:00
}
2014-12-30 14:13:57 -07:00
wc_FreeDhKey(&dhKey);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
return ret;
2015-12-03 12:37:49 -08:00
}
length = LENGTH_SZ * 3 + /* p, g, pub */
ssl->buffers.serverDH_P.length +
ssl->buffers.serverDH_G.length +
ssl->buffers.serverDH_Pub.length;
/* include size part */
hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
2015-12-03 12:37:49 -08:00
if (hintLen > MAX_PSK_ID_LEN) {
return SERVER_HINT_ERROR;
2015-12-03 12:37:49 -08:00
}
length += hintLen + HINT_LEN_SZ;
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
length += qshSz;
sendSz += qshSz;
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
}
#endif
/* check for available size */
2015-12-03 12:37:49 -08:00
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
return ret;
}
/* get ouput buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
AddHeaders(output, length, server_key_exchange, ssl);
/* key data */
c16toa((word16)hintLen, output + idx);
idx += HINT_LEN_SZ;
XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen);
idx += hintLen;
/* add p, g, pub */
c16toa((word16)ssl->buffers.serverDH_P.length, output + idx);
idx += LENGTH_SZ;
XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length);
idx += ssl->buffers.serverDH_P.length;
/* g */
c16toa((word16)ssl->buffers.serverDH_G.length, output + idx);
idx += LENGTH_SZ;
XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length);
idx += ssl->buffers.serverDH_G.length;
/* pub */
c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx);
idx += LENGTH_SZ;
XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer,
ssl->buffers.serverDH_Pub.length);
idx += ssl->buffers.serverDH_Pub.length;
2014-09-12 11:14:23 -07:00
(void)idx; /* suppress analyzer warning, and keep idx current */
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
if (ssl->peerQSHKeyPresent) {
if (qshSz > 0) {
idx = sendSz - qshSz;
QSH_KeyExchangeWrite(ssl, 1);
/* extension type */
2015-11-02 15:51:01 -03:00
c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx);
2015-07-07 09:55:58 -06:00
idx += OPAQUE16_LEN;
/* write to output and check amount written */
if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx)
2015-12-03 12:37:49 -08:00
> qshSz - OPAQUE16_LEN) {
2015-07-07 09:55:58 -06:00
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
2015-07-07 09:55:58 -06:00
}
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2015-12-03 12:37:49 -08:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) {
return ret;
2015-12-03 12:37:49 -08:00
}
}
#endif
ret = HashOutput(ssl, output, sendSz, 0);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
return ret;
2015-12-03 12:37:49 -08:00
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2015-12-03 12:37:49 -08:00
if (ssl->hsInfoOn) {
AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
2015-12-03 12:37:49 -08:00
}
if (ssl->toInfoOn) {
AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output,
2015-12-03 12:37:49 -08:00
sendSz, ssl->heap);
}
#endif
ssl->buffers.outputBuffer.length += sendSz;
2015-12-03 12:37:49 -08:00
if (ssl->options.groupMessages) {
ret = 0;
2015-12-03 12:37:49 -08:00
}
else {
ret = SendBuffered(ssl);
2015-12-03 12:37:49 -08:00
}
ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
2015-12-03 12:37:49 -08:00
break;
}
#endif /* !NO_DH && !NO_PSK */
#ifdef HAVE_ECC
2015-12-03 12:37:49 -08:00
case ecc_diffie_hellman_kea:
2011-02-05 11:14:47 -08:00
{
byte *output;
word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
int sendSz;
word32 sigSz;
word32 preSigSz, preSigIdx;
#ifndef NO_RSA
2011-02-05 11:14:47 -08:00
RsaKey rsaKey;
#endif
2011-02-05 11:14:47 -08:00
ecc_key dsaKey;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* exportBuf = NULL;
#else
byte exportBuf[MAX_EXPORT_ECC_SZ];
#endif
word32 expSz = MAX_EXPORT_ECC_SZ;
2011-02-05 11:14:47 -08:00
#ifndef NO_OLD_TLS
byte doMd5 = 0;
byte doSha = 0;
#endif
#ifndef NO_SHA256
byte doSha256 = 0;
#endif
#ifdef WOLFSSL_SHA384
byte doSha384 = 0;
#endif
#ifdef WOLFSSL_SHA512
byte doSha512 = 0;
#endif
2012-05-03 08:18:59 -07:00
if (ssl->specs.static_ecdh) {
2015-12-03 12:37:49 -08:00
WOLFSSL_MSG("Using Static ECDH, not sending ServerKeyExchange");
2012-05-03 08:18:59 -07:00
return 0;
}
2011-02-05 11:14:47 -08:00
/* curve type, named curve, length(1) */
length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
/* pub key size */
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Using ephemeral ECDH");
/* need ephemeral key now, create it if missing */
if (ssl->eccTempKey == NULL) {
/* alloc/init on demand */
ssl->eccTempKey = (ecc_key*)XMALLOC(sizeof(ecc_key),
2015-12-03 12:37:49 -08:00
ssl->ctx->heap, DYNAMIC_TYPE_ECC);
if (ssl->eccTempKey == NULL) {
WOLFSSL_MSG("EccTempKey Memory error");
return MEMORY_E;
}
wc_ecc_init(ssl->eccTempKey);
}
if (ssl->eccTempKeyPresent == 0) {
2014-12-30 15:14:27 -07:00
if (wc_ecc_make_key(ssl->rng, ssl->eccTempKeySz,
ssl->eccTempKey) != 0) {
return ECC_MAKEKEY_ERROR;
}
ssl->eccTempKeyPresent = 1;
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
exportBuf = (byte*)XMALLOC(MAX_EXPORT_ECC_SZ, NULL,
2015-12-03 12:37:49 -08:00
DYNAMIC_TYPE_TMP_BUFFER);
if (exportBuf == NULL) {
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
#endif
2015-12-03 12:37:49 -08:00
if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &expSz) != 0) {
ERROR_OUT(ECC_EXPORT_ERROR, done_a);
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
length += expSz;
preSigSz = length;
preSigIdx = idx;
#ifndef NO_RSA
ret = wc_InitRsaKey(&rsaKey, ssl->heap);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
goto done_a;
2015-12-03 12:37:49 -08:00
}
#endif
2014-12-30 15:14:27 -07:00
wc_ecc_init(&dsaKey);
2011-02-05 11:14:47 -08:00
/* sig length */
length += LENGTH_SZ;
if (!ssl->buffers.key.buffer) {
#ifndef NO_RSA
wc_FreeRsaKey(&rsaKey);
#endif
2014-12-30 15:14:27 -07:00
wc_ecc_free(&dsaKey);
ERROR_OUT(NO_PRIVATE_KEY, done_a);
2011-02-05 11:14:47 -08:00
}
#ifndef NO_RSA
2011-02-05 11:14:47 -08:00
if (ssl->specs.sig_algo == rsa_sa_algo) {
/* rsa sig size */
word32 i = 0;
ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i,
2011-02-05 11:14:47 -08:00
&rsaKey, ssl->buffers.key.length);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
goto done_a;
2015-12-03 12:37:49 -08:00
}
sigSz = wc_RsaEncryptSize(&rsaKey);
2014-10-24 10:33:24 -03:00
} else
#endif
if (ssl->specs.sig_algo == ecc_dsa_sa_algo) {
2011-02-05 11:14:47 -08:00
/* ecdsa sig size */
word32 i = 0;
2014-12-30 15:14:27 -07:00
ret = wc_EccPrivateKeyDecode(ssl->buffers.key.buffer, &i,
2011-02-05 11:14:47 -08:00
&dsaKey, ssl->buffers.key.length);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
goto done_a;
2015-12-03 12:37:49 -08:00
}
2014-12-30 15:14:27 -07:00
sigSz = wc_ecc_sig_size(&dsaKey); /* worst case estimate */
2011-02-05 11:14:47 -08:00
}
else {
#ifndef NO_RSA
2014-12-30 15:14:27 -07:00
wc_FreeRsaKey(&rsaKey);
#endif
2014-12-30 15:14:27 -07:00
wc_ecc_free(&dsaKey);
ERROR_OUT(ALGO_ID_E, done_a); /* unsupported type */
2011-02-05 11:14:47 -08:00
}
length += sigSz;
2015-12-03 12:37:49 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
2011-03-01 15:03:47 -08:00
length += HASH_SIG_SIZE;
2015-12-03 12:37:49 -08:00
}
2011-03-01 15:03:47 -08:00
2011-02-05 11:14:47 -08:00
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
length += qshSz;
sendSz += qshSz;
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
preSigIdx = idx;
}
#endif
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
#ifndef NO_RSA
2014-12-30 15:14:27 -07:00
wc_FreeRsaKey(&rsaKey);
#endif
2014-12-30 15:14:27 -07:00
wc_ecc_free(&dsaKey);
goto done_a;
2014-10-24 10:33:24 -03:00
}
2011-02-05 11:14:47 -08:00
/* get ouput buffer */
2014-10-24 10:33:24 -03:00
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
/* record and message headers will be added below, when we're sure
of the sig length */
2011-02-05 11:14:47 -08:00
/* key exchange data */
output[idx++] = named_curve;
output[idx++] = 0x00; /* leading zero */
2014-12-30 15:14:27 -07:00
output[idx++] = SetCurveId(wc_ecc_size(ssl->eccTempKey));
2012-03-23 10:42:07 -07:00
output[idx++] = (byte)expSz;
XMEMCPY(output + idx, exportBuf, expSz);
2011-02-05 11:14:47 -08:00
idx += expSz;
2011-03-01 15:03:47 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
byte setHash = 0;
2013-02-18 14:36:50 -08:00
output[idx++] = ssl->suites->hashAlgo;
output[idx++] = ssl->suites->sigAlgo;
switch (ssl->suites->hashAlgo) {
case sha512_mac:
#ifdef WOLFSSL_SHA512
doSha512 = 1;
setHash = 1;
#endif
break;
case sha384_mac:
#ifdef WOLFSSL_SHA384
doSha384 = 1;
setHash = 1;
#endif
break;
case sha256_mac:
#ifndef NO_SHA256
doSha256 = 1;
setHash = 1;
#endif
break;
case sha_mac:
#ifndef NO_OLD_TLS
doSha = 1;
setHash = 1;
#endif
break;
default:
WOLFSSL_MSG("Bad hash sig algo");
break;
}
if (setHash == 0) {
#ifndef NO_RSA
wc_FreeRsaKey(&rsaKey);
#endif
wc_ecc_free(&dsaKey);
ERROR_OUT(ALGO_ID_E, done_a);
}
} else {
/* only using sha and md5 for rsa */
#ifndef NO_OLD_TLS
doSha = 1;
if (ssl->suites->sigAlgo == rsa_sa_algo) {
doMd5 = 1;
}
#else
#ifndef NO_RSA
wc_FreeRsaKey(&rsaKey);
#endif
wc_ecc_free(&dsaKey);
ERROR_OUT(ALGO_ID_E, done_a);
#endif
2011-03-01 15:03:47 -08:00
}
/* Signtaure length will be written later, when we're sure what it
is */
2011-02-05 11:14:47 -08:00
#ifdef HAVE_FUZZER
2015-12-03 12:37:49 -08:00
if (ssl->fuzzerCb) {
2016-01-18 20:48:12 -03:00
ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz,
2015-12-03 12:37:49 -08:00
FUZZ_SIGNATURE, ssl->fuzzerCtx);
}
#endif
2014-08-11 16:29:19 -06:00
2011-02-05 11:14:47 -08:00
/* do signature */
{
#ifndef NO_OLD_TLS
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
Md5* md5 = NULL;
Sha* sha = NULL;
#else
Md5 md5[1];
Sha sha[1];
#endif
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* hash = NULL;
#else
2011-02-05 11:14:47 -08:00
byte hash[FINISHED_SZ];
#endif
#ifndef NO_SHA256
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
Sha256* sha256 = NULL;
byte* hash256 = NULL;
#else
Sha256 sha256[1];
byte hash256[SHA256_DIGEST_SIZE];
#endif
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
#ifdef WOLFSSL_SMALL_STACK
Sha384* sha384 = NULL;
byte* hash384 = NULL;
#else
Sha384 sha384[1];
byte hash384[SHA384_DIGEST_SIZE];
#endif
#endif
#ifdef WOLFSSL_SHA512
#ifdef WOLFSSL_SMALL_STACK
Sha512* sha512 = NULL;
byte* hash512 = NULL;
#else
Sha512 sha512[1];
byte hash512[SHA512_DIGEST_SIZE];
#endif
#endif
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
hash = (byte*)XMALLOC(FINISHED_SZ, NULL,
2015-12-03 12:37:49 -08:00
DYNAMIC_TYPE_TMP_BUFFER);
if (hash == NULL) {
ERROR_OUT(MEMORY_E, done_a);
2015-12-03 12:37:49 -08:00
}
#endif
#ifndef NO_OLD_TLS
2011-02-05 11:14:47 -08:00
/* md5 */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (doMd5) {
md5 = (Md5*)XMALLOC(sizeof(Md5), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (md5 == NULL) {
ERROR_OUT(MEMORY_E, done_a2);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doMd5) {
wc_InitMd5(md5);
wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN);
wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN);
wc_Md5Update(md5, output + preSigIdx, preSigSz);
wc_Md5Final(md5, hash);
}
2011-02-05 11:14:47 -08:00
/* sha */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (doSha) {
sha = (Sha*)XMALLOC(sizeof(Sha), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha == NULL) {
ERROR_OUT(MEMORY_E, done_a2);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha) {
ret = wc_InitSha(sha);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
goto done_a2;
}
wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN);
wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN);
wc_ShaUpdate(sha, output + preSigIdx, preSigSz);
wc_ShaFinal(sha, &hash[MD5_DIGEST_SIZE]);
}
#endif
2011-02-05 11:14:47 -08:00
#ifndef NO_SHA256
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (doSha256) {
sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha256 == NULL || hash256 == NULL) {
ERROR_OUT(MEMORY_E, done_a2);
2015-12-03 12:37:49 -08:00
}
}
#endif
2013-02-18 14:36:50 -08:00
if (doSha256) {
if (!(ret = wc_InitSha256(sha256))
&& !(ret = wc_Sha256Update(sha256,
2015-12-03 12:37:49 -08:00
ssl->arrays->clientRandom, RAN_LEN))
&& !(ret = wc_Sha256Update(sha256,
2015-12-03 12:37:49 -08:00
ssl->arrays->serverRandom, RAN_LEN))
&& !(ret = wc_Sha256Update(sha256,
2015-12-03 12:37:49 -08:00
output + preSigIdx, preSigSz))) {
ret = wc_Sha256Final(sha256, hash256);
2015-12-03 12:37:49 -08:00
}
if (ret != 0) {
goto done_a2;
}
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
#ifdef WOLFSSL_SMALL_STACK
if (doSha384) {
sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha384 == NULL || hash384 == NULL) {
ERROR_OUT(MEMORY_E, done_a2);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha384) {
if (!(ret = wc_InitSha384(sha384))
&& !(ret = wc_Sha384Update(sha384,
2015-12-03 12:37:49 -08:00
ssl->arrays->clientRandom, RAN_LEN))
&& !(ret = wc_Sha384Update(sha384,
2015-12-03 12:37:49 -08:00
ssl->arrays->serverRandom, RAN_LEN))
&& !(ret = wc_Sha384Update(sha384,
2015-12-03 12:37:49 -08:00
output + preSigIdx, preSigSz))) {
ret = wc_Sha384Final(sha384, hash384);
2015-12-03 12:37:49 -08:00
}
if (ret != 0) {
goto done_a2;
}
}
#endif
#ifdef WOLFSSL_SHA512
#ifdef WOLFSSL_SMALL_STACK
if (doSha512) {
sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha512 == NULL || hash512 == NULL) {
ERROR_OUT(MEMORY_E, done_a2);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha512) {
if (!(ret = wc_InitSha512(sha512))
&& !(ret = wc_Sha512Update(sha512,
2015-12-03 12:37:49 -08:00
ssl->arrays->clientRandom, RAN_LEN))
&& !(ret = wc_Sha512Update(sha512,
2015-12-03 12:37:49 -08:00
ssl->arrays->serverRandom, RAN_LEN))
&& !(ret = wc_Sha512Update(sha512,
2015-12-03 12:37:49 -08:00
output + preSigIdx, preSigSz))) {
ret = wc_Sha512Final(sha512, hash512);
2015-12-03 12:37:49 -08:00
}
if (ret != 0) {
goto done_a2;
}
}
#endif
#ifndef NO_RSA
2013-02-18 14:36:50 -08:00
if (ssl->suites->sigAlgo == rsa_sa_algo) {
2013-01-02 11:39:12 -08:00
byte* signBuffer = hash;
word32 signSz = FINISHED_SZ;
byte doUserRsa = 0;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* encodedSig = NULL;
#else
byte encodedSig[MAX_ENCODED_SIG_SZ];
#endif
#ifdef HAVE_PK_CALLBACKS
if (ssl->ctx->RsaSignCb)
doUserRsa = 1;
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
2015-12-03 12:37:49 -08:00
DYNAMIC_TYPE_TMP_BUFFER);
if (encodedSig == NULL) {
ERROR_OUT(MEMORY_E, done_a2);
2015-12-03 12:37:49 -08:00
}
#endif
2011-02-05 11:14:47 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
2013-02-18 14:36:50 -08:00
byte* digest = &hash[MD5_DIGEST_SIZE];
int typeH = SHAh;
int digestSz = SHA_DIGEST_SIZE;
if (ssl->suites->hashAlgo == sha256_mac) {
#ifndef NO_SHA256
digest = hash256;
typeH = SHA256h;
digestSz = SHA256_DIGEST_SIZE;
#endif
2013-02-18 14:36:50 -08:00
}
else if (ssl->suites->hashAlgo == sha384_mac) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
digest = hash384;
typeH = SHA384h;
digestSz = SHA384_DIGEST_SIZE;
#endif
2013-02-18 14:36:50 -08:00
}
else if (ssl->suites->hashAlgo == sha512_mac) {
#ifdef WOLFSSL_SHA512
digest = hash512;
typeH = SHA512h;
digestSz = SHA512_DIGEST_SIZE;
#endif
}
2011-02-05 11:14:47 -08:00
if (digest == NULL) {
#ifndef NO_RSA
wc_FreeRsaKey(&rsaKey);
#endif
wc_ecc_free(&dsaKey);
ERROR_OUT(ALGO_ID_E, done_a2);
}
signSz = wc_EncodeSignature(encodedSig, digest,
digestSz, typeH);
2011-02-05 11:14:47 -08:00
signBuffer = encodedSig;
}
/* write sig size here */
c16toa((word16)sigSz, output + idx);
idx += LENGTH_SZ;
if (doUserRsa) {
#ifdef HAVE_PK_CALLBACKS
word32 ioLen = sigSz;
ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz,
output + idx, &ioLen,
ssl->buffers.key.buffer,
ssl->buffers.key.length,
ssl->RsaSignCtx);
#endif /*HAVE_PK_CALLBACKS */
}
else {
ret = wc_RsaSSL_Sign(signBuffer, signSz, output + idx,
2015-12-03 12:37:49 -08:00
sigSz, &rsaKey, ssl->rng);
}
if (ret > 0) {
/* check for signature faults */
ret = VerifyRsaSign(output + idx, ret,
2015-12-03 12:37:49 -08:00
signBuffer, signSz, &rsaKey);
}
wc_FreeRsaKey(&rsaKey);
2014-12-30 15:14:27 -07:00
wc_ecc_free(&dsaKey);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2015-12-03 12:37:49 -08:00
if (ret < 0) {
goto done_a2;
2015-12-03 12:37:49 -08:00
}
2014-10-24 10:33:24 -03:00
} else
#endif
if (ssl->suites->sigAlgo == ecc_dsa_sa_algo) {
#ifndef NO_OLD_TLS
2013-02-18 14:36:50 -08:00
byte* digest = &hash[MD5_DIGEST_SIZE];
word32 digestSz = SHA_DIGEST_SIZE;
#else
byte* digest = hash256;
word32 digestSz = SHA256_DIGEST_SIZE;
#endif
word32 sz = sigSz;
byte doUserEcc = 0;
#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC)
2015-12-03 12:37:49 -08:00
if (ssl->ctx->EccSignCb) {
doUserEcc = 1;
2015-12-03 12:37:49 -08:00
}
#endif
if (IsAtLeastTLSv1_2(ssl)) {
if (ssl->suites->hashAlgo == sha_mac) {
#ifndef NO_SHA
digest = &hash[MD5_DIGEST_SIZE];
digestSz = SHA_DIGEST_SIZE;
#endif
}
else if (ssl->suites->hashAlgo == sha256_mac) {
#ifndef NO_SHA256
digest = hash256;
digestSz = SHA256_DIGEST_SIZE;
#endif
}
else if (ssl->suites->hashAlgo == sha384_mac) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
digest = hash384;
digestSz = SHA384_DIGEST_SIZE;
#endif
}
else if (ssl->suites->hashAlgo == sha512_mac) {
#ifdef WOLFSSL_SHA512
digest = hash512;
digestSz = SHA512_DIGEST_SIZE;
#endif
}
}
if (doUserEcc) {
#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC)
ret = ssl->ctx->EccSignCb(ssl, digest, digestSz,
2015-12-03 12:37:49 -08:00
output + LENGTH_SZ + idx,
&sz,
ssl->buffers.key.buffer,
ssl->buffers.key.length,
ssl->EccSignCtx);
#endif
}
else {
2014-12-30 15:14:27 -07:00
ret = wc_ecc_sign_hash(digest, digestSz,
2015-12-03 12:37:49 -08:00
output + LENGTH_SZ + idx, &sz, ssl->rng, &dsaKey);
}
#ifndef NO_RSA
wc_FreeRsaKey(&rsaKey);
#endif
2014-12-30 15:14:27 -07:00
wc_ecc_free(&dsaKey);
2015-12-03 12:37:49 -08:00
if (ret < 0) {
goto done_a2;
2015-12-03 12:37:49 -08:00
}
/* Now that we know the real sig size, write it. */
c16toa((word16)sz, output + idx);
/* And adjust length and sendSz from estimates */
length += sz - sigSz;
sendSz += sz - sigSz;
}
done_a2:
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
#ifndef NO_OLD_TLS
XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#ifndef NO_SHA256
XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef WOLFSSL_SHA512
XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#endif
if (ret < 0)
goto done_a;
}
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
if (ssl->peerQSHKeyPresent) {
if (qshSz > 0) {
idx = sendSz - qshSz;
QSH_KeyExchangeWrite(ssl, 1);
/* extension type */
2015-11-02 15:51:01 -03:00
c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx);
2015-07-07 09:55:58 -06:00
idx += OPAQUE16_LEN;
/* write to output and check amount written */
if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx)
2015-12-03 12:37:49 -08:00
> qshSz - OPAQUE16_LEN) {
2015-07-07 09:55:58 -06:00
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
2015-07-07 09:55:58 -06:00
}
}
#endif
AddHeaders(output, length, server_key_exchange, ssl);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2015-12-03 12:37:49 -08:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) {
goto done_a;
2015-12-03 12:37:49 -08:00
}
}
#endif
2015-12-03 12:37:49 -08:00
if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0) {
goto done_a;
2015-12-03 12:37:49 -08:00
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2015-12-03 12:37:49 -08:00
if (ssl->hsInfoOn) {
AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
2015-12-03 12:37:49 -08:00
}
if (ssl->toInfoOn) {
AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
output, sendSz, ssl->heap);
2015-12-03 12:37:49 -08:00
}
#endif
ssl->buffers.outputBuffer.length += sendSz;
2015-12-03 12:37:49 -08:00
if (ssl->options.groupMessages) {
ret = 0;
2015-12-03 12:37:49 -08:00
}
else {
ret = SendBuffered(ssl);
2015-12-03 12:37:49 -08:00
}
ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
done_a:
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(exportBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
#endif /* HAVE_ECC */
#if !defined(NO_DH) && !defined(NO_RSA)
2015-12-03 12:37:49 -08:00
case diffie_hellman_kea:
{
byte *output;
word32 length = 0, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
int sendSz;
word32 sigSz = 0, i = 0;
word32 preSigSz = 0, preSigIdx = 0;
RsaKey rsaKey;
DhKey dhKey;
2014-10-24 10:33:24 -03:00
if (ssl->buffers.serverDH_P.buffer == NULL ||
2015-12-03 12:37:49 -08:00
ssl->buffers.serverDH_G.buffer == NULL) {
return NO_DH_PARAMS;
2015-12-03 12:37:49 -08:00
}
if (ssl->buffers.serverDH_Pub.buffer == NULL) {
ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_Pub.buffer == NULL) {
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
2014-10-24 10:33:24 -03:00
}
if (ssl->buffers.serverDH_Priv.buffer == NULL) {
ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
DYNAMIC_TYPE_DH);
2015-12-03 12:37:49 -08:00
if (ssl->buffers.serverDH_Priv.buffer == NULL) {
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
2014-10-24 10:33:24 -03:00
}
2014-12-30 14:13:57 -07:00
wc_InitDhKey(&dhKey);
ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length,
ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length);
2015-12-03 12:37:49 -08:00
if (ret == 0) {
2014-12-30 14:13:57 -07:00
ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng,
ssl->buffers.serverDH_Priv.buffer,
&ssl->buffers.serverDH_Priv.length,
ssl->buffers.serverDH_Pub.buffer,
&ssl->buffers.serverDH_Pub.length);
2015-12-03 12:37:49 -08:00
}
2014-12-30 14:13:57 -07:00
wc_FreeDhKey(&dhKey);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
return ret;
}
length = LENGTH_SZ * 3; /* p, g, pub */
length += ssl->buffers.serverDH_P.length +
ssl->buffers.serverDH_G.length +
ssl->buffers.serverDH_Pub.length;
preSigIdx = idx;
preSigSz = length;
if (!ssl->options.usingAnon_cipher) {
ret = wc_InitRsaKey(&rsaKey, ssl->heap);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
return ret;
}
/* sig length */
length += LENGTH_SZ;
2015-12-03 12:37:49 -08:00
if (!ssl->buffers.key.buffer) {
return NO_PRIVATE_KEY;
2015-12-03 12:37:49 -08:00
}
2016-01-18 20:48:12 -03:00
ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i,
2015-12-03 12:37:49 -08:00
&rsaKey, ssl->buffers.key.length);
if (ret == 0) {
sigSz = wc_RsaEncryptSize(&rsaKey);
length += sigSz;
}
else {
wc_FreeRsaKey(&rsaKey);
return ret;
}
2014-10-24 10:33:24 -03:00
2015-12-03 12:37:49 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
length += HASH_SIG_SIZE;
2015-12-03 12:37:49 -08:00
}
}
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
length += qshSz;
sendSz += qshSz;
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
preSigIdx = idx;
}
#endif
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
2015-12-03 12:37:49 -08:00
if (!ssl->options.usingAnon_cipher) {
wc_FreeRsaKey(&rsaKey);
2015-12-03 12:37:49 -08:00
}
return ret;
2014-10-24 10:33:24 -03:00
}
/* get ouput buffer */
2014-10-24 10:33:24 -03:00
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
AddHeaders(output, length, server_key_exchange, ssl);
/* add p, g, pub */
c16toa((word16)ssl->buffers.serverDH_P.length, output + idx);
idx += LENGTH_SZ;
XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length);
idx += ssl->buffers.serverDH_P.length;
/* g */
c16toa((word16)ssl->buffers.serverDH_G.length, output + idx);
idx += LENGTH_SZ;
XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length);
idx += ssl->buffers.serverDH_G.length;
/* pub */
c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx);
idx += LENGTH_SZ;
XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer,
ssl->buffers.serverDH_Pub.length);
idx += ssl->buffers.serverDH_Pub.length;
#ifdef HAVE_FUZZER
2015-12-03 12:37:49 -08:00
if (ssl->fuzzerCb) {
2016-01-18 20:48:12 -03:00
ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz,
2015-12-03 12:37:49 -08:00
FUZZ_SIGNATURE, ssl->fuzzerCtx);
}
#endif
2014-08-11 16:29:19 -06:00
/* Add signature */
if (!ssl->options.usingAnon_cipher) {
#ifndef NO_OLD_TLS
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
Md5* md5 = NULL;
Sha* sha = NULL;
#else
Md5 md5[1];
Sha sha[1];
#endif
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* hash = NULL;
#else
byte hash[FINISHED_SZ];
#endif
#ifndef NO_SHA256
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
Sha256* sha256 = NULL;
byte* hash256 = NULL;
#else
Sha256 sha256[1];
byte hash256[SHA256_DIGEST_SIZE];
#endif
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
#ifdef WOLFSSL_SMALL_STACK
Sha384* sha384 = NULL;
byte* hash384 = NULL;
#else
Sha384 sha384[1];
byte hash384[SHA384_DIGEST_SIZE];
#endif
#endif
#ifdef WOLFSSL_SHA512
#ifdef WOLFSSL_SMALL_STACK
Sha512* sha512 = NULL;
byte* hash512 = NULL;
#else
Sha512 sha512[1];
byte hash512[SHA512_DIGEST_SIZE];
#endif
#endif
#ifndef NO_OLD_TLS
byte doMd5 = 0;
byte doSha = 0;
#endif
#ifndef NO_SHA256
byte doSha256 = 0;
#endif
#ifdef WOLFSSL_SHA384
byte doSha384 = 0;
#endif
#ifdef WOLFSSL_SHA512
byte doSha512 = 0;
#endif
/* Add hash/signature algo ID */
if (IsAtLeastTLSv1_2(ssl)) {
byte setHash = 0;
output[idx++] = ssl->suites->hashAlgo;
output[idx++] = ssl->suites->sigAlgo;
switch (ssl->suites->hashAlgo) {
case sha512_mac:
#ifdef WOLFSSL_SHA512
doSha512 = 1;
setHash = 1;
#endif
break;
case sha384_mac:
#ifdef WOLFSSL_SHA384
doSha384 = 1;
setHash = 1;
#endif
break;
case sha256_mac:
#ifndef NO_SHA256
doSha256 = 1;
setHash = 1;
#endif
break;
case sha_mac:
#ifndef NO_OLD_TLS
doSha = 1;
setHash = 1;
#endif
break;
default:
WOLFSSL_MSG("Bad hash sig algo");
break;
}
if (setHash == 0) {
wc_FreeRsaKey(&rsaKey);
return ALGO_ID_E;
}
} else {
/* only using sha and md5 for rsa */
#ifndef NO_OLD_TLS
doSha = 1;
if (ssl->suites->sigAlgo == rsa_sa_algo) {
doMd5 = 1;
}
#else
wc_FreeRsaKey(&rsaKey);
return ALGO_ID_E;
#endif
}
/* signature size */
c16toa((word16)sigSz, output + idx);
idx += LENGTH_SZ;
/* do signature */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
hash = (byte*)XMALLOC(FINISHED_SZ, NULL,
2015-12-03 12:37:49 -08:00
DYNAMIC_TYPE_TMP_BUFFER);
if (hash == NULL) {
return MEMORY_E; /* No heap commitment before this point,
from now on, the resources are freed
at done_b. */
2015-12-03 12:37:49 -08:00
}
#endif
#ifndef NO_OLD_TLS
/* md5 */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (doMd5) {
md5 = (Md5*)XMALLOC(sizeof(Md5), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (md5 == NULL) {
ERROR_OUT(MEMORY_E, done_b);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doMd5) {
wc_InitMd5(md5);
wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN);
wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN);
wc_Md5Update(md5, output + preSigIdx, preSigSz);
wc_Md5Final(md5, hash);
}
2013-01-21 10:53:42 -08:00
/* sha */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (doSha) {
sha = (Sha*)XMALLOC(sizeof(Sha), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha == NULL) {
ERROR_OUT(MEMORY_E, done_b);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha) {
2015-12-03 12:37:49 -08:00
if ((ret = wc_InitSha(sha)) != 0) {
goto done_b;
2015-12-03 12:37:49 -08:00
}
wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN);
wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN);
wc_ShaUpdate(sha, output + preSigIdx, preSigSz);
wc_ShaFinal(sha, &hash[MD5_DIGEST_SIZE]);
}
#endif
#ifndef NO_SHA256
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
if (doSha256) {
sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha256 == NULL || hash256 == NULL) {
ERROR_OUT(MEMORY_E, done_b);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha256) {
if (!(ret = wc_InitSha256(sha256))
&& !(ret = wc_Sha256Update(sha256,
2015-12-03 12:37:49 -08:00
ssl->arrays->clientRandom, RAN_LEN))
&& !(ret = wc_Sha256Update(sha256,
2015-12-03 12:37:49 -08:00
ssl->arrays->serverRandom, RAN_LEN))
&& !(ret = wc_Sha256Update(sha256,
2015-12-03 12:37:49 -08:00
output + preSigIdx, preSigSz))) {
ret = wc_Sha256Final(sha256, hash256);
2015-12-03 12:37:49 -08:00
}
if (ret != 0) {
goto done_b;
}
}
#endif
2013-01-21 10:53:42 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
#ifdef WOLFSSL_SMALL_STACK
if (doSha384) {
sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL,
2015-12-03 12:37:49 -08:00
DYNAMIC_TYPE_TMP_BUFFER);
if (sha384 == NULL || hash384 == NULL) {
ERROR_OUT(MEMORY_E, done_b);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha384) {
if (!(ret = wc_InitSha384(sha384))
&& !(ret = wc_Sha384Update(sha384,
2015-12-03 12:37:49 -08:00
ssl->arrays->clientRandom, RAN_LEN))
&& !(ret = wc_Sha384Update(sha384,
2015-12-03 12:37:49 -08:00
ssl->arrays->serverRandom, RAN_LEN))
&& !(ret = wc_Sha384Update(sha384,
2015-12-03 12:37:49 -08:00
output + preSigIdx, preSigSz))) {
ret = wc_Sha384Final(sha384, hash384);
2015-12-03 12:37:49 -08:00
}
if (ret != 0) {
goto done_b;
}
}
#endif
#ifdef WOLFSSL_SHA512
#ifdef WOLFSSL_SMALL_STACK
if (doSha512) {
sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
2015-12-03 12:37:49 -08:00
if (sha512 == NULL || hash512 == NULL) {
ERROR_OUT(MEMORY_E, done_b);
2015-12-03 12:37:49 -08:00
}
}
#endif
if (doSha512) {
if (!(ret = wc_InitSha512(sha512))
&& !(ret = wc_Sha512Update(sha512,
2015-12-03 12:37:49 -08:00
ssl->arrays->clientRandom, RAN_LEN))
&& !(ret = wc_Sha512Update(sha512,
2015-12-03 12:37:49 -08:00
ssl->arrays->serverRandom, RAN_LEN))
&& !(ret = wc_Sha512Update(sha512,
2015-12-03 12:37:49 -08:00
output + preSigIdx, preSigSz))) {
ret = wc_Sha512Final(sha512, hash512);
2015-12-03 12:37:49 -08:00
}
if (ret != 0) {
goto done_b;
}
}
#endif
#ifndef NO_RSA
if (ssl->suites->sigAlgo == rsa_sa_algo) {
byte* signBuffer = hash;
word32 signSz = FINISHED_SZ;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* encodedSig = NULL;
#else
byte encodedSig[MAX_ENCODED_SIG_SZ];
#endif
byte doUserRsa = 0;
#ifdef HAVE_PK_CALLBACKS
2015-12-03 12:37:49 -08:00
if (ssl->ctx->RsaSignCb) {
doUserRsa = 1;
2015-12-03 12:37:49 -08:00
}
#endif
if (IsAtLeastTLSv1_2(ssl)) {
byte* digest = &hash[MD5_DIGEST_SIZE];
int typeH = SHAh;
int digestSz = SHA_DIGEST_SIZE;
2016-01-18 20:48:12 -03:00
#ifdef WOLFSSL_SMALL_STACK
encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (encodedSig == NULL)
ERROR_OUT(MEMORY_E, done_b);
#endif
if (ssl->suites->hashAlgo == sha256_mac) {
#ifndef NO_SHA256
digest = hash256;
typeH = SHA256h;
digestSz = SHA256_DIGEST_SIZE;
#endif
}
else if (ssl->suites->hashAlgo == sha384_mac) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
digest = hash384;
typeH = SHA384h;
digestSz = SHA384_DIGEST_SIZE;
#endif
}
else if (ssl->suites->hashAlgo == sha512_mac) {
#ifdef WOLFSSL_SHA512
digest = hash512;
typeH = SHA512h;
digestSz = SHA512_DIGEST_SIZE;
#endif
}
if (digest == NULL) {
ret = ALGO_ID_E;
} else {
signSz = wc_EncodeSignature(encodedSig, digest,
digestSz, typeH);
signBuffer = encodedSig;
}
}
if (doUserRsa && ret == 0) {
#ifdef HAVE_PK_CALLBACKS
word32 ioLen = sigSz;
ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz,
output + idx, &ioLen,
ssl->buffers.key.buffer,
ssl->buffers.key.length,
ssl->RsaSignCtx);
#endif
} else if (ret == 0) {
ret = wc_RsaSSL_Sign(signBuffer, signSz, output + idx,
sigSz, &rsaKey, ssl->rng);
}
if (ret > 0) {
/* check for signature faults */
ret = VerifyRsaSign(output + idx, ret,
signBuffer, signSz, &rsaKey);
}
wc_FreeRsaKey(&rsaKey);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
#endif
done_b:
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
#ifndef NO_OLD_TLS
XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#ifndef NO_SHA256
XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef WOLFSSL_SHA512
XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#endif
2015-12-03 12:37:49 -08:00
if (ret < 0) {
return ret;
}
}
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
if (ssl->peerQSHKeyPresent) {
if (qshSz > 0) {
idx = sendSz - qshSz;
QSH_KeyExchangeWrite(ssl, 1);
/* extension type */
2015-11-02 15:51:01 -03:00
c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx);
2015-07-07 09:55:58 -06:00
idx += OPAQUE16_LEN;
/* write to output and check amount written */
if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx)
2015-12-03 12:37:49 -08:00
> qshSz - OPAQUE16_LEN) {
2015-07-07 09:55:58 -06:00
return MEMORY_E;
2015-12-03 12:37:49 -08:00
}
2015-07-07 09:55:58 -06:00
}
}
#endif
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2015-12-03 12:37:49 -08:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) {
return ret;
2015-12-03 12:37:49 -08:00
}
}
#endif
2015-12-03 12:37:49 -08:00
if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0) {
return ret;
2015-12-03 12:37:49 -08:00
}
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2015-12-03 12:37:49 -08:00
if (ssl->hsInfoOn) {
AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
2015-12-03 12:37:49 -08:00
}
if (ssl->toInfoOn) {
AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
output, sendSz, ssl->heap);
2015-12-03 12:37:49 -08:00
}
#endif
ssl->buffers.outputBuffer.length += sendSz;
2015-12-03 12:37:49 -08:00
if (ssl->options.groupMessages) {
ret = 0;
2015-12-03 12:37:49 -08:00
}
else {
ret = SendBuffered(ssl);
2015-12-03 12:37:49 -08:00
}
ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
2015-12-03 12:37:49 -08:00
break;
}
#endif /* NO_DH */
2015-12-03 12:37:49 -08:00
default:
break;
} /* switch(ssl->specs.kea) */
2014-04-10 14:13:18 -07:00
return ret;
#undef ERROR_OUT
}
/* Make sure server cert/key are valid for this suite, true on success */
2014-12-19 11:27:01 -07:00
static int VerifyServerSuite(WOLFSSL* ssl, word16 idx)
{
int haveRSA = !ssl->options.haveStaticECC;
int havePSK = 0;
byte first;
byte second;
2014-12-19 11:27:01 -07:00
WOLFSSL_ENTER("VerifyServerSuite");
if (ssl->suites == NULL) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Suites pointer error");
return 0;
}
first = ssl->suites->suites[idx];
second = ssl->suites->suites[idx+1];
#ifndef NO_PSK
havePSK = ssl->options.havePSK;
#endif
2015-07-11 12:52:22 -06:00
if (ssl->options.haveNTRU)
haveRSA = 0;
if (CipherRequires(first, second, REQUIRES_RSA)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Requires RSA");
if (haveRSA == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Don't have RSA");
return 0;
}
}
if (CipherRequires(first, second, REQUIRES_DHE)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Requires DHE");
if (ssl->options.haveDH == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Don't have DHE");
return 0;
}
}
if (CipherRequires(first, second, REQUIRES_ECC_DSA)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Requires ECCDSA");
if (ssl->options.haveECDSAsig == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Don't have ECCDSA");
return 0;
}
}
if (CipherRequires(first, second, REQUIRES_ECC_STATIC)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Requires static ECC");
if (ssl->options.haveStaticECC == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Don't have static ECC");
return 0;
}
}
if (CipherRequires(first, second, REQUIRES_PSK)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Requires PSK");
if (havePSK == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Don't have PSK");
return 0;
}
}
if (CipherRequires(first, second, REQUIRES_NTRU)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Requires NTRU");
if (ssl->options.haveNTRU == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Don't have NTRU");
return 0;
}
}
if (CipherRequires(first, second, REQUIRES_RSA_SIG)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Requires RSA Signature");
if (ssl->options.side == WOLFSSL_SERVER_END &&
2013-08-09 17:27:15 -07:00
ssl->options.haveECDSAsig == 1) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Don't have RSA Signature");
return 0;
}
}
#ifdef HAVE_SUPPORTED_CURVES
2014-01-14 15:39:06 -03:00
if (!TLSX_ValidateEllipticCurves(ssl, first, second)) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Don't have matching curves");
2014-01-14 15:39:06 -03:00
return 0;
}
#endif
/* ECCDHE is always supported if ECC on */
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
/* need to negotiate a classic suite in addition to TLS_QSH */
if (first == QSH_BYTE && second == TLS_QSH) {
if (TLSX_SupportExtensions(ssl)) {
2015-07-11 12:52:22 -06:00
ssl->options.haveQSH = 1; /* matched TLS_QSH */
2015-07-07 09:55:58 -06:00
}
else {
WOLFSSL_MSG("Version of SSL connection does not support TLS_QSH");
}
return 0;
}
#endif
return 1;
}
2014-12-19 11:27:01 -07:00
static int MatchSuite(WOLFSSL* ssl, Suites* peerSuites)
2011-02-05 11:14:47 -08:00
{
word16 i, j;
2014-12-19 11:27:01 -07:00
WOLFSSL_ENTER("MatchSuite");
2011-02-05 11:14:47 -08:00
/* & 0x1 equivalent % 2 */
if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1)
return MATCH_SUITE_ERROR;
if (ssl->suites == NULL)
return SUITES_ERROR;
2011-02-05 11:14:47 -08:00
/* start with best, if a match we are good */
for (i = 0; i < ssl->suites->suiteSz; i += 2)
2011-02-05 11:14:47 -08:00
for (j = 0; j < peerSuites->suiteSz; j += 2)
if (ssl->suites->suites[i] == peerSuites->suites[j] &&
ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) {
2011-02-05 11:14:47 -08:00
if (VerifyServerSuite(ssl, i)) {
2013-02-18 14:36:50 -08:00
int result;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Verified suite validity");
ssl->options.cipherSuite0 = ssl->suites->suites[i];
ssl->options.cipherSuite = ssl->suites->suites[i+1];
2013-02-18 14:36:50 -08:00
result = SetCipherSpecs(ssl);
if (result == 0)
PickHashSigAlgo(ssl, peerSuites->hashSigAlgo,
peerSuites->hashSigAlgoSz);
return result;
}
else {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Could not verify suite validity, continue");
}
2011-02-05 11:14:47 -08:00
}
return MATCH_SUITE_ERROR;
}
#ifdef OLD_HELLO_ALLOWED
2011-04-27 17:31:08 -07:00
/* process old style client hello, deprecate? */
2014-12-19 11:27:01 -07:00
int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
2011-02-05 11:14:47 -08:00
word32 inSz, word16 sz)
{
word32 idx = *inOutIdx;
word16 sessionSz;
word16 randomSz;
word16 i, j;
ProtocolVersion pv;
Suites clSuites;
2011-04-27 17:31:08 -07:00
(void)inSz;
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Got old format client hello");
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn)
AddPacketName("ClientHello", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddLateName("ClientHello", &ssl->timeoutInfo);
#endif
/* manually hash input since different format */
#ifndef NO_OLD_TLS
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, input + idx, sz);
#endif
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, input + idx, sz);
#endif
#endif
2011-02-28 12:21:06 -08:00
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl)) {
int shaRet = wc_Sha256Update(&ssl->hsHashes->hashSha256,
input + idx, sz);
if (shaRet != 0)
return shaRet;
}
2011-02-28 12:21:06 -08:00
#endif
2011-02-05 11:14:47 -08:00
/* does this value mean client_hello? */
idx++;
/* version */
pv.major = input[idx++];
pv.minor = input[idx++];
ssl->chVersion = pv; /* store */
if (ssl->version.minor > pv.minor) {
2012-10-29 15:39:42 -07:00
byte haveRSA = 0;
byte havePSK = 0;
if (!ssl->options.downgrade) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Client trying to connect with lesser version");
2011-02-05 11:14:47 -08:00
return VERSION_ERROR;
}
if (pv.minor < ssl->options.minDowngrade) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" version below minimum allowed, fatal error");
return VERSION_ERROR;
}
if (pv.minor == SSLv3_MINOR) {
/* turn off tls */
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" downgrading to SSLv3");
ssl->options.tls = 0;
ssl->options.tls1_1 = 0;
ssl->version.minor = SSLv3_MINOR;
}
else if (pv.minor == TLSv1_MINOR) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" downgrading to TLSv1");
/* turn off tls 1.1+ */
ssl->options.tls1_1 = 0;
ssl->version.minor = TLSv1_MINOR;
}
else if (pv.minor == TLSv1_1_MINOR) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" downgrading to TLSv1.1");
ssl->version.minor = TLSv1_1_MINOR;
}
2012-10-29 15:39:42 -07:00
#ifndef NO_RSA
haveRSA = 1;
#endif
#ifndef NO_PSK
havePSK = ssl->options.havePSK;
#endif
2012-10-29 15:39:42 -07:00
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
ssl->options.haveDH, ssl->options.haveNTRU,
ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
ssl->options.side);
2011-02-05 11:14:47 -08:00
}
/* suite size */
ato16(&input[idx], &clSuites.suiteSz);
idx += 2;
if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
2011-02-05 11:14:47 -08:00
return BUFFER_ERROR;
clSuites.hashSigAlgoSz = 0;
2011-02-05 11:14:47 -08:00
/* session size */
ato16(&input[idx], &sessionSz);
idx += 2;
if (sessionSz > ID_LEN)
return BUFFER_ERROR;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* random size */
ato16(&input[idx], &randomSz);
idx += 2;
if (randomSz > RAN_LEN)
return BUFFER_ERROR;
/* suites */
2014-10-24 10:33:24 -03:00
for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) {
2011-02-05 11:14:47 -08:00
byte first = input[idx++];
if (!first) { /* implicit: skip sslv2 type */
XMEMCPY(&clSuites.suites[j], &input[idx], 2);
j += 2;
}
idx += 2;
}
clSuites.suiteSz = j;
/* session id */
if (sessionSz) {
2012-09-14 21:19:06 -07:00
XMEMCPY(ssl->arrays->sessionID, input + idx, sessionSz);
ssl->arrays->sessionIDSz = (byte)sessionSz;
2011-02-05 11:14:47 -08:00
idx += sessionSz;
ssl->options.resuming = 1;
}
/* random */
if (randomSz < RAN_LEN)
2012-09-14 21:19:06 -07:00
XMEMSET(ssl->arrays->clientRandom, 0, RAN_LEN - randomSz);
XMEMCPY(&ssl->arrays->clientRandom[RAN_LEN - randomSz], input + idx,
2011-02-05 11:14:47 -08:00
randomSz);
idx += randomSz;
if (ssl->options.usingCompression)
ssl->options.usingCompression = 0; /* turn off */
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
*inOutIdx = idx;
2012-05-17 10:55:42 -07:00
ssl->options.haveSessionId = 1;
2011-02-05 11:14:47 -08:00
/* DoClientHello uses same resume code */
2012-12-11 11:33:49 -08:00
if (ssl->options.resuming) { /* let's try */
2014-10-24 10:33:24 -03:00
int ret = -1;
WOLFSSL_SESSION* session = GetSession(ssl,
ssl->arrays->masterSecret);
#ifdef HAVE_SESSION_TICKET
if (ssl->options.useTicket == 1) {
session = &ssl->session;
}
#endif
2011-02-05 11:14:47 -08:00
if (!session) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Session lookup for resume failed");
2011-02-05 11:14:47 -08:00
ssl->options.resuming = 0;
2012-12-11 11:33:49 -08:00
} else {
if (MatchSuite(ssl, &clSuites) < 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Unsupported cipher suite, OldClientHello");
2012-12-11 11:33:49 -08:00
return UNSUPPORTED_SUITE;
}
#ifdef SESSION_CERTS
ssl->session = *session; /* restore session certs. */
#endif
2015-01-01 07:33:07 -07:00
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
RAN_LEN);
if (ret != 0)
return ret;
2013-05-09 15:33:37 -07:00
#ifdef NO_OLD_TLS
ret = DeriveTlsKeys(ssl);
2013-05-09 15:33:37 -07:00
#else
#ifndef NO_TLS
if (ssl->options.tls)
ret = DeriveTlsKeys(ssl);
#endif
if (!ssl->options.tls)
ret = DeriveKeys(ssl);
2012-12-11 11:33:49 -08:00
#endif
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
2011-02-05 11:14:47 -08:00
2012-12-11 11:33:49 -08:00
return ret;
}
2011-02-05 11:14:47 -08:00
}
return MatchSuite(ssl, &clSuites);
}
#endif /* OLD_HELLO_ALLOWED */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
static int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32 helloSz)
2011-02-05 11:14:47 -08:00
{
byte b;
2011-02-05 11:14:47 -08:00
ProtocolVersion pv;
Suites clSuites;
word32 i = *inOutIdx;
word32 begin = i;
#ifdef WOLFSSL_DTLS
Hmac cookieHmac;
byte peerCookie[MAX_COOKIE_LEN];
2015-09-14 17:13:16 -07:00
byte peerCookieSz = 0;
byte cookieType;
byte cookieSz;
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
#endif
/* protocol version, random and session id length check */
if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
/* protocol version */
XMEMCPY(&pv, input + i, OPAQUE16_LEN);
2011-02-05 11:14:47 -08:00
ssl->chVersion = pv; /* store */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
int ret;
#if defined(NO_SHA) && defined(NO_SHA256)
#error "DTLS needs either SHA or SHA-256"
#endif /* NO_SHA && NO_SHA256 */
2016-01-04 15:03:39 -07:00
#if !defined(NO_SHA) && defined(NO_SHA256)
cookieType = SHA;
cookieSz = SHA_DIGEST_SIZE;
#endif /* NO_SHA */
#ifndef NO_SHA256
cookieType = SHA256;
cookieSz = SHA256_DIGEST_SIZE;
#endif /* NO_SHA256 */
ret = wc_HmacSetKey(&cookieHmac, cookieType,
ssl->buffers.dtlsCookieSecret.buffer,
ssl->buffers.dtlsCookieSecret.length);
if (ret != 0) return ret;
ret = wc_HmacUpdate(&cookieHmac,
ssl->buffers.dtlsCtx.peer.sa,
ssl->buffers.dtlsCtx.peer.sz);
if (ret != 0) return ret;
ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN);
if (ret != 0) return ret;
}
#endif /* WOLFSSL_DTLS */
i += OPAQUE16_LEN;
if ((!ssl->options.dtls && ssl->version.minor > pv.minor) ||
(ssl->options.dtls && ssl->version.minor != DTLS_MINOR
&& ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR
&& pv.minor != DTLSv1_2_MINOR)) {
2015-12-21 16:11:02 -07:00
word16 haveRSA = 0;
word16 havePSK = 0;
if (!ssl->options.downgrade) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Client trying to connect with lesser version");
2011-02-05 11:14:47 -08:00
return VERSION_ERROR;
}
if (pv.minor < ssl->options.minDowngrade) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" version below minimum allowed, fatal error");
return VERSION_ERROR;
}
if (pv.minor == SSLv3_MINOR) {
/* turn off tls */
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" downgrading to SSLv3");
ssl->options.tls = 0;
ssl->options.tls1_1 = 0;
ssl->version.minor = SSLv3_MINOR;
}
else if (pv.minor == TLSv1_MINOR) {
/* turn off tls 1.1+ */
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" downgrading to TLSv1");
ssl->options.tls1_1 = 0;
ssl->version.minor = TLSv1_MINOR;
}
else if (pv.minor == TLSv1_1_MINOR) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG(" downgrading to TLSv1.1");
ssl->version.minor = TLSv1_1_MINOR;
}
2012-10-29 15:39:42 -07:00
#ifndef NO_RSA
haveRSA = 1;
#endif
#ifndef NO_PSK
havePSK = ssl->options.havePSK;
#endif
2012-10-29 15:39:42 -07:00
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
ssl->options.haveDH, ssl->options.haveNTRU,
ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
ssl->options.side);
2011-02-05 11:14:47 -08:00
}
2011-02-05 11:14:47 -08:00
/* random */
2012-09-14 21:19:06 -07:00
XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
int ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN);
if (ret != 0) return ret;
}
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
i += RAN_LEN;
#ifdef SHOW_SECRETS
{
int j;
printf("client random: ");
for (j = 0; j < RAN_LEN; j++)
2012-09-14 21:19:06 -07:00
printf("%02x", ssl->arrays->clientRandom[j]);
2011-02-05 11:14:47 -08:00
printf("\n");
}
#endif
2011-02-05 11:14:47 -08:00
/* session id */
b = input[i++];
if (b == ID_LEN) {
if ((i - begin) + ID_LEN > helloSz)
return BUFFER_ERROR;
2012-09-14 21:19:06 -07:00
XMEMCPY(ssl->arrays->sessionID, input + i, ID_LEN);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
int ret = wc_HmacUpdate(&cookieHmac, input + i - 1, ID_LEN + 1);
if (ret != 0) return ret;
}
#endif /* WOLFSSL_DTLS */
ssl->arrays->sessionIDSz = ID_LEN;
i += ID_LEN;
ssl->options.resuming = 1; /* client wants to resume */
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Client wants to resume session");
2011-02-05 11:14:47 -08:00
}
else if (b) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Invalid session ID size");
return BUFFER_ERROR; /* session ID nor 0 neither 32 bytes long */
}
2014-10-24 10:33:24 -03:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
/* cookie */
if (ssl->options.dtls) {
if ((i - begin) + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
peerCookieSz = input[i++];
if (peerCookieSz) {
if (peerCookieSz > MAX_COOKIE_LEN)
2011-02-05 11:14:47 -08:00
return BUFFER_ERROR;
if ((i - begin) + peerCookieSz > helloSz)
return BUFFER_ERROR;
XMEMCPY(peerCookie, input + i, peerCookieSz);
i += peerCookieSz;
2011-02-05 11:14:47 -08:00
}
}
#endif
/* suites */
if ((i - begin) + OPAQUE16_LEN > helloSz)
return BUFFER_ERROR;
2011-02-05 11:14:47 -08:00
ato16(&input[i], &clSuites.suiteSz);
i += OPAQUE16_LEN;
/* suites and compression length check */
if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
2011-02-05 11:14:47 -08:00
if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
2011-02-05 11:14:47 -08:00
return BUFFER_ERROR;
2011-02-05 11:14:47 -08:00
XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
int ret = wc_HmacUpdate(&cookieHmac,
input + i - OPAQUE16_LEN,
clSuites.suiteSz + OPAQUE16_LEN);
if (ret != 0) return ret;
}
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
i += clSuites.suiteSz;
2013-02-18 14:36:50 -08:00
clSuites.hashSigAlgoSz = 0;
2011-02-05 11:14:47 -08:00
/* compression length */
b = input[i++];
if ((i - begin) + b > helloSz)
return BUFFER_ERROR;
2011-02-05 11:14:47 -08:00
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
byte newCookie[MAX_COOKIE_LEN];
int ret;
ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
if (ret != 0) return ret;
ret = wc_HmacFinal(&cookieHmac, newCookie);
if (ret != 0) return ret;
/* If a cookie callback is set, call it to overwrite the cookie.
* This should be deprecated. The code now calculates the cookie
* using an HMAC as expected. */
if (ssl->ctx->CBIOCookie != NULL &&
ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz,
ssl->IOCB_CookieCtx) != cookieSz) {
return COOKIE_ERROR;
}
/* Check the cookie, see if we progress the state machine. */
if (peerCookieSz != cookieSz ||
XMEMCMP(peerCookie, newCookie, cookieSz) != 0) {
/* Send newCookie to client in a HelloVerifyRequest message
* and let the state machine alone. */
ssl->msgsReceived.got_client_hello = 0;
*inOutIdx += helloSz;
return SendHelloVerifyRequest(ssl, newCookie, cookieSz);
}
/* This was skipped in the DTLS case so we could handle the hello
* verify request. */
ret = HashInput(ssl, input + *inOutIdx, helloSz);
if (ret != 0) return ret;
}
#endif /* WOLFSSL_DTLS */
2011-02-05 11:14:47 -08:00
if (ssl->options.usingCompression) {
int match = 0;
2011-02-05 11:14:47 -08:00
while (b--) {
byte comp = input[i++];
2011-02-05 11:14:47 -08:00
if (comp == ZLIB_COMPRESSION)
match = 1;
}
2011-04-25 09:24:21 -07:00
if (!match) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Not matching compression, turning off");
2011-02-05 11:14:47 -08:00
ssl->options.usingCompression = 0; /* turn off */
2011-04-25 09:24:21 -07:00
}
2011-02-05 11:14:47 -08:00
}
else
i += b; /* ignore, since we're not on */
2011-02-05 11:14:47 -08:00
*inOutIdx = i;
/* tls extensions */
if ((i - begin) < helloSz) {
2013-05-21 14:37:50 -07:00
#ifdef HAVE_TLS_EXTENSIONS
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
QSH_Init(ssl);
#endif
2014-06-25 11:52:37 -03:00
if (TLSX_SupportExtensions(ssl)) {
2013-05-21 14:37:50 -07:00
int ret = 0;
#else
2013-02-18 14:36:50 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
2013-05-21 14:37:50 -07:00
#endif
2013-02-18 14:36:50 -08:00
/* Process the hello extension. Skip unsupported. */
word16 totalExtSz;
#ifdef HAVE_TLS_EXTENSIONS
/* auto populate extensions supported unless user defined */
if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
return ret;
#endif
if ((i - begin) + OPAQUE16_LEN > helloSz)
return BUFFER_ERROR;
2013-02-18 14:36:50 -08:00
ato16(&input[i], &totalExtSz);
i += OPAQUE16_LEN;
if ((i - begin) + totalExtSz > helloSz)
return BUFFER_ERROR;
2013-05-21 14:37:50 -07:00
#ifdef HAVE_TLS_EXTENSIONS
2015-07-07 09:55:58 -06:00
/* tls extensions */
2013-05-21 14:37:50 -07:00
if ((ret = TLSX_Parse(ssl, (byte *) input + i,
totalExtSz, 1, &clSuites)))
return ret;
#ifdef HAVE_STUNNEL
if((ret=SNI_Callback(ssl)))
return ret;
#endif /*HAVE_STUNNEL*/
2013-05-21 14:37:50 -07:00
i += totalExtSz;
#else
2013-02-18 14:36:50 -08:00
while (totalExtSz) {
word16 extId, extSz;
if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz)
return BUFFER_ERROR;
2014-10-24 10:33:24 -03:00
2013-02-18 14:36:50 -08:00
ato16(&input[i], &extId);
i += OPAQUE16_LEN;
2013-02-18 14:36:50 -08:00
ato16(&input[i], &extSz);
i += OPAQUE16_LEN;
if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz)
return BUFFER_ERROR;
2013-02-18 14:36:50 -08:00
if (extId == HELLO_EXT_SIG_ALGO) {
ato16(&input[i], &clSuites.hashSigAlgoSz);
i += OPAQUE16_LEN;
if (OPAQUE16_LEN + clSuites.hashSigAlgoSz > extSz)
return BUFFER_ERROR;
2013-02-18 14:36:50 -08:00
XMEMCPY(clSuites.hashSigAlgo, &input[i],
min(clSuites.hashSigAlgoSz, HELLO_EXT_SIGALGO_MAX));
i += clSuites.hashSigAlgoSz;
if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX)
clSuites.hashSigAlgoSz = HELLO_EXT_SIGALGO_MAX;
2013-02-18 14:36:50 -08:00
}
else
i += extSz;
totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
2013-02-18 14:36:50 -08:00
}
2013-05-21 14:37:50 -07:00
#endif
2013-02-18 14:36:50 -08:00
*inOutIdx = i;
}
else
*inOutIdx = begin + helloSz; /* skip extensions */
2013-02-18 14:36:50 -08:00
}
2013-05-21 14:37:50 -07:00
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
2012-05-17 10:55:42 -07:00
ssl->options.haveSessionId = 1;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
/* ProcessOld uses same resume code */
if (ssl->options.resuming) {
2014-10-24 10:33:24 -03:00
int ret = -1;
WOLFSSL_SESSION* session = GetSession(ssl,
ssl->arrays->masterSecret);
#ifdef HAVE_SESSION_TICKET
if (ssl->options.useTicket == 1) {
session = &ssl->session;
}
#endif
2011-02-05 11:14:47 -08:00
if (!session) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Session lookup for resume failed");
2012-12-11 11:33:49 -08:00
ssl->options.resuming = 0;
}
else {
2012-12-11 11:33:49 -08:00
if (MatchSuite(ssl, &clSuites) < 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
2012-12-11 11:33:49 -08:00
return UNSUPPORTED_SUITE;
}
#ifdef SESSION_CERTS
ssl->session = *session; /* restore session certs. */
#endif
2015-01-01 07:33:07 -07:00
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
RAN_LEN);
if (ret != 0)
return ret;
2013-05-09 15:33:37 -07:00
#ifdef NO_OLD_TLS
ret = DeriveTlsKeys(ssl);
2013-05-09 15:33:37 -07:00
#else
#ifndef NO_TLS
if (ssl->options.tls)
ret = DeriveTlsKeys(ssl);
#endif
if (!ssl->options.tls)
ret = DeriveKeys(ssl);
2012-12-11 11:33:49 -08:00
#endif
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
2011-02-05 11:14:47 -08:00
2012-12-11 11:33:49 -08:00
return ret;
}
2011-02-05 11:14:47 -08:00
}
return MatchSuite(ssl, &clSuites);
}
2012-10-29 15:39:42 -07:00
#if !defined(NO_RSA) || defined(HAVE_ECC)
2014-12-19 11:27:01 -07:00
static int DoCertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 size)
2011-02-05 11:14:47 -08:00
{
word16 sz = 0;
int ret = VERIFY_CERT_ERROR; /* start in error state */
2013-02-18 14:36:50 -08:00
byte hashAlgo = sha_mac;
2013-02-25 10:47:55 -08:00
byte sigAlgo = anonymous_sa_algo;
word32 begin = *inOutIdx;
2013-03-07 18:10:18 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn)
AddPacketName("CertificateVerify", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddLateName("CertificateVerify", &ssl->timeoutInfo);
#endif
2011-02-05 11:14:47 -08:00
2013-02-18 14:36:50 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size)
return BUFFER_ERROR;
2011-02-05 11:14:47 -08:00
hashAlgo = input[(*inOutIdx)++];
sigAlgo = input[(*inOutIdx)++];
}
2011-02-05 11:14:47 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
2011-02-05 11:14:47 -08:00
return BUFFER_ERROR;
ato16(input + *inOutIdx, &sz);
*inOutIdx += OPAQUE16_LEN;
if ((*inOutIdx - begin) + sz > size || sz > ENCRYPT_LEN)
return BUFFER_ERROR;
2012-05-02 10:30:15 -07:00
/* RSA */
2012-10-29 15:39:42 -07:00
#ifndef NO_RSA
if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
2014-03-02 11:11:39 -08:00
byte* out = NULL;
int outLen = 0;
byte doUserRsa = 0;
#ifdef HAVE_PK_CALLBACKS
if (ssl->ctx->RsaVerifyCb)
doUserRsa = 1;
#endif /*HAVE_PK_CALLBACKS */
2013-06-13 12:13:46 -07:00
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Doing RSA peer cert verify");
2012-05-02 10:30:15 -07:00
if (doUserRsa) {
#ifdef HAVE_PK_CALLBACKS
outLen = ssl->ctx->RsaVerifyCb(ssl, input + *inOutIdx, sz,
2014-10-24 10:33:24 -03:00
&out,
ssl->buffers.peerRsaKey.buffer,
ssl->buffers.peerRsaKey.length,
ssl->RsaVerifyCtx);
#endif /*HAVE_PK_CALLBACKS */
}
else {
outLen = wc_RsaSSL_VerifyInline(input + *inOutIdx, sz, &out,
ssl->peerRsaKey);
}
2011-02-05 11:14:47 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
byte* encodedSig = NULL;
#else
2011-02-05 11:14:47 -08:00
byte encodedSig[MAX_ENCODED_SIG_SZ];
#endif
2011-02-05 11:14:47 -08:00
word32 sigSz;
byte* digest = ssl->hsHashes->certHashes.sha;
2013-02-18 14:36:50 -08:00
int typeH = SHAh;
int digestSz = SHA_DIGEST_SIZE;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (encodedSig == NULL)
return MEMORY_E;
#endif
if (sigAlgo != rsa_sa_algo) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Oops, peer sent RSA key but not in verify");
}
2013-02-18 14:36:50 -08:00
if (hashAlgo == sha256_mac) {
#ifndef NO_SHA256
digest = ssl->hsHashes->certHashes.sha256;
2013-02-18 14:36:50 -08:00
typeH = SHA256h;
digestSz = SHA256_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha384_mac) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
digest = ssl->hsHashes->certHashes.sha384;
2013-02-18 14:36:50 -08:00
typeH = SHA384h;
digestSz = SHA384_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha512_mac) {
#ifdef WOLFSSL_SHA512
digest = ssl->hsHashes->certHashes.sha512;
typeH = SHA512h;
digestSz = SHA512_DIGEST_SIZE;
#endif
}
2011-02-05 11:14:47 -08:00
2014-12-30 15:14:27 -07:00
sigSz = wc_EncodeSignature(encodedSig, digest, digestSz, typeH);
2011-02-05 11:14:47 -08:00
2014-03-02 11:11:39 -08:00
if (outLen == (int)sigSz && out && XMEMCMP(out, encodedSig,
2012-06-01 15:25:46 -07:00
min(sigSz, MAX_ENCODED_SIG_SZ)) == 0)
ret = 0; /* verified */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SMALL_STACK
XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
2011-02-05 11:14:47 -08:00
}
else {
2014-03-02 11:11:39 -08:00
if (outLen == FINISHED_SZ && out && XMEMCMP(out,
&ssl->hsHashes->certHashes,
FINISHED_SZ) == 0) {
ret = 0; /* verified */
}
2011-02-05 11:14:47 -08:00
}
}
2012-10-29 15:39:42 -07:00
#endif
2012-05-02 10:30:15 -07:00
#ifdef HAVE_ECC
2012-10-29 15:39:42 -07:00
if (ssl->peerEccDsaKeyPresent) {
2012-05-02 10:30:15 -07:00
int verify = 0;
int err = -1;
byte* digest = ssl->hsHashes->certHashes.sha;
2013-02-18 14:36:50 -08:00
word32 digestSz = SHA_DIGEST_SIZE;
byte doUserEcc = 0;
#ifdef HAVE_PK_CALLBACKS
if (ssl->ctx->EccVerifyCb)
doUserEcc = 1;
#endif
2012-05-02 10:30:15 -07:00
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Doing ECC peer cert verify");
2012-05-02 10:30:15 -07:00
2013-02-18 14:36:50 -08:00
if (IsAtLeastTLSv1_2(ssl)) {
if (sigAlgo != ecc_dsa_sa_algo) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
}
2013-02-18 14:36:50 -08:00
if (hashAlgo == sha256_mac) {
#ifndef NO_SHA256
digest = ssl->hsHashes->certHashes.sha256;
2013-02-18 14:36:50 -08:00
digestSz = SHA256_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha384_mac) {
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_SHA384
digest = ssl->hsHashes->certHashes.sha384;
2013-02-18 14:36:50 -08:00
digestSz = SHA384_DIGEST_SIZE;
#endif
}
else if (hashAlgo == sha512_mac) {
#ifdef WOLFSSL_SHA512
digest = ssl->hsHashes->certHashes.sha512;
digestSz = SHA512_DIGEST_SIZE;
#endif
}
2013-02-18 14:36:50 -08:00
}
if (doUserEcc) {
#ifdef HAVE_PK_CALLBACKS
ret = ssl->ctx->EccVerifyCb(ssl, input + *inOutIdx, sz, digest,
digestSz,
ssl->buffers.peerEccDsaKey.buffer,
ssl->buffers.peerEccDsaKey.length,
&verify, ssl->EccVerifyCtx);
#endif
}
else {
err = wc_ecc_verify_hash(input + *inOutIdx, sz, digest,
digestSz, &verify, ssl->peerEccDsaKey);
}
2012-05-02 10:30:15 -07:00
if (err == 0 && verify == 1)
ret = 0; /* verified */
2012-05-02 10:30:15 -07:00
}
#endif
*inOutIdx += sz;
if (ret == 0)
ssl->options.havePeerVerify = 1;
2014-10-24 10:33:24 -03:00
2011-02-05 11:14:47 -08:00
return ret;
}
2012-10-29 15:39:42 -07:00
#endif /* !NO_RSA || HAVE_ECC */
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
int SendServerHelloDone(WOLFSSL* ssl)
2011-02-05 11:14:47 -08:00
{
byte *output;
int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
int ret;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2011-02-05 11:14:47 -08:00
if (ssl->options.dtls)
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
#endif
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
2011-02-05 11:14:47 -08:00
return ret;
/* get ouput buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
AddHeaders(output, 0, server_hello_done, ssl);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
2012-09-14 09:35:34 -07:00
if (ssl->options.dtls) {
if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0)
return 0;
2012-09-14 09:35:34 -07:00
}
#endif
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0)
return ret;
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn)
AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz,
ssl->heap);
#endif
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
ssl->buffers.outputBuffer.length += sendSz;
return SendBuffered(ssl);
}
#ifdef HAVE_SESSION_TICKET
#define WOLFSSL_TICKET_FIXED_SZ (WOLFSSL_TICKET_NAME_SZ + \
WOLFSSL_TICKET_IV_SZ + WOLFSSL_TICKET_MAC_SZ + LENGTH_SZ)
#define WOLFSSL_TICKET_ENC_SZ (SESSION_TICKET_LEN - WOLFSSL_TICKET_FIXED_SZ)
/* our ticket format */
typedef struct InternalTicket {
ProtocolVersion pv; /* version when ticket created */
byte suite[SUITE_LEN]; /* cipher suite when created */
byte msecret[SECRET_LEN]; /* master secret */
word32 timestamp; /* born on */
} InternalTicket;
/* fit within SESSION_TICKET_LEN */
typedef struct ExternalTicket {
byte key_name[WOLFSSL_TICKET_NAME_SZ]; /* key context name */
byte iv[WOLFSSL_TICKET_IV_SZ]; /* this ticket's iv */
byte enc_len[LENGTH_SZ]; /* encrypted length */
byte enc_ticket[WOLFSSL_TICKET_ENC_SZ]; /* encrypted internal ticket */
byte mac[WOLFSSL_TICKET_MAC_SZ]; /* total mac */
/* !! if add to structure, add to TICKET_FIXED_SZ !! */
} ExternalTicket;
/* create a new session ticket, 0 on success */
static int CreateTicket(WOLFSSL* ssl)
{
InternalTicket it;
ExternalTicket* et = (ExternalTicket*)ssl->session.ticket;
int encLen;
int ret;
byte zeros[WOLFSSL_TICKET_MAC_SZ]; /* biggest cmp size */
/* build internal */
it.pv.major = ssl->version.major;
it.pv.minor = ssl->version.minor;
it.suite[0] = ssl->options.cipherSuite0;
it.suite[1] = ssl->options.cipherSuite;
XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN);
c32toa(LowResTimer(), (byte*)&it.timestamp);
/* build external */
XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket));
/* encrypt */
encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */
ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1,
et->enc_ticket, sizeof(InternalTicket),
&encLen, ssl->ctx->ticketEncCtx);
if (ret == WOLFSSL_TICKET_RET_OK) {
if (encLen < (int)sizeof(InternalTicket) ||
encLen > WOLFSSL_TICKET_ENC_SZ) {
WOLFSSL_MSG("Bad user ticket encrypt size");
return BAD_TICKET_KEY_CB_SZ;
}
/* sanity checks on encrypt callback */
/* internal ticket can't be the same if encrypted */
if (XMEMCMP(et->enc_ticket, &it, sizeof(InternalTicket)) == 0) {
WOLFSSL_MSG("User ticket encrypt didn't encrypt");
return BAD_TICKET_ENCRYPT;
}
XMEMSET(zeros, 0, sizeof(zeros));
/* name */
if (XMEMCMP(et->key_name, zeros, WOLFSSL_TICKET_NAME_SZ) == 0) {
WOLFSSL_MSG("User ticket encrypt didn't set name");
return BAD_TICKET_ENCRYPT;
}
/* iv */
if (XMEMCMP(et->iv, zeros, WOLFSSL_TICKET_IV_SZ) == 0) {
WOLFSSL_MSG("User ticket encrypt didn't set iv");
return BAD_TICKET_ENCRYPT;
}
/* mac */
if (XMEMCMP(et->mac, zeros, WOLFSSL_TICKET_MAC_SZ) == 0) {
WOLFSSL_MSG("User ticket encrypt didn't set mac");
return BAD_TICKET_ENCRYPT;
}
/* set size */
2015-05-15 16:10:38 -07:00
c16toa((word16)encLen, et->enc_len);
ssl->session.ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ);
if (encLen < WOLFSSL_TICKET_ENC_SZ) {
/* move mac up since whole enc buffer not used */
XMEMMOVE(et->enc_ticket +encLen, et->mac,WOLFSSL_TICKET_MAC_SZ);
}
}
return ret;
}
/* Parse ticket sent by client, returns callback return value */
int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len)
{
ExternalTicket* et;
InternalTicket* it;
int ret;
int outLen;
word16 inLen;
if (len > SESSION_TICKET_LEN ||
len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) {
return BAD_TICKET_MSG_SZ;
}
et = (ExternalTicket*)input;
it = (InternalTicket*)et->enc_ticket;
/* decrypt */
ato16(et->enc_len, &inLen);
if (inLen > (word16)(len - WOLFSSL_TICKET_FIXED_SZ)) {
return BAD_TICKET_MSG_SZ;
}
outLen = inLen; /* may be reduced by user padding */
ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv,
et->enc_ticket + inLen, 0,
et->enc_ticket, inLen, &outLen,
ssl->ctx->ticketEncCtx);
if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) return ret;
if (outLen > inLen || outLen < (int)sizeof(InternalTicket)) {
WOLFSSL_MSG("Bad user ticket decrypt len");
return BAD_TICKET_KEY_CB_SZ;
}
/* get master secret */
if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE)
XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
return ret;
}
/* send Session Ticket */
int SendTicket(WOLFSSL* ssl)
{
byte* output;
int ret;
int sendSz;
word32 length = SESSION_HINT_SZ + LENGTH_SZ;
word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
length += DTLS_RECORD_EXTRA;
idx += DTLS_RECORD_EXTRA;
}
#endif
if (ssl->options.createTicket) {
ret = CreateTicket(ssl);
if (ret != 0) return ret;
}
length += ssl->session.ticketLen;
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
/* get ouput buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
AddHeaders(output, length, session_ticket, ssl);
/* hint */
c32toa(ssl->ctx->ticketHint, output + idx);
idx += SESSION_HINT_SZ;
/* length */
c16toa(ssl->session.ticketLen, output + idx);
idx += LENGTH_SZ;
/* ticket */
XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen);
/* idx += ssl->session.ticketLen; */
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0) return ret;
ssl->buffers.outputBuffer.length += sendSz;
return SendBuffered(ssl);
}
#endif /* HAVE_SESSION_TICKET */
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_DTLS
static int SendHelloVerifyRequest(WOLFSSL* ssl,
const byte* cookie, byte cookieSz)
2011-02-05 11:14:47 -08:00
{
byte* output;
int length = VERSION_SZ + ENUM_LEN + cookieSz;
2011-02-05 11:14:47 -08:00
int idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
int sendSz = length + idx;
int ret;
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
2011-02-05 11:14:47 -08:00
return ret;
/* get ouput buffer */
output = ssl->buffers.outputBuffer.buffer +
ssl->buffers.outputBuffer.length;
2011-02-05 11:14:47 -08:00
/* Hello Verify Request should use the same sequence number as the
* Client Hello. */
ssl->keys.dtls_sequence_number = ssl->keys.dtls_state.curSeq;
2011-02-05 11:14:47 -08:00
AddHeaders(output, length, hello_verify_request, ssl);
{
DtlsRecordLayerHeader* rh = (DtlsRecordLayerHeader*)output;
rh->pvMajor = DTLS_MAJOR;
rh->pvMinor = DTLS_MINOR;
}
2011-02-05 11:14:47 -08:00
output[idx++] = DTLS_MAJOR;
output[idx++] = DTLS_MINOR;
output[idx++] = cookieSz;
if (cookie == NULL || cookieSz == 0)
return COOKIE_ERROR;
2011-02-05 11:14:47 -08:00
XMEMCPY(output + idx, cookie, cookieSz);
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2011-02-05 11:14:47 -08:00
if (ssl->hsInfoOn)
AddPacketName("HelloVerifyRequest", &ssl->handShakeInfo);
if (ssl->toInfoOn)
AddPacketInfo("HelloVerifyRequest", &ssl->timeoutInfo, output,
sendSz, ssl->heap);
#endif
ssl->buffers.outputBuffer.length += sendSz;
return SendBuffered(ssl);
}
#endif
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 size)
2011-02-05 11:14:47 -08:00
{
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
word16 name;
2015-09-15 17:46:45 -06:00
int qshSz;
2015-07-07 09:55:58 -06:00
#endif
2011-02-05 11:14:47 -08:00
int ret = 0;
word32 length = 0;
2012-11-13 18:32:13 -08:00
byte* out = NULL;
word32 begin = *inOutIdx;
2011-02-05 11:14:47 -08:00
2012-10-29 15:39:42 -07:00
(void)length; /* shut up compiler warnings */
(void)out;
(void)input;
(void)size;
2014-06-19 15:59:24 -07:00
(void)begin;
2012-10-29 15:39:42 -07:00
2014-12-19 11:27:01 -07:00
if (ssl->options.side != WOLFSSL_SERVER_END) {
WOLFSSL_MSG("Client received client keyexchange, attack?");
WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
return SSL_FATAL_ERROR;
}
if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Client sending keyexchange at wrong time");
SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E;
}
#ifndef NO_CERTS
2015-12-03 12:37:49 -08:00
if (ssl->options.verifyPeer && ssl->options.failNoCert) {
if (!ssl->options.havePeerCert) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("client didn't present peer cert");
return NO_PEER_CERT;
}
2015-12-03 12:37:49 -08:00
}
#endif
2011-02-05 11:14:47 -08:00
2014-12-19 11:27:01 -07:00
#ifdef WOLFSSL_CALLBACKS
2015-12-03 12:37:49 -08:00
if (ssl->hsInfoOn) {
2011-02-05 11:14:47 -08:00
AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
2015-12-03 12:37:49 -08:00
}
if (ssl->toInfoOn) {
2011-02-05 11:14:47 -08:00
AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
#endif
2012-10-29 15:39:42 -07:00
switch (ssl->specs.kea) {
#ifndef NO_RSA
2014-10-24 10:33:24 -03:00
case rsa_kea:
2012-10-29 15:39:42 -07:00
{
word32 idx = 0;
RsaKey key;
byte doUserRsa = 0;
#ifdef HAVE_PK_CALLBACKS
2015-12-03 12:37:49 -08:00
if (ssl->ctx->RsaDecCb) {
doUserRsa = 1;
2015-12-03 12:37:49 -08:00
}
#endif
2011-02-05 11:14:47 -08:00
ret = wc_InitRsaKey(&key, ssl->heap);
2015-12-03 12:37:49 -08:00
if (ret != 0) {
return ret;
}
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
if (!ssl->buffers.key.buffer) {
2012-10-29 15:39:42 -07:00
return NO_PRIVATE_KEY;
2015-12-03 12:37:49 -08:00
}
2016-01-18 20:48:12 -03:00
2015-12-03 12:37:49 -08:00
ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx,
&key, ssl->buffers.key.length);
2011-02-05 11:14:47 -08:00
2012-10-29 15:39:42 -07:00
if (ret == 0) {
length = wc_RsaEncryptSize(&key);
2012-10-29 15:39:42 -07:00
ssl->arrays->preMasterSz = SECRET_LEN;
2011-02-05 11:14:47 -08:00
2012-12-28 12:28:25 -08:00
if (ssl->options.tls) {
word16 check;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
2012-12-28 12:28:25 -08:00
ato16(input + *inOutIdx, &check);
*inOutIdx += OPAQUE16_LEN;
if ((word32) check != length) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("RSA explicit size doesn't match");
wc_FreeRsaKey(&key);
2012-12-28 12:28:25 -08:00
return RSA_PRIVATE_ERROR;
}
}
2012-10-29 15:39:42 -07:00
if ((*inOutIdx - begin) + length > size) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("RSA message too big");
wc_FreeRsaKey(&key);
return BUFFER_ERROR;
2012-12-28 12:28:25 -08:00
}
if (doUserRsa) {
#ifdef HAVE_PK_CALLBACKS
ret = ssl->ctx->RsaDecCb(ssl,
input + *inOutIdx, length, &out,
ssl->buffers.key.buffer,
ssl->buffers.key.length,
ssl->RsaDecCtx);
#endif
}
else {
ret = wc_RsaPrivateDecryptInline(input + *inOutIdx, length,
&out, &key);
}
*inOutIdx += length;
if (ret == SECRET_LEN) {
2012-10-29 15:39:42 -07:00
XMEMCPY(ssl->arrays->preMasterSecret, out, SECRET_LEN);
if (ssl->arrays->preMasterSecret[0] !=
ssl->chVersion.major
2014-10-24 10:33:24 -03:00
|| ssl->arrays->preMasterSecret[1] !=
2015-12-03 12:37:49 -08:00
ssl->chVersion.minor) {
2012-10-29 15:39:42 -07:00
ret = PMS_VERSION_ERROR;
2015-12-03 12:37:49 -08:00
}
2012-10-29 15:39:42 -07:00
else
2015-07-07 09:55:58 -06:00
{
#ifdef HAVE_QSH
2015-07-11 12:52:22 -06:00
if (ssl->options.haveQSH) {
2015-07-07 09:55:58 -06:00
/* extension name */
ato16(input + *inOutIdx, &name);
*inOutIdx += OPAQUE16_LEN;
2015-11-02 15:51:01 -03:00
if (name == TLSX_QUANTUM_SAFE_HYBRID) {
2015-09-15 17:46:45 -06:00
/* if qshSz is larger than 0 it is the
length of buffer used */
if ((qshSz = TLSX_QSHCipher_Parse(ssl, input
+ *inOutIdx, size - *inOutIdx
2015-12-03 12:37:49 -08:00
+ begin, 1)) < 0) {
2015-09-15 17:46:45 -06:00
return qshSz;
2015-12-03 12:37:49 -08:00
}
2015-09-15 17:46:45 -06:00
*inOutIdx += qshSz;
2015-07-07 09:55:58 -06:00
}
else {
/* unknown extension sent client ignored
handshake */
return BUFFER_ERROR;
}
}
#endif
2012-10-29 15:39:42 -07:00
ret = MakeMasterSecret(ssl);
2015-07-07 09:55:58 -06:00
}
2012-10-29 15:39:42 -07:00
}
else {
2012-10-29 15:39:42 -07:00
ret = RSA_PRIVATE_ERROR;
}
2011-02-05 11:14:47 -08:00
}
2012-10-29 15:39:42 -07:00
wc_FreeRsaKey(&key);
2011-02-05 11:14:47 -08:00
}
2012-10-29 15:39:42 -07:00
break;
#endif
#ifndef NO_PSK
case psk_kea:
{
byte* pms = ssl->arrays->preMasterSecret;
word16 ci_sz;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ato16(input + *inOutIdx, &ci_sz);
*inOutIdx += OPAQUE16_LEN;
2012-10-29 15:39:42 -07:00
2015-12-03 12:37:49 -08:00
if (ci_sz > MAX_PSK_ID_LEN) {
return CLIENT_ID_ERROR;
2015-12-03 12:37:49 -08:00
}
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + ci_sz > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
2012-10-29 15:39:42 -07:00
XMEMCPY(ssl->arrays->client_identity, input + *inOutIdx, ci_sz);
2012-10-29 15:39:42 -07:00
*inOutIdx += ci_sz;
ssl->arrays->client_identity[min(ci_sz, MAX_PSK_ID_LEN-1)] = 0;
2012-10-29 15:39:42 -07:00
ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
ssl->arrays->client_identity, ssl->arrays->psk_key,
MAX_PSK_KEY_LEN);
2014-10-24 10:33:24 -03:00
if (ssl->arrays->psk_keySz == 0 ||
2015-12-03 12:37:49 -08:00
ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
2012-10-29 15:39:42 -07:00
return PSK_KEY_ERROR;
2015-12-03 12:37:49 -08:00
}
2014-10-24 10:33:24 -03:00
2012-10-29 15:39:42 -07:00
/* make psk pre master secret */
/* length of key + length 0s + length of key + key */
c16toa((word16) ssl->arrays->psk_keySz, pms);
pms += OPAQUE16_LEN;
2012-10-29 15:39:42 -07:00
XMEMSET(pms, 0, ssl->arrays->psk_keySz);
pms += ssl->arrays->psk_keySz;
c16toa((word16) ssl->arrays->psk_keySz, pms);
pms += OPAQUE16_LEN;
2012-10-29 15:39:42 -07:00
XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4;
2011-02-05 11:14:47 -08:00
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
2015-07-11 12:52:22 -06:00
if (ssl->options.haveQSH) {
2015-07-07 09:55:58 -06:00
/* extension name */
ato16(input + *inOutIdx, &name);
*inOutIdx += OPAQUE16_LEN;
2015-11-02 15:51:01 -03:00
if (name == TLSX_QUANTUM_SAFE_HYBRID) {
2015-09-15 17:46:45 -06:00
/* if qshSz is larger than 0 it is the length of
buffer used */
if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx,
2015-12-03 12:37:49 -08:00
size - *inOutIdx + begin, 1)) < 0) {
2015-09-15 17:46:45 -06:00
return qshSz;
2015-12-03 12:37:49 -08:00
}
2015-09-15 17:46:45 -06:00
*inOutIdx += qshSz;
2015-07-07 09:55:58 -06:00
}
else {
/* unknown extension sent client ignored
handshake */
return BUFFER_ERROR;
}
}
#endif
2012-10-29 15:39:42 -07:00
ret = MakeMasterSecret(ssl);
2013-03-20 09:12:00 -07:00
/* No further need for PSK */
2015-02-20 15:51:21 -08:00
ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
2013-03-20 09:12:00 -07:00
ssl->arrays->psk_keySz = 0;
2012-10-29 15:39:42 -07:00
}
break;
#endif /* NO_PSK */
2015-07-11 12:52:22 -06:00
#ifdef HAVE_NTRU
case ntru_kea:
{
word16 cipherLen;
word16 plainLen = sizeof(ssl->arrays->preMasterSecret);
2015-12-03 12:37:49 -08:00
if (!ssl->buffers.key.buffer) {
2015-07-11 12:52:22 -06:00
return NO_PRIVATE_KEY;
2015-12-03 12:37:49 -08:00
}
2015-07-11 12:52:22 -06:00
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
2015-07-11 12:52:22 -06:00
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
2015-07-11 12:52:22 -06:00
ato16(input + *inOutIdx, &cipherLen);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if (cipherLen > MAX_NTRU_ENCRYPT_SZ) {
2015-07-11 12:52:22 -06:00
return NTRU_KEY_ERROR;
2015-12-03 12:37:49 -08:00
}
2015-07-11 12:52:22 -06:00
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + cipherLen > size) {
2015-07-11 12:52:22 -06:00
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
2015-07-11 12:52:22 -06:00
if (NTRU_OK != ntru_crypto_ntru_decrypt(
(word16) ssl->buffers.key.length,
ssl->buffers.key.buffer, cipherLen,
input + *inOutIdx, &plainLen,
2015-12-03 12:37:49 -08:00
ssl->arrays->preMasterSecret)) {
2015-07-11 12:52:22 -06:00
return NTRU_DECRYPT_ERROR;
2015-12-03 12:37:49 -08:00
}
2015-07-11 12:52:22 -06:00
2015-12-03 12:37:49 -08:00
if (plainLen != SECRET_LEN) {
2015-07-11 12:52:22 -06:00
return NTRU_DECRYPT_ERROR;
2015-12-03 12:37:49 -08:00
}
2015-07-11 12:52:22 -06:00
*inOutIdx += cipherLen;
#ifdef HAVE_QSH
if (ssl->options.haveQSH) {
/* extension name */
ato16(input + *inOutIdx, &name);
*inOutIdx += OPAQUE16_LEN;
2015-11-02 15:51:01 -03:00
if (name == TLSX_QUANTUM_SAFE_HYBRID) {
2015-09-15 17:46:45 -06:00
/* if qshSz is larger than 0 it is the length of
buffer used */
if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx,
2015-12-03 12:37:49 -08:00
size - *inOutIdx + begin, 1)) < 0) {
2015-09-15 17:46:45 -06:00
return qshSz;
2015-12-03 12:37:49 -08:00
}
2015-09-15 17:46:45 -06:00
*inOutIdx += qshSz;
2015-07-11 12:52:22 -06:00
}
else {
/* unknown extension sent client ignored
handshake */
return BUFFER_ERROR;
}
}
#endif
ssl->arrays->preMasterSz = plainLen;
ret = MakeMasterSecret(ssl);
}
break;
#endif /* HAVE_NTRU */
2012-10-29 15:39:42 -07:00
#ifdef HAVE_ECC
case ecc_diffie_hellman_kea:
{
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE8_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
length = input[(*inOutIdx)++];
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + length > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
if (ssl->peerEccKey == NULL) {
/* alloc/init on demand */
ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key),
ssl->ctx->heap, DYNAMIC_TYPE_ECC);
if (ssl->peerEccKey == NULL) {
WOLFSSL_MSG("PeerEccKey Memory error");
return MEMORY_E;
}
wc_ecc_init(ssl->peerEccKey);
} else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */
2014-12-30 15:14:27 -07:00
wc_ecc_free(ssl->peerEccKey);
ssl->peerEccKeyPresent = 0;
2014-12-30 15:14:27 -07:00
wc_ecc_init(ssl->peerEccKey);
}
2015-12-03 12:37:49 -08:00
if (wc_ecc_import_x963(input + *inOutIdx, length, ssl->peerEccKey)) {
2012-10-29 15:39:42 -07:00
return ECC_PEERKEY_ERROR;
2015-12-03 12:37:49 -08:00
}
*inOutIdx += length;
2012-10-29 15:39:42 -07:00
ssl->peerEccKeyPresent = 1;
2011-02-05 11:14:47 -08:00
length = sizeof(ssl->arrays->preMasterSecret);
2012-10-29 15:39:42 -07:00
if (ssl->specs.static_ecdh) {
ecc_key staticKey;
word32 i = 0;
2014-12-30 15:14:27 -07:00
wc_ecc_init(&staticKey);
ret = wc_EccPrivateKeyDecode(ssl->buffers.key.buffer, &i,
&staticKey, ssl->buffers.key.length);
2015-12-03 12:37:49 -08:00
if (ret == 0) {
2014-12-30 15:14:27 -07:00
ret = wc_ecc_shared_secret(&staticKey, ssl->peerEccKey,
ssl->arrays->preMasterSecret, &length);
2015-12-03 12:37:49 -08:00
}
2014-12-30 15:14:27 -07:00
wc_ecc_free(&staticKey);
2012-10-29 15:39:42 -07:00
}
else {
if (ssl->eccTempKeyPresent == 0) {
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Ecc ephemeral key not made correctly");
ret = ECC_MAKEKEY_ERROR;
} else {
2014-12-30 15:14:27 -07:00
ret = wc_ecc_shared_secret(ssl->eccTempKey,ssl->peerEccKey,
ssl->arrays->preMasterSecret, &length);
}
}
2015-12-03 12:37:49 -08:00
if (ret != 0) {
2012-10-29 15:39:42 -07:00
return ECC_SHARED_ERROR;
2015-12-03 12:37:49 -08:00
}
ssl->arrays->preMasterSz = length;
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
2015-07-11 12:52:22 -06:00
if (ssl->options.haveQSH) {
2015-07-07 09:55:58 -06:00
/* extension name */
ato16(input + *inOutIdx, &name);
*inOutIdx += OPAQUE16_LEN;
2015-11-02 15:51:01 -03:00
if (name == TLSX_QUANTUM_SAFE_HYBRID) {
2015-09-15 17:46:45 -06:00
/* if qshSz is larger than 0 it is the length of
buffer used */
if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx,
2015-12-03 12:37:49 -08:00
size - *inOutIdx + begin, 1)) < 0) {
2015-09-15 17:46:45 -06:00
return qshSz;
2015-12-03 12:37:49 -08:00
}
2015-09-15 17:46:45 -06:00
*inOutIdx += qshSz;
2015-07-07 09:55:58 -06:00
}
else {
/* unknown extension sent client ignored
handshake */
return BUFFER_ERROR;
}
}
#endif
2012-10-29 15:39:42 -07:00
ret = MakeMasterSecret(ssl);
}
break;
#endif /* HAVE_ECC */
#ifndef NO_DH
2012-10-29 15:39:42 -07:00
case diffie_hellman_kea:
{
word16 clientPubSz;
DhKey dhKey;
2011-02-05 11:14:47 -08:00
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
2011-02-05 11:14:47 -08:00
ato16(input + *inOutIdx, &clientPubSz);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + clientPubSz > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
2012-05-03 08:18:59 -07:00
2014-12-30 14:13:57 -07:00
wc_InitDhKey(&dhKey);
ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
2012-10-29 15:39:42 -07:00
ssl->buffers.serverDH_P.length,
ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length);
2015-12-03 12:37:49 -08:00
if (ret == 0) {
2014-12-30 14:13:57 -07:00
ret = wc_DhAgree(&dhKey, ssl->arrays->preMasterSecret,
2012-10-29 15:39:42 -07:00
&ssl->arrays->preMasterSz,
ssl->buffers.serverDH_Priv.buffer,
ssl->buffers.serverDH_Priv.length,
input + *inOutIdx, clientPubSz);
2015-12-03 12:37:49 -08:00
}
2014-12-30 14:13:57 -07:00
wc_FreeDhKey(&dhKey);
*inOutIdx += clientPubSz;
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
2015-07-11 12:52:22 -06:00
if (ssl->options.haveQSH) {
2015-07-07 09:55:58 -06:00
/* extension name */
ato16(input + *inOutIdx, &name);
*inOutIdx += OPAQUE16_LEN;
2015-11-02 15:51:01 -03:00
if (name == TLSX_QUANTUM_SAFE_HYBRID) {
2015-09-15 17:46:45 -06:00
/* if qshSz is larger than 0 it is the length of
buffer used */
if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx,
2015-12-03 12:37:49 -08:00
size - *inOutIdx + begin, 1)) < 0) {
2015-09-15 17:46:45 -06:00
return qshSz;
2015-12-03 12:37:49 -08:00
}
2015-09-15 17:46:45 -06:00
*inOutIdx += qshSz;
2015-07-07 09:55:58 -06:00
}
else {
/* unknown extension sent client ignored
handshake */
return BUFFER_ERROR;
}
}
#endif
2015-12-03 12:37:49 -08:00
if (ret == 0) {
2012-10-29 15:39:42 -07:00
ret = MakeMasterSecret(ssl);
2015-12-03 12:37:49 -08:00
}
2012-05-03 08:18:59 -07:00
}
2012-10-29 15:39:42 -07:00
break;
#endif /* NO_DH */
#if !defined(NO_DH) && !defined(NO_PSK)
case dhe_psk_kea:
{
byte* pms = ssl->arrays->preMasterSecret;
word16 clientSz;
DhKey dhKey;
/* Read in the PSK hint */
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ato16(input + *inOutIdx, &clientSz);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if (clientSz > MAX_PSK_ID_LEN) {
return CLIENT_ID_ERROR;
2015-12-03 12:37:49 -08:00
}
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + clientSz > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
XMEMCPY(ssl->arrays->client_identity,
input + *inOutIdx, clientSz);
*inOutIdx += clientSz;
ssl->arrays->client_identity[min(clientSz, MAX_PSK_ID_LEN-1)] =
0;
/* Read in the DHE business */
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
ato16(input + *inOutIdx, &clientSz);
*inOutIdx += OPAQUE16_LEN;
2015-12-03 12:37:49 -08:00
if ((*inOutIdx - begin) + clientSz > size) {
return BUFFER_ERROR;
2015-12-03 12:37:49 -08:00
}
2014-12-30 14:13:57 -07:00
wc_InitDhKey(&dhKey);
ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length,
ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length);
2015-12-03 12:37:49 -08:00
if (ret == 0) {
2014-12-30 14:13:57 -07:00
ret = wc_DhAgree(&dhKey, pms + OPAQUE16_LEN,
&ssl->arrays->preMasterSz,
ssl->buffers.serverDH_Priv.buffer,
ssl->buffers.serverDH_Priv.length,
input + *inOutIdx, clientSz);
2015-12-03 12:37:49 -08:00
}
2014-12-30 14:13:57 -07:00
wc_FreeDhKey(&dhKey);
*inOutIdx += clientSz;
2014-06-03 23:11:18 -07:00
c16toa((word16)ssl->arrays->preMasterSz, pms);
ssl->arrays->preMasterSz += OPAQUE16_LEN;
pms += ssl->arrays->preMasterSz;
/* Use the PSK hint to look up the PSK and add it to the
* preMasterSecret here. */
ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
ssl->arrays->client_identity, ssl->arrays->psk_key,
MAX_PSK_KEY_LEN);
if (ssl->arrays->psk_keySz == 0 ||
2015-12-03 12:37:49 -08:00
ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
return PSK_KEY_ERROR;
2015-12-03 12:37:49 -08:00
}
c16toa((word16) ssl->arrays->psk_keySz, pms);
pms += OPAQUE16_LEN;
XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
ssl->arrays->preMasterSz +=
ssl->arrays->psk_keySz + OPAQUE16_LEN;
2015-07-07 09:55:58 -06:00
#ifdef HAVE_QSH
2015-07-11 12:52:22 -06:00
if (ssl->options.haveQSH) {
2015-07-07 09:55:58 -06:00
/* extension name */
ato16(input + *inOutIdx, &name);
*inOutIdx += OPAQUE16_LEN;
2015-11-02 15:51:01 -03:00
if (name == TLSX_QUANTUM_SAFE_HYBRID) {
2015-09-15 17:46:45 -06:00
/* if qshSz is larger than 0 it is the length of
buffer used */
if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx,
2015-12-03 12:37:49 -08:00
size - *inOutIdx + begin, 1)) < 0) {
2015-09-15 17:46:45 -06:00
return qshSz;
2015-12-03 12:37:49 -08:00
}
2015-09-15 17:46:45 -06:00
*inOutIdx += qshSz;
2015-07-07 09:55:58 -06:00
}
else {
/* unknown extension sent client ignored
handshake */
return BUFFER_ERROR;
}
}
#endif
if (ret == 0)
ret = MakeMasterSecret(ssl);
/* No further need for PSK */
2015-02-20 15:51:21 -08:00
ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
ssl->arrays->psk_keySz = 0;
}
break;
#endif /* !NO_DH && !NO_PSK */
2012-10-29 15:39:42 -07:00
default:
{
2014-12-19 11:27:01 -07:00
WOLFSSL_MSG("Bad kea type");
2014-10-24 10:33:24 -03:00
ret = BAD_KEA_TYPE_E;
2012-10-29 15:39:42 -07:00
}
break;
}
2013-03-20 09:12:00 -07:00
/* No further need for PMS */
2015-02-20 15:51:21 -08:00
ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
2013-03-20 09:12:00 -07:00
ssl->arrays->preMasterSz = 0;
2011-02-05 11:14:47 -08:00
if (ret == 0) {
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
#ifndef NO_CERTS
2015-12-03 12:37:49 -08:00
if (ssl->options.verifyPeer) {
ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
2015-12-03 12:37:49 -08:00
}
#endif
2011-02-05 11:14:47 -08:00
}
return ret;
}
#ifdef HAVE_STUNNEL
static int SNI_Callback(WOLFSSL* ssl)
{
/* Stunnel supports a custom sni callback to switch an SSL's ctx
* when SNI is received. Call it now if exists */
if(ssl && ssl->ctx && ssl->ctx->sniRecvCb) {
WOLFSSL_MSG("Calling custom sni callback");
if(ssl->ctx->sniRecvCb(ssl, NULL, ssl->ctx->sniRecvCbArg)
== alert_fatal) {
WOLFSSL_MSG("Error in custom sni callback. Fatal alert");
SendAlert(ssl, alert_fatal, unrecognized_name);
return FATAL_ERROR;
}
}
return 0;
}
#endif /* HAVE_STUNNEL */
#endif /* NO_WOLFSSL_SERVER */
2015-09-10 16:24:25 -07:00
#endif /* WOLFCRYPT_ONLY */