Add FreeRTOS-Plus directory.

This commit is contained in:
Richard Barry 2012-08-11 21:34:11 +00:00
parent 7bd5f21ad5
commit f508a5f653
6798 changed files with 134949 additions and 19 deletions

View file

@ -0,0 +1,303 @@
/* crl.c
*
* Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
*
* This file is part of CyaSSL.
*
* CyaSSL 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.
*
* CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_CRL
#include <cyassl/internal.h>
#include <cyassl/error.h>
#include <dirent.h>
#include <string.h>
/* Initialze CRL members */
int InitCRL(CYASSL_CRL* crl, CYASSL_CERT_MANAGER* cm)
{
CYASSL_ENTER("InitCRL");
crl->cm = cm;
crl->crlList = NULL;
if (InitMutex(&crl->crlLock) != 0)
return BAD_MUTEX_ERROR;
return 0;
}
/* Initialze CRL Entry */
static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl)
{
CYASSL_ENTER("FreeCRL_Entry");
XMEMCPY(crle->issuerHash, dcrl->issuerHash, SHA_DIGEST_SIZE);
XMEMCPY(crle->crlHash, dcrl->crlHash, MD5_DIGEST_SIZE);
XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
crle->certs = dcrl->certs; /* take ownsership */
dcrl->certs = NULL;
crle->totalCerts = dcrl->totalCerts;
return 0;
}
/* Free all CRL Entry resources */
static void FreeCRL_Entry(CRL_Entry* crle)
{
RevokedCert* tmp = crle->certs;
CYASSL_ENTER("FreeCRL_Entry");
while(tmp) {
RevokedCert* next = tmp->next;
XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED);
tmp = next;
}
}
/* Free all CRL resources */
void FreeCRL(CYASSL_CRL* crl)
{
CRL_Entry* tmp = crl->crlList;
CYASSL_ENTER("FreeCRL");
while(tmp) {
CRL_Entry* next = tmp->next;
FreeCRL_Entry(tmp);
XFREE(tmp, NULL, DYNAMIC_TYPE_CRL_ENTRY);
tmp = next;
}
FreeMutex(&crl->crlLock);
}
/* Is the cert ok with CRL, return 0 on success */
int CheckCertCRL(CYASSL_CRL* crl, DecodedCert* cert)
{
CRL_Entry* crle;
int foundEntry = 0;
int revoked = 0;
int ret = 0;
CYASSL_ENTER("CheckCertCRL");
if (LockMutex(&crl->crlLock) != 0) {
CYASSL_MSG("LockMutex failed");
return BAD_MUTEX_ERROR;
}
crle = crl->crlList;
while (crle) {
if (XMEMCMP(crle->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0) {
CYASSL_MSG("Found CRL Entry on list");
foundEntry = 1;
break;
}
crle = crle->next;
}
if (foundEntry) {
RevokedCert* rc = crle->certs;
while (rc) {
if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
CYASSL_MSG("Cert revoked");
revoked = 1;
ret = CRL_CERT_REVOKED;
break;
}
rc = rc->next;
}
}
UnLockMutex(&crl->crlLock);
if (foundEntry == 0) {
CYASSL_MSG("Couldn't find CRL for status check");
ret = CRL_MISSING;
if (crl->cm->cbMissingCRL) {
char url[256];
CYASSL_MSG("Issuing missing CRL callback");
url[0] = '\0';
if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
url[cert->extCrlInfoSz] = '\0';
}
else {
CYASSL_MSG("CRL url too long");
}
crl->cm->cbMissingCRL(url);
}
}
return ret;
}
/* Add Decoded CRL, 0 on success */
static int AddCRL(CYASSL_CRL* crl, DecodedCRL* dcrl)
{
CRL_Entry* crle;
CYASSL_ENTER("AddCRL");
crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY);
if (crle == NULL) {
CYASSL_MSG("alloc CRL Entry failed");
return -1;
}
if (InitCRL_Entry(crle, dcrl) < 0) {
CYASSL_MSG("Init CRL Entry failed");
return -1;
}
if (LockMutex(&crl->crlLock) != 0) {
CYASSL_MSG("LockMutex failed");
FreeCRL_Entry(crle);
return BAD_MUTEX_ERROR;
}
crle->next = crl->crlList;
crl->crlList = crle;
UnLockMutex(&crl->crlLock);
return 0;
}
/* Load CRL File of type, SSL_SUCCESS on ok */
int BufferLoadCRL(CYASSL_CRL* crl, const byte* buff, long sz, int type)
{
int ret = SSL_SUCCESS;
const byte* myBuffer = buff; /* if DER ok, otherwise switch */
buffer der;
DecodedCRL dcrl;
der.buffer = NULL;
CYASSL_ENTER("BufferLoadCRL");
if (crl == NULL || buff == NULL || sz == 0)
return BAD_FUNC_ARG;
if (type == SSL_FILETYPE_PEM) {
int eccKey = 0; /* not used */
EncryptedInfo info;
info.ctx = NULL;
ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey);
if (ret == 0) {
myBuffer = der.buffer;
sz = der.length;
}
else {
CYASSL_MSG("Pem to Der failed");
return -1;
}
}
InitDecodedCRL(&dcrl);
ret = ParseCRL(&dcrl, myBuffer, sz);
if (ret != 0) {
CYASSL_MSG("ParseCRL error");
}
else {
ret = AddCRL(crl, &dcrl);
if (ret != 0) {
CYASSL_MSG("AddCRL error");
}
}
FreeDecodedCRL(&dcrl);
if (der.buffer)
XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL);
if (ret == 0)
return SSL_SUCCESS; /* convert */
return ret;
}
/* Load CRL path files of type, SSL_SUCCESS on ok */
int LoadCRL(CYASSL_CRL* crl, const char* path, int type, int monitor)
{
struct dirent* entry;
DIR* dir;
int ret = SSL_SUCCESS;
CYASSL_ENTER("LoadCRL");
if (crl == NULL)
return BAD_FUNC_ARG;
dir = opendir(path);
if (dir == NULL) {
CYASSL_MSG("opendir path crl load failed");
return BAD_PATH_ERROR;
}
while ( ret == SSL_SUCCESS && (entry = readdir(dir)) != NULL) {
if (entry->d_type & DT_REG) {
char name[MAX_FILENAME_SZ];
if (type == SSL_FILETYPE_PEM) {
if (strstr(entry->d_name, ".pem") == NULL) {
CYASSL_MSG("not .pem file, skipping");
continue;
}
}
else {
if (strstr(entry->d_name, ".der") == NULL &&
strstr(entry->d_name, ".crl") == NULL) {
CYASSL_MSG("not .der or .crl file, skipping");
continue;
}
}
XMEMSET(name, 0, sizeof(name));
XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2);
XSTRNCAT(name, "/", 1);
XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2);
ret = ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl);
}
}
if (monitor) {
CYASSL_MSG("monitor path requested");
}
return SSL_SUCCESS;
}
#endif /* HAVE_CRL */

View file

@ -0,0 +1,76 @@
# vim:ft=automake
# included from Top Level Makefile.am
# All paths should be given relative to the root
lib_LTLIBRARIES+= src/libcyassl.la
src_libcyassl_la_SOURCES = \
src/internal.c \
src/io.c \
src/keys.c \
src/ssl.c \
src/tls.c \
ctaocrypt/src/asn.c \
ctaocrypt/src/coding.c \
ctaocrypt/src/des3.c \
ctaocrypt/src/hmac.c \
ctaocrypt/src/md5.c \
ctaocrypt/src/md4.c \
ctaocrypt/src/random.c \
ctaocrypt/src/rsa.c \
ctaocrypt/src/sha.c \
ctaocrypt/src/aes.c \
ctaocrypt/src/sha256.c \
ctaocrypt/src/dh.c \
ctaocrypt/src/dsa.c \
ctaocrypt/src/arc4.c \
ctaocrypt/src/rabbit.c \
ctaocrypt/src/pwdbased.c \
ctaocrypt/src/logging.c \
ctaocrypt/src/memory.c
src_libcyassl_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${CYASSL_LIBRARY_VERSION}
src_libcyassl_la_LIBADD = $(LIBM)
src_libcyassl_la_CFLAGS = -DBUILDING_CYASSL $(AM_CFLAGS)
src_libcyassl_la_CPPFLAGS = -DBUILDING_CYASSL $(AM_CPPFLAGS)
if BUILD_AESNI
src_libcyassl_la_SOURCES += ctaocrypt/src/aes_asm.s
endif
if BUILD_RIPEMD
src_libcyassl_la_SOURCES += ctaocrypt/src/ripemd.c
endif
if BUILD_SHA512
src_libcyassl_la_SOURCES += ctaocrypt/src/sha512.c
endif
if BUILD_SNIFFER
src_libcyassl_la_SOURCES += src/sniffer.c
endif
if BUILD_HC128
src_libcyassl_la_SOURCES += ctaocrypt/src/hc128.c
endif
if BUILD_NOINLINE
src_libcyassl_la_SOURCES += ctaocrypt/src/misc.c
endif
if BUILD_FASTMATH
src_libcyassl_la_SOURCES += ctaocrypt/src/tfm.c
else
src_libcyassl_la_SOURCES += ctaocrypt/src/integer.c
endif
if BUILD_ECC
src_libcyassl_la_SOURCES += ctaocrypt/src/ecc.c
endif
if BUILD_OCSP
src_libcyassl_la_SOURCES += src/ocsp.c
endif
if BUILD_CRL
src_libcyassl_la_SOURCES += src/crl.c
endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,227 @@
/* io.c
*
* Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
*
* This file is part of CyaSSL.
*
* CyaSSL 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.
*
* CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef _WIN32_WCE
/* On WinCE winsock2.h must be included before windows.h for socket stuff */
#include <winsock2.h>
#endif
#include <cyassl/internal.h>
/* if user writes own I/O callbacks they can define CYASSL_USER_IO to remove
automatic setting of default I/O functions EmbedSend() and EmbedReceive()
but they'll still need SetCallback xxx() at end of file
*/
#ifndef CYASSL_USER_IO
#ifdef HAVE_LIBZ
#include "zlib.h"
#endif
#ifndef USE_WINDOWS_API
#ifdef CYASSL_LWIP
/* lwIP needs to be configured to use sockets API in this mode */
/* LWIP_SOCKET 1 && LWIP_COMPAT_SOCKETS 1 in lwip/opt.h or in build */
#define LWIP_PROVIDE_ERRNO 1
#include "sockets.h"
#else
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#if !(defined(DEVKITPRO) || defined(THREADX))
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#ifdef __PPU
#include <netex/errno.h>
#else
#include <sys/ioctl.h>
#endif
#endif
#ifdef THREADX
#include <socket.h>
#endif
#endif
#endif /* USE_WINDOWS_API */
#ifdef __sun
#include <sys/filio.h>
#endif
#ifdef USE_WINDOWS_API
/* no epipe yet */
#ifndef WSAEPIPE
#define WSAEPIPE -12345
#endif
#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
#define SOCKET_EAGAIN WSAEWOULDBLOCK
#define SOCKET_ECONNRESET WSAECONNRESET
#define SOCKET_EINTR WSAEINTR
#define SOCKET_EPIPE WSAEPIPE
#elif defined(__PPU)
#define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK
#define SOCKET_EAGAIN SYS_NET_EAGAIN
#define SOCKET_ECONNRESET SYS_NET_ECONNRESET
#define SOCKET_EINTR SYS_NET_EINTR
#define SOCKET_EPIPE SYS_NET_EPIPE
#else
#define SOCKET_EWOULDBLOCK EWOULDBLOCK
#define SOCKET_EAGAIN EAGAIN
#define SOCKET_ECONNRESET ECONNRESET
#define SOCKET_EINTR EINTR
#define SOCKET_EPIPE EPIPE
#endif /* USE_WINDOWS_API */
#ifdef DEVKITPRO
/* from network.h */
int net_send(int, const void*, int, unsigned int);
int net_recv(int, void*, int, unsigned int);
#define SEND_FUNCTION net_send
#define RECV_FUNCTION net_recv
#else
#define SEND_FUNCTION send
#define RECV_FUNCTION recv
#endif
static INLINE int LastError(void)
{
#ifdef USE_WINDOWS_API
return WSAGetLastError();
#else
return errno;
#endif
}
/* The receive embedded callback
* return : nb bytes read, or error
*/
int EmbedReceive(char *buf, int sz, void *ctx)
{
int recvd;
int err;
int sd = *(int*)ctx;
recvd = RECV_FUNCTION(sd, (char *)buf, sz, 0);
if (recvd < 0) {
err = LastError();
CYASSL_MSG("Embed Receive error");
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
CYASSL_MSG(" Would block");
return IO_ERR_WANT_READ;
}
else if (err == SOCKET_ECONNRESET) {
CYASSL_MSG(" Connection reset");
return IO_ERR_CONN_RST;
}
else if (err == SOCKET_EINTR) {
CYASSL_MSG(" Socket interrupted");
return IO_ERR_ISR;
}
else {
CYASSL_MSG(" General error");
return IO_ERR_GENERAL;
}
}
else if (recvd == 0) {
CYASSL_MSG("Embed receive connection closed");
return IO_ERR_CONN_CLOSE;
}
return recvd;
}
/* The send embedded callback
* return : nb bytes sent, or error
*/
int EmbedSend(char *buf, int sz, void *ctx)
{
int sd = *(int*)ctx;
int sent;
int len = sz;
int err;
sent = SEND_FUNCTION(sd, &buf[sz - len], len, 0);
if (sent < 0) {
err = LastError();
CYASSL_MSG("Embed Send error");
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
CYASSL_MSG(" Would Block");
return IO_ERR_WANT_WRITE;
}
else if (err == SOCKET_ECONNRESET) {
CYASSL_MSG(" Connection reset");
return IO_ERR_CONN_RST;
}
else if (err == SOCKET_EINTR) {
CYASSL_MSG(" Socket interrupted");
return IO_ERR_ISR;
}
else if (err == SOCKET_EPIPE) {
CYASSL_MSG(" Socket EPIPE");
return IO_ERR_CONN_CLOSE;
}
else {
CYASSL_MSG(" General error");
return IO_ERR_GENERAL;
}
}
return sent;
}
#endif /* CYASSL_USER_IO */
CYASSL_API void CyaSSL_SetIORecv(CYASSL_CTX *ctx, CallbackIORecv CBIORecv)
{
ctx->CBIORecv = CBIORecv;
}
CYASSL_API void CyaSSL_SetIOSend(CYASSL_CTX *ctx, CallbackIOSend CBIOSend)
{
ctx->CBIOSend = CBIOSend;
}
CYASSL_API void CyaSSL_SetIOReadCtx(CYASSL* ssl, void *rctx)
{
ssl->IOCB_ReadCtx = rctx;
}
CYASSL_API void CyaSSL_SetIOWriteCtx(CYASSL* ssl, void *wctx)
{
ssl->IOCB_WriteCtx = wctx;
}

View file

@ -0,0 +1,975 @@
/* keys.c
*
* Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
*
* This file is part of CyaSSL.
*
* CyaSSL 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.
*
* CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <cyassl/internal.h>
#include <cyassl/error.h>
#ifdef SHOW_SECRETS
#include <stdio.h>
#endif
int SetCipherSpecs(CYASSL* ssl)
{
#ifdef HAVE_ECC
/* ECC extensions */
if (ssl->options.cipherSuite0 == ECC_BYTE) {
switch (ssl->options.cipherSuite) {
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = triple_des;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = DES3_KEY_SIZE;
ssl->specs.block_size = DES_BLOCK_SIZE;
ssl->specs.iv_size = DES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = triple_des;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = DES3_KEY_SIZE;
ssl->specs.block_size = DES_BLOCK_SIZE;
ssl->specs.iv_size = DES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
ssl->specs.bulk_cipher_algorithm = rc4;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = RC4_KEY_SIZE;
ssl->specs.iv_size = 0;
ssl->specs.block_size = 0;
break;
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
case TLS_ECDH_RSA_WITH_RC4_128_SHA :
ssl->specs.bulk_cipher_algorithm = rc4;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = RC4_KEY_SIZE;
ssl->specs.iv_size = 0;
ssl->specs.block_size = 0;
break;
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = triple_des;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = DES3_KEY_SIZE;
ssl->specs.block_size = DES_BLOCK_SIZE;
ssl->specs.iv_size = DES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = triple_des;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = DES3_KEY_SIZE;
ssl->specs.block_size = DES_BLOCK_SIZE;
ssl->specs.iv_size = DES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
ssl->specs.bulk_cipher_algorithm = rc4;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = RC4_KEY_SIZE;
ssl->specs.iv_size = 0;
ssl->specs.block_size = 0;
break;
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
ssl->specs.bulk_cipher_algorithm = rc4;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = RC4_KEY_SIZE;
ssl->specs.iv_size = 0;
ssl->specs.block_size = 0;
break;
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
default:
CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC");
return UNSUPPORTED_SUITE;
} /* switch */
} /* if */
#endif /* HAVE_ECC */
if (ssl->options.cipherSuite0 != ECC_BYTE) { /* normal suites */
switch (ssl->options.cipherSuite) {
#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
case SSL_RSA_WITH_RC4_128_SHA :
ssl->specs.bulk_cipher_algorithm = rc4;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = RC4_KEY_SIZE;
ssl->specs.iv_size = 0;
ssl->specs.block_size = 0;
break;
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
case TLS_NTRU_RSA_WITH_RC4_128_SHA :
ssl->specs.bulk_cipher_algorithm = rc4;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ntru_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = RC4_KEY_SIZE;
ssl->specs.iv_size = 0;
ssl->specs.block_size = 0;
break;
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
case SSL_RSA_WITH_RC4_128_MD5 :
ssl->specs.bulk_cipher_algorithm = rc4;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = md5_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = MD5_DIGEST_SIZE;
ssl->specs.pad_size = PAD_MD5;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = RC4_KEY_SIZE;
ssl->specs.iv_size = 0;
ssl->specs.block_size = 0;
break;
#endif
#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = triple_des;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = DES3_KEY_SIZE;
ssl->specs.block_size = DES_BLOCK_SIZE;
ssl->specs.iv_size = DES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = triple_des;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ntru_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = DES3_KEY_SIZE;
ssl->specs.block_size = DES_BLOCK_SIZE;
ssl->specs.iv_size = DES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
case TLS_RSA_WITH_AES_128_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
case TLS_RSA_WITH_AES_128_CBC_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ntru_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
case TLS_RSA_WITH_AES_256_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
case TLS_RSA_WITH_AES_256_CBC_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = ntru_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
case TLS_PSK_WITH_AES_128_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = psk_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
ssl->options.usingPSK_cipher = 1;
break;
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
case TLS_PSK_WITH_AES_256_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = psk_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
ssl->options.usingPSK_cipher = 1;
break;
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = aes;
ssl->specs.cipher_type = block;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
case TLS_RSA_WITH_HC_128_CBC_MD5 :
ssl->specs.bulk_cipher_algorithm = hc128;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = md5_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = MD5_DIGEST_SIZE;
ssl->specs.pad_size = PAD_MD5;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = HC_128_KEY_SIZE;
ssl->specs.block_size = 0;
ssl->specs.iv_size = HC_128_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
case TLS_RSA_WITH_HC_128_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = hc128;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = HC_128_KEY_SIZE;
ssl->specs.block_size = 0;
ssl->specs.iv_size = HC_128_IV_SIZE;
break;
#endif
#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
case TLS_RSA_WITH_RABBIT_CBC_SHA :
ssl->specs.bulk_cipher_algorithm = rabbit;
ssl->specs.cipher_type = stream;
ssl->specs.mac_algorithm = sha_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.hash_size = SHA_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = RABBIT_KEY_SIZE;
ssl->specs.block_size = 0;
ssl->specs.iv_size = RABBIT_IV_SIZE;
break;
#endif
default:
CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs");
return UNSUPPORTED_SUITE;
} /* switch */
} /* if ECC / Normal suites else */
/* set TLS if it hasn't been turned off */
if (ssl->version.major == 3 && ssl->version.minor >= 1) {
#ifndef NO_TLS
ssl->options.tls = 1;
ssl->hmac = TLS_hmac;
if (ssl->version.minor >= 2)
ssl->options.tls1_1 = 1;
#endif
}
#ifdef CYASSL_DTLS
if (ssl->options.dtls)
ssl->hmac = TLS_hmac;
#endif
return 0;
}
enum KeyStuff {
MASTER_ROUNDS = 3,
PREFIX = 3, /* up to three letters for master prefix */
KEY_PREFIX = 7 /* up to 7 prefix letters for key rounds */
};
/* true or false, zero for error */
static int SetPrefix(byte* sha_input, int idx)
{
switch (idx) {
case 0:
XMEMCPY(sha_input, "A", 1);
break;
case 1:
XMEMCPY(sha_input, "BB", 2);
break;
case 2:
XMEMCPY(sha_input, "CCC", 3);
break;
case 3:
XMEMCPY(sha_input, "DDDD", 4);
break;
case 4:
XMEMCPY(sha_input, "EEEEE", 5);
break;
case 5:
XMEMCPY(sha_input, "FFFFFF", 6);
break;
case 6:
XMEMCPY(sha_input, "GGGGGGG", 7);
break;
default:
CYASSL_MSG("Set Prefix error, bad input");
return 0;
}
return 1;
}
static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
byte side)
{
#ifdef BUILD_ARC4
word32 sz = specs->key_size;
if (specs->bulk_cipher_algorithm == rc4) {
if (side == CLIENT_END) {
Arc4SetKey(&enc->arc4, keys->client_write_key, sz);
Arc4SetKey(&dec->arc4, keys->server_write_key, sz);
}
else {
Arc4SetKey(&enc->arc4, keys->server_write_key, sz);
Arc4SetKey(&dec->arc4, keys->client_write_key, sz);
}
}
#endif
#ifdef HAVE_HC128
if (specs->bulk_cipher_algorithm == hc128) {
if (side == CLIENT_END) {
Hc128_SetKey(&enc->hc128, keys->client_write_key,
keys->client_write_IV);
Hc128_SetKey(&dec->hc128, keys->server_write_key,
keys->server_write_IV);
}
else {
Hc128_SetKey(&enc->hc128, keys->server_write_key,
keys->server_write_IV);
Hc128_SetKey(&dec->hc128, keys->client_write_key,
keys->client_write_IV);
}
}
#endif
#ifdef BUILD_RABBIT
if (specs->bulk_cipher_algorithm == rabbit) {
if (side == CLIENT_END) {
RabbitSetKey(&enc->rabbit, keys->client_write_key,
keys->client_write_IV);
RabbitSetKey(&dec->rabbit, keys->server_write_key,
keys->server_write_IV);
}
else {
RabbitSetKey(&enc->rabbit, keys->server_write_key,
keys->server_write_IV);
RabbitSetKey(&dec->rabbit, keys->client_write_key,
keys->client_write_IV);
}
}
#endif
#ifdef BUILD_DES3
if (specs->bulk_cipher_algorithm == triple_des) {
if (side == CLIENT_END) {
Des3_SetKey(&enc->des3, keys->client_write_key,
keys->client_write_IV, DES_ENCRYPTION);
Des3_SetKey(&dec->des3, keys->server_write_key,
keys->server_write_IV, DES_DECRYPTION);
}
else {
Des3_SetKey(&enc->des3, keys->server_write_key,
keys->server_write_IV, DES_ENCRYPTION);
Des3_SetKey(&dec->des3, keys->client_write_key,
keys->client_write_IV, DES_DECRYPTION);
}
}
#endif
#ifdef BUILD_AES
if (specs->bulk_cipher_algorithm == aes) {
if (side == CLIENT_END) {
AesSetKey(&enc->aes, keys->client_write_key,
specs->key_size, keys->client_write_IV,
AES_ENCRYPTION);
AesSetKey(&dec->aes, keys->server_write_key,
specs->key_size, keys->server_write_IV,
AES_DECRYPTION);
}
else {
AesSetKey(&enc->aes, keys->server_write_key,
specs->key_size, keys->server_write_IV,
AES_ENCRYPTION);
AesSetKey(&dec->aes, keys->client_write_key,
specs->key_size, keys->client_write_IV,
AES_DECRYPTION);
}
}
#endif
keys->sequence_number = 0;
keys->peer_sequence_number = 0;
keys->encryptionOn = 0;
return 0;
}
/* TLS can call too */
int StoreKeys(CYASSL* ssl, const byte* keyData)
{
int sz = ssl->specs.hash_size, i;
XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz);
i = sz;
XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
i += sz;
sz = ssl->specs.key_size;
XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz);
i += sz;
XMEMCPY(ssl->keys.server_write_key, &keyData[i], sz);
i += sz;
sz = ssl->specs.iv_size;
XMEMCPY(ssl->keys.client_write_IV, &keyData[i], sz);
i += sz;
XMEMCPY(ssl->keys.server_write_IV, &keyData[i], sz);
return SetKeys(&ssl->encrypt, &ssl->decrypt, &ssl->keys, &ssl->specs,
ssl->options.side);
}
int DeriveKeys(CYASSL* ssl)
{
int length = 2 * ssl->specs.hash_size +
2 * ssl->specs.key_size +
2 * ssl->specs.iv_size;
int rounds = (length + MD5_DIGEST_SIZE - 1 ) / MD5_DIGEST_SIZE, i;
byte shaOutput[SHA_DIGEST_SIZE];
byte md5Input[SECRET_LEN + SHA_DIGEST_SIZE];
byte shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN];
Md5 md5;
Sha sha;
byte keyData[KEY_PREFIX * MD5_DIGEST_SIZE]; /* max size */
InitMd5(&md5);
InitSha(&sha);
XMEMCPY(md5Input, ssl->arrays.masterSecret, SECRET_LEN);
for (i = 0; i < rounds; ++i) {
int j = i + 1;
int idx = j;
if (!SetPrefix(shaInput, i)) {
return PREFIX_ERROR;
}
XMEMCPY(shaInput + idx, ssl->arrays.masterSecret, SECRET_LEN);
idx += SECRET_LEN;
XMEMCPY(shaInput + idx, ssl->arrays.serverRandom, RAN_LEN);
idx += RAN_LEN;
XMEMCPY(shaInput + idx, ssl->arrays.clientRandom, RAN_LEN);
idx += RAN_LEN;
ShaUpdate(&sha, shaInput, sizeof(shaInput) - KEY_PREFIX + j);
ShaFinal(&sha, shaOutput);
XMEMCPY(&md5Input[SECRET_LEN], shaOutput, SHA_DIGEST_SIZE);
Md5Update(&md5, md5Input, sizeof(md5Input));
Md5Final(&md5, keyData + i * MD5_DIGEST_SIZE);
}
return StoreKeys(ssl, keyData);
}
static void CleanPreMaster(CYASSL* ssl)
{
int i, sz = ssl->arrays.preMasterSz;
for (i = 0; i < sz; i++)
ssl->arrays.preMasterSecret[i] = 0;
RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret, sz);
for (i = 0; i < sz; i++)
ssl->arrays.preMasterSecret[i] = 0;
}
/* Create and store the master secret see page 32, 6.1 */
int MakeMasterSecret(CYASSL* ssl)
{
byte shaOutput[SHA_DIGEST_SIZE];
byte md5Input[ENCRYPT_LEN + SHA_DIGEST_SIZE];
byte shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN];
int i, ret;
word32 idx;
word32 pmsSz = ssl->arrays.preMasterSz;
Md5 md5;
Sha sha;
#ifdef SHOW_SECRETS
{
int j;
printf("pre master secret: ");
for (j = 0; j < pmsSz; j++)
printf("%02x", ssl->arrays.preMasterSecret[j]);
printf("\n");
}
#endif
#ifndef NO_TLS
if (ssl->options.tls) return MakeTlsMasterSecret(ssl);
#endif
InitMd5(&md5);
InitSha(&sha);
XMEMCPY(md5Input, ssl->arrays.preMasterSecret, pmsSz);
for (i = 0; i < MASTER_ROUNDS; ++i) {
byte prefix[PREFIX];
if (!SetPrefix(prefix, i)) {
return PREFIX_ERROR;
}
idx = 0;
XMEMCPY(shaInput, prefix, i + 1);
idx += i + 1;
XMEMCPY(shaInput + idx, ssl->arrays.preMasterSecret, pmsSz);
idx += pmsSz;
XMEMCPY(shaInput + idx, ssl->arrays.clientRandom, RAN_LEN);
idx += RAN_LEN;
XMEMCPY(shaInput + idx, ssl->arrays.serverRandom, RAN_LEN);
idx += RAN_LEN;
ShaUpdate(&sha, shaInput, idx);
ShaFinal(&sha, shaOutput);
idx = pmsSz; /* preSz */
XMEMCPY(md5Input + idx, shaOutput, SHA_DIGEST_SIZE);
idx += SHA_DIGEST_SIZE;
Md5Update(&md5, md5Input, idx);
Md5Final(&md5, &ssl->arrays.masterSecret[i * MD5_DIGEST_SIZE]);
}
#ifdef SHOW_SECRETS
{
int i;
printf("master secret: ");
for (i = 0; i < SECRET_LEN; i++)
printf("%02x", ssl->arrays.masterSecret[i]);
printf("\n");
}
#endif
ret = DeriveKeys(ssl);
CleanPreMaster(ssl);
return ret;
}

View file

@ -0,0 +1,356 @@
/* ocsp.c
*
* Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
*
* This file is part of CyaSSL.
*
* CyaSSL 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.
*
* CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <cyassl/error.h>
#include <cyassl/ocsp.h>
#include <cyassl/internal.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef HAVE_OCSP
CYASSL_API int ocsp_test(unsigned char* buf, int sz);
#define CYASSL_OCSP_ENABLE 0x0001 /* Enable OCSP lookups */
#define CYASSL_OCSP_URL_OVERRIDE 0x0002 /* Use the override URL instead of URL
* in certificate */
typedef struct sockaddr_in SOCKADDR_IN_T;
#define AF_INET_V AF_INET
#define SOCKET_T unsigned int
int ocsp_test(unsigned char* buf, int sz)
{
CYASSL_OCSP ocsp;
OcspResponse resp;
int result;
CyaSSL_OCSP_Init(&ocsp);
InitOcspResponse(&resp, buf, sz, NULL);
ocsp.enabled = 1;
ocsp.useOverrideUrl = 1;
CyaSSL_OCSP_set_override_url(&ocsp, "http://ocsp.example.com:8080/bob");
CyaSSL_OCSP_Lookup_Cert(&ocsp, NULL);
result = OcspResponseDecode(&resp);
FreeOcspResponse(&resp);
CyaSSL_OCSP_Cleanup(&ocsp);
return result;
}
int CyaSSL_OCSP_Init(CYASSL_OCSP* ocsp)
{
if (ocsp != NULL) {
XMEMSET(ocsp, 0, sizeof(*ocsp));
return 0;
}
return -1;
}
void CyaSSL_OCSP_Cleanup(CYASSL_OCSP* ocsp)
{
ocsp->enabled = 0;
}
int CyaSSL_OCSP_set_override_url(CYASSL_OCSP* ocsp, const char* url)
{
if (ocsp != NULL && url != NULL) {
int i, cur, hostname;
/* need to break the url down into scheme, address, and port */
/* "http://example.com:8080/" */
if (XSTRNCMP(url, "http://", 7) == 0) {
cur = 7;
} else cur = 0;
i = 0;
while (url[cur] != 0 && url[cur] != ':' && url[cur] != '/') {
ocsp->overrideName[i++] = url[cur++];
}
ocsp->overrideName[i] = 0;
/* Need to pick out the path after the domain name */
if (url[cur] == ':') {
char port[6];
int j;
i = 0;
cur++;
while (url[cur] != 0 && url[cur] != '/' && i < 6) {
port[i++] = url[cur++];
}
ocsp->overridePort = 0;
for (j = 0; j < i; j++) {
if (port[j] < '0' || port[j] > '9') return -1;
ocsp->overridePort =
(ocsp->overridePort * 10) + (port[j] - '0');
}
}
else
ocsp->overridePort = 80;
if (url[cur] == '/') {
i = 0;
while (url[cur] != 0 && i < 80) {
ocsp->overridePath[i++] = url[cur++];
}
ocsp->overridePath[i] = 0;
}
else {
ocsp->overridePath[0] = '/';
ocsp->overridePath[1] = 0;
}
return 1;
}
return 0;
}
static INLINE void tcp_socket(SOCKET_T* sockfd, SOCKADDR_IN_T* addr,
const char* peer, word16 port)
{
const char* host = peer;
/* peer could be in human readable form */
if (peer != INADDR_ANY && isalpha(peer[0])) {
struct hostent* entry = gethostbyname(peer);
if (entry) {
struct sockaddr_in tmp;
memset(&tmp, 0, sizeof(struct sockaddr_in));
memcpy(&tmp.sin_addr.s_addr, entry->h_addr_list[0],
entry->h_length);
host = inet_ntoa(tmp.sin_addr);
}
else
CYASSL_MSG("no entry for host");
}
*sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
memset(addr, 0, sizeof(SOCKADDR_IN_T));
addr->sin_family = AF_INET_V;
addr->sin_port = htons(port);
if (host == INADDR_ANY)
addr->sin_addr.s_addr = INADDR_ANY;
else
addr->sin_addr.s_addr = inet_addr(host);
}
static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port)
{
SOCKADDR_IN_T addr;
tcp_socket(sockfd, &addr, ip, port);
if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
CYASSL_MSG("tcp connect failed");
}
static int build_http_request(CYASSL_OCSP* ocsp, int ocspReqSz,
byte* buf, int bufSize)
{
return snprintf((char*)buf, bufSize,
"POST %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Content-Length: %d\r\n"
"Content-Type: application/ocsp-request\r\n"
"\r\n",
ocsp->overridePath, ocsp->overrideName, ocspReqSz);
}
#if 0
static const char foo[] = \
"\x30\x81\xB7\x30\x81\xB4\x30\x81\x8C\x30\x44\x30\x42\x30\x09\x06\x05\x2B\x0E\x03" \
"\x02\x1A\x05\x00\x04\x14\x49\x2D\x52\x83\x4B\x40\x37\xF5\xA9\x9E\x26\xA2\x3E\x48" \
"\x2F\x2E\x37\x34\xC9\x54\x04\x14\x21\xA2\x25\xEE\x57\x38\x34\x5A\x24\x9D\xF3\x7C" \
"\x18\x60\x59\x7A\x04\x3D\xF5\x69\x02\x09\x00\x89\x5A\xA2\xBD\xFE\x26\x8B\xEE\x30" \
"\x44\x30\x42\x30\x09\x06\x05\x2B\x0E\x03\x02\x1A\x05\x00\x04\x14\x49\x2D\x52\x83" \
"\x4B\x40\x37\xF5\xA9\x9E\x26\xA2\x3E\x48\x2F\x2E\x37\x34\xC9\x54\x04\x14\x21\xA2" \
"\x25\xEE\x57\x38\x34\x5A\x24\x9D\xF3\x7C\x18\x60\x59\x7A\x04\x3D\xF5\x69\x02\x09" \
"\x00\x89\x5A\xA2\xBD\xFE\x26\x8B\xEF\xA2\x23\x30\x21\x30\x1F\x06\x09\x2B\x06\x01" \
"\x05\x05\x07\x30\x01\x02\x04\x12\x04\x10\x20\x56\x47\x19\x65\x33\xB6\xB5\xAD\x39" \
"\x1F\x21\x65\xE0\x44\x1E";
static int build_ocsp_request(CYASSL_OCSP* ocsp, byte* buf, int bufSz)
{
memcpy(buf, foo, sizeof(foo));
return sizeof(foo) - 1;
}
#endif
static byte* decode_http_response(byte* httpBuf, int httpBufSz, int* ocspRespSz)
{
int idx = 0;
int stop = 0;
byte* contentType = NULL;
byte* contentLength = NULL;
byte* content = NULL;
char* buf = (char*)httpBuf; /* kludge so I'm not constantly casting */
if (strncasecmp(buf, "HTTP/1", 6) != 0)
return NULL;
idx = 9; /* sets to the first byte after "HTTP/1.X ", which should be the
* HTTP result code */
if (strncasecmp(&buf[idx], "200 OK", 6) != 0)
return NULL;
idx += 8;
while (idx < httpBufSz && !stop) {
if (buf[idx] == '\r' && buf[idx+1] == '\n') {
stop = 1;
idx += 2;
}
else {
if (contentType == NULL &&
strncasecmp(&buf[idx], "Content-Type:", 13) == 0) {
idx += 13;
if (buf[idx] == ' ') idx++;
if (strncasecmp(&buf[idx], "application/ocsp-response", 25) != 0)
return NULL;
idx += 27;
} else if (contentLength == NULL &&
strncasecmp(&buf[idx], "Content-Length:", 15) == 0) {
int len = 0;
idx += 15;
if (buf[idx] == ' ') idx++;
while (buf[idx] > '0' && buf[idx] < '9' && idx < httpBufSz) {
len = (len * 10) + (buf[idx] - '0');
idx++;
}
*ocspRespSz = len;
idx += 2; /* skip the crlf */
} else {
/* Advance idx past the next \r\n */
char* end = strstr(&buf[idx], "\r\n");
idx = end - buf + 2;
stop = 1;
}
}
}
return &httpBuf[idx];
}
#define SCRATCH_BUFFER_SIZE 2048
int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert)
{
SOCKET_T sfd = -1;
byte buf[SCRATCH_BUFFER_SIZE];
byte* httpBuf = &buf[0];
int httpBufSz = SCRATCH_BUFFER_SIZE/4;
byte* ocspReqBuf = &buf[httpBufSz];
int ocspReqSz = SCRATCH_BUFFER_SIZE - httpBufSz;
OcspResponse ocspResponse;
int result = CERT_UNKNOWN;
/* If OCSP lookups are disabled, return success. */
if (!ocsp->enabled) {
CYASSL_MSG("OCSP lookup disabled, assuming CERT_GOOD");
return CERT_GOOD;
}
/* If OCSP lookups are enabled, but URL Override is disabled, return
** a failure. Need to have an override URL for right now. */
if (!ocsp->useOverrideUrl || cert == NULL) {
CYASSL_MSG("OCSP lookup enabled, but URL Override disabled");
return CERT_UNKNOWN;
}
XMEMCPY(ocsp->status[0].issuerHash, cert->issuerHash, SHA_SIZE);
XMEMCPY(ocsp->status[0].issuerKeyHash, cert->issuerKeyHash, SHA_SIZE);
XMEMCPY(ocsp->status[0].serial, cert->serial, cert->serialSz);
ocsp->status[0].serialSz = cert->serialSz;
ocsp->statusLen = 1;
/*ocspReqSz = build_ocsp_request(ocsp, ocspReqBuf, ocspReqSz);*/
ocspReqSz = EncodeOcspRequest(cert, ocspReqBuf, ocspReqSz);
httpBufSz = build_http_request(ocsp, ocspReqSz, httpBuf, httpBufSz);
tcp_connect(&sfd, ocsp->overrideName, ocsp->overridePort);
if (sfd > 0) {
int written;
written = write(sfd, httpBuf, httpBufSz);
if (written == httpBufSz) {
written = write(sfd, ocspReqBuf, ocspReqSz);
if (written == ocspReqSz) {
httpBufSz = read(sfd, buf, SCRATCH_BUFFER_SIZE);
if (httpBufSz > 0) {
ocspReqBuf = decode_http_response(buf, httpBufSz,
&ocspReqSz);
}
}
}
close(sfd);
if (ocspReqBuf == NULL) {
CYASSL_MSG("HTTP response was not OK, no OCSP response");
return CERT_UNKNOWN;
}
} else {
CYASSL_MSG("OCSP Responder connection failed");
return CERT_UNKNOWN;
}
InitOcspResponse(&ocspResponse, ocspReqBuf, ocspReqSz, NULL);
OcspResponseDecode(&ocspResponse);
if (ocspResponse.responseStatus != OCSP_SUCCESSFUL) {
CYASSL_MSG("OCSP Responder failure");
} else {
result = ocspResponse.certStatus[0];
}
FreeOcspResponse(&ocspResponse);
return result;
}
#endif /* HAVE_OCSP */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,477 @@
/* tls.c
*
* Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
*
* This file is part of CyaSSL.
*
* CyaSSL 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.
*
* CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <cyassl/ssl.h>
#include <cyassl/internal.h>
#include <cyassl/error.h>
#include <cyassl/ctaocrypt/hmac.h>
#ifndef NO_TLS
/* calculate XOR for TLSv1 PRF */
static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha)
{
word32 i;
for (i = 0; i < digLen; i++)
digest[i] = md5[i] ^ sha[i];
}
/* compute p_hash for MD5, SHA-1, or SHA-256 for TLSv1 PRF */
static void p_hash(byte* result, word32 resLen, const byte* secret,
word32 secLen, const byte* seed, word32 seedLen, int hash)
{
word32 len = hash == md5_mac ? MD5_DIGEST_SIZE : hash == sha_mac ?
SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE;
word32 times = resLen / len;
word32 lastLen = resLen % len;
word32 lastTime;
word32 i;
word32 idx = 0;
byte previous[SHA256_DIGEST_SIZE]; /* max size */
byte current[SHA256_DIGEST_SIZE]; /* max size */
Hmac hmac;
if (lastLen) times += 1;
lastTime = times - 1;
HmacSetKey(&hmac, hash == md5_mac ? MD5 : hash == sha_mac ? SHA : SHA256,
secret, secLen);
HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */
HmacFinal(&hmac, previous); /* A1 */
for (i = 0; i < times; i++) {
HmacUpdate(&hmac, previous, len);
HmacUpdate(&hmac, seed, seedLen);
HmacFinal(&hmac, current);
if ( (i == lastTime) && lastLen)
XMEMCPY(&result[idx], current, lastLen);
else {
XMEMCPY(&result[idx], current, len);
idx += len;
HmacUpdate(&hmac, previous, len);
HmacFinal(&hmac, previous);
}
}
}
/* compute TLSv1 PRF (pseudo random function using HMAC) */
static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
const byte* label, word32 labLen, const byte* seed, word32 seedLen,
int useSha256)
{
word32 half = (secLen + 1) / 2;
byte md5_half[MAX_PRF_HALF]; /* half is real size */
byte sha_half[MAX_PRF_HALF]; /* half is real size */
byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */
byte md5_result[MAX_PRF_DIG]; /* digLen is real size */
byte sha_result[MAX_PRF_DIG]; /* digLen is real size */
if (half > MAX_PRF_HALF)
return;
if (labLen + seedLen > MAX_PRF_LABSEED)
return;
if (digLen > MAX_PRF_DIG)
return;
XMEMCPY(md5_half, secret, half);
XMEMCPY(sha_half, secret + half - secLen % 2, half);
XMEMCPY(labelSeed, label, labLen);
XMEMCPY(labelSeed + labLen, seed, seedLen);
if (useSha256) {
p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen,
sha256_mac);
return;
}
p_hash(md5_result, digLen, md5_half, half, labelSeed, labLen + seedLen,
md5_mac);
p_hash(sha_result, digLen, sha_half, half, labelSeed, labLen + seedLen,
sha_mac);
get_xor(digest, digLen, md5_result, sha_result);
}
void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
{
const byte* side;
byte handshake_hash[FINISHED_SZ];
word32 hashSz = FINISHED_SZ;
Md5Final(&ssl->hashMd5, handshake_hash);
ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl)) {
Sha256Final(&ssl->hashSha256, handshake_hash);
hashSz = SHA256_DIGEST_SIZE;
}
#endif
if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
side = tls_client;
else
side = tls_server;
PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays.masterSecret, SECRET_LEN,
side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl));
}
ProtocolVersion MakeTLSv1(void)
{
ProtocolVersion pv;
pv.major = SSLv3_MAJOR;
pv.minor = TLSv1_MINOR;
return pv;
}
ProtocolVersion MakeTLSv1_1(void)
{
ProtocolVersion pv;
pv.major = SSLv3_MAJOR;
pv.minor = TLSv1_1_MINOR;
return pv;
}
ProtocolVersion MakeTLSv1_2(void)
{
ProtocolVersion pv;
pv.major = SSLv3_MAJOR;
pv.minor = TLSv1_2_MINOR;
return pv;
}
static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion";
int DeriveTlsKeys(CYASSL* ssl)
{
int length = 2 * ssl->specs.hash_size +
2 * ssl->specs.key_size +
2 * ssl->specs.iv_size;
byte seed[SEED_LEN];
byte key_data[MAX_PRF_DIG];
XMEMCPY(seed, ssl->arrays.serverRandom, RAN_LEN);
XMEMCPY(&seed[RAN_LEN], ssl->arrays.clientRandom, RAN_LEN);
PRF(key_data, length, ssl->arrays.masterSecret, SECRET_LEN, key_label,
KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
return StoreKeys(ssl, key_data);
}
int MakeTlsMasterSecret(CYASSL* ssl)
{
byte seed[SEED_LEN];
XMEMCPY(seed, ssl->arrays.clientRandom, RAN_LEN);
XMEMCPY(&seed[RAN_LEN], ssl->arrays.serverRandom, RAN_LEN);
PRF(ssl->arrays.masterSecret, SECRET_LEN,
ssl->arrays.preMasterSecret, ssl->arrays.preMasterSz,
master_label, MASTER_LABEL_SZ,
seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
#ifdef SHOW_SECRETS
{
int i;
printf("master secret: ");
for (i = 0; i < SECRET_LEN; i++)
printf("%02x", ssl->arrays.masterSecret[i]);
printf("\n");
}
#endif
return DeriveTlsKeys(ssl);
}
/*** next for static INLINE s copied from cyassl_int.c ***/
/* convert 16 bit integer to opaque */
INLINE static void c16toa(word16 u16, byte* c)
{
c[0] = (u16 >> 8) & 0xff;
c[1] = u16 & 0xff;
}
/* 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;
}
static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify)
{
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
if (verify)
return ssl->keys.dtls_peer_sequence_number; /* 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++;
}
#ifdef CYASSL_DTLS
static INLINE word32 GetEpoch(CYASSL* ssl, int verify)
{
if (verify)
return ssl->keys.dtls_peer_epoch;
else
return ssl->keys.dtls_epoch;
}
#endif /* CYASSL_DTLS */
static INLINE const byte* GetMacSecret(CYASSL* ssl, int verify)
{
if ( (ssl->options.side == CLIENT_END && !verify) ||
(ssl->options.side == SERVER_END && verify) )
return ssl->keys.client_write_MAC_secret;
else
return ssl->keys.server_write_MAC_secret;
}
/*** end copy ***/
/* TLS type HMAC */
void TLS_hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz,
int content, int verify)
{
Hmac hmac;
byte seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
byte length[LENGTH_SZ];
byte inner[ENUM_LEN + VERSION_SZ + LENGTH_SZ]; /* type + version +len */
int type;
c16toa((word16)sz, length);
#ifdef CYASSL_DTLS
if (ssl->options.dtls)
c16toa(GetEpoch(ssl, verify), seq);
#endif
c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
if (ssl->specs.mac_algorithm == md5_mac)
type = MD5;
else if (ssl->specs.mac_algorithm == sha_mac)
type = SHA;
else
type = SHA256;
HmacSetKey(&hmac, type, GetMacSecret(ssl, verify), ssl->specs.hash_size);
HmacUpdate(&hmac, seq, SEQ_SZ); /* seq_num */
inner[0] = (byte)content; /* type */
inner[ENUM_LEN] = ssl->version.major;
inner[ENUM_LEN + ENUM_LEN] = ssl->version.minor; /* version */
XMEMCPY(&inner[ENUM_LEN + VERSION_SZ], length, LENGTH_SZ); /* length */
HmacUpdate(&hmac, inner, sizeof(inner));
HmacUpdate(&hmac, in, sz); /* content */
HmacFinal(&hmac, digest);
}
#ifndef NO_CYASSL_CLIENT
CYASSL_METHOD* CyaTLSv1_client_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
if (method)
InitSSL_Method(method, MakeTLSv1());
return method;
}
CYASSL_METHOD* CyaTLSv1_1_client_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
if (method)
InitSSL_Method(method, MakeTLSv1_1());
return method;
}
#ifndef NO_SHA256 /* can't use without SHA256 */
CYASSL_METHOD* CyaTLSv1_2_client_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
if (method)
InitSSL_Method(method, MakeTLSv1_2());
return method;
}
#endif
CYASSL_METHOD* CyaSSLv23_client_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
if (method) {
#ifndef NO_SHA256 /* 1.2 requires SHA256 */
InitSSL_Method(method, MakeTLSv1_2());
#else
InitSSL_Method(method, MakeTLSv1_1());
#endif
method->downgrade = 1;
}
return method;
}
#endif /* NO_CYASSL_CLIENT */
#ifndef NO_CYASSL_SERVER
CYASSL_METHOD* CyaTLSv1_server_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
if (method) {
InitSSL_Method(method, MakeTLSv1());
method->side = SERVER_END;
}
return method;
}
CYASSL_METHOD* CyaTLSv1_1_server_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
if (method) {
InitSSL_Method(method, MakeTLSv1_1());
method->side = SERVER_END;
}
return method;
}
#ifndef NO_SHA256 /* can't use without SHA256 */
CYASSL_METHOD* CyaTLSv1_2_server_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
if (method) {
InitSSL_Method(method, MakeTLSv1_2());
method->side = SERVER_END;
}
return method;
}
#endif
CYASSL_METHOD* CyaSSLv23_server_method(void)
{
CYASSL_METHOD* method =
(CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0,
DYNAMIC_TYPE_METHOD);
if (method) {
#ifndef NO_SHA256 /* 1.2 requires SHA256 */
InitSSL_Method(method, MakeTLSv1_2());
#else
InitSSL_Method(method, MakeTLSv1_1());
#endif
method->side = SERVER_END;
method->downgrade = 1;
}
return method;
}
#endif /* NO_CYASSL_SERVER */
#else /* NO_TLS */
/* catch CyaSSL programming errors */
void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
{
}
int DeriveTlsKeys(CYASSL* ssl)
{
return NOT_COMPILED_IN;
}
int MakeTlsMasterSecret(CYASSL* ssl)
{
return NOT_COMPILED_IN;
}
#endif /* NO_TLS */