merge in sni
This commit is contained in:
parent
b347df8d9a
commit
d2003bb8b7
13
configure.ac
13
configure.ac
@ -1049,6 +1049,18 @@ then
|
||||
AC_MSG_ERROR([cannot enable ntru and small, ntru requires TLS which small turns off.])
|
||||
fi
|
||||
|
||||
# SNI
|
||||
AC_ARG_ENABLE([sni],
|
||||
[ --enable-sni Enable SNI (default: disabled)],
|
||||
[ ENABLED_SNI=$enableval ],
|
||||
[ ENABLED_SNI=no ]
|
||||
)
|
||||
|
||||
if test "x$ENABLED_SNI" = "xyes"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI"
|
||||
fi
|
||||
|
||||
|
||||
#valgrind
|
||||
AC_ARG_ENABLE([valgrind],
|
||||
@ -1415,6 +1427,7 @@ echo " * CRL-MONITOR: $ENABLED_CRL_MONITOR"
|
||||
echo " * Persistent session cache: $ENABLED_SAVESESSION"
|
||||
echo " * Persistent cert cache: $ENABLED_SAVECERT"
|
||||
echo " * NTRU: $ENABLED_NTRU"
|
||||
echo " * SNI: $ENABLED_SNI"
|
||||
echo " * valgrind unit tests: $ENABLED_VALGRIND"
|
||||
echo " * LIBZ: $ENABLED_LIBZ"
|
||||
echo " * Examples: $ENABLED_EXAMPLES"
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
#include <cyassl/ctaocrypt/settings.h>
|
||||
|
||||
/* submitted by eof */
|
||||
|
||||
#ifdef USE_CYASSL_MEMORY
|
||||
|
||||
#include <cyassl/ctaocrypt/memory.h>
|
||||
|
@ -26,7 +26,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edited by Moisés Guimarães (moises.guimaraes@phoebus.com.br)
|
||||
* Edited by Moisés Guimarães (moisesguimaraesm@gmail.com)
|
||||
* to fit CyaSSL's needs.
|
||||
*/
|
||||
|
||||
|
@ -89,7 +89,6 @@
|
||||
#ifdef MICROCHIP_PIC32
|
||||
#define SIZEOF_LONG_LONG 8
|
||||
#define SINGLE_THREADED
|
||||
#define CYASSL_USER_IO
|
||||
#define NO_WRITEV
|
||||
#define NO_DEV_RANDOM
|
||||
#define NO_FILESYSTEM
|
||||
|
@ -202,30 +202,30 @@ enum {
|
||||
|
||||
/* memory allocation types for user hints */
|
||||
enum {
|
||||
DYNAMIC_TYPE_CA = 1,
|
||||
DYNAMIC_TYPE_CERT = 2,
|
||||
DYNAMIC_TYPE_KEY = 3,
|
||||
DYNAMIC_TYPE_FILE = 4,
|
||||
DYNAMIC_TYPE_SUBJECT_CN = 5,
|
||||
DYNAMIC_TYPE_PUBLIC_KEY = 6,
|
||||
DYNAMIC_TYPE_SIGNER = 7,
|
||||
DYNAMIC_TYPE_NONE = 8,
|
||||
DYNAMIC_TYPE_BIGINT = 9,
|
||||
DYNAMIC_TYPE_RSA = 10,
|
||||
DYNAMIC_TYPE_METHOD = 11,
|
||||
DYNAMIC_TYPE_OUT_BUFFER = 12,
|
||||
DYNAMIC_TYPE_IN_BUFFER = 13,
|
||||
DYNAMIC_TYPE_INFO = 14,
|
||||
DYNAMIC_TYPE_DH = 15,
|
||||
DYNAMIC_TYPE_DOMAIN = 16,
|
||||
DYNAMIC_TYPE_SSL = 17,
|
||||
DYNAMIC_TYPE_CTX = 18,
|
||||
DYNAMIC_TYPE_WRITEV = 19,
|
||||
DYNAMIC_TYPE_OPENSSL = 20,
|
||||
DYNAMIC_TYPE_DSA = 21,
|
||||
DYNAMIC_TYPE_CRL = 22,
|
||||
DYNAMIC_TYPE_REVOKED = 23,
|
||||
DYNAMIC_TYPE_CRL_ENTRY = 24,
|
||||
DYNAMIC_TYPE_CA = 1,
|
||||
DYNAMIC_TYPE_CERT = 2,
|
||||
DYNAMIC_TYPE_KEY = 3,
|
||||
DYNAMIC_TYPE_FILE = 4,
|
||||
DYNAMIC_TYPE_SUBJECT_CN = 5,
|
||||
DYNAMIC_TYPE_PUBLIC_KEY = 6,
|
||||
DYNAMIC_TYPE_SIGNER = 7,
|
||||
DYNAMIC_TYPE_NONE = 8,
|
||||
DYNAMIC_TYPE_BIGINT = 9,
|
||||
DYNAMIC_TYPE_RSA = 10,
|
||||
DYNAMIC_TYPE_METHOD = 11,
|
||||
DYNAMIC_TYPE_OUT_BUFFER = 12,
|
||||
DYNAMIC_TYPE_IN_BUFFER = 13,
|
||||
DYNAMIC_TYPE_INFO = 14,
|
||||
DYNAMIC_TYPE_DH = 15,
|
||||
DYNAMIC_TYPE_DOMAIN = 16,
|
||||
DYNAMIC_TYPE_SSL = 17,
|
||||
DYNAMIC_TYPE_CTX = 18,
|
||||
DYNAMIC_TYPE_WRITEV = 19,
|
||||
DYNAMIC_TYPE_OPENSSL = 20,
|
||||
DYNAMIC_TYPE_DSA = 21,
|
||||
DYNAMIC_TYPE_CRL = 22,
|
||||
DYNAMIC_TYPE_REVOKED = 23,
|
||||
DYNAMIC_TYPE_CRL_ENTRY = 24,
|
||||
DYNAMIC_TYPE_CERT_MANAGER = 25,
|
||||
DYNAMIC_TYPE_CRL_MONITOR = 26,
|
||||
DYNAMIC_TYPE_OCSP_STATUS = 27,
|
||||
@ -243,7 +243,8 @@ enum {
|
||||
DYNAMIC_TYPE_DTLS_MSG = 39,
|
||||
DYNAMIC_TYPE_CAVIUM_TMP = 40,
|
||||
DYNAMIC_TYPE_CAVIUM_RSA = 41,
|
||||
DYNAMIC_TYPE_X509 = 42
|
||||
DYNAMIC_TYPE_X509 = 42,
|
||||
DYNAMIC_TYPE_TLSX = 43
|
||||
};
|
||||
|
||||
/* stack protection */
|
||||
|
167
cyassl/error.h
167
cyassl/error.h
@ -30,94 +30,95 @@
|
||||
#endif
|
||||
|
||||
enum CyaSSL_ErrorCodes {
|
||||
INPUT_CASE_ERROR = -201, /* process input state error */
|
||||
PREFIX_ERROR = -202, /* bad index to key rounds */
|
||||
MEMORY_ERROR = -203, /* out of memory */
|
||||
VERIFY_FINISHED_ERROR = -204, /* verify problem on finished */
|
||||
VERIFY_MAC_ERROR = -205, /* verify mac problem */
|
||||
PARSE_ERROR = -206, /* parse error on header */
|
||||
UNKNOWN_HANDSHAKE_TYPE = -207, /* weird handshake type */
|
||||
SOCKET_ERROR_E = -208, /* error state on socket */
|
||||
SOCKET_NODATA = -209, /* expected data, not there */
|
||||
INCOMPLETE_DATA = -210, /* don't have enough data to
|
||||
complete task */
|
||||
UNKNOWN_RECORD_TYPE = -211, /* unknown type in record hdr */
|
||||
DECRYPT_ERROR = -212, /* error during decryption */
|
||||
FATAL_ERROR = -213, /* recvd alert fatal error */
|
||||
ENCRYPT_ERROR = -214, /* error during encryption */
|
||||
FREAD_ERROR = -215, /* fread problem */
|
||||
NO_PEER_KEY = -216, /* need peer's key */
|
||||
NO_PRIVATE_KEY = -217, /* need the private key */
|
||||
RSA_PRIVATE_ERROR = -218, /* error during rsa priv op */
|
||||
NO_DH_PARAMS = -219, /* server missing DH params */
|
||||
BUILD_MSG_ERROR = -220, /* build message failure */
|
||||
INPUT_CASE_ERROR = -201, /* process input state error */
|
||||
PREFIX_ERROR = -202, /* bad index to key rounds */
|
||||
MEMORY_ERROR = -203, /* out of memory */
|
||||
VERIFY_FINISHED_ERROR = -204, /* verify problem on finished */
|
||||
VERIFY_MAC_ERROR = -205, /* verify mac problem */
|
||||
PARSE_ERROR = -206, /* parse error on header */
|
||||
UNKNOWN_HANDSHAKE_TYPE = -207, /* weird handshake type */
|
||||
SOCKET_ERROR_E = -208, /* error state on socket */
|
||||
SOCKET_NODATA = -209, /* expected data, not there */
|
||||
INCOMPLETE_DATA = -210, /* don't have enough data to
|
||||
complete task */
|
||||
UNKNOWN_RECORD_TYPE = -211, /* unknown type in record hdr */
|
||||
DECRYPT_ERROR = -212, /* error during decryption */
|
||||
FATAL_ERROR = -213, /* recvd alert fatal error */
|
||||
ENCRYPT_ERROR = -214, /* error during encryption */
|
||||
FREAD_ERROR = -215, /* fread problem */
|
||||
NO_PEER_KEY = -216, /* need peer's key */
|
||||
NO_PRIVATE_KEY = -217, /* need the private key */
|
||||
RSA_PRIVATE_ERROR = -218, /* error during rsa priv op */
|
||||
NO_DH_PARAMS = -219, /* server missing DH params */
|
||||
BUILD_MSG_ERROR = -220, /* build message failure */
|
||||
|
||||
BAD_HELLO = -221, /* client hello malformed */
|
||||
DOMAIN_NAME_MISMATCH = -222, /* peer subject name mismatch */
|
||||
WANT_READ = -223, /* want read, call again */
|
||||
NOT_READY_ERROR = -224, /* handshake layer not ready */
|
||||
PMS_VERSION_ERROR = -225, /* pre m secret version error */
|
||||
VERSION_ERROR = -226, /* record layer version error */
|
||||
WANT_WRITE = -227, /* want write, call again */
|
||||
BUFFER_ERROR = -228, /* malformed buffer input */
|
||||
VERIFY_CERT_ERROR = -229, /* verify cert error */
|
||||
VERIFY_SIGN_ERROR = -230, /* verify sign error */
|
||||
CLIENT_ID_ERROR = -231, /* psk client identity error */
|
||||
SERVER_HINT_ERROR = -232, /* psk server hint error */
|
||||
PSK_KEY_ERROR = -233, /* psk key error */
|
||||
ZLIB_INIT_ERROR = -234, /* zlib init error */
|
||||
ZLIB_COMPRESS_ERROR = -235, /* zlib compression error */
|
||||
ZLIB_DECOMPRESS_ERROR = -236, /* zlib decompression error */
|
||||
BAD_HELLO = -221, /* client hello malformed */
|
||||
DOMAIN_NAME_MISMATCH = -222, /* peer subject name mismatch */
|
||||
WANT_READ = -223, /* want read, call again */
|
||||
NOT_READY_ERROR = -224, /* handshake layer not ready */
|
||||
PMS_VERSION_ERROR = -225, /* pre m secret version error */
|
||||
VERSION_ERROR = -226, /* record layer version error */
|
||||
WANT_WRITE = -227, /* want write, call again */
|
||||
BUFFER_ERROR = -228, /* malformed buffer input */
|
||||
VERIFY_CERT_ERROR = -229, /* verify cert error */
|
||||
VERIFY_SIGN_ERROR = -230, /* verify sign error */
|
||||
CLIENT_ID_ERROR = -231, /* psk client identity error */
|
||||
SERVER_HINT_ERROR = -232, /* psk server hint error */
|
||||
PSK_KEY_ERROR = -233, /* psk key error */
|
||||
ZLIB_INIT_ERROR = -234, /* zlib init error */
|
||||
ZLIB_COMPRESS_ERROR = -235, /* zlib compression error */
|
||||
ZLIB_DECOMPRESS_ERROR = -236, /* zlib decompression error */
|
||||
|
||||
GETTIME_ERROR = -237, /* gettimeofday failed ??? */
|
||||
GETITIMER_ERROR = -238, /* getitimer failed ??? */
|
||||
SIGACT_ERROR = -239, /* sigaction failed ??? */
|
||||
SETITIMER_ERROR = -240, /* setitimer failed ??? */
|
||||
LENGTH_ERROR = -241, /* record layer length error */
|
||||
PEER_KEY_ERROR = -242, /* can't decode peer key */
|
||||
ZERO_RETURN = -243, /* peer sent close notify */
|
||||
SIDE_ERROR = -244, /* wrong client/server type */
|
||||
NO_PEER_CERT = -245, /* peer didn't send key */
|
||||
NTRU_KEY_ERROR = -246, /* NTRU key error */
|
||||
NTRU_DRBG_ERROR = -247, /* NTRU drbg error */
|
||||
NTRU_ENCRYPT_ERROR = -248, /* NTRU encrypt error */
|
||||
NTRU_DECRYPT_ERROR = -249, /* NTRU decrypt error */
|
||||
ECC_CURVETYPE_ERROR = -250, /* Bad ECC Curve Type */
|
||||
ECC_CURVE_ERROR = -251, /* Bad ECC Curve */
|
||||
ECC_PEERKEY_ERROR = -252, /* Bad Peer ECC Key */
|
||||
ECC_MAKEKEY_ERROR = -253, /* Bad Make ECC Key */
|
||||
ECC_EXPORT_ERROR = -254, /* Bad ECC Export Key */
|
||||
ECC_SHARED_ERROR = -255, /* Bad ECC Shared Secret */
|
||||
BAD_MUTEX_ERROR = -256, /* Bad mutex */
|
||||
NOT_CA_ERROR = -257, /* Not a CA cert error */
|
||||
BAD_PATH_ERROR = -258, /* Bad path for opendir */
|
||||
BAD_CERT_MANAGER_ERROR = -259, /* Bad Cert Manager */
|
||||
OCSP_CERT_REVOKED = -260, /* OCSP Certificate revoked */
|
||||
CRL_CERT_REVOKED = -261, /* CRL Certificate revoked */
|
||||
CRL_MISSING = -262, /* CRL Not loaded */
|
||||
MONITOR_RUNNING_E = -263, /* CRL Monitor already running */
|
||||
THREAD_CREATE_E = -264, /* Thread Create Error */
|
||||
OCSP_NEED_URL = -265, /* OCSP need an URL for lookup */
|
||||
OCSP_CERT_UNKNOWN = -266, /* OCSP responder doesn't know */
|
||||
OCSP_LOOKUP_FAIL = -267, /* OCSP lookup not successful */
|
||||
MAX_CHAIN_ERROR = -268, /* max chain depth exceeded */
|
||||
COOKIE_ERROR = -269, /* dtls cookie error */
|
||||
SEQUENCE_ERROR = -270, /* dtls sequence error */
|
||||
SUITES_ERROR = -271, /* suites pointer error */
|
||||
SSL_NO_PEM_HEADER = -272, /* no PEM header found */
|
||||
OUT_OF_ORDER_E = -273, /* out of order message */
|
||||
BAD_KEA_TYPE_E = -274, /* bad KEA type found */
|
||||
SANITY_CIPHER_E = -275, /* sanity check on cipher error */
|
||||
RECV_OVERFLOW_E = -276, /* RXCB returned more than rqed */
|
||||
GEN_COOKIE_E = -277, /* Generate Cookie Error */
|
||||
NO_PEER_VERIFY = -278, /* Need peer cert verify Error */
|
||||
FWRITE_ERROR = -279, /* fwrite problem */
|
||||
CACHE_MATCH_ERROR = -280, /* cache hdr match err */
|
||||
GETTIME_ERROR = -237, /* gettimeofday failed ??? */
|
||||
GETITIMER_ERROR = -238, /* getitimer failed ??? */
|
||||
SIGACT_ERROR = -239, /* sigaction failed ??? */
|
||||
SETITIMER_ERROR = -240, /* setitimer failed ??? */
|
||||
LENGTH_ERROR = -241, /* record layer length error */
|
||||
PEER_KEY_ERROR = -242, /* can't decode peer key */
|
||||
ZERO_RETURN = -243, /* peer sent close notify */
|
||||
SIDE_ERROR = -244, /* wrong client/server type */
|
||||
NO_PEER_CERT = -245, /* peer didn't send key */
|
||||
NTRU_KEY_ERROR = -246, /* NTRU key error */
|
||||
NTRU_DRBG_ERROR = -247, /* NTRU drbg error */
|
||||
NTRU_ENCRYPT_ERROR = -248, /* NTRU encrypt error */
|
||||
NTRU_DECRYPT_ERROR = -249, /* NTRU decrypt error */
|
||||
ECC_CURVETYPE_ERROR = -250, /* Bad ECC Curve Type */
|
||||
ECC_CURVE_ERROR = -251, /* Bad ECC Curve */
|
||||
ECC_PEERKEY_ERROR = -252, /* Bad Peer ECC Key */
|
||||
ECC_MAKEKEY_ERROR = -253, /* Bad Make ECC Key */
|
||||
ECC_EXPORT_ERROR = -254, /* Bad ECC Export Key */
|
||||
ECC_SHARED_ERROR = -255, /* Bad ECC Shared Secret */
|
||||
BAD_MUTEX_ERROR = -256, /* Bad mutex */
|
||||
NOT_CA_ERROR = -257, /* Not a CA cert error */
|
||||
BAD_PATH_ERROR = -258, /* Bad path for opendir */
|
||||
BAD_CERT_MANAGER_ERROR = -259, /* Bad Cert Manager */
|
||||
OCSP_CERT_REVOKED = -260, /* OCSP Certificate revoked */
|
||||
CRL_CERT_REVOKED = -261, /* CRL Certificate revoked */
|
||||
CRL_MISSING = -262, /* CRL Not loaded */
|
||||
MONITOR_RUNNING_E = -263, /* CRL Monitor already running */
|
||||
THREAD_CREATE_E = -264, /* Thread Create Error */
|
||||
OCSP_NEED_URL = -265, /* OCSP need an URL for lookup */
|
||||
OCSP_CERT_UNKNOWN = -266, /* OCSP responder doesn't know */
|
||||
OCSP_LOOKUP_FAIL = -267, /* OCSP lookup not successful */
|
||||
MAX_CHAIN_ERROR = -268, /* max chain depth exceeded */
|
||||
COOKIE_ERROR = -269, /* dtls cookie error */
|
||||
SEQUENCE_ERROR = -270, /* dtls sequence error */
|
||||
SUITES_ERROR = -271, /* suites pointer error */
|
||||
SSL_NO_PEM_HEADER = -272, /* no PEM header found */
|
||||
OUT_OF_ORDER_E = -273, /* out of order message */
|
||||
BAD_KEA_TYPE_E = -274, /* bad KEA type found */
|
||||
SANITY_CIPHER_E = -275, /* sanity check on cipher error */
|
||||
RECV_OVERFLOW_E = -276, /* RXCB returned more than rqed */
|
||||
GEN_COOKIE_E = -277, /* Generate Cookie Error */
|
||||
NO_PEER_VERIFY = -278, /* Need peer cert verify Error */
|
||||
FWRITE_ERROR = -279, /* fwrite problem */
|
||||
CACHE_MATCH_ERROR = -280, /* chache hdr match error */
|
||||
UNKNOWN_SNI_HOST_NAME_E = -281, /* Unrecognized host name Error */
|
||||
/* add strings to SetErrorString !!!!! */
|
||||
|
||||
/* begin negotiation parameter errors */
|
||||
UNSUPPORTED_SUITE = -290, /* unsupported cipher suite */
|
||||
MATCH_SUITE_ERROR = -291 /* can't match cipher suite */
|
||||
UNSUPPORTED_SUITE = -290, /* unsupported cipher suite */
|
||||
MATCH_SUITE_ERROR = -291 /* can't match cipher suite */
|
||||
/* end negotiation parameter errors only 10 for now */
|
||||
/* add strings to SetErrorString !!!!! */
|
||||
};
|
||||
|
@ -592,18 +592,20 @@ enum Misc {
|
||||
COOKIE_SZ = 20, /* use a 20 byte cookie */
|
||||
SUITE_LEN = 2, /* cipher suite sz length */
|
||||
ENUM_LEN = 1, /* always a byte */
|
||||
OPAQUE16_LEN = 2, /* always 2 bytes */
|
||||
COMP_LEN = 1, /* compression length */
|
||||
CURVE_LEN = 2, /* ecc named curve length */
|
||||
SERVER_ID_LEN = 20, /* server session id length */
|
||||
|
||||
HANDSHAKE_HEADER_SZ = 4, /* type + length(3) */
|
||||
RECORD_HEADER_SZ = 5, /* type + version + len(2) */
|
||||
CERT_HEADER_SZ = 3, /* always 3 bytes */
|
||||
REQ_HEADER_SZ = 2, /* cert request header sz */
|
||||
HINT_LEN_SZ = 2, /* length of hint size field */
|
||||
HELLO_EXT_SZ = 8, /* total length of the lazy hello extensions */
|
||||
HELLO_EXT_LEN = 6, /* length of the lazy hello extensions */
|
||||
HELLO_EXT_SIGALGO_SZ = 2, /* length of signature algo extension */
|
||||
HANDSHAKE_HEADER_SZ = 4, /* type + length(3) */
|
||||
RECORD_HEADER_SZ = 5, /* type + version + len(2) */
|
||||
CERT_HEADER_SZ = 3, /* always 3 bytes */
|
||||
REQ_HEADER_SZ = 2, /* cert request header sz */
|
||||
HINT_LEN_SZ = 2, /* length of hint size field */
|
||||
HELLO_EXT_TYPE_SZ = 2, /* length of a hello extension type */
|
||||
HELLO_EXT_SZ = 8, /* total length of the lazy hello extensions */
|
||||
HELLO_EXT_LEN = 6, /* length of the lazy hello extensions */
|
||||
HELLO_EXT_SIGALGO_SZ = 2, /* length of signature algo extension */
|
||||
HELLO_EXT_SIGALGO_MAX = 32, /* number of items in the signature algo list */
|
||||
|
||||
DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */
|
||||
@ -1110,6 +1112,61 @@ typedef struct CYASSL_DTLS_CTX {
|
||||
int fd;
|
||||
} CYASSL_DTLS_CTX;
|
||||
|
||||
/* RFC 6066 TLS Extensions */
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
|
||||
typedef enum {
|
||||
SERVER_NAME_INDICATION = 0,/*
|
||||
MAX_FRAGMENT_LENGTH = 1,
|
||||
CLIENT_CERTIFICATE_URL = 2,
|
||||
TRUSTED_CA_KEYS = 3,
|
||||
TRUNCATED_HMAC = 4,
|
||||
STATUS_REQUEST = 5,
|
||||
SIGNATURE_ALGORITHMS = 13,*/
|
||||
} TLSX_Type;
|
||||
|
||||
typedef struct TLSX {
|
||||
TLSX_Type type; /* Extension Type */
|
||||
void* data; /* Extension Data */
|
||||
byte resp; /* IsResponse Flag */
|
||||
struct TLSX* next; /* List Behavior */
|
||||
} TLSX;
|
||||
|
||||
CYASSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type);
|
||||
CYASSL_LOCAL void TLSX_FreeAll(TLSX* list);
|
||||
|
||||
#ifndef NO_CYASSL_CLIENT
|
||||
CYASSL_LOCAL word16 TLSX_GetRequestSize(CYASSL* ssl);
|
||||
CYASSL_LOCAL word16 TLSX_WriteRequest(CYASSL* ssl, byte* output);
|
||||
#endif
|
||||
|
||||
#ifndef NO_CYASSL_SERVER
|
||||
CYASSL_LOCAL word16 TLSX_GetResponseSize(CYASSL* ssl);
|
||||
CYASSL_LOCAL word16 TLSX_WriteResponse(CYASSL* ssl, byte* output);
|
||||
#endif
|
||||
|
||||
CYASSL_LOCAL int TLSX_Parse(CYASSL* ssl, byte* input, word16 length,
|
||||
byte isRequest, Suites *suites);
|
||||
|
||||
/* Server Name Indication */
|
||||
#ifdef HAVE_SNI
|
||||
|
||||
typedef enum {
|
||||
HOST_NAME = 0
|
||||
} SNI_Type;
|
||||
|
||||
typedef struct SNI {
|
||||
SNI_Type type; /* SNI Type */
|
||||
union { char* host_name; } data; /* SNI Data */
|
||||
struct SNI* next; /* List Behavior */
|
||||
} SNI;
|
||||
|
||||
CYASSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data,
|
||||
word16 size);
|
||||
|
||||
#endif /* HAVE_SNI */
|
||||
|
||||
#endif /* HAVE_TLS_EXTENSIONS */
|
||||
|
||||
/* CyaSSL context type */
|
||||
struct CYASSL_CTX {
|
||||
@ -1167,6 +1224,9 @@ struct CYASSL_CTX {
|
||||
#ifdef HAVE_CAVIUM
|
||||
int devId; /* cavium device id to use */
|
||||
#endif
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
TLSX* extensions; /* RFC 6066 TLS Extensions data */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -1709,6 +1769,9 @@ struct CYASSL {
|
||||
#endif
|
||||
#ifdef HAVE_CAVIUM
|
||||
int devId; /* cavium device id to use */
|
||||
#endif
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
TLSX* extensions; /* RFC 6066 TLS Extensions data */
|
||||
#endif
|
||||
CYASSL_ALERT_HISTORY alert_history;
|
||||
};
|
||||
@ -1829,7 +1892,8 @@ enum AlertDescription {
|
||||
illegal_parameter = 47,
|
||||
decrypt_error = 51,
|
||||
protocol_version = 70,
|
||||
no_renegotiation = 100
|
||||
no_renegotiation = 100,
|
||||
unrecognized_name = 112
|
||||
};
|
||||
|
||||
|
||||
|
@ -929,6 +929,13 @@ CYASSL_API void CyaSSL_FreeArrays(CYASSL*);
|
||||
CYASSL_API int CyaSSL_UseCavium(CYASSL*, int devId);
|
||||
CYASSL_API int CyaSSL_CTX_UseCavium(CYASSL_CTX*, int devId);
|
||||
|
||||
/* tls extensions */
|
||||
#ifdef HAVE_SNI
|
||||
CYASSL_API int CyaSSL_UseSNI(CYASSL* ssl, unsigned char type, const void* data,
|
||||
unsigned short size);
|
||||
CYASSL_API int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, unsigned char type,
|
||||
const void* data, unsigned short size);
|
||||
#endif
|
||||
|
||||
#define CYASSL_CRL_MONITOR 0x01 /* monitor this dir flag */
|
||||
#define CYASSL_CRL_START_MON 0x02 /* start monitoring flag */
|
||||
|
@ -32,6 +32,8 @@
|
||||
|
||||
#include <cyassl/ctaocrypt/settings.h>
|
||||
|
||||
#include <cyassl/ctaocrypt/settings.h>
|
||||
|
||||
#if !defined(CYASSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER)
|
||||
/* in case memory tracker wants stats */
|
||||
#define CYASSL_TRACK_MEMORY
|
||||
@ -130,6 +132,7 @@ static void Usage(void)
|
||||
#ifdef SHOW_SIZES
|
||||
printf("-z Print structure sizes\n");
|
||||
#endif
|
||||
printf("-S <str> Use Host Name Indication\n");
|
||||
}
|
||||
|
||||
|
||||
@ -178,6 +181,10 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
char* ourCert = (char*)cliCert;
|
||||
char* ourKey = (char*)cliKey;
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
char* sniHostName = NULL;
|
||||
#endif
|
||||
|
||||
int argc = ((func_args*)args)->argc;
|
||||
char** argv = ((func_args*)args)->argv;
|
||||
|
||||
@ -193,7 +200,7 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
(void)sslResume;
|
||||
(void)trackMemory;
|
||||
|
||||
while ((ch = mygetopt(argc, argv, "?gdusmNrtfxh:p:v:l:A:c:k:b:z")) != -1) {
|
||||
while ((ch = mygetopt(argc, argv, "?gdusmNrtfxh:p:v:l:A:c:k:b:zS:")) != -1){
|
||||
switch (ch) {
|
||||
case '?' :
|
||||
Usage();
|
||||
@ -292,6 +299,12 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'S' :
|
||||
#ifdef HAVE_SNI
|
||||
sniHostName = myoptarg;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
Usage();
|
||||
exit(MY_EX_USAGE);
|
||||
@ -358,6 +371,7 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
|
||||
default:
|
||||
err_sys("Bad SSL version");
|
||||
break;
|
||||
}
|
||||
|
||||
if (method == NULL)
|
||||
@ -445,6 +459,12 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
CyaSSL_CTX_UseCavium(ctx, CAVIUM_DEV_ID);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
if (sniHostName)
|
||||
if (CyaSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName)))
|
||||
err_sys("UseSNI failed");
|
||||
#endif
|
||||
|
||||
if (benchmark) {
|
||||
/* time passed in number of connects give average */
|
||||
int times = benchmark;
|
||||
|
@ -122,6 +122,7 @@ static void Usage(void)
|
||||
" add -v 2 for DTLSv1 (default), -v 3 for DTLSv1.2\n");
|
||||
printf("-f Fewer packets/group messages\n");
|
||||
printf("-N Use Non-blocking sockets\n");
|
||||
printf("-S <str> Use Host Name Indication\n");
|
||||
}
|
||||
|
||||
#ifdef CYASSL_MDK_SHELL
|
||||
@ -159,6 +160,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
int argc = ((func_args*)args)->argc;
|
||||
char** argv = ((func_args*)args)->argv;
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
char* sniHostName = NULL;
|
||||
#endif
|
||||
|
||||
((func_args*)args)->return_code = -1; /* error state */
|
||||
|
||||
#ifdef NO_RSA
|
||||
@ -168,7 +173,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
#endif
|
||||
(void)trackMemory;
|
||||
|
||||
while ((ch = mygetopt(argc, argv, "?dbstnNufp:v:l:A:c:k:")) != -1) {
|
||||
while ((ch = mygetopt(argc, argv, "?dbstnNufp:v:l:A:c:k:S:")) != -1) {
|
||||
switch (ch) {
|
||||
case '?' :
|
||||
Usage();
|
||||
@ -240,6 +245,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
nonBlocking = 1;
|
||||
break;
|
||||
|
||||
case 'S' :
|
||||
#ifdef HAVE_SNI
|
||||
sniHostName = myoptarg;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
Usage();
|
||||
exit(MY_EX_USAGE);
|
||||
@ -396,6 +407,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
if (sniHostName)
|
||||
if (CyaSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName)))
|
||||
err_sys("UseSNI failed");
|
||||
#endif
|
||||
|
||||
ssl = SSL_new(ctx);
|
||||
if (ssl == NULL)
|
||||
err_sys("unable to get SSL");
|
||||
|
@ -421,6 +421,9 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
|
||||
#ifdef HAVE_CAVIUM
|
||||
ctx->devId = NO_CAVIUM_DEVICE;
|
||||
#endif
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
ctx->extensions = NULL;
|
||||
#endif
|
||||
|
||||
if (InitMutex(&ctx->countMutex) < 0) {
|
||||
CYASSL_MSG("Mutex error on CTX init");
|
||||
@ -452,6 +455,9 @@ void SSL_CtxResourceFree(CYASSL_CTX* ctx)
|
||||
#ifdef HAVE_OCSP
|
||||
CyaSSL_OCSP_Cleanup(&ctx->ocsp);
|
||||
#endif
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
TLSX_FreeAll(ctx->extensions);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1436,6 +1442,10 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
|
||||
ssl->devId = ctx->devId;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
ssl->extensions = NULL;
|
||||
#endif
|
||||
|
||||
ssl->rng = NULL;
|
||||
ssl->arrays = NULL;
|
||||
|
||||
@ -1655,6 +1665,9 @@ void SSL_ResourceFree(CYASSL* ssl)
|
||||
XFREE(ssl->eccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
TLSX_FreeAll(ssl->extensions);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -5802,6 +5815,10 @@ void SetErrorString(int error, char* str)
|
||||
XSTRNCPY(str, "Cache restore header match Error", max);
|
||||
break;
|
||||
|
||||
case UNKNOWN_SNI_HOST_NAME_E:
|
||||
XSTRNCPY(str, "Unrecognized host name Error", max);
|
||||
break;
|
||||
|
||||
default :
|
||||
XSTRNCPY(str, "unknown error number", max);
|
||||
}
|
||||
@ -6693,9 +6710,13 @@ int SetCipherList(Suites* s, const char* list)
|
||||
+ ssl->suites->suiteSz + SUITE_LEN
|
||||
+ COMP_LEN + ENUM_LEN;
|
||||
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
length += TLSX_GetRequestSize(ssl);
|
||||
#else
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) {
|
||||
length += ssl->suites->hashSigAlgoSz + HELLO_EXT_SZ;
|
||||
}
|
||||
#endif
|
||||
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
|
||||
|
||||
#ifdef CYASSL_DTLS
|
||||
@ -6768,6 +6789,11 @@ int SetCipherList(Suites* s, const char* list)
|
||||
else
|
||||
output[idx++] = NO_COMPRESSION;
|
||||
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
idx += TLSX_WriteRequest(ssl, output + idx);
|
||||
|
||||
(void)idx; /* suppress analyzer warning, keep idx current */
|
||||
#else
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
|
||||
{
|
||||
int i;
|
||||
@ -6785,6 +6811,7 @@ int SetCipherList(Suites* s, const char* list)
|
||||
output[idx] = ssl->suites->hashSigAlgo[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CYASSL_DTLS
|
||||
if (ssl->options.dtls) {
|
||||
@ -6906,8 +6933,29 @@ int SetCipherList(Suites* s, const char* list)
|
||||
}
|
||||
|
||||
*inOutIdx = i;
|
||||
if ( (i - begin) < helloSz)
|
||||
*inOutIdx = begin + helloSz; /* skip extensions */
|
||||
if ( (i - begin) < helloSz) {
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
if (IsTLS(ssl)) {
|
||||
int ret = 0;
|
||||
word16 totalExtSz;
|
||||
Suites clSuites; /* just for compatibility right now */
|
||||
|
||||
ato16(&input[i], &totalExtSz);
|
||||
i += LENGTH_SZ;
|
||||
if (totalExtSz > helloSz + begin - i)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
if ((ret = TLSX_Parse(ssl, (byte *) input + i,
|
||||
totalExtSz, 0, &clSuites)))
|
||||
return ret;
|
||||
|
||||
i += totalExtSz;
|
||||
*inOutIdx = i;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
*inOutIdx = begin + helloSz; /* skip extensions */
|
||||
}
|
||||
|
||||
ssl->options.serverState = SERVER_HELLO_COMPLETE;
|
||||
|
||||
@ -7779,7 +7827,11 @@ int SetCipherList(Suites* s, const char* list)
|
||||
+ SUITE_LEN
|
||||
+ ENUM_LEN;
|
||||
|
||||
/* check for available size */
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
length += TLSX_GetResponseSize(ssl);
|
||||
#endif
|
||||
|
||||
/* check for avalaible size */
|
||||
if ((ret = CheckAvailableSize(ssl, MAX_HELLO_SZ)) != 0)
|
||||
return ret;
|
||||
|
||||
@ -7827,11 +7879,17 @@ int SetCipherList(Suites* s, const char* list)
|
||||
output[idx++] = ssl->options.cipherSuite0;
|
||||
output[idx++] = ssl->options.cipherSuite;
|
||||
|
||||
/* last, compression */
|
||||
/* then compression */
|
||||
if (ssl->options.usingCompression)
|
||||
output[idx++] = ZLIB_COMPRESSION;
|
||||
else
|
||||
output[idx++] = NO_COMPRESSION;
|
||||
|
||||
/* last, extensions */
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
if (IsTLS(ssl))
|
||||
TLSX_WriteResponse(ssl, output + idx);
|
||||
#endif
|
||||
|
||||
ssl->buffers.outputBuffer.length += sendSz;
|
||||
#ifdef CYASSL_DTLS
|
||||
@ -9324,11 +9382,14 @@ int SetCipherList(Suites* s, const char* list)
|
||||
else
|
||||
i += b; /* ignore, since we're not on */
|
||||
|
||||
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
|
||||
|
||||
*inOutIdx = i;
|
||||
if ( (i - begin) < helloSz) {
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
if (IsTLS(ssl)) {
|
||||
int ret = 0;
|
||||
#else
|
||||
if (IsAtLeastTLSv1_2(ssl)) {
|
||||
#endif
|
||||
/* Process the hello extension. Skip unsupported. */
|
||||
word16 totalExtSz;
|
||||
|
||||
@ -9336,6 +9397,14 @@ int SetCipherList(Suites* s, const char* list)
|
||||
i += LENGTH_SZ;
|
||||
if (totalExtSz > helloSz + begin - i)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
if ((ret = TLSX_Parse(ssl, (byte *) input + i,
|
||||
totalExtSz, 1, &clSuites)))
|
||||
return ret;
|
||||
|
||||
i += totalExtSz;
|
||||
#else
|
||||
while (totalExtSz) {
|
||||
word16 extId, extSz;
|
||||
|
||||
@ -9361,11 +9430,14 @@ int SetCipherList(Suites* s, const char* list)
|
||||
|
||||
totalExtSz -= LENGTH_SZ + EXT_ID_SZ + extSz;
|
||||
}
|
||||
#endif
|
||||
*inOutIdx = i;
|
||||
}
|
||||
else
|
||||
*inOutIdx = begin + helloSz; /* skip extensions */
|
||||
}
|
||||
|
||||
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
|
||||
|
||||
ssl->options.haveSessionId = 1;
|
||||
/* ProcessOld uses same resume code */
|
||||
|
21
src/ssl.c
21
src/ssl.c
@ -509,6 +509,27 @@ int CyaSSL_CTX_UseCavium(CYASSL_CTX* ctx, int devId)
|
||||
|
||||
#endif /* HAVE_CAVIUM */
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
|
||||
int CyaSSL_UseSNI(CYASSL* ssl, unsigned char type, const void* data,
|
||||
unsigned short size)
|
||||
{
|
||||
if (ssl == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
return TLSX_UseSNI(&ssl->extensions, type, data, size);
|
||||
}
|
||||
|
||||
int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, unsigned char type, const void* data,
|
||||
unsigned short size)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
return TLSX_UseSNI(&ctx->extensions, type, data, size);
|
||||
}
|
||||
|
||||
#endif /* HAVE_SNI */
|
||||
|
||||
#ifndef CYASSL_LEANPSK
|
||||
int CyaSSL_send(CYASSL* ssl, const void* data, int sz, int flags)
|
||||
|
580
src/tls.c
580
src/tls.c
@ -370,6 +370,12 @@ static INLINE void c16toa(word16 u16, byte* c)
|
||||
c[1] = u16 & 0xff;
|
||||
}
|
||||
|
||||
/* convert opaque to 16 bit integer */
|
||||
static INLINE void ato16(const byte* c, word16* u16)
|
||||
{
|
||||
*u16 = (c[0] << 8) | (c[1]);
|
||||
}
|
||||
|
||||
|
||||
/* convert 32 bit integer to opaque */
|
||||
static INLINE void c32toa(word32 u32, byte* c)
|
||||
@ -484,6 +490,580 @@ void TLS_hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz,
|
||||
HmacFinal(&hmac, digest);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
|
||||
static int TLSX_Append(TLSX** list, TLSX_Type type)
|
||||
{
|
||||
TLSX* extension;
|
||||
|
||||
if (list == NULL) /* won't check type since this function is static */
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if ((extension = XMALLOC(sizeof(TLSX), 0, DYNAMIC_TYPE_TLSX)) == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
extension->type = type;
|
||||
extension->data = NULL;
|
||||
extension->resp = 0;
|
||||
extension->next = *list;
|
||||
*list = extension;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef NO_CYASSL_SERVER
|
||||
|
||||
static void TLSX_SetResponse(CYASSL* ssl, TLSX_Type type)
|
||||
{
|
||||
TLSX *ext = TLSX_Find(ssl->extensions, type);
|
||||
|
||||
if (ext)
|
||||
ext->resp = 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* SNI - Server Name Indication */
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
|
||||
static void TLSX_SNI_Free(SNI* sni)
|
||||
{
|
||||
if (sni) {
|
||||
switch (sni->type) {
|
||||
case HOST_NAME:
|
||||
XFREE(sni->data.host_name, 0, DYNAMIC_TYPE_TLSX);
|
||||
break;
|
||||
}
|
||||
|
||||
XFREE(sni, 0, DYNAMIC_TYPE_TLSX);
|
||||
}
|
||||
}
|
||||
|
||||
static void TLSX_SNI_FreeAll(SNI* list)
|
||||
{
|
||||
SNI* sni;
|
||||
|
||||
while ((sni = list)) {
|
||||
list = sni->next;
|
||||
TLSX_SNI_Free(sni);
|
||||
}
|
||||
}
|
||||
|
||||
static int TLSX_SNI_Append(SNI** list, SNI_Type type, const void* data,
|
||||
word16 size)
|
||||
{
|
||||
SNI* sni;
|
||||
|
||||
if (list == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if ((sni = XMALLOC(sizeof(SNI), 0, DYNAMIC_TYPE_TLSX)) == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
switch (type) {
|
||||
case HOST_NAME: {
|
||||
sni->data.host_name = XMALLOC(size + 1, 0, DYNAMIC_TYPE_TLSX);
|
||||
|
||||
if (sni->data.host_name) {
|
||||
XSTRNCPY(sni->data.host_name, (const char*) data, size);
|
||||
sni->data.host_name[size] = 0;
|
||||
} else {
|
||||
XFREE(sni, 0, DYNAMIC_TYPE_TLSX);
|
||||
return MEMORY_E;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* invalid type */
|
||||
XFREE(sni, 0, DYNAMIC_TYPE_TLSX);
|
||||
return BAD_FUNC_ARG;
|
||||
break;
|
||||
}
|
||||
|
||||
sni->type = type;
|
||||
sni->next = *list;
|
||||
*list = sni;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static word16 TLSX_SNI_GetSize(SNI* list)
|
||||
{
|
||||
SNI* sni;
|
||||
word16 length = OPAQUE16_LEN; /* list length */
|
||||
|
||||
while ((sni = list)) {
|
||||
list = sni->next;
|
||||
|
||||
length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */
|
||||
|
||||
switch (sni->type) {
|
||||
case HOST_NAME:
|
||||
length += XSTRLEN((char*) sni->data.host_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static word16 TLSX_SNI_Write(SNI* list, byte* output)
|
||||
{
|
||||
SNI* sni;
|
||||
word16 length = 0;
|
||||
word16 offset = OPAQUE16_LEN; /* list length offset */
|
||||
|
||||
while ((sni = list)) {
|
||||
list = sni->next;
|
||||
|
||||
output[offset++] = sni->type; /* sni type */
|
||||
|
||||
switch (sni->type) {
|
||||
case HOST_NAME:
|
||||
length = XSTRLEN((char*) sni->data.host_name);
|
||||
|
||||
c16toa(length, output + offset); /* sni length */
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
XMEMCPY(output + offset, sni->data.host_name, length);
|
||||
|
||||
offset += length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static SNI* TLSX_SNI_Find(SNI *list, SNI_Type type)
|
||||
{
|
||||
SNI *sni = list;
|
||||
|
||||
while (sni && sni->type != type)
|
||||
sni = sni->next;
|
||||
|
||||
return sni;
|
||||
}
|
||||
|
||||
static int TLSX_SNI_Parse(CYASSL* ssl, byte* input, word16 length,
|
||||
byte isRequest)
|
||||
{
|
||||
#ifndef NO_CYASSL_SERVER
|
||||
word16 size = 0;
|
||||
word16 offset = 0;
|
||||
#endif
|
||||
|
||||
TLSX *extension = TLSX_Find(ssl->extensions, SERVER_NAME_INDICATION);
|
||||
|
||||
if (!extension)
|
||||
extension = TLSX_Find(ssl->ctx->extensions, SERVER_NAME_INDICATION);
|
||||
|
||||
if (!extension || !extension->data) {
|
||||
if (!isRequest) {
|
||||
CYASSL_MSG("Unexpected SNI response from server");
|
||||
}
|
||||
|
||||
return 0; /* not using SNI */
|
||||
}
|
||||
|
||||
if (!isRequest) {
|
||||
if (length) {
|
||||
CYASSL_MSG("SNI response should be empty!");
|
||||
}
|
||||
|
||||
return 0; /* nothing to do */
|
||||
}
|
||||
|
||||
#ifndef NO_CYASSL_SERVER
|
||||
|
||||
if (OPAQUE16_LEN > length)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
ato16(input, &size);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
/* validating sni list length */
|
||||
if (length != OPAQUE16_LEN + size)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
for (size = 0; offset < length; offset += size) {
|
||||
SNI *sni;
|
||||
SNI_Type type = input[offset++];
|
||||
|
||||
if (offset + OPAQUE16_LEN > length)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
ato16(input + offset, &size);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
if (offset + size > length)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
if (!(sni = TLSX_SNI_Find((SNI *) extension->data, type))) {
|
||||
continue; /* not using this SNI type */
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case HOST_NAME:
|
||||
if (XSTRNCMP(sni->data.host_name,
|
||||
(const char *) input + offset, size)) {
|
||||
SendAlert(ssl, alert_fatal, unrecognized_name);
|
||||
|
||||
return UNKNOWN_SNI_HOST_NAME_E;
|
||||
} else {
|
||||
int r = TLSX_UseSNI(&ssl->extensions, type, (byte *) "", 0);
|
||||
|
||||
if (r) return r; /* throw error */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
TLSX_SetResponse(ssl, SERVER_NAME_INDICATION);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size)
|
||||
{
|
||||
TLSX* extension = NULL;
|
||||
SNI* sni = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (extensions == NULL || data == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if ((ret = TLSX_SNI_Append(&sni, type, data, size)) != 0)
|
||||
return ret;
|
||||
|
||||
extension = *extensions;
|
||||
|
||||
/* find SNI extension if it already exists. */
|
||||
while (extension && extension->type != SERVER_NAME_INDICATION)
|
||||
extension = extension->next;
|
||||
|
||||
/* push new SNI extension if it doesn't exists. */
|
||||
if (!extension) {
|
||||
if ((ret = TLSX_Append(extensions, SERVER_NAME_INDICATION)) != 0) {
|
||||
TLSX_SNI_Free(sni);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extension = *extensions;
|
||||
}
|
||||
|
||||
/* push new SNI object to extension data. */
|
||||
sni->next = (SNI*) extension->data;
|
||||
extension->data = (void*) sni;
|
||||
|
||||
/* look for another server name of the same type to remove (replacement) */
|
||||
while ((sni = sni->next)) {
|
||||
if (sni->next && sni->next->type == type) {
|
||||
SNI *next = sni->next;
|
||||
|
||||
sni->next = next->next;
|
||||
TLSX_SNI_Free(next);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SNI_FREE_ALL TLSX_SNI_FreeAll
|
||||
#define SNI_GET_SIZE TLSX_SNI_GetSize
|
||||
#define SNI_WRITE TLSX_SNI_Write
|
||||
#define SNI_PARSE TLSX_SNI_Parse
|
||||
|
||||
#else
|
||||
|
||||
#define SNI_FREE_ALL(x)
|
||||
#define SNI_GET_SIZE(x) 0
|
||||
#define SNI_WRITE(x) 0
|
||||
#define SNI_PARSE(x) 0
|
||||
|
||||
#endif /* HAVE_SNI */
|
||||
|
||||
TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
|
||||
{
|
||||
TLSX* extension = list;
|
||||
|
||||
while (extension && extension->type != type)
|
||||
extension = extension->next;
|
||||
|
||||
return extension;
|
||||
}
|
||||
|
||||
void TLSX_FreeAll(TLSX* list)
|
||||
{
|
||||
TLSX* extension;
|
||||
|
||||
while ((extension = list)) {
|
||||
list = extension->next;
|
||||
|
||||
switch (extension->type) {
|
||||
case SERVER_NAME_INDICATION:
|
||||
SNI_FREE_ALL((SNI *) extension->data);
|
||||
break;
|
||||
}
|
||||
|
||||
XFREE(extension, 0, DYNAMIC_TYPE_TLSX);
|
||||
}
|
||||
}
|
||||
|
||||
#define IS_OFF(cemaphor, light) \
|
||||
((cemaphor)[(light) / 8] ^ (0x01 >> ((light) % 8)))
|
||||
|
||||
#define TURN_ON(cemaphor, light) \
|
||||
((cemaphor)[(light) / 8] |= (0x01 >> ((light) % 8)))
|
||||
|
||||
static word16 TLSX_GetSize(TLSX* list, byte* cemaphor, byte isRequest)
|
||||
{
|
||||
TLSX* extension;
|
||||
word16 length = 0;
|
||||
|
||||
while ((extension = list)) {
|
||||
list = extension->next;
|
||||
|
||||
if (!isRequest && !extension->resp)
|
||||
continue; /* skip! */
|
||||
|
||||
if (IS_OFF(cemaphor, extension->type)) {
|
||||
/* type + data length */
|
||||
length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
|
||||
|
||||
switch (extension->type) {
|
||||
case SERVER_NAME_INDICATION:
|
||||
if (isRequest)
|
||||
length += SNI_GET_SIZE((SNI *) extension->data);
|
||||
break;
|
||||
}
|
||||
|
||||
TURN_ON(cemaphor, extension->type);
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static word16 TLSX_Write(TLSX* list, byte* output, byte* cemaphor,
|
||||
byte isRequest)
|
||||
{
|
||||
TLSX* extension;
|
||||
word16 offset = 0;
|
||||
word16 length_offset = 0;
|
||||
|
||||
while ((extension = list)) {
|
||||
list = extension->next;
|
||||
|
||||
if (!isRequest && !extension->resp)
|
||||
continue; /* skip! */
|
||||
|
||||
if (IS_OFF(cemaphor, extension->type)) {
|
||||
/* extension type */
|
||||
c16toa(extension->type, output + offset);
|
||||
offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
|
||||
length_offset = offset;
|
||||
|
||||
/* extension data should be written internally */
|
||||
switch (extension->type) {
|
||||
case SERVER_NAME_INDICATION:
|
||||
if (isRequest)
|
||||
offset += SNI_WRITE((SNI *) extension->data,
|
||||
output + offset);
|
||||
break;
|
||||
}
|
||||
|
||||
/* writing extension data length */
|
||||
c16toa(offset - length_offset,
|
||||
output + length_offset - OPAQUE16_LEN);
|
||||
|
||||
TURN_ON(cemaphor, extension->type);
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#ifndef NO_CYASSL_CLIENT
|
||||
|
||||
word16 TLSX_GetRequestSize(CYASSL* ssl)
|
||||
{
|
||||
word16 length = 0;
|
||||
|
||||
if (ssl && IsTLS(ssl)) {
|
||||
byte cemaphor[16] = {0};
|
||||
|
||||
if (ssl->extensions)
|
||||
length += TLSX_GetSize(ssl->extensions, cemaphor, 1);
|
||||
|
||||
if (ssl->ctx && ssl->ctx->extensions)
|
||||
length += TLSX_GetSize(ssl->ctx->extensions, cemaphor, 1);
|
||||
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
|
||||
length += ssl->suites->hashSigAlgoSz + HELLO_EXT_LEN;
|
||||
}
|
||||
|
||||
if (length)
|
||||
length += OPAQUE16_LEN; /* for total length storage */
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
word16 TLSX_WriteRequest(CYASSL* ssl, byte* output)
|
||||
{
|
||||
word16 offset = 0;
|
||||
|
||||
if (ssl && IsTLS(ssl) && output) {
|
||||
byte cemaphor[16] = {0};
|
||||
|
||||
offset += OPAQUE16_LEN; /* extensions length */
|
||||
|
||||
if (ssl->extensions)
|
||||
offset += TLSX_Write(ssl->extensions, output + offset,
|
||||
cemaphor, 1);
|
||||
|
||||
if (ssl->ctx && ssl->ctx->extensions)
|
||||
offset += TLSX_Write(ssl->ctx->extensions, output + offset,
|
||||
cemaphor, 1);
|
||||
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
|
||||
{
|
||||
int i;
|
||||
/* extension type */
|
||||
c16toa(HELLO_EXT_SIG_ALGO, output + offset);
|
||||
offset += HELLO_EXT_TYPE_SZ;
|
||||
|
||||
/* extension data length */
|
||||
c16toa(OPAQUE16_LEN + ssl->suites->hashSigAlgoSz, output + offset);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
/* sig algos length */
|
||||
c16toa(ssl->suites->hashSigAlgoSz, output + offset);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
/* sig algos */
|
||||
for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++)
|
||||
output[offset] = ssl->suites->hashSigAlgo[i];
|
||||
}
|
||||
|
||||
if (offset > OPAQUE16_LEN)
|
||||
c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#endif /* NO_CYASSL_CLIENT */
|
||||
|
||||
#ifndef NO_CYASSL_SERVER
|
||||
|
||||
word16 TLSX_GetResponseSize(CYASSL* ssl)
|
||||
{
|
||||
word16 length = 0;
|
||||
byte cemaphor[16] = {0};
|
||||
|
||||
if (ssl && IsTLS(ssl))
|
||||
length += TLSX_GetSize(ssl->extensions, cemaphor, 0);
|
||||
|
||||
/* All the response data is set at the ssl object only, so no ctx here. */
|
||||
|
||||
if (length)
|
||||
length += OPAQUE16_LEN; /* for total length storage */
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
word16 TLSX_WriteResponse(CYASSL *ssl, byte* output)
|
||||
{
|
||||
word16 offset = 0;
|
||||
|
||||
if (ssl && IsTLS(ssl) && output) {
|
||||
byte cemaphor[16] = {0};
|
||||
|
||||
offset += OPAQUE16_LEN; /* extensions length */
|
||||
|
||||
offset += TLSX_Write(ssl->extensions, output + offset, cemaphor, 0);
|
||||
|
||||
if (offset > OPAQUE16_LEN)
|
||||
c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#endif /* NO_CYASSL_SERVER */
|
||||
|
||||
int TLSX_Parse(CYASSL* ssl, byte* input, word16 length, byte isRequest,
|
||||
Suites *suites)
|
||||
{
|
||||
int ret = 0;
|
||||
word16 offset = 0;
|
||||
|
||||
if (!ssl || !input || !suites)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
while (ret == 0 && offset < length) {
|
||||
word16 type;
|
||||
word16 size;
|
||||
|
||||
if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
ato16(input + offset, &type);
|
||||
offset += HELLO_EXT_TYPE_SZ;
|
||||
|
||||
ato16(input + offset, &size);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
if (offset + size > length)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
switch (type) {
|
||||
case SERVER_NAME_INDICATION:
|
||||
ret = SNI_PARSE(ssl, input + offset, size, isRequest);
|
||||
break;
|
||||
|
||||
case HELLO_EXT_SIG_ALGO:
|
||||
if (isRequest) {
|
||||
/* do not mess with offset inside the switch! */
|
||||
if (IsAtLeastTLSv1_2(ssl)) {
|
||||
ato16(input + offset, &suites->hashSigAlgoSz);
|
||||
|
||||
if (suites->hashSigAlgoSz > size - OPAQUE16_LEN)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
XMEMCPY(suites->hashSigAlgo,
|
||||
input + offset + OPAQUE16_LEN,
|
||||
min(suites->hashSigAlgoSz,
|
||||
HELLO_EXT_SIGALGO_MAX));
|
||||
}
|
||||
} else {
|
||||
CYASSL_MSG("Servers MUST NOT send SIG ALGO extension.");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* offset should be updated here! */
|
||||
offset += size;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* undefining cemaphor macros */
|
||||
#undef IS_OFF
|
||||
#undef TURN_ON
|
||||
|
||||
#endif /* HAVE_TLS_EXTENSIONS */
|
||||
|
||||
|
||||
#ifndef NO_CYASSL_CLIENT
|
||||
|
||||
|
38
tests/api.c
38
tests/api.c
@ -47,6 +47,11 @@ static int test_client_CyaSSL_new(void);
|
||||
static int test_CyaSSL_read_write(void);
|
||||
#endif /* NO_RSA */
|
||||
#endif /* NO_FILESYSTEM */
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
#ifdef HAVE_SNI
|
||||
static void test_CyaSSL_UseSNI(void);
|
||||
#endif /* HAVE_TLS_EXTENSIONS */
|
||||
#endif /* HAVE_SNI */
|
||||
|
||||
/* test function helpers */
|
||||
static int test_method(CYASSL_METHOD *method, const char *name);
|
||||
@ -91,6 +96,11 @@ int ApiTest(void)
|
||||
test_CyaSSL_read_write();
|
||||
#endif /* NO_RSA */
|
||||
#endif /* NO_FILESYSTEM */
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
#ifdef HAVE_SNI
|
||||
test_CyaSSL_UseSNI();
|
||||
#endif /* HAVE_SNI */
|
||||
#endif /* HAVE_TLS_EXTENSIONS */
|
||||
test_CyaSSL_Cleanup();
|
||||
printf(" End API Tests\n");
|
||||
|
||||
@ -211,6 +221,34 @@ int test_CyaSSL_CTX_new(CYASSL_METHOD *method)
|
||||
return TEST_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
#ifdef HAVE_SNI
|
||||
void test_CyaSSL_UseSNI(void)
|
||||
{
|
||||
CYASSL_CTX *ctx = CyaSSL_CTX_new(CyaSSLv23_client_method());
|
||||
CYASSL *ssl = CyaSSL_new(ctx);
|
||||
|
||||
AssertNotNull(ctx);
|
||||
AssertNotNull(ssl);
|
||||
|
||||
/* error cases */
|
||||
AssertIntNE(0, CyaSSL_CTX_UseSNI(NULL, 0, (void *) "ctx", XSTRLEN("ctx")));
|
||||
AssertIntNE(0, CyaSSL_UseSNI( NULL, 0, (void *) "ssl", XSTRLEN("ssl")));
|
||||
AssertIntNE(0, CyaSSL_CTX_UseSNI(ctx, -1, (void *) "ctx", XSTRLEN("ctx")));
|
||||
AssertIntNE(0, CyaSSL_UseSNI( ssl, -1, (void *) "ssl", XSTRLEN("ssl")));
|
||||
AssertIntNE(0, CyaSSL_CTX_UseSNI(ctx, 0, (void *) NULL, XSTRLEN("ctx")));
|
||||
AssertIntNE(0, CyaSSL_UseSNI( ssl, 0, (void *) NULL, XSTRLEN("ssl")));
|
||||
|
||||
/* success case */
|
||||
AssertIntEQ(0, CyaSSL_CTX_UseSNI(ctx, 0, (void *) "ctx", XSTRLEN("ctx")));
|
||||
AssertIntEQ(0, CyaSSL_UseSNI( ssl, 0, (void *) "ssl", XSTRLEN("ssl")));
|
||||
|
||||
CyaSSL_free(ssl);
|
||||
CyaSSL_CTX_free(ctx);
|
||||
}
|
||||
#endif /* HAVE_SNI */
|
||||
#endif /* HAVE_TLS_EXTENSIONS */
|
||||
|
||||
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
|
||||
/* Helper for testing CyaSSL_CTX_use_certificate_file() */
|
||||
int test_ucf(CYASSL_CTX *ctx, const char* file, int type, int cond,
|
||||
|
50
tests/unit.h
50
tests/unit.h
@ -5,6 +5,56 @@
|
||||
|
||||
#include <cyassl/test.h> /* thread and tcp stuff */
|
||||
|
||||
#define Fail(description, result) do { \
|
||||
printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \
|
||||
printf("\n\n test: "); printf description; \
|
||||
printf("\n\n result: "); printf result; \
|
||||
abort(); \
|
||||
} while(0)
|
||||
|
||||
#define Assert(test, description, result) if (!(test)) Fail(description, result)
|
||||
|
||||
#define AssertTrue(x) Assert( (x), ("%s is true", #x), (#x " => FALSE"))
|
||||
#define AssertFalse(x) Assert(!(x), ("%s is false", #x), (#x " => TRUE"))
|
||||
#define AssertNotNull(x) Assert( (x), ("%s is not null", #x), (#x " => NULL"))
|
||||
|
||||
#define AssertNull(x) do { \
|
||||
void* _x = (void *) (x); \
|
||||
\
|
||||
Assert(!_x, ("%s is null", #x), (#x " => %p", _x)); \
|
||||
} while(0)
|
||||
|
||||
#define AssertInt(x, y, op, er) do { \
|
||||
int _x = x; \
|
||||
int _y = y; \
|
||||
\
|
||||
Assert(_x op _y, ("%s " #op " %s", #x, #y), ("%d " #er " %d", _x, _y)); \
|
||||
} while(0)
|
||||
|
||||
#define AssertIntEQ(x, y) AssertInt(x, y, ==, !=)
|
||||
#define AssertIntNE(x, y) AssertInt(x, y, !=, ==)
|
||||
#define AssertIntGT(x, y) AssertInt(x, y, >, <=)
|
||||
#define AssertIntLT(x, y) AssertInt(x, y, <, >=)
|
||||
#define AssertIntGE(x, y) AssertInt(x, y, >=, <)
|
||||
#define AssertIntLE(x, y) AssertInt(x, y, <=, >)
|
||||
|
||||
#define AssertStr(x, y, op, er) do { \
|
||||
const char* _x = x; \
|
||||
const char* _y = y; \
|
||||
int _z = strcmp(_x, _y); \
|
||||
\
|
||||
Assert(_z op 0, ("%s " #op " %s", #x, #y), \
|
||||
("\"%s\" " #er " \"%s\"", _x, _y));\
|
||||
} while(0)
|
||||
|
||||
#define AssertStrEQ(x, y) AssertStr(x, y, ==, !=)
|
||||
#define AssertStrNE(x, y) AssertStr(x, y, !=, ==)
|
||||
#define AssertStrGT(x, y) AssertStr(x, y, >, <=)
|
||||
#define AssertStrLT(x, y) AssertStr(x, y, <, >=)
|
||||
#define AssertStrGE(x, y) AssertStr(x, y, >=, <)
|
||||
#define AssertStrLE(x, y) AssertStr(x, y, <=, >)
|
||||
|
||||
|
||||
int ApiTest(void);
|
||||
int SuiteTest(void);
|
||||
int HashTest(void);
|
||||
|
Loading…
Reference in New Issue
Block a user