mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-04 05:04:41 +02:00
Merge branch 'master' into ssh
This commit is contained in:
@@ -8030,6 +8030,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
|
||||
case DH_KEY_SIZE_E:
|
||||
return "DH key too small Error";
|
||||
|
||||
case SNI_ABSENT_ERROR:
|
||||
return "No Server Name Indication extension Error";
|
||||
|
||||
default :
|
||||
return "unknown error number";
|
||||
}
|
||||
|
314
src/tls.c
314
src/tls.c
@@ -713,15 +713,38 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
|
||||
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
|
||||
/**
|
||||
* The TLSX semaphore is used to calculate the size of the extensions to be sent
|
||||
* from one peer to another.
|
||||
*/
|
||||
|
||||
/** Supports up to 64 flags. Update as needed. */
|
||||
/** Supports up to 64 flags. Increase as needed. */
|
||||
#define SEMAPHORE_SIZE 8
|
||||
|
||||
|
||||
/**
|
||||
* Converts the extension type (id) to an index in the semaphore.
|
||||
*
|
||||
* Oficial reference for TLS extension types:
|
||||
* http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml
|
||||
*
|
||||
* Motivation:
|
||||
* Previously, we used the extension type itself as the index of that
|
||||
* extension in the semaphore as the extension types were declared
|
||||
* sequentially, but maintain a semaphore as big as the number of available
|
||||
* extensions is no longer an option since the release of renegotiation_info.
|
||||
*
|
||||
* How to update:
|
||||
* Assign extension types that extrapolate the number of available semaphores
|
||||
* to the first available index going backwards in the semaphore array.
|
||||
* When adding a new extension type that don't extrapolate the number of
|
||||
* available semaphores, check for a possible collision with with a
|
||||
* 'remapped' extension type.
|
||||
*/
|
||||
static INLINE word16 TLSX_ToSemaphore(word16 type)
|
||||
{
|
||||
switch (type) {
|
||||
case SECURE_RENEGOTIATION:
|
||||
|
||||
case SECURE_RENEGOTIATION: /* 0xFF01 */
|
||||
return 63;
|
||||
|
||||
default:
|
||||
@@ -739,30 +762,45 @@ static INLINE word16 TLSX_ToSemaphore(word16 type)
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/** Checks if a specific light (tls extension) is not set in the semaphore. */
|
||||
#define IS_OFF(semaphore, light) \
|
||||
((semaphore)[(light) / 8] ^ (byte) (0x01 << ((light) % 8)))
|
||||
|
||||
|
||||
/** Turn on a specific light (tls extension) in the semaphore. */
|
||||
#define TURN_ON(semaphore, light) \
|
||||
((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8)))
|
||||
|
||||
/** Creates a new extension. */
|
||||
static TLSX* TLSX_New(TLSX_Type type, void* data)
|
||||
{
|
||||
TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), 0, DYNAMIC_TYPE_TLSX);
|
||||
|
||||
if (extension) {
|
||||
extension->type = type;
|
||||
extension->data = data;
|
||||
extension->resp = 0;
|
||||
extension->next = NULL;
|
||||
}
|
||||
|
||||
return extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new extension and pushes it to the provided list.
|
||||
* Checks for duplicate extensions, keeps the newest.
|
||||
*/
|
||||
static int TLSX_Push(TLSX** list, TLSX_Type type, void* data)
|
||||
{
|
||||
TLSX* extension;
|
||||
TLSX* extension = TLSX_New(type, data);
|
||||
|
||||
extension = (TLSX*)XMALLOC(sizeof(TLSX), 0, DYNAMIC_TYPE_TLSX);
|
||||
if (extension == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
extension->type = type;
|
||||
extension->data = data;
|
||||
extension->resp = 0;
|
||||
/* pushes the new extension on the list. */
|
||||
extension->next = *list;
|
||||
*list = extension;
|
||||
|
||||
/* remove duplicated extensions, there should be only one of each type. */
|
||||
/* remove duplicate extensions, there should be only one of each type. */
|
||||
do {
|
||||
if (extension->next && extension->next->type == type) {
|
||||
TLSX *next = extension->next;
|
||||
@@ -781,9 +819,9 @@ static int TLSX_Push(TLSX** list, TLSX_Type type, void* data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
|
||||
/** Mark an extension to be sent back to the client. */
|
||||
void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type);
|
||||
|
||||
void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type)
|
||||
@@ -796,10 +834,46 @@ void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type)
|
||||
|
||||
#endif
|
||||
|
||||
/* SNI - Server Name Indication */
|
||||
|
||||
/* Server Name Indication */
|
||||
#ifdef HAVE_SNI
|
||||
|
||||
/** Creates a new SNI object. */
|
||||
static SNI* TLSX_SNI_New(byte type, const void* data, word16 size)
|
||||
{
|
||||
SNI* sni = (SNI*)XMALLOC(sizeof(SNI), 0, DYNAMIC_TYPE_TLSX);
|
||||
|
||||
if (sni) {
|
||||
sni->type = type;
|
||||
sni->next = NULL;
|
||||
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
sni->options = 0;
|
||||
sni->status = WOLFSSL_SNI_NO_MATCH;
|
||||
#endif
|
||||
|
||||
switch (sni->type) {
|
||||
case WOLFSSL_SNI_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);
|
||||
sni = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* invalid type */
|
||||
XFREE(sni, 0, DYNAMIC_TYPE_TLSX);
|
||||
sni = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return sni;
|
||||
}
|
||||
|
||||
/** Releases a SNI object. */
|
||||
static void TLSX_SNI_Free(SNI* sni)
|
||||
{
|
||||
if (sni) {
|
||||
@@ -813,6 +887,7 @@ static void TLSX_SNI_Free(SNI* sni)
|
||||
}
|
||||
}
|
||||
|
||||
/** Releases all SNI objects in the provided list. */
|
||||
static void TLSX_SNI_FreeAll(SNI* list)
|
||||
{
|
||||
SNI* sni;
|
||||
@@ -823,48 +898,7 @@ static void TLSX_SNI_FreeAll(SNI* list)
|
||||
}
|
||||
}
|
||||
|
||||
static int TLSX_SNI_Append(SNI** list, byte 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 WOLFSSL_SNI_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;
|
||||
}
|
||||
|
||||
sni->type = type;
|
||||
sni->next = *list;
|
||||
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
sni->options = 0;
|
||||
sni->status = WOLFSSL_SNI_NO_MATCH;
|
||||
#endif
|
||||
|
||||
*list = sni;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Tells the buffered size of the SNI objects in a list. */
|
||||
static word16 TLSX_SNI_GetSize(SNI* list)
|
||||
{
|
||||
SNI* sni;
|
||||
@@ -885,6 +919,7 @@ static word16 TLSX_SNI_GetSize(SNI* list)
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Writes the SNI objects of a list in a buffer. */
|
||||
static word16 TLSX_SNI_Write(SNI* list, byte* output)
|
||||
{
|
||||
SNI* sni;
|
||||
@@ -915,6 +950,7 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output)
|
||||
return offset;
|
||||
}
|
||||
|
||||
/** Finds a SNI object in the provided list. */
|
||||
static SNI* TLSX_SNI_Find(SNI *list, byte type)
|
||||
{
|
||||
SNI *sni = list;
|
||||
@@ -926,17 +962,18 @@ static SNI* TLSX_SNI_Find(SNI *list, byte type)
|
||||
}
|
||||
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
|
||||
/** Sets the status of a SNI object. */
|
||||
static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status)
|
||||
{
|
||||
TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION);
|
||||
SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type);
|
||||
|
||||
if (sni) {
|
||||
if (sni)
|
||||
sni->status = status;
|
||||
WOLFSSL_MSG("SNI did match!");
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the status of a SNI object. */
|
||||
byte TLSX_SNI_Status(TLSX* extensions, byte type)
|
||||
{
|
||||
TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION);
|
||||
@@ -947,8 +984,10 @@ byte TLSX_SNI_Status(TLSX* extensions, byte type)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NO_WOLFSSL_SERVER */
|
||||
|
||||
/** Parses a buffer of SNI extensions. */
|
||||
static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
||||
byte isRequest)
|
||||
{
|
||||
@@ -963,12 +1002,12 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
||||
extension = TLSX_Find(ssl->ctx->extensions, SERVER_NAME_INDICATION);
|
||||
|
||||
if (!extension || !extension->data)
|
||||
return isRequest ? 0 : BUFFER_ERROR; /* not using SNI OR unexpected
|
||||
SNI response from server. */
|
||||
return isRequest ? 0 /* not using SNI. */
|
||||
: BUFFER_ERROR; /* unexpected SNI response. */
|
||||
|
||||
if (!isRequest)
|
||||
return length ? BUFFER_ERROR : 0; /* SNI response must be empty!
|
||||
Nothing else to do. */
|
||||
return length ? BUFFER_ERROR /* SNI response MUST be empty. */
|
||||
: 0; /* nothing else to do. */
|
||||
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
|
||||
@@ -995,9 +1034,8 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
||||
if (offset + size > length)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
if (!(sni = TLSX_SNI_Find((SNI*)extension->data, type))) {
|
||||
continue; /* not using this SNI type */
|
||||
}
|
||||
if (!(sni = TLSX_SNI_Find((SNI*)extension->data, type)))
|
||||
continue; /* not using this type of SNI. */
|
||||
|
||||
switch(type) {
|
||||
case WOLFSSL_SNI_HOST_NAME: {
|
||||
@@ -1009,10 +1047,15 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
||||
int r = TLSX_UseSNI(&ssl->extensions,
|
||||
type, input + offset, size);
|
||||
|
||||
if (r != SSL_SUCCESS) return r; /* throw error */
|
||||
if (r != SSL_SUCCESS)
|
||||
return r; /* throws error. */
|
||||
|
||||
TLSX_SNI_SetStatus(ssl->extensions, type,
|
||||
matched ? WOLFSSL_SNI_REAL_MATCH : WOLFSSL_SNI_FAKE_MATCH);
|
||||
matched ? WOLFSSL_SNI_REAL_MATCH
|
||||
: WOLFSSL_SNI_FAKE_MATCH);
|
||||
|
||||
TLSX_SetResponse(ssl, SERVER_NAME_INDICATION);
|
||||
WOLFSSL_MSG("SNI did match!");
|
||||
|
||||
} else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) {
|
||||
SendAlert(ssl, alert_fatal, unrecognized_name);
|
||||
@@ -1022,8 +1065,6 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TLSX_SetResponse(ssl, SERVER_NAME_INDICATION);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1031,21 +1072,63 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest)
|
||||
{
|
||||
if (isRequest) {
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, SERVER_NAME_INDICATION);
|
||||
TLSX* ssl_ext = TLSX_Find(ssl->extensions, SERVER_NAME_INDICATION);
|
||||
SNI* ctx_sni = ctx_ext ? ctx_ext->data : NULL;
|
||||
SNI* ssl_sni = ssl_ext ? ssl_ext->data : NULL;
|
||||
SNI* sni = NULL;
|
||||
|
||||
for (; ctx_sni; ctx_sni = ctx_sni->next) {
|
||||
if (ctx_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
|
||||
sni = TLSX_SNI_Find(ssl_sni, ctx_sni->type);
|
||||
|
||||
if (sni) {
|
||||
if (sni->status != WOLFSSL_SNI_NO_MATCH)
|
||||
continue;
|
||||
|
||||
/* if ssl level overrides ctx level, it is ok. */
|
||||
if ((sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
SendAlert(ssl, alert_fatal, handshake_failure);
|
||||
return SNI_ABSENT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
for (; ssl_sni; ssl_sni = ssl_sni->next) {
|
||||
if (ssl_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
|
||||
if (ssl_sni->status != WOLFSSL_SNI_NO_MATCH)
|
||||
continue;
|
||||
|
||||
SendAlert(ssl, alert_fatal, handshake_failure);
|
||||
return SNI_ABSENT_ERROR;
|
||||
}
|
||||
}
|
||||
#endif /* NO_WOLFSSL_SERVER */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size)
|
||||
{
|
||||
TLSX* extension = TLSX_Find(*extensions, SERVER_NAME_INDICATION);
|
||||
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;
|
||||
if ((sni = TLSX_SNI_New(type, data, size)) == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
if (!extension) {
|
||||
if ((ret = TLSX_Push(extensions, SERVER_NAME_INDICATION, (void*)sni))
|
||||
!= 0) {
|
||||
int ret = TLSX_Push(extensions, SERVER_NAME_INDICATION, (void*)sni);
|
||||
if (ret != 0) {
|
||||
TLSX_SNI_Free(sni);
|
||||
return ret;
|
||||
}
|
||||
@@ -1055,7 +1138,7 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size)
|
||||
sni->next = (SNI*)extension->data;
|
||||
extension->data = (void*)sni;
|
||||
|
||||
/* look for another server name of the same type to remove */
|
||||
/* remove duplicate SNI, there should be only one of each type. */
|
||||
do {
|
||||
if (sni->next && sni->next->type == type) {
|
||||
SNI *next = sni->next;
|
||||
@@ -1063,6 +1146,8 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size)
|
||||
sni->next = next->next;
|
||||
TLSX_SNI_Free(next);
|
||||
|
||||
/* there is no way to occur more than */
|
||||
/* two SNIs of the same type. */
|
||||
break;
|
||||
}
|
||||
} while ((sni = sni->next));
|
||||
@@ -1072,6 +1157,8 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size)
|
||||
}
|
||||
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
|
||||
/** Tells the SNI requested by the client. */
|
||||
word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data)
|
||||
{
|
||||
TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION);
|
||||
@@ -1088,6 +1175,7 @@ word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Sets the options for a SNI object. */
|
||||
void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options)
|
||||
{
|
||||
TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION);
|
||||
@@ -1097,6 +1185,7 @@ void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options)
|
||||
sni->options = options;
|
||||
}
|
||||
|
||||
/** Retrieves a SNI request from a client hello buffer. */
|
||||
int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
|
||||
byte type, byte* sni, word32* inOutSz)
|
||||
{
|
||||
@@ -1114,19 +1203,19 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
|
||||
/* http://tools.ietf.org/html/rfc4346#appendix-E.1 */
|
||||
if ((enum HandShakeType) clientHello[++offset] == client_hello) {
|
||||
offset += ENUM_LEN + VERSION_SZ; /* skip version */
|
||||
|
||||
|
||||
ato16(clientHello + offset, &len16);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
|
||||
if (len16 % 3) /* cipher_spec_length must be multiple of 3 */
|
||||
return BUFFER_ERROR;
|
||||
|
||||
ato16(clientHello + offset, &len16);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
|
||||
if (len16 != 0) /* session_id_length must be 0 */
|
||||
return BUFFER_ERROR;
|
||||
|
||||
|
||||
return SNI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@@ -1249,17 +1338,19 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
|
||||
|
||||
#endif
|
||||
|
||||
#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
|
||||
#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
|
||||
#define SNI_VERIFY_PARSE TLSX_SNI_VerifyParse
|
||||
|
||||
#else
|
||||
|
||||
#define SNI_FREE_ALL(list)
|
||||
#define SNI_GET_SIZE(list) 0
|
||||
#define SNI_WRITE(a, b) 0
|
||||
#define SNI_PARSE(a, b, c, d) 0
|
||||
#define SNI_GET_SIZE(list) 0
|
||||
#define SNI_WRITE(a, b) 0
|
||||
#define SNI_PARSE(a, b, c, d) 0
|
||||
#define SNI_VERIFY_PARSE(a, b) 0
|
||||
|
||||
#endif /* HAVE_SNI */
|
||||
|
||||
@@ -1433,7 +1524,7 @@ static void TLSX_EllipticCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
|
||||
if (ssl->suites->suites[i] == ECC_BYTE)
|
||||
return;
|
||||
|
||||
/* No elliptic curve suite found */
|
||||
/* turns semaphore on to avoid sending this extension. */
|
||||
TURN_ON(semaphore, TLSX_ToSemaphore(ELLIPTIC_CURVES));
|
||||
}
|
||||
|
||||
@@ -1956,7 +2047,7 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket)
|
||||
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
|
||||
|
||||
/** Finds an extension in the provided list. */
|
||||
TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
|
||||
{
|
||||
TLSX* extension = list;
|
||||
@@ -1967,6 +2058,7 @@ TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
|
||||
return extension;
|
||||
}
|
||||
|
||||
/** Releases all extensions in the provided list. */
|
||||
void TLSX_FreeAll(TLSX* list)
|
||||
{
|
||||
TLSX* extension;
|
||||
@@ -1975,6 +2067,7 @@ void TLSX_FreeAll(TLSX* list)
|
||||
list = extension->next;
|
||||
|
||||
switch (extension->type) {
|
||||
|
||||
case SERVER_NAME_INDICATION:
|
||||
SNI_FREE_ALL((SNI*)extension->data);
|
||||
break;
|
||||
@@ -2004,10 +2097,12 @@ void TLSX_FreeAll(TLSX* list)
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks if the tls extensions are supported based on the protocol version. */
|
||||
int TLSX_SupportExtensions(WOLFSSL* ssl) {
|
||||
return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR);
|
||||
}
|
||||
|
||||
/** Tells the buffered size of the extensions in a list. */
|
||||
static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest)
|
||||
{
|
||||
TLSX* extension;
|
||||
@@ -2016,26 +2111,31 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest)
|
||||
while ((extension = list)) {
|
||||
list = extension->next;
|
||||
|
||||
/* only extensions marked as response are sent back to the client. */
|
||||
if (!isRequest && !extension->resp)
|
||||
continue; /* skip! */
|
||||
|
||||
/* ssl level extensions are expected to override ctx level ones. */
|
||||
if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type)))
|
||||
continue; /* skip! */
|
||||
|
||||
/* type + data length */
|
||||
/* extension type + extension data length. */
|
||||
length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
|
||||
|
||||
switch (extension->type) {
|
||||
|
||||
case SERVER_NAME_INDICATION:
|
||||
/* SNI only sends the name on the request. */
|
||||
if (isRequest)
|
||||
length += SNI_GET_SIZE(extension->data);
|
||||
break;
|
||||
|
||||
case MAX_FRAGMENT_LENGTH:
|
||||
length += MFL_GET_SIZE(extension->data);
|
||||
break;
|
||||
|
||||
case TRUNCATED_HMAC:
|
||||
/* empty extension. */
|
||||
/* always empty. */
|
||||
break;
|
||||
|
||||
case ELLIPTIC_CURVES:
|
||||
@@ -2051,12 +2151,15 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest)
|
||||
break;
|
||||
}
|
||||
|
||||
/* marks the extension as processed so ctx level */
|
||||
/* extensions don't overlap with ssl level ones. */
|
||||
TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Writes the extensions of a list in a buffer. */
|
||||
static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
|
||||
byte isRequest)
|
||||
{
|
||||
@@ -2067,18 +2170,20 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
|
||||
while ((extension = list)) {
|
||||
list = extension->next;
|
||||
|
||||
/* only extensions marked as response are written in a response. */
|
||||
if (!isRequest && !extension->resp)
|
||||
continue; /* skip! */
|
||||
|
||||
/* ssl level extensions are expected to override ctx level ones. */
|
||||
if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type)))
|
||||
continue; /* skip! */
|
||||
|
||||
/* extension type */
|
||||
/* writes extension type. */
|
||||
c16toa(extension->type, output + offset);
|
||||
offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
|
||||
length_offset = offset;
|
||||
|
||||
/* extension data should be written internally */
|
||||
/* extension data should be written internally. */
|
||||
switch (extension->type) {
|
||||
case SERVER_NAME_INDICATION:
|
||||
if (isRequest)
|
||||
@@ -2090,7 +2195,7 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
|
||||
break;
|
||||
|
||||
case TRUNCATED_HMAC:
|
||||
/* empty extension. */
|
||||
/* always empty. */
|
||||
break;
|
||||
|
||||
case ELLIPTIC_CURVES:
|
||||
@@ -2108,9 +2213,11 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
|
||||
break;
|
||||
}
|
||||
|
||||
/* writing extension data length */
|
||||
/* writes extension data length. */
|
||||
c16toa(offset - length_offset, output + length_offset - OPAQUE16_LEN);
|
||||
|
||||
/* marks the extension as processed so ctx level */
|
||||
/* extensions don't overlap with ssl level ones. */
|
||||
TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
|
||||
}
|
||||
|
||||
@@ -2119,6 +2226,7 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
|
||||
|
||||
#ifndef NO_WOLFSSL_CLIENT
|
||||
|
||||
/** Tells the buffered size of extensions to be sent into the client hello. */
|
||||
word16 TLSX_GetRequestSize(WOLFSSL* ssl)
|
||||
{
|
||||
word16 length = 0;
|
||||
@@ -2140,11 +2248,12 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl)
|
||||
}
|
||||
|
||||
if (length)
|
||||
length += OPAQUE16_LEN; /* for total length storage */
|
||||
length += OPAQUE16_LEN; /* for total length storage. */
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Writes the extensions to be sent into the client hello. */
|
||||
word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output)
|
||||
{
|
||||
word16 offset = 0;
|
||||
@@ -2155,6 +2264,7 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output)
|
||||
offset += OPAQUE16_LEN; /* extensions length */
|
||||
|
||||
EC_VALIDATE_REQUEST(ssl, semaphore);
|
||||
STK_VALIDATE_REQUEST(ssl);
|
||||
|
||||
if (ssl->extensions)
|
||||
offset += TLSX_Write(ssl->extensions, output + offset,
|
||||
@@ -2195,6 +2305,7 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output)
|
||||
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
|
||||
/** Tells the buffered size of extensions to be sent into the server hello. */
|
||||
word16 TLSX_GetResponseSize(WOLFSSL* ssl)
|
||||
{
|
||||
word16 length = 0;
|
||||
@@ -2211,6 +2322,7 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl)
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Writes the server hello extensions into a buffer. */
|
||||
word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output)
|
||||
{
|
||||
word16 offset = 0;
|
||||
@@ -2231,6 +2343,7 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output)
|
||||
|
||||
#endif /* NO_WOLFSSL_SERVER */
|
||||
|
||||
/** Parses a buffer of TLS extensions. */
|
||||
int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest,
|
||||
Suites *suites)
|
||||
{
|
||||
@@ -2318,6 +2431,9 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest,
|
||||
offset += size;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
ret = SNI_VERIFY_PARSE(ssl, isRequest);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2326,8 +2442,7 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest,
|
||||
#undef TURN_ON
|
||||
#undef SEMAPHORE_SIZE
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_TLS_EXTENSIONS */
|
||||
|
||||
#ifndef NO_WOLFSSL_CLIENT
|
||||
|
||||
@@ -2465,4 +2580,3 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest,
|
||||
|
||||
#endif /* NO_WOLFSSL_SERVER */
|
||||
#endif /* NO_TLS */
|
||||
|
||||
|
346
tests/api.c
346
tests/api.c
@@ -134,9 +134,9 @@ static void test_wolfSSL_Method_Allocators(void)
|
||||
static void test_wolfSSL_CTX_new(WOLFSSL_METHOD *method)
|
||||
{
|
||||
WOLFSSL_CTX *ctx;
|
||||
|
||||
|
||||
AssertNull(ctx = wolfSSL_CTX_new(NULL));
|
||||
|
||||
|
||||
AssertNotNull(method);
|
||||
AssertNotNull(ctx = wolfSSL_CTX_new(method));
|
||||
|
||||
@@ -152,10 +152,10 @@ static void test_wolfSSL_CTX_use_certificate_file(void)
|
||||
AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
||||
|
||||
/* invalid context */
|
||||
AssertFalse(wolfSSL_CTX_use_certificate_file(NULL, svrCert,
|
||||
AssertFalse(wolfSSL_CTX_use_certificate_file(NULL, svrCert,
|
||||
SSL_FILETYPE_PEM));
|
||||
/* invalid cert file */
|
||||
AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, bogusFile,
|
||||
AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, bogusFile,
|
||||
SSL_FILETYPE_PEM));
|
||||
/* invalid cert type */
|
||||
AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCert, 9999));
|
||||
@@ -181,10 +181,10 @@ static void test_wolfSSL_CTX_use_PrivateKey_file(void)
|
||||
AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
||||
|
||||
/* invalid context */
|
||||
AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKey,
|
||||
AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKey,
|
||||
SSL_FILETYPE_PEM));
|
||||
/* invalid key file */
|
||||
AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, bogusFile,
|
||||
AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, bogusFile,
|
||||
SSL_FILETYPE_PEM));
|
||||
/* invalid key type */
|
||||
AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, 9999));
|
||||
@@ -209,7 +209,7 @@ static void test_wolfSSL_CTX_load_verify_locations(void)
|
||||
WOLFSSL_CTX *ctx;
|
||||
|
||||
AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
||||
|
||||
|
||||
/* invalid context */
|
||||
AssertFalse(wolfSSL_CTX_load_verify_locations(NULL, caCert, 0));
|
||||
|
||||
@@ -272,18 +272,18 @@ static void test_client_wolfSSL_new(void)
|
||||
AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
||||
|
||||
AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCert, 0));
|
||||
|
||||
|
||||
/* invalid context */
|
||||
AssertNull(ssl = wolfSSL_new(NULL));
|
||||
|
||||
/* success */
|
||||
AssertNotNull(ssl = wolfSSL_new(ctx_nocert));
|
||||
wolfSSL_free(ssl);
|
||||
|
||||
|
||||
/* success */
|
||||
AssertNotNull(ssl = wolfSSL_new(ctx));
|
||||
wolfSSL_free(ssl);
|
||||
|
||||
|
||||
wolfSSL_CTX_free(ctx);
|
||||
wolfSSL_CTX_free(ctx_nocert);
|
||||
#endif
|
||||
@@ -353,7 +353,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
|
||||
"Please run from wolfSSL home dir");*/
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
ssl = wolfSSL_new(ctx);
|
||||
tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0);
|
||||
CloseSocket(sockfd);
|
||||
@@ -382,7 +382,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
|
||||
input[idx] = 0;
|
||||
printf("Client message: %s\n", input);
|
||||
}
|
||||
|
||||
|
||||
if (wolfSSL_write(ssl, msg, sizeof(msg)) != sizeof(msg))
|
||||
{
|
||||
/*err_sys("SSL_write failed");*/
|
||||
@@ -401,7 +401,7 @@ done:
|
||||
wolfSSL_shutdown(ssl);
|
||||
wolfSSL_free(ssl);
|
||||
wolfSSL_CTX_free(ctx);
|
||||
|
||||
|
||||
CloseSocket(clientfd);
|
||||
((func_args*)args)->return_code = TEST_SUCCESS;
|
||||
|
||||
@@ -494,7 +494,7 @@ static void test_client_nofail(void* args)
|
||||
done2:
|
||||
wolfSSL_free(ssl);
|
||||
wolfSSL_CTX_free(ctx);
|
||||
|
||||
|
||||
CloseSocket(sockfd);
|
||||
((func_args*)args)->return_code = TEST_SUCCESS;
|
||||
|
||||
@@ -720,10 +720,10 @@ static void test_wolfSSL_read_write(void)
|
||||
|
||||
StartTCP();
|
||||
InitTcpReady(&ready);
|
||||
|
||||
|
||||
server_args.signal = &ready;
|
||||
client_args.signal = &ready;
|
||||
|
||||
|
||||
start_thread(test_server_nofail, &server_args, &serverThread);
|
||||
wait_tcp_ready(&server_args);
|
||||
test_client_nofail(&client_args);
|
||||
@@ -746,68 +746,106 @@ static void test_wolfSSL_read_write(void)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
static void test_wolfSSL_UseSNI_params(void)
|
||||
{
|
||||
WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
|
||||
WOLFSSL *ssl = wolfSSL_new(ctx);
|
||||
|
||||
AssertNotNull(ctx);
|
||||
AssertNotNull(ssl);
|
||||
|
||||
/* invalid [ctx|ssl] */
|
||||
AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseSNI(NULL, 0, "ctx", 3));
|
||||
AssertIntNE(SSL_SUCCESS, wolfSSL_UseSNI( NULL, 0, "ssl", 3));
|
||||
/* invalid type */
|
||||
AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, -1, "ctx", 3));
|
||||
AssertIntNE(SSL_SUCCESS, wolfSSL_UseSNI( ssl, -1, "ssl", 3));
|
||||
/* invalid data */
|
||||
AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, 0, NULL, 3));
|
||||
AssertIntNE(SSL_SUCCESS, wolfSSL_UseSNI( ssl, 0, NULL, 3));
|
||||
/* success case */
|
||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, 0, "ctx", 3));
|
||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseSNI( ssl, 0, "ssl", 3));
|
||||
|
||||
wolfSSL_free(ssl);
|
||||
wolfSSL_CTX_free(ctx);
|
||||
}
|
||||
|
||||
/* BEGIN of connection tests callbacks */
|
||||
static void use_SNI_at_ctx(WOLFSSL_CTX* ctx)
|
||||
{
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
char name[] = "www.yassl.com";
|
||||
|
||||
AssertIntEQ(SSL_SUCCESS,
|
||||
wolfSSL_CTX_UseSNI(ctx, type, (void *) name, XSTRLEN(name)));
|
||||
wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, "www.wolfssl.com", 15));
|
||||
}
|
||||
|
||||
static void use_SNI_at_ssl(WOLFSSL* ssl)
|
||||
{
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
char name[] = "www.yassl.com";
|
||||
|
||||
AssertIntEQ(SSL_SUCCESS,
|
||||
wolfSSL_UseSNI(ssl, type, (void *) name, XSTRLEN(name)));
|
||||
wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "www.wolfssl.com", 15));
|
||||
}
|
||||
|
||||
static void different_SNI_at_ssl(WOLFSSL* ssl)
|
||||
{
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
char name[] = "ww2.yassl.com";
|
||||
|
||||
AssertIntEQ(SSL_SUCCESS,
|
||||
wolfSSL_UseSNI(ssl, type, (void *) name, XSTRLEN(name)));
|
||||
wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "ww2.wolfssl.com", 15));
|
||||
}
|
||||
|
||||
static void use_SNI_WITH_CONTINUE_at_ssl(WOLFSSL* ssl)
|
||||
{
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
|
||||
use_SNI_at_ssl(ssl);
|
||||
|
||||
wolfSSL_SNI_SetOptions(ssl, type, WOLFSSL_SNI_CONTINUE_ON_MISMATCH);
|
||||
wolfSSL_SNI_SetOptions(ssl, WOLFSSL_SNI_HOST_NAME,
|
||||
WOLFSSL_SNI_CONTINUE_ON_MISMATCH);
|
||||
}
|
||||
|
||||
static void use_SNI_WITH_FAKE_ANSWER_at_ssl(WOLFSSL* ssl)
|
||||
{
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
|
||||
use_SNI_at_ssl(ssl);
|
||||
|
||||
wolfSSL_SNI_SetOptions(ssl, type, WOLFSSL_SNI_ANSWER_ON_MISMATCH);
|
||||
wolfSSL_SNI_SetOptions(ssl, WOLFSSL_SNI_HOST_NAME,
|
||||
WOLFSSL_SNI_ANSWER_ON_MISMATCH);
|
||||
}
|
||||
|
||||
static void verify_SNI_abort_on_client(WOLFSSL* ssl)
|
||||
static void use_MANDATORY_SNI_at_ctx(WOLFSSL_CTX* ctx)
|
||||
{
|
||||
use_SNI_at_ctx(ctx);
|
||||
wolfSSL_CTX_SNI_SetOptions(ctx, WOLFSSL_SNI_HOST_NAME,
|
||||
WOLFSSL_SNI_ABORT_ON_ABSENCE);
|
||||
}
|
||||
|
||||
static void use_MANDATORY_SNI_at_ssl(WOLFSSL* ssl)
|
||||
{
|
||||
use_SNI_at_ssl(ssl);
|
||||
wolfSSL_SNI_SetOptions(ssl, WOLFSSL_SNI_HOST_NAME,
|
||||
WOLFSSL_SNI_ABORT_ON_ABSENCE);
|
||||
}
|
||||
|
||||
static void use_PSEUDO_MANDATORY_SNI_at_ctx(WOLFSSL_CTX* ctx)
|
||||
{
|
||||
use_SNI_at_ctx(ctx);
|
||||
wolfSSL_CTX_SNI_SetOptions(ctx, WOLFSSL_SNI_HOST_NAME,
|
||||
WOLFSSL_SNI_ANSWER_ON_MISMATCH | WOLFSSL_SNI_ABORT_ON_ABSENCE);
|
||||
}
|
||||
|
||||
static void verify_FATAL_ERROR_on_client(WOLFSSL* ssl)
|
||||
{
|
||||
AssertIntEQ(FATAL_ERROR, wolfSSL_get_error(ssl, 0));
|
||||
}
|
||||
|
||||
static void verify_SNI_abort_on_server(WOLFSSL* ssl)
|
||||
static void verify_UNKNOWN_SNI_on_server(WOLFSSL* ssl)
|
||||
{
|
||||
AssertIntEQ(UNKNOWN_SNI_HOST_NAME_E, wolfSSL_get_error(ssl, 0));
|
||||
}
|
||||
|
||||
static void verify_SNI_ABSENT_on_server(WOLFSSL* ssl)
|
||||
{
|
||||
AssertIntEQ(SNI_ABSENT_ERROR, wolfSSL_get_error(ssl, 0));
|
||||
}
|
||||
|
||||
static void verify_SNI_no_matching(WOLFSSL* ssl)
|
||||
{
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
char* request = (char*) &type; /* to be overwriten */
|
||||
|
||||
AssertIntEQ(WOLFSSL_SNI_NO_MATCH, wolfSSL_SNI_Status(ssl, type));
|
||||
|
||||
AssertNotNull(request);
|
||||
AssertIntEQ(0, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request));
|
||||
AssertNull(request);
|
||||
@@ -815,30 +853,118 @@ static void verify_SNI_no_matching(WOLFSSL* ssl)
|
||||
|
||||
static void verify_SNI_real_matching(WOLFSSL* ssl)
|
||||
{
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
char* request = NULL;
|
||||
char name[] = "www.yassl.com";
|
||||
word16 length = XSTRLEN(name);
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
char* request = NULL;
|
||||
|
||||
AssertIntEQ(WOLFSSL_SNI_REAL_MATCH, wolfSSL_SNI_Status(ssl, type));
|
||||
|
||||
AssertIntEQ(length, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request));
|
||||
AssertIntEQ(15, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request));
|
||||
AssertNotNull(request);
|
||||
AssertStrEQ(name, request);
|
||||
AssertStrEQ("www.wolfssl.com", request);
|
||||
}
|
||||
|
||||
static void verify_SNI_fake_matching(WOLFSSL* ssl)
|
||||
{
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
char* request = NULL;
|
||||
char name[] = "ww2.yassl.com";
|
||||
word16 length = XSTRLEN(name);
|
||||
byte type = WOLFSSL_SNI_HOST_NAME;
|
||||
char* request = NULL;
|
||||
|
||||
AssertIntEQ(WOLFSSL_SNI_FAKE_MATCH, wolfSSL_SNI_Status(ssl, type));
|
||||
|
||||
AssertIntEQ(length, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request));
|
||||
AssertIntEQ(15, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request));
|
||||
AssertNotNull(request);
|
||||
AssertStrEQ(name, request);
|
||||
AssertStrEQ("ww2.wolfssl.com", request);
|
||||
}
|
||||
/* END of connection tests callbacks */
|
||||
|
||||
/* connection test runner */
|
||||
static void test_wolfSSL_client_server(callback_functions* client_callbacks,
|
||||
callback_functions* server_callbacks)
|
||||
{
|
||||
#ifdef HAVE_IO_TESTS_DEPENDENCIES
|
||||
tcp_ready ready;
|
||||
func_args client_args;
|
||||
func_args server_args;
|
||||
THREAD_TYPE serverThread;
|
||||
|
||||
StartTCP();
|
||||
|
||||
client_args.callbacks = client_callbacks;
|
||||
server_args.callbacks = server_callbacks;
|
||||
|
||||
#ifdef WOLFSSL_TIRTOS
|
||||
fdOpenSession(Task_self());
|
||||
#endif
|
||||
|
||||
/* RUN Server side */
|
||||
InitTcpReady(&ready);
|
||||
server_args.signal = &ready;
|
||||
client_args.signal = &ready;
|
||||
start_thread(run_wolfssl_server, &server_args, &serverThread);
|
||||
wait_tcp_ready(&server_args);
|
||||
|
||||
/* RUN Client side */
|
||||
run_wolfssl_client(&client_args);
|
||||
join_thread(serverThread);
|
||||
|
||||
FreeTcpReady(&ready);
|
||||
#ifdef WOLFSSL_TIRTOS
|
||||
fdCloseSession(Task_self());
|
||||
#endif
|
||||
|
||||
#else
|
||||
(void)client_callbacks;
|
||||
(void)server_callbacks;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_wolfSSL_UseSNI_connection(void)
|
||||
{
|
||||
unsigned long i;
|
||||
callback_functions callbacks[] = {
|
||||
/* success case at ctx */
|
||||
{0, use_SNI_at_ctx, 0, 0},
|
||||
{0, use_SNI_at_ctx, 0, verify_SNI_real_matching},
|
||||
|
||||
/* success case at ssl */
|
||||
{0, 0, use_SNI_at_ssl, 0},
|
||||
{0, 0, use_SNI_at_ssl, verify_SNI_real_matching},
|
||||
|
||||
/* default missmatch behavior */
|
||||
{0, 0, different_SNI_at_ssl, verify_FATAL_ERROR_on_client},
|
||||
{0, 0, use_SNI_at_ssl, verify_UNKNOWN_SNI_on_server},
|
||||
|
||||
/* continue on missmatch */
|
||||
{0, 0, different_SNI_at_ssl, 0},
|
||||
{0, 0, use_SNI_WITH_CONTINUE_at_ssl, verify_SNI_no_matching},
|
||||
|
||||
/* fake answer on missmatch */
|
||||
{0, 0, different_SNI_at_ssl, 0},
|
||||
{0, 0, use_SNI_WITH_FAKE_ANSWER_at_ssl, verify_SNI_fake_matching},
|
||||
|
||||
/* sni abort - success */
|
||||
{0, use_SNI_at_ctx, 0, 0},
|
||||
{0, use_MANDATORY_SNI_at_ctx, 0, verify_SNI_real_matching},
|
||||
|
||||
/* sni abort - abort when absent (ctx) */
|
||||
{0, 0, 0, verify_FATAL_ERROR_on_client},
|
||||
{0, use_MANDATORY_SNI_at_ctx, 0, verify_SNI_ABSENT_on_server},
|
||||
|
||||
/* sni abort - abort when absent (ssl) */
|
||||
{0, 0, 0, verify_FATAL_ERROR_on_client},
|
||||
{0, 0, use_MANDATORY_SNI_at_ssl, verify_SNI_ABSENT_on_server},
|
||||
|
||||
/* sni abort - success when overwriten */
|
||||
{0, 0, 0, 0},
|
||||
{0, use_MANDATORY_SNI_at_ctx, use_SNI_at_ssl, verify_SNI_no_matching},
|
||||
|
||||
/* sni abort - success when allowing missmatches */
|
||||
{0, 0, different_SNI_at_ssl, 0},
|
||||
{0, use_PSEUDO_MANDATORY_SNI_at_ctx, 0, verify_SNI_fake_matching},
|
||||
};
|
||||
|
||||
for (i = 0; i < sizeof(callbacks) / sizeof(callback_functions); i += 2) {
|
||||
callbacks[i ].method = wolfSSLv23_client_method;
|
||||
callbacks[i + 1].method = wolfSSLv23_server_method;
|
||||
test_wolfSSL_client_server(&callbacks[i], &callbacks[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_wolfSSL_SNI_GetFromBuffer(void)
|
||||
@@ -904,7 +1030,7 @@ static void test_wolfSSL_SNI_GetFromBuffer(void)
|
||||
0x01, 0x04, 0x03, 0x05, 0x03, 0x02, 0x03, 0x04, 0x02, 0x02, 0x02, 0x00,
|
||||
0x12, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
byte buffer5[] = { /* SSL v2.0 client hello */
|
||||
0x00, 0x2b, 0x01, 0x03, 0x01, 0x00, 0x09, 0x00, 0x00,
|
||||
/* dummy bytes bellow, just to pass size check */
|
||||
@@ -933,7 +1059,7 @@ static void test_wolfSSL_SNI_GetFromBuffer(void)
|
||||
0, result, &length));
|
||||
buffer[1] = 0x03;
|
||||
|
||||
AssertIntEQ(SNI_UNSUPPORTED, wolfSSL_SNI_GetFromBuffer(buffer,
|
||||
AssertIntEQ(SNI_UNSUPPORTED, wolfSSL_SNI_GetFromBuffer(buffer,
|
||||
sizeof(buffer), 0, result, &length));
|
||||
buffer[2] = 0x03;
|
||||
|
||||
@@ -964,121 +1090,19 @@ static void test_wolfSSL_SNI_GetFromBuffer(void)
|
||||
buffer5[2] = 0x01; buffer5[6] = 0x08;
|
||||
AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer5,
|
||||
sizeof(buffer5), 0, result, &length));
|
||||
|
||||
|
||||
buffer5[6] = 0x09; buffer5[8] = 0x01;
|
||||
AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer5,
|
||||
sizeof(buffer5), 0, result, &length));
|
||||
}
|
||||
|
||||
static void test_wolfSSL_client_server(callback_functions* client_callbacks,
|
||||
callback_functions* server_callbacks)
|
||||
{
|
||||
#ifdef HAVE_IO_TESTS_DEPENDENCIES
|
||||
tcp_ready ready;
|
||||
func_args client_args;
|
||||
func_args server_args;
|
||||
THREAD_TYPE serverThread;
|
||||
|
||||
StartTCP();
|
||||
|
||||
client_args.callbacks = client_callbacks;
|
||||
server_args.callbacks = server_callbacks;
|
||||
|
||||
#ifdef WOLFSSL_TIRTOS
|
||||
fdOpenSession(Task_self());
|
||||
#endif
|
||||
|
||||
/* RUN Server side */
|
||||
InitTcpReady(&ready);
|
||||
server_args.signal = &ready;
|
||||
client_args.signal = &ready;
|
||||
start_thread(run_wolfssl_server, &server_args, &serverThread);
|
||||
wait_tcp_ready(&server_args);
|
||||
|
||||
/* RUN Client side */
|
||||
run_wolfssl_client(&client_args);
|
||||
join_thread(serverThread);
|
||||
|
||||
FreeTcpReady(&ready);
|
||||
#ifdef WOLFSSL_TIRTOS
|
||||
fdCloseSession(Task_self());
|
||||
#endif
|
||||
|
||||
#else
|
||||
(void)client_callbacks;
|
||||
(void)server_callbacks;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* HAVE_SNI */
|
||||
|
||||
static void test_wolfSSL_UseSNI(void)
|
||||
{
|
||||
#ifdef HAVE_SNI
|
||||
callback_functions client_callbacks = {wolfSSLv23_client_method, 0, 0, 0};
|
||||
callback_functions server_callbacks = {wolfSSLv23_server_method, 0, 0, 0};
|
||||
|
||||
WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
|
||||
WOLFSSL *ssl = wolfSSL_new(ctx);
|
||||
|
||||
AssertNotNull(ctx);
|
||||
AssertNotNull(ssl);
|
||||
|
||||
/* error cases */
|
||||
AssertIntNE(SSL_SUCCESS,
|
||||
wolfSSL_CTX_UseSNI(NULL, 0, (void *) "ctx", XSTRLEN("ctx")));
|
||||
AssertIntNE(SSL_SUCCESS,
|
||||
wolfSSL_UseSNI( NULL, 0, (void *) "ssl", XSTRLEN("ssl")));
|
||||
AssertIntNE(SSL_SUCCESS,
|
||||
wolfSSL_CTX_UseSNI(ctx, -1, (void *) "ctx", XSTRLEN("ctx")));
|
||||
AssertIntNE(SSL_SUCCESS,
|
||||
wolfSSL_UseSNI( ssl, -1, (void *) "ssl", XSTRLEN("ssl")));
|
||||
AssertIntNE(SSL_SUCCESS,
|
||||
wolfSSL_CTX_UseSNI(ctx, 0, (void *) NULL, XSTRLEN("ctx")));
|
||||
AssertIntNE(SSL_SUCCESS,
|
||||
wolfSSL_UseSNI( ssl, 0, (void *) NULL, XSTRLEN("ssl")));
|
||||
|
||||
/* success case */
|
||||
AssertIntEQ(SSL_SUCCESS,
|
||||
wolfSSL_CTX_UseSNI(ctx, 0, (void *) "ctx", XSTRLEN("ctx")));
|
||||
AssertIntEQ(SSL_SUCCESS,
|
||||
wolfSSL_UseSNI( ssl, 0, (void *) "ssl", XSTRLEN("ssl")));
|
||||
|
||||
wolfSSL_free(ssl);
|
||||
wolfSSL_CTX_free(ctx);
|
||||
|
||||
/* Testing success case at ctx */
|
||||
client_callbacks.ctx_ready = server_callbacks.ctx_ready = use_SNI_at_ctx;
|
||||
server_callbacks.on_result = verify_SNI_real_matching;
|
||||
|
||||
test_wolfSSL_client_server(&client_callbacks, &server_callbacks);
|
||||
|
||||
/* Testing success case at ssl */
|
||||
client_callbacks.ctx_ready = server_callbacks.ctx_ready = NULL;
|
||||
client_callbacks.ssl_ready = server_callbacks.ssl_ready = use_SNI_at_ssl;
|
||||
|
||||
test_wolfSSL_client_server(&client_callbacks, &server_callbacks);
|
||||
|
||||
/* Testing default mismatch behaviour */
|
||||
client_callbacks.ssl_ready = different_SNI_at_ssl;
|
||||
client_callbacks.on_result = verify_SNI_abort_on_client;
|
||||
server_callbacks.on_result = verify_SNI_abort_on_server;
|
||||
|
||||
test_wolfSSL_client_server(&client_callbacks, &server_callbacks);
|
||||
client_callbacks.on_result = NULL;
|
||||
|
||||
/* Testing continue on mismatch */
|
||||
client_callbacks.ssl_ready = different_SNI_at_ssl;
|
||||
server_callbacks.ssl_ready = use_SNI_WITH_CONTINUE_at_ssl;
|
||||
server_callbacks.on_result = verify_SNI_no_matching;
|
||||
|
||||
test_wolfSSL_client_server(&client_callbacks, &server_callbacks);
|
||||
|
||||
/* Testing fake answer on mismatch */
|
||||
server_callbacks.ssl_ready = use_SNI_WITH_FAKE_ANSWER_at_ssl;
|
||||
server_callbacks.on_result = verify_SNI_fake_matching;
|
||||
|
||||
test_wolfSSL_client_server(&client_callbacks, &server_callbacks);
|
||||
test_wolfSSL_UseSNI_params();
|
||||
test_wolfSSL_UseSNI_connection();
|
||||
|
||||
test_wolfSSL_SNI_GetFromBuffer();
|
||||
#endif
|
||||
|
@@ -134,6 +134,7 @@ enum wolfSSL_ErrorCodes {
|
||||
BAD_TICKET_ENCRYPT = -400, /* Bad user ticket encrypt */
|
||||
|
||||
DH_KEY_SIZE_E = -401, /* DH Key too small */
|
||||
SNI_ABSENT_ERROR = -402, /* No SNI request. */
|
||||
|
||||
/* add strings to SetErrorString !!!!! */
|
||||
|
||||
@@ -165,5 +166,3 @@ void SetErrorString(int err, char* buff);
|
||||
|
||||
|
||||
#endif /* wolfSSL_ERROR_H */
|
||||
|
||||
|
||||
|
@@ -1273,8 +1273,8 @@ enum {
|
||||
WOLFSSL_SNI_HOST_NAME = 0
|
||||
};
|
||||
|
||||
WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type, const void* data,
|
||||
unsigned short size);
|
||||
WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type,
|
||||
const void* data, unsigned short size);
|
||||
WOLFSSL_API int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, unsigned char type,
|
||||
const void* data, unsigned short size);
|
||||
|
||||
@@ -1282,26 +1282,33 @@ WOLFSSL_API int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, unsigned char type,
|
||||
|
||||
/* SNI options */
|
||||
enum {
|
||||
WOLFSSL_SNI_CONTINUE_ON_MISMATCH = 0x01, /* do not abort on mismatch flag */
|
||||
WOLFSSL_SNI_ANSWER_ON_MISMATCH = 0x02 /* fake match on mismatch flag */
|
||||
/* Do not abort the handshake if the requested SNI didn't match. */
|
||||
WOLFSSL_SNI_CONTINUE_ON_MISMATCH = 0x01,
|
||||
|
||||
/* Behave as if the requested SNI matched in a case of missmatch. */
|
||||
/* In this case, the status will be set to WOLFSSL_SNI_FAKE_MATCH. */
|
||||
WOLFSSL_SNI_ANSWER_ON_MISMATCH = 0x02,
|
||||
|
||||
/* Abort the handshake if the client didn't send a SNI request. */
|
||||
WOLFSSL_SNI_ABORT_ON_ABSENCE = 0x04,
|
||||
};
|
||||
|
||||
WOLFSSL_API void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, unsigned char type,
|
||||
unsigned char options);
|
||||
WOLFSSL_API void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, unsigned char type,
|
||||
unsigned char options);
|
||||
WOLFSSL_API void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx,
|
||||
unsigned char type, unsigned char options);
|
||||
|
||||
/* SNI status */
|
||||
enum {
|
||||
WOLFSSL_SNI_NO_MATCH = 0,
|
||||
WOLFSSL_SNI_FAKE_MATCH = 1, /* if WOLFSSL_SNI_ANSWER_ON_MISMATCH is enabled */
|
||||
WOLFSSL_SNI_FAKE_MATCH = 1, /**< @see WOLFSSL_SNI_ANSWER_ON_MISMATCH */
|
||||
WOLFSSL_SNI_REAL_MATCH = 2
|
||||
};
|
||||
|
||||
WOLFSSL_API unsigned char wolfSSL_SNI_Status(WOLFSSL* ssl, unsigned char type);
|
||||
|
||||
WOLFSSL_API unsigned short wolfSSL_SNI_GetRequest(WOLFSSL *ssl, unsigned char type,
|
||||
void** data);
|
||||
WOLFSSL_API unsigned short wolfSSL_SNI_GetRequest(WOLFSSL *ssl,
|
||||
unsigned char type, void** data);
|
||||
WOLFSSL_API int wolfSSL_SNI_GetFromBuffer(
|
||||
const unsigned char* clientHello, unsigned int helloSz,
|
||||
unsigned char type, unsigned char* sni, unsigned int* inOutSz);
|
||||
@@ -1467,4 +1474,3 @@ WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack,
|
||||
|
||||
|
||||
#endif /* WOLFSSL_SSL_H */
|
||||
|
||||
|
Reference in New Issue
Block a user