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