#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <AssertMacros.h>
#include "secCrypto.h"
#include <tls_ciphersuites.h>
#include <Security/SecCertificate.h>
#include <Security/SecKeyPriv.h>
#include <Security/SecIdentity.h>
#include <Security/oidsalg.h>
#include "tls_regressions.h"
#include <tls_handshake.h>
#include <tls_cache.h>
#include <tls_helpers.h>
#include "sslMemory.h"
#define DEBUG_ONLY __attribute__((unused))
struct _myFilterCtx;
typedef struct {
bool dtls;
int client_protocol_min; int client_protocol_max; int server_protocol_min; int server_protocol_max; const uint16_t *ciphersuites;
int num_ciphersuites;
const uint16_t *client_ciphersuites;
int num_client_ciphersuites;
const uint16_t *server_ciphersuites;
int num_server_ciphersuites;
bool allow_resumption;
uintptr_t session_id;
bool client_trigger_renegotiation;
bool server_trigger_renegotiation;
bool server_allow_renegotiation;
bool request_client_auth;
bool server_rsa_key_exchange;
bool fallback;
tls_buffer *dh_parameters;
unsigned min_dh_size;
SSLCertificate *server_certs;
tls_private_key_t server_key;
SSLCertificate *client_certs;
tls_private_key_t client_key;
tls_buffer *peer_hostname;
tls_buffer *ocsp_response;
tls_buffer_list_t *ocsp_responder_id_list;
tls_buffer *ocsp_request_extensions;
bool client_ocsp_enable;
bool server_ocsp_enable;
bool sct_enable;
tls_buffer_list_t *sct_list;
bool client_extMS_enable;
bool server_extMS_enable;
int (*fuzzer)(struct _myFilterCtx *myCtx, const tls_buffer in, uint8_t content_type);
intptr_t fuzz_ctx;
tls_handshake_trust_t (*server_trust)(intptr_t trust_ctx);
intptr_t server_trust_ctx;
tls_handshake_trust_t (*client_trust)(intptr_t trust_ctx);
intptr_t client_trust_ctx;
bool forget_to_set_pubkey;
tls_handshake_config_t client_config;
tls_handshake_config_t server_config;
const uint16_t *server_ec_curves;
int num_server_ec_curves;
const uint16_t *client_ec_curves;
int num_client_ec_curves;
const tls_signature_and_hash_algorithm *server_sigalgs;
int num_server_sigalgs;
const tls_signature_and_hash_algorithm *client_sigalgs;
int num_client_sigalgs;
bool handshake_ok;
int client_err;
int server_err;
bool is_session_resumed;
bool is_session_resumption_proposed;
int certificate_requested;
uint16_t negotiated_ciphersuite;
tls_protocol_version negotiated_version;
uint16_t negotiated_ec_curve;
bool received_cert;
} tls_test_case;
typedef struct _myFilterCtx {
tls_test_case *test;
bool server;
tls_handshake_t filter;
tls_cache_t cache;
dispatch_group_t group;
dispatch_queue_t queue;
dispatch_source_t timer;
struct _myFilterCtx *peer;
int epoch;
int peer_epoch;
int n; int read_ready;
int write_ready;
bool peer_ocsp_enabled;
bool bad_client_hello_size; tls_buffer session_data; int err;
} myFilterCtx_t;
static const char *side(myFilterCtx_t *myCtx)
{
return myCtx->server?"server":"client";
}
static int send_to_peer(myFilterCtx_t *myCtx, const tls_buffer data, uint8_t content_type)
{
myFilterCtx_t *peerCtx = myCtx->peer;
int record_epoch = myCtx->epoch;
if(peerCtx==NULL) {
test_printf("%s: [%s] peer has been disconnected\n", __FUNCTION__, side(myCtx));
return -1; }
if((content_type==tls_record_type_Handshake) &&
(data.data[0]==tls_handshake_message_client_hello) &&
(data.length>=256) && (data.length<512))
{
myCtx->bad_client_hello_size = true;
}
if(peerCtx->queue) {
tls_buffer localData;
localData.data=malloc(data.length);
localData.length=data.length;
memcpy(localData.data, data.data, data.length);
dispatch_group_async(peerCtx->group, peerCtx->queue, ^{
if(peerCtx->err) {
test_printf("%s: [%s] receiving message after errors, ignoring\n", __FUNCTION__, side(peerCtx));
} else if(record_epoch!=peerCtx->peer_epoch) {
test_printf("%s: [%s] wrong epoch: %d expected :%d, do not process\n", __FUNCTION__, side(peerCtx), record_epoch, peerCtx->peer_epoch);
} else {
int err;
test_printf("%s: [%s] Processing (len=%zd, type=%d, p=%p, data[0]=%d)\n", __FUNCTION__,
side(peerCtx), localData.length, content_type, localData.data, localData.data[0]);
err = tls_handshake_process(peerCtx->filter, localData, content_type);
test_printf("%s: [%s] Done Processing (len=%zd, type=%d, p=%p, data[0]=%d) -- err=%d\n", __FUNCTION__,
side(peerCtx), localData.length, content_type, localData.data, localData.data[0], err);
if(err && err!=-9849) {
test_printf("Error %d while processing data in %s, closing.\n", err, side(peerCtx));
myCtx->peer=NULL;
peerCtx->err = err;
}
}
free(localData.data);
});
return 0;
} else {
fprintf(stderr, "Peer ctx queue (%s) is NULL, returning error.\n", side(peerCtx));
return -2;
}
}
static int tls_handshake_write_callback(tls_handshake_ctx_t ctx, const tls_buffer data, uint8_t content_type)
{
myFilterCtx_t *myCtx = (myFilterCtx_t *)ctx;
myCtx->n++;
test_printf("%s: [%s] (epoch=%d, len=%zd, type=%d, p=%p, data[0]=%d)\n", __FUNCTION__, side(myCtx), myCtx->epoch, data.length, content_type, data.data, data.data[0]);
if(myCtx->test->fuzzer) {
return myCtx->test->fuzzer(myCtx, data, content_type);
} else {
return send_to_peer(myCtx, data, content_type);
}
}
static int
tls_handshake_message_callback(tls_handshake_ctx_t ctx, tls_handshake_message_t event)
{
myFilterCtx_t *myCtx = (myFilterCtx_t *)ctx;
int err = 0;
tls_handshake_trust_t trust;
test_printf("%s: [%s] event = %d\n", __FUNCTION__, side(myCtx), event);
switch(event) {
case tls_handshake_message_client_hello_request:
break;
case tls_handshake_message_client_hello:
case tls_handshake_message_server_hello:
myCtx->peer_ocsp_enabled=tls_handshake_get_peer_ocsp_enabled(myCtx->filter);
break;
case tls_handshake_message_certificate_request:
require_noerr((err=tls_handshake_set_client_auth_type(myCtx->filter, tls_client_auth_type_RSASign)), errOut);
require_noerr((err=tls_handshake_set_identity(myCtx->filter, myCtx->test->client_certs, myCtx->test->client_key)), errOut);
break;
case tls_handshake_message_certificate:
if(!myCtx->test->forget_to_set_pubkey) {
require_noerr((err = tls_helper_set_peer_pubkey(myCtx->filter)), errOut);
}
break;
case tls_handshake_message_server_hello_done:
if(myCtx->test->server_trust) {
trust = myCtx->test->server_trust(myCtx->test->server_trust_ctx);
} else {
trust = tls_handshake_trust_ok;
}
require_noerr((err = tls_handshake_set_peer_trust(myCtx->filter, trust)), errOut);
break;
case tls_handshake_message_finished:
if(myCtx->server) {
if(myCtx->test->client_trust) {
trust = myCtx->test->client_trust(myCtx->test->client_trust_ctx);
} else {
trust = tls_handshake_trust_ok;
}
require_noerr((err = tls_handshake_set_peer_trust(myCtx->filter, trust)), errOut);
}
default:
test_printf("%s: [%s] Not handling this event: %d\n", __FUNCTION__, side(myCtx), event);
break;
}
errOut:
return err;
}
static void
tls_handshake_ready_callback(tls_handshake_ctx_t ctx, bool write, bool ready)
{
myFilterCtx_t *myCtx = (myFilterCtx_t *)ctx;
test_printf("%s: [%s] %s, ready=%s\n", __FUNCTION__, side(myCtx), write?"write":"read", ready?"true":"false");
if(ready) {
if(write) {
myCtx->write_ready++;
} else {
myCtx->read_ready++;
}
if(myCtx->write_ready == myCtx->read_ready) {
test_printf("%s: [%s] handshake %d all done\n", __FUNCTION__, side(myCtx), myCtx->read_ready);
if(myCtx->write_ready==1) {
if(myCtx->server && myCtx->test->server_trigger_renegotiation) {
test_printf("%s: [%s] first handshake %d all done, request renegotiation\n", __FUNCTION__, side(myCtx), myCtx->read_ready);
dispatch_group_async(myCtx->group, myCtx->queue, ^{
tls_handshake_request_renegotiation(myCtx->filter);
});
}
if(!myCtx->server && myCtx->test->client_trigger_renegotiation) {
test_printf("%s: [%s] first handshake %d all done, starting renegotiation\n", __FUNCTION__, side(myCtx), myCtx->read_ready);
dispatch_group_async(myCtx->group, myCtx->queue, ^{
tls_handshake_negotiate(myCtx->filter, NULL);
});
}
}
}
}
}
#warning There is probably a race condition here.
static int
tls_handshake_set_retransmit_timer_callback(tls_handshake_ctx_t ctx, int attempt)
{
myFilterCtx_t *myCtx = (myFilterCtx_t *)ctx;
test_printf("%s: [%s] set_retransmit_time attempt=%d\n", __FUNCTION__, side(myCtx), attempt);
if(attempt==0) {
if(myCtx->timer) {
test_printf("%s: [%s] cancelling timer [%p]\n", __FUNCTION__, side(myCtx), myCtx->timer);
dispatch_source_cancel(myCtx->timer);
dispatch_release(myCtx->timer);
myCtx->timer=NULL;
}
} else {
assert(myCtx->timer==NULL);
require((myCtx->timer=dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
0, 0, myCtx->queue)), fail);
test_printf("%s: [%s] Created timer [%p] attempt %d\n", __FUNCTION__, side(myCtx), myCtx->timer, attempt);
dispatch_source_set_event_handler(myCtx->timer, ^{
test_printf("%s: [%s], timer [%p] fired attempt %d\n", __FUNCTION__, side(myCtx), myCtx->timer, attempt);
dispatch_source_cancel(myCtx->timer);
dispatch_release(myCtx->timer);
myCtx->timer=NULL;
tls_handshake_retransmit_timer_expired(myCtx->filter);
});
dispatch_source_set_timer(myCtx->timer, dispatch_time(DISPATCH_TIME_NOW, attempt*NSEC_PER_SEC), DISPATCH_TIME_FOREVER, NSEC_PER_SEC);
dispatch_resume(myCtx->timer);
}
return 0;
fail:
return errSecAllocate;
}
static
int mySSLRecordInitPendingCiphersFunc(tls_handshake_ctx_t ref,
uint16_t selectedCipher,
bool server,
tls_buffer key)
{
myFilterCtx_t *myCtx = (myFilterCtx_t *)ref;
test_printf("%s: [%s], cipher=%04x, server=%d\n", __FUNCTION__, side(myCtx), selectedCipher, server);
return 0;
}
static
int mySSLRecordAdvanceWriteCipherFunc(tls_handshake_ctx_t ref)
{
myFilterCtx_t *myCtx = (myFilterCtx_t *)ref;
test_printf("%s: [%s]\n", __FUNCTION__, side(myCtx));
myCtx->epoch++;
return 0;
}
static
int mySSLRecordRollbackWriteCipherFunc(tls_handshake_ctx_t ref)
{
myFilterCtx_t *myCtx = (myFilterCtx_t *)ref;
test_printf("%s: [%s]\n", __FUNCTION__, side(myCtx));
myCtx->epoch--;
return 0;
}
static
int mySSLRecordAdvanceReadCipherFunc(tls_handshake_ctx_t ref)
{
myFilterCtx_t *myCtx = (myFilterCtx_t *)ref;
test_printf("%s: [%s]\n", __FUNCTION__, side(myCtx));
myCtx->peer_epoch++;
return 0;
}
static
int mySSLRecordSetProtocolVersionFunc(tls_handshake_ctx_t ref,
tls_protocol_version protocolVersion)
{
myFilterCtx_t *myCtx = (myFilterCtx_t *)ref;
test_printf("%s: [%s] pv=%04x\n", __FUNCTION__, side(myCtx), protocolVersion);
return 0;
}
static int
tls_handshake_save_session_data_callback(tls_handshake_ctx_t ctx, tls_buffer sessionKey, tls_buffer sessionData)
{
myFilterCtx_t DEBUG_ONLY *myCtx = (myFilterCtx_t *)ctx;
test_printf("%s:[%s]\n", __FUNCTION__, side(myCtx));
test_printf("%s:[%s] key=[%p,%zd] data=[%p,%zd]\n",__FUNCTION__, side(myCtx), sessionKey.data, sessionKey.length, sessionData.data, sessionData.length);
return tls_cache_save_session_data(myCtx->cache, &sessionKey, &sessionData, 0);
}
static int
tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx, tls_buffer sessionKey, tls_buffer *sessionData)
{
myFilterCtx_t DEBUG_ONLY *myCtx = (myFilterCtx_t *)ctx;
test_printf("%s:[%s]\n", __FUNCTION__, side(myCtx));
int err = tls_cache_load_session_data(myCtx->cache, &sessionKey, sessionData);
test_printf("%s:[%s] key=[%p,%zd] data=[%p,%zd], err=%d\n", __FUNCTION__, side(myCtx), sessionKey.data, sessionKey.length, sessionData->data, sessionData->length, err);
SSLFreeBuffer(&myCtx->session_data);
myCtx->session_data = *sessionData;
return err;
}
static int
tls_handshake_delete_session_data_callback(tls_handshake_ctx_t ctx, tls_buffer sessionKey)
{
myFilterCtx_t DEBUG_ONLY *myCtx = (myFilterCtx_t *)ctx;
test_printf("%s:[%s]\n", __FUNCTION__, side(myCtx));
return tls_cache_delete_session_data(myCtx->cache, &sessionKey);
}
static int
tls_handshake_delete_all_sessions_callback(tls_handshake_ctx_t ctx)
{
myFilterCtx_t DEBUG_ONLY *myCtx = (myFilterCtx_t *)ctx;
test_printf("%s:[%s]\n", __FUNCTION__, side(myCtx));
return -1;
}
static
tls_handshake_callbacks_t tls_handshake_callbacks = {
.write = tls_handshake_write_callback,
.message = tls_handshake_message_callback,
.ready = tls_handshake_ready_callback,
.set_retransmit_timer = tls_handshake_set_retransmit_timer_callback,
.init_pending_cipher = mySSLRecordInitPendingCiphersFunc,
.advance_write_cipher = mySSLRecordAdvanceWriteCipherFunc,
.rollback_write_cipher = mySSLRecordRollbackWriteCipherFunc,
.advance_read_cipher = mySSLRecordAdvanceReadCipherFunc,
.set_protocol_version = mySSLRecordSetProtocolVersionFunc,
.load_session_data = tls_handshake_load_session_data_callback,
.save_session_data = tls_handshake_save_session_data_callback,
.delete_session_data = tls_handshake_delete_session_data_callback,
.delete_all_sessions = tls_handshake_delete_all_sessions_callback,
};
typedef struct _CipherSuiteName {
uint16_t cipher;
const char *name;
} CipherSuiteName;
#define CIPHER(cipher) { cipher, #cipher},
static const CipherSuiteName ssl_ciphers[] = {
CIPHER(SSL_RSA_WITH_NULL_SHA)
CIPHER(SSL_RSA_WITH_NULL_MD5)
CIPHER(TLS_RSA_WITH_NULL_SHA256)
CIPHER(SSL_RSA_WITH_RC4_128_MD5)
CIPHER(SSL_RSA_WITH_RC4_128_SHA)
CIPHER(SSL_RSA_WITH_3DES_EDE_CBC_SHA)
CIPHER(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
CIPHER(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
CIPHER(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
CIPHER(TLS_RSA_WITH_AES_128_CBC_SHA)
CIPHER(TLS_RSA_WITH_AES_256_CBC_SHA)
};
static int n_ssl_ciphers = sizeof(ssl_ciphers)/sizeof(ssl_ciphers[0]);
static const CipherSuiteName anon_ciphers[] = {
CIPHER(SSL_DH_anon_WITH_RC4_128_MD5)
CIPHER(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA)
CIPHER(TLS_DH_anon_WITH_AES_128_CBC_SHA)
CIPHER(TLS_DH_anon_WITH_AES_256_CBC_SHA)
};
static int n_anon_ciphers = sizeof(anon_ciphers)/sizeof(anon_ciphers[0]);
static const CipherSuiteName psk_ciphers[] = {
CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA384)
CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA256)
CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA)
CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA)
CIPHER(TLS_PSK_WITH_RC4_128_SHA)
CIPHER(TLS_PSK_WITH_3DES_EDE_CBC_SHA)
CIPHER(TLS_PSK_WITH_NULL_SHA384)
CIPHER(TLS_PSK_WITH_NULL_SHA256)
CIPHER(TLS_PSK_WITH_NULL_SHA)
};
static int n_psk_ciphers = sizeof(psk_ciphers)/sizeof(psk_ciphers[0]);
static const CipherSuiteName gcm_ciphers[] = {
CIPHER(TLS_RSA_WITH_AES_256_GCM_SHA384)
CIPHER(TLS_RSA_WITH_AES_128_GCM_SHA256)
CIPHER(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384)
CIPHER(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
CIPHER(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
CIPHER(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
CIPHER(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
CIPHER(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
};
static int n_gcm_ciphers = sizeof(gcm_ciphers)/sizeof(gcm_ciphers[0]);
static const CipherSuiteName ecdhe_ciphers[] = {
CIPHER(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384)
CIPHER(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
CIPHER(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
CIPHER(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
CIPHER(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA)
CIPHER(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
};
static int n_ecdhe_ciphers = sizeof(ecdhe_ciphers)/sizeof(ecdhe_ciphers[0]);
static const CipherSuiteName ecanon_ciphers[] = {
CIPHER(TLS_ECDH_anon_WITH_NULL_SHA)
CIPHER(TLS_ECDH_anon_WITH_RC4_128_SHA)
CIPHER(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA)
CIPHER(TLS_ECDH_anon_WITH_AES_128_CBC_SHA)
CIPHER(TLS_ECDH_anon_WITH_AES_256_CBC_SHA)
};
static int n_ecanon_ciphers = sizeof(ecanon_ciphers)/sizeof(ecanon_ciphers[0]);
static int protos[]={
tls_protocol_version_SSL_3,
tls_protocol_version_TLS_1_0,
tls_protocol_version_TLS_1_1,
tls_protocol_version_TLS_1_2,
0, };
static int nprotos = sizeof(protos)/sizeof(protos[0]);
static uint8_t shared_secret[] = "secret";
static tls_cache_t g_cache;
static
int init_context(myFilterCtx_t *c, bool server, const char *name, tls_test_case *test, dispatch_group_t group)
{
c->test=test;
c->server=server;
c->n=0;
c->epoch=0;
c->peer_epoch=0;
c->group=group;
c->timer=NULL;
require((c->queue=dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL)), fail);
require((c->filter=tls_handshake_create(false, server)), fail);
require((c->cache=g_cache), fail);
require_noerr(tls_handshake_set_user_agent(c->filter, "tls_test"), fail);
if(server) {
if(test->server_config)
require_noerr(tls_handshake_set_config(c->filter, test->server_config), fail);
require_noerr(tls_handshake_set_client_auth(c->filter, test->request_client_auth), fail);
require_noerr(tls_handshake_set_identity(c->filter, test->server_certs, test->server_key), fail);
require_noerr(tls_handshake_set_renegotiation(c->filter, test->server_allow_renegotiation), fail);
require_noerr(tls_handshake_set_ocsp_enable(c->filter, test->server_ocsp_enable), fail);
if(test->ocsp_response)
require_noerr(tls_handshake_set_ocsp_response(c->filter, test->ocsp_response), fail);
require_noerr(tls_handshake_set_sct_list(c->filter, test->sct_list), fail);
if(test->server_rsa_key_exchange)
require_noerr(tls_set_encrypt_pubkey(c->filter, test->server_certs), fail);
if(test->dh_parameters)
require_noerr(tls_handshake_set_dh_parameters(c->filter, test->dh_parameters), fail);
require_noerr(tls_handshake_set_ems_enable(c->filter, test->server_extMS_enable), fail);
} else {
if(test->client_config)
require_noerr(tls_handshake_set_config(c->filter, test->client_config), fail);
require_noerr(tls_handshake_set_ocsp_enable(c->filter, test->client_ocsp_enable), fail);
if(test->ocsp_request_extensions)
require_noerr(tls_handshake_set_ocsp_request_extensions(c->filter, *test->ocsp_request_extensions), fail);
if(test->ocsp_responder_id_list)
require_noerr(tls_handshake_set_ocsp_responder_id_list(c->filter, test->ocsp_responder_id_list), fail);
if(test->peer_hostname) {
require_noerr(tls_handshake_set_peer_hostname(c->filter, (char *)test->peer_hostname->data, test->peer_hostname->length), fail);
} else {
require_noerr(tls_handshake_set_peer_hostname(c->filter, "localhost", strlen("localhost")), fail);
}
require_noerr(tls_handshake_set_sct_enable(c->filter, test->sct_enable), fail);
require_noerr(tls_handshake_set_fallback(c->filter, test->fallback), fail);
if(test->min_dh_size)
require_noerr(tls_handshake_set_min_dh_group_size(c->filter, test->min_dh_size), fail);
require_noerr(tls_handshake_set_ems_enable(c->filter, test->client_extMS_enable), fail);
}
require_noerr(tls_handshake_set_callbacks(c->filter,
&tls_handshake_callbacks,
c), fail);
if(test->ciphersuites) {
require_noerr(tls_handshake_set_ciphersuites(c->filter, test->ciphersuites, test->num_ciphersuites), fail);
} else {
if(server && test->server_ciphersuites) {
require_noerr(tls_handshake_set_ciphersuites(c->filter, test->server_ciphersuites, test->num_server_ciphersuites), fail);
}
if(!server && test->client_ciphersuites) {
require_noerr(tls_handshake_set_ciphersuites(c->filter, test->client_ciphersuites, test->num_client_ciphersuites), fail);
}
}
tls_buffer psk_secret = {
.data = shared_secret,
.length = sizeof(shared_secret),
};
require_noerr(tls_handshake_set_psk_secret(c->filter, &psk_secret), fail);
if(server) {
if(test->server_protocol_min)
require_noerr(tls_handshake_set_min_protocol_version(c->filter, test->server_protocol_min), fail);
if(test->server_protocol_max)
require_noerr(tls_handshake_set_max_protocol_version(c->filter, test->server_protocol_max), fail);
} else {
if(test->client_protocol_min)
require_noerr(tls_handshake_set_min_protocol_version(c->filter, test->client_protocol_min), fail);
if(test->client_protocol_max)
require_noerr(tls_handshake_set_max_protocol_version(c->filter, test->client_protocol_max), fail);
}
require_noerr(tls_handshake_set_resumption(c->filter, test->allow_resumption), fail);
if (server && test->num_server_ec_curves) {
require_noerr(tls_handshake_set_curves(c->filter, test->server_ec_curves, test->num_server_ec_curves), fail);
}
if (!server && test->num_client_ec_curves) {
require_noerr(tls_handshake_set_curves(c->filter, test->client_ec_curves, test->num_client_ec_curves), fail);
}
if (server && test->num_server_sigalgs) {
require_noerr(tls_handshake_set_sigalgs(c->filter, test->server_sigalgs, test->num_server_sigalgs), fail);
}
if (!server && test->num_client_sigalgs) {
require_noerr(tls_handshake_set_sigalgs(c->filter, test->client_sigalgs, test->num_client_sigalgs), fail);
}
return 0;
fail:
return -1;
}
static
void clean_context(myFilterCtx_t *c)
{
test_printf("%s: [%s] timer [%p]\n", __FUNCTION__, side(c), c->timer);
if(c->queue) {
dispatch_sync(c->queue, ^{
test_printf("%s: [%s] releasing timer [%p]\n", __FUNCTION__, side(c), c->timer);
if(c->filter) tls_handshake_destroy(c->filter); c->filter = NULL;
if(c->timer) dispatch_release(c->timer); c->timer = NULL;
SSLFreeBuffer(&c->session_data);
});
if(c->queue) dispatch_release(c->queue); c->queue = NULL;
}
}
static bool tls_buffer_equal(const tls_buffer *a, const tls_buffer *b)
{
if(a->length!=b->length) return false;
if(memcmp(a->data, b->data, a->length)) return false;
return true;
}
static bool tls_buffer_list_equal(const tls_buffer_list_t *a, const tls_buffer_list_t *b)
{
while(a && b) {
if(!tls_buffer_equal(&a->buffer, &b->buffer)) return false;
a=a->next;
b=b->next;
}
if(a || b) return false;
return true;
}
const uint16_t anon_ciphersuites[] = {
TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
TLS_DH_anon_WITH_AES_256_CBC_SHA256,
TLS_DH_anon_WITH_AES_256_CBC_SHA,
TLS_DH_anon_WITH_AES_128_CBC_SHA256,
TLS_DH_anon_WITH_AES_128_CBC_SHA,
};
const uint16_t legacy_ciphersuites[] = {
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_RSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA256,
TLS_RSA_WITH_AES_128_CBC_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
SSL_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
SSL_RSA_WITH_RC4_128_SHA,
SSL_RSA_WITH_RC4_128_MD5,
};
const uint16_t DHE_ciphersuites[] = {
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_RSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA256,
TLS_RSA_WITH_AES_128_CBC_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
SSL_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
SSL_RSA_WITH_RC4_128_SHA,
SSL_RSA_WITH_RC4_128_MD5,
};
const uint16_t standard_ciphersuites[] = {
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_RSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA256,
TLS_RSA_WITH_AES_128_CBC_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
};
const uint16_t default_ciphersuites[] = {
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_RSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA256,
TLS_RSA_WITH_AES_128_CBC_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
SSL_RSA_WITH_3DES_EDE_CBC_SHA,
};
const uint16_t ATSv1_ciphersuites[] = {
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
};
const uint16_t ATSv1_noPFS_ciphersuites[] = {
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_RSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA256,
TLS_RSA_WITH_AES_128_CBC_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
};
static bool test_ciphersuites(tls_test_case *test, bool server, const uint16_t *ciphersuites, unsigned int n)
{
unsigned expected_n = 0;
const uint16_t *expected_ciphersuites = NULL;
if(test->ciphersuites) {
expected_n = test->num_ciphersuites;
expected_ciphersuites = test->ciphersuites;
} else if(!server && test->client_ciphersuites) {
expected_n = test->num_client_ciphersuites;
expected_ciphersuites = test->client_ciphersuites;
} else if(server && test->server_ciphersuites) {
expected_n = test->num_server_ciphersuites;
expected_ciphersuites = test->server_ciphersuites;
} else {
switch(server?test->server_config:test->client_config) {
case tls_handshake_config_ATSv1:
expected_n = sizeof(ATSv1_ciphersuites)/sizeof(uint16_t);
expected_ciphersuites = ATSv1_ciphersuites;
break;
case tls_handshake_config_ATSv1_noPFS:
expected_n = sizeof(ATSv1_noPFS_ciphersuites)/sizeof(uint16_t);
expected_ciphersuites = ATSv1_noPFS_ciphersuites;
break;
case tls_handshake_config_standard:
expected_n = sizeof(standard_ciphersuites)/sizeof(uint16_t);
expected_ciphersuites = standard_ciphersuites;
break;
case tls_handshake_config_legacy_DHE:
expected_n = sizeof(DHE_ciphersuites)/sizeof(uint16_t);
expected_ciphersuites = DHE_ciphersuites;
break;
case tls_handshake_config_RC4_fallback:
case tls_handshake_config_TLSv1_RC4_fallback:
case tls_handshake_config_legacy:
expected_n = sizeof(legacy_ciphersuites)/sizeof(uint16_t);
expected_ciphersuites = legacy_ciphersuites;
break;
case tls_handshake_config_3DES_fallback:
case tls_handshake_config_TLSv1_3DES_fallback:
case tls_handshake_config_TLSv1_fallback:
case tls_handshake_config_default:
expected_n = sizeof(default_ciphersuites)/sizeof(uint16_t);
expected_ciphersuites = default_ciphersuites;
break;
case tls_handshake_config_anonymous:
expected_n = sizeof(anon_ciphersuites)/sizeof(uint16_t);
expected_ciphersuites = anon_ciphersuites;
break;
case tls_handshake_config_none:
expected_n = n;
expected_ciphersuites = ciphersuites;
break;
}
}
return (n==expected_n) && (memcmp(ciphersuites, expected_ciphersuites, expected_n*sizeof(uint16_t))==0);
}
static int test_result(myFilterCtx_t *client, myFilterCtx_t *server)
{
int err = 0;
tls_test_case *test;
assert(server->test==client->test);
test = client->test;
{
tls_protocol_version pv_min, pv_max;
tls_handshake_get_max_protocol_version(client->filter, &pv_max);
tls_handshake_get_min_protocol_version(client->filter, &pv_min);
if(pv_min>pv_max) {
fprintf(stderr,"client has inconsistent protocol version (%04x>%04x)\n",pv_min, pv_max);
err = -1;
}
tls_handshake_get_max_protocol_version(server->filter, &pv_max);
tls_handshake_get_min_protocol_version(server->filter, &pv_min);
if(pv_min>pv_max) {
fprintf(stderr,"server has inconsistent protocol version (%04x>%04x)\n",pv_min, pv_max);
err = -1;
}
const uint16_t *ciphersuites;
unsigned int n;
tls_handshake_get_ciphersuites(client->filter, &ciphersuites, &n);
if(!test_ciphersuites(test, false, ciphersuites, n)) {
fprintf(stderr,"client has unexpected ciphersuites\n");
err = -1;
}
tls_handshake_get_ciphersuites(server->filter, &ciphersuites, &n);
if(!test_ciphersuites(test, true, ciphersuites, n)) {
fprintf(stderr,"server has unexpected ciphersuites\n");
err = -1;
}
if(client->bad_client_hello_size) {
fprintf(stderr,"client hello size was bad\n");
err = -1;
}
}
if(test->handshake_ok) {
int expected_handshake_count;
if((test->client_trigger_renegotiation || test->server_trigger_renegotiation) && test->server_allow_renegotiation) {
expected_handshake_count = 2;
} else {
expected_handshake_count = 1;
}
if(client->read_ready!=expected_handshake_count) {
fprintf(stderr,"client read_ready received: %d, expected %d\n",client->read_ready, expected_handshake_count);
err = -1;
}
if(client->write_ready!=expected_handshake_count) {
fprintf(stderr,"client write_ready received: %d, expected %d\n",client->write_ready, expected_handshake_count);
err = -1;
}
if(server->read_ready!=expected_handshake_count) {
fprintf(stderr,"server read_ready received: %d, expected %d\n",server->read_ready, expected_handshake_count);
err = -1;
}
if(server->write_ready!=expected_handshake_count) {
fprintf(stderr,"server write_ready received: %d, expected %d\n",server->write_ready, expected_handshake_count);
err = -1;
}
uint16_t client_negotiated_ciphersuite = tls_handshake_get_negotiated_cipherspec(client->filter);
test_printf("client negotiated ciphersuite: %04x\n", client_negotiated_ciphersuite);
uint16_t server_negotiated_ciphersuite = tls_handshake_get_negotiated_cipherspec(server->filter);
test_printf("server negotiated ciphersuite: %04x\n", server_negotiated_ciphersuite);
if(client_negotiated_ciphersuite!=server_negotiated_ciphersuite) {
fprintf(stderr, "client and server ciphersuites do not match. client=%04x, server=%04x\n", client_negotiated_ciphersuite, server_negotiated_ciphersuite);
err = -1;
} else if(test->negotiated_ciphersuite && (client_negotiated_ciphersuite!=test->negotiated_ciphersuite)) {
fprintf(stderr, "ciphersuite negotiated: %04x, expected %04x\n",client_negotiated_ciphersuite,client->test->negotiated_ciphersuite);
err = -1;
}
bool client_session_match, server_session_match;
bool client_session_proposed, server_session_proposed;
tls_buffer client_sessionID, server_sessionID;
tls_buffer client_proposed_sessionID, server_proposed_sessionID;
client_session_match = tls_handshake_get_session_match(client->filter, &client_sessionID);
server_session_match = tls_handshake_get_session_match(server->filter, &server_sessionID);
client_session_proposed = tls_handshake_get_session_proposed(client->filter, &client_proposed_sessionID);
server_session_proposed = tls_handshake_get_session_proposed(server->filter, &server_proposed_sessionID);
if(client_session_proposed!=server_session_proposed) {
fprintf(stderr, "client and server session proposed resumption state do no match. client=%d, server=%d\n",client_session_proposed, server_session_proposed);
err = -1;
}
if(test->is_session_resumption_proposed!=client_session_proposed) {
fprintf(stderr, "session proposed resumption state: %d, expected %d\n",
client_session_proposed, test->is_session_resumption_proposed);
err = -1;
} else if(client_session_proposed) {
if((client_proposed_sessionID.length!=server_proposed_sessionID.length) ||
(memcmp(client_proposed_sessionID.data, server_proposed_sessionID.data, client_proposed_sessionID.length)!=0))
{
fprintf(stderr, "session resumption was proposed, but proposed session IDs do not match\n");
err = -1;
}
}
if(client_session_match!=server_session_match) {
fprintf(stderr, "client and server session resumption state do no match. client=%d, server=%d\n",
client_session_match, server_session_match);
err = -1;
}
if(test->allow_resumption) {
if(client_session_match!=test->is_session_resumed) {
fprintf(stderr, "session resumption state: %d, expected %d\n", client_session_match, test->is_session_resumed);
err = -1;
} else if(client_session_match) {
if((client_sessionID.length!=server_sessionID.length) ||
(memcmp(client_sessionID.data, server_sessionID.data, client_sessionID.length)!=0))
{
fprintf(stderr, "session was resumed, but session IDs do not match\n");
err = -1;
}
if((client_sessionID.length!=client_proposed_sessionID.length) ||
(memcmp(client_sessionID.data, client_proposed_sessionID.data, client_sessionID.length)!=0))
{
fprintf(stderr, "session was resumed, but session ID do not match proposed session ID\n");
err = -1;
}
}
} else {
if(client_session_match) {
fprintf(stderr, "session resumed while not allowed\n");
err = -1;
}
}
bool expected_peer_ocsp_enabled = test->client_ocsp_enable && test->server_ocsp_enable;
const tls_buffer *ocsp_response = tls_handshake_get_peer_ocsp_response(client->filter);
const tls_buffer_list_t *ocsp_responder_id_list = tls_handshake_get_peer_ocsp_responder_id_list(server->filter);
const tls_buffer *ocsp_request_extensions = tls_handshake_get_peer_ocsp_request_extensions(server->filter);
if(expected_peer_ocsp_enabled!=server->peer_ocsp_enabled) {
fprintf(stderr, "server peer ocsp enable state: %d, expected %d\n", server->peer_ocsp_enabled, expected_peer_ocsp_enabled);
err = -1;
}
if(expected_peer_ocsp_enabled!=client->peer_ocsp_enabled) {
fprintf(stderr, "client peer ocsp enable state: %d, expected %d\n", client->peer_ocsp_enabled, expected_peer_ocsp_enabled);
err = -1;
}
if(expected_peer_ocsp_enabled) {
if(test->ocsp_response) {
if(ocsp_response==NULL) {
fprintf(stderr, "Unexpected: no ocsp response received\n");
err = -1;
} else if(!tls_buffer_equal(test->ocsp_response, ocsp_response)) {
fprintf(stderr, "OCSP response mismatch\n");
err = -1;
}
}
if(test->ocsp_request_extensions) {
if(ocsp_request_extensions==NULL) {
fprintf(stderr, "Unexpected: no ocsp request extension received\n");
err = -1;
} else if(!tls_buffer_equal(test->ocsp_request_extensions, ocsp_request_extensions)) {
fprintf(stderr, "OCSP request extension mismatch\n");
err = -1;
}
}
if(test->ocsp_responder_id_list) {
if(ocsp_responder_id_list==NULL) {
fprintf(stderr, "Unexpected: no ocsp responder list received\n");
err = -1;
} else if(!tls_buffer_list_equal(test->ocsp_responder_id_list, ocsp_responder_id_list)) {
fprintf(stderr, "OCSP responder list mismatch\n");
err = -1;
}
}
}
const tls_buffer_list_t *sct_list = tls_handshake_get_peer_sct_list(client->filter);
if(test->sct_enable) {
if(!tls_handshake_get_peer_sct_enabled(server->filter)) {
fprintf(stderr, "Server should have received SCT enabled\n");
err = -1;
}
if(!tls_buffer_list_equal(test->sct_list, sct_list)){
fprintf(stderr, "Received SCT list mismatch\n");
err = -1;
}
} else {
if(tls_handshake_get_peer_sct_enabled(server->filter)) {
fprintf(stderr, "Server should NOT have received SCT enabled\n");
err = -1;
}
if(sct_list) {
fprintf(stderr, "Client should not received a SCT list");
err = -1;
}
}
uint16_t client_negotiated_ec_curve = tls_handshake_get_negotiated_curve(client->filter);
test_printf("client negotiated ec curve: %04x\n", client_negotiated_ec_curve);
uint16_t server_negotiated_ec_curve = tls_handshake_get_negotiated_curve(server->filter);
test_printf("server negotiated ciphersuite: %04x\n", server_negotiated_ec_curve);
if(client_negotiated_ec_curve != server_negotiated_ec_curve) {
fprintf(stderr, "client and server ec curves do not match. client=%04x, server=%04x\n", client_negotiated_ec_curve, server_negotiated_ec_curve);
err = -1;
} else if(test->negotiated_ec_curve && (client_negotiated_ec_curve != test->negotiated_ec_curve)) {
fprintf(stderr, "EC curve negotiated: %04x, expected %04x\n", client_negotiated_ec_curve, test->negotiated_ec_curve);
err = -1;
}
if(test->request_client_auth) {
}
if (test->client_extMS_enable && test->server_extMS_enable) {
if (!tls_handshake_get_negotiated_ems(client->filter) || !tls_handshake_get_negotiated_ems(server->filter)) {
fprintf(stderr, "extended master secret should have been used\n");
err = -1;
}
} else {
if (tls_handshake_get_negotiated_ems(client->filter) || tls_handshake_get_negotiated_ems(server->filter)) {
fprintf(stderr, "Unexpected: extended master secret should NOT have been used\n");
err = -1;
}
}
} else {
if(test->client_err) { if(client->err!=test->client_err) {
fprintf(stderr, "client err: %d, expected %d\n", client->err, test->client_err);
err = client->err?client->err:-1;
}
} else { if(client->read_ready && client->write_ready && (client->err==0 || client->err==-9805)) {
fprintf(stderr, "client handshake completed, expected failure\n");
err = -1;
}
}
if(test->server_err) { if(server->err!=test->server_err) {
printf("server err: %d, expected %d\n", server->err, test->server_err);
err = server->err?server->err:-1;
}
} else { if(server->read_ready && server->write_ready && (server->err==0 || server->err==-9805)) {
printf("server handshake completed, expected failure\n");
err = -1;
}
}
}
return err;
}
static SSLCertificate g_server_cert; static tls_private_key_t g_server_key;
static SSLCertificate g_server_ecdsa_cert; static tls_private_key_t g_server_ecdsa_key;
static SSLCertificate g_client_cert;
static tls_private_key_t g_client_key;
static
int test_one_case(tls_test_case *test)
{
int err;
myFilterCtx_t client_c = {0,};
myFilterCtx_t server_c = {0,};
dispatch_group_t dg = dispatch_group_create();
dispatch_queue_t gq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, 600LL*NSEC_PER_SEC);
require_action(dg!=NULL, fail, err=-1);
require_action(gq!=NULL, fail, err=-1);
require_noerr((err=init_context(&client_c, false, "client write queue", test, dg)), fail);
require_noerr((err=init_context(&server_c, true, "server write queue", test, dg)), fail);
client_c.peer=&server_c;
server_c.peer=&client_c;
myFilterCtx_t *myCtx = &client_c;
dispatch_group_async(dg, myCtx->queue, ^{
tls_buffer peerID = {
.data = (uint8_t *)&test->session_id,
.length = sizeof(test->session_id),
};
int err;
if(test->session_id) {
err = tls_handshake_negotiate(myCtx->filter, &peerID);
} else {
err = tls_handshake_negotiate(myCtx->filter, NULL);
}
if(err) {
test_printf("Error %d while initiating handshake, closing.\n", err);
myCtx->peer = NULL;
myCtx->err = err;
}
});
require_noerr((err=(int)dispatch_group_wait(dg, timeout)), fail);
test_printf("Done - client: err=%d, read=%d, write=%d\n", client_c.err, client_c.read_ready, client_c.write_ready);
test_printf("Done - server: err=%d, read=%d, write=%d\n", server_c.err, server_c.read_ready, server_c.write_ready);
dispatch_sync(client_c.queue,^{
tls_handshake_close(client_c.filter);
});
dispatch_sync(server_c.queue,^{
tls_handshake_close(server_c.filter);
});
err = test_result(&client_c, &server_c);
fail:
if(dg) dispatch_release(dg);
clean_context(&client_c);
clean_context(&server_c);
return err;
}
static SSLCertificate * server_cert_for_cipher(uint16_t cs)
{
KeyExchangeMethod kem = sslCipherSuiteGetKeyExchangeMethod(cs);
if(kem==SSL_ECDHE_ECDSA)
return &g_server_ecdsa_cert;
else
return &g_server_cert;
}
static tls_private_key_t server_key_for_cipher(uint16_t cs)
{
KeyExchangeMethod kem = sslCipherSuiteGetKeyExchangeMethod(cs);
if(kem==SSL_ECDHE_ECDSA)
return g_server_ecdsa_key;
else
return g_server_key;
}
static void good_tests(const CipherSuiteName *ciphers, size_t n_ciphers, int min_proto, bool csa)
{
tls_test_case test = {0,};
int i, j, err;
for(i=0; i<n_ciphers; i++) {
for(j=min_proto; j<nprotos; j++) {
test.client_protocol_min = protos[j];
test.client_protocol_max = protos[j];
test.server_protocol_min = protos[j];
test.server_protocol_max = protos[j];
test.ciphersuites = &ciphers[i].cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = 0;
test.server_certs = server_cert_for_cipher(ciphers[i].cipher);
test.server_key = server_key_for_cipher(ciphers[i].cipher);
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.request_client_auth = csa;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = ciphers[i].cipher;
test.negotiated_version = (protos[j]==0)? tls_protocol_version_TLS_1_2:protos[j];
test_log_start();
test_printf("Good Test case i=%d, j=%d , csa=%d (%s, %04x)\n", i, j, csa, ciphers[i].name, protos[j]);
err = test_one_case(&test);
ok(!err, "Good Test case (i=%d, j=%d , csa=%d / %s, %04x)", i, j, csa, ciphers[i].name, protos[j]);
test_log_end(err);
}
}
}
static void ciphersuites_tests(void)
{
tls_test_case test = {0,};
int err;
for(int i=0; i<2; i++) {
test.client_protocol_min = tls_protocol_version_SSL_3;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_SSL_3;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.allow_resumption = false;
test.session_id = 0;
if(i==1) {
test.server_certs = &g_server_ecdsa_cert;
test.server_key = g_server_ecdsa_key;
} else {
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
}
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false;
test.certificate_requested = 0;
if(i==1) {
test.negotiated_ciphersuite = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
} else {
test.negotiated_ciphersuite = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
}
test.negotiated_version = tls_protocol_version_TLS_1_2;
test.ciphersuites = KnownCipherSuites;
test.num_ciphersuites = CipherSuiteCount;
test_log_start();
test_printf("Test case: ciphersuites KnownCipherSuites\n");
err = test_one_case(&test);
ok(!err, "Test case: ciphersuites KnownCipherSuites");
test_log_end(err);
test.ciphersuites = NULL;
test.num_ciphersuites = 0;
test_log_start();
test_printf("Test case: ciphersuites NULL\n");
err = test_one_case(&test);
ok(!err, "Test case: ciphersuites NULL");
test_log_end(err);
}
}
static void resumption_tests(const CipherSuiteName *ciphers, size_t n_ciphers, int min_proto)
{
tls_test_case test = {0,};
int i, j, err;
for(i=0; i<n_ciphers; i++) {
for(j=min_proto; j<nprotos; j++) {
test.client_protocol_min = protos[j];
test.client_protocol_max = protos[j];
test.server_protocol_min = protos[j];
test.server_protocol_max = protos[j];
test.ciphersuites = &ciphers[i].cipher;
test.num_ciphersuites = 1;
test.allow_resumption = true;
test.session_id = (ciphers[i].cipher<<8 | j) + 1;
test.server_certs = server_cert_for_cipher(ciphers[i].cipher);
test.server_key = server_key_for_cipher(ciphers[i].cipher);
if (j > 0) {
test.server_extMS_enable = true;
test.client_extMS_enable = true;
} else {
test.server_extMS_enable = false;
test.client_extMS_enable = false;
}
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.certificate_requested = 0;
test.negotiated_ciphersuite = ciphers[i].cipher;
test.negotiated_version = protos[j];
test.is_session_resumption_proposed = false; test.is_session_resumed = false;
test_log_start();
test_printf("Resumption test case %d, %d (%s, %04x) - 1st connection\n", i, j, ciphers[i].name, protos[j]);
err = test_one_case(&test);
ok(!err, "Resumption test case (%d, %d / %s, %04x) - 1st connection", i, j, ciphers[i].name, protos[j]);
test_log_end(err);
test.is_session_resumption_proposed = true; test.is_session_resumed = true;
test_log_start();
test_printf("Resumption test case %d, %d (%s, %04x) - 2nd connection\n", i, j, ciphers[i].name, protos[j]);
err = test_one_case(&test);
ok(!err, "Resumption test case (%d, %d / %s, %04x) - 2nd connection", i, j, ciphers[i].name, protos[j]);
test_log_end(err);
}
}
}
static void resumption_mismatch_tests(void)
{
tls_test_case test = {0,};
int i, err;
uint16_t cipherA = TLS_RSA_WITH_AES_128_CBC_SHA;
uint16_t cipherB = TLS_RSA_WITH_AES_256_CBC_SHA;
tls_cache_empty(g_cache);
for(i=0; i<2; i++) {
test.client_ciphersuites = &cipherA;
test.num_client_ciphersuites = 1;
test.allow_resumption = true;
test.session_id = i+1;
test.server_certs = server_cert_for_cipher(cipherA);
test.server_key = server_key_for_cipher(cipherA);
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipherA;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Resumption mismatch test case (%d) - 1st connection\n", i);
err = test_one_case(&test);
ok(!err, "Resumption mismatch test case (%d) - 1st connection", i);
test_log_end(err);
switch (i) {
case 0:
test.client_protocol_max = tls_protocol_version_TLS_1_0;
break;
case 1:
test.client_ciphersuites = &cipherB;
test.negotiated_ciphersuite = cipherB;
break;
default:
break;
}
test_log_start();
test_printf("Resumption mismatch test case (%d) - 2nd connection\n", i);
err = test_one_case(&test);
ok(!err, "Resumption mismatch test case (%d) - 2nd connection", i);
test_log_end(err);
}
}
static void renegotiation_tests(void)
{
tls_test_case test = {0,};
int t, err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
for(t=0; t<8; t++) {
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = &renegotiation_tests; test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_trigger_renegotiation = t&1;
test.server_trigger_renegotiation = t&2;
test.server_allow_renegotiation = t&4;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test.is_session_resumed = false;
test_log_start();
test_printf("Renegotiation case %d\n", t);
err = test_one_case(&test);
ok(!err, "Renegotiation test case (%d)", t);
test_log_end(err);
}
}
extern SSLCertificate google_cert0;
static void goto_fail_test(void)
{
uint16_t cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
tls_protocol_version pv = tls_protocol_version_TLS_1_2;
tls_test_case test = {0,};
int err;
test.client_protocol_min = pv;
test.client_protocol_max = pv;
test.server_protocol_min = pv;
test.server_protocol_max = pv;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = 0;
test.server_certs = &google_cert0;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.handshake_ok = false;
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = pv;
test_log_start();
test_printf("Test case \"goto fail;\"\n");
err = test_one_case(&test);
ok(!err, "Test case \"goto fail;\"");
test_log_end(err);
}
tls_handshake_message_t messages[] = {
tls_handshake_message_client_hello,
tls_handshake_message_server_hello,
tls_handshake_message_certificate,
tls_handshake_message_server_hello_done,
tls_handshake_message_server_key_exchange,
tls_handshake_message_client_key_exchange,
tls_handshake_message_finished,
};
int nmessages = sizeof(messages)/sizeof(messages[0]);
static int tls_handshake_fuzz_handshake_msg_len(myFilterCtx_t *myCtx, const tls_buffer in, uint8_t content_type)
{
tls_handshake_message_t msgtype = (tls_handshake_message_t)(myCtx->test->fuzz_ctx & 0xff);
uint8_t byte = (myCtx->test->fuzz_ctx>>8) & 0xff;
if((content_type==tls_record_type_Handshake) && (in.data[0]==msgtype)) {
tls_buffer out;
int err;
out.data=malloc(in.length);
out.length=in.length;
if(out.data==NULL) return -1;
memcpy(out.data, in.data, in.length);
out.data[3]=out.data[3]+byte;
err = send_to_peer(myCtx, out, content_type);
free(out.data);
return err;
} else {
return send_to_peer(myCtx, in, content_type);
}
}
static void corrupted_message_len_tests(void)
{
tls_test_case test = {0,};
int err;
int i,j;
uint16_t cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
for(i=0; i<nmessages; i++)
{
for(j=0; j<2; j++)
{
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = 0;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.fuzzer = tls_handshake_fuzz_handshake_msg_len;
test.fuzz_ctx = ((j?0xff:1)<<8) | messages[i];
test.handshake_ok = false; test.client_err = 0; test.server_err = 0; test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case corrupting message len (%d, %d)\n", i, j);
err = test_one_case(&test);
ok(!err, "Test case fuzzing message len (%d, %d)", i, j);
test_log_end(err);
}
}
}
static int decode_len(uint8_t *p)
{
return (p[0]<<16)|(p[1]<<8)|p[2];
}
static void encode_len(int l, uint8_t *p)
{
p[0]=(l>>16)&0xff;
p[1]=(l>>8)&0xff;
p[2]=(l)&0xff;
}
static int tls_handshake_fuzz_cert_len(myFilterCtx_t *myCtx, const tls_buffer in, uint8_t content_type)
{
if((content_type==tls_record_type_Handshake) && (in.data[0]==tls_handshake_message_certificate)) {
tls_buffer out;
int err;
out.data=malloc(in.length);
out.length=in.length;
if(out.data==NULL) return -1;
memcpy(out.data, in.data, in.length);
unsigned listLen = decode_len(out.data+4);
switch(myCtx->test->fuzz_ctx){
case 0:
encode_len(listLen+1, out.data+4);
break;
case 1:
encode_len(listLen-1, out.data+4);
break;
case 2:
encode_len(listLen-2, out.data+7);
break;
case 3:
encode_len(listLen-4, out.data+7);
break;
default:
assert(0);
}
err = send_to_peer(myCtx, out, content_type);
free(out.data);
return err;
} else {
return send_to_peer(myCtx, in, content_type);
}
}
static void corrupted_cert_len_tests(void)
{
tls_test_case test = {0,};
int err;
int i;
uint16_t cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
for(i=0; i<4; i++)
{
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = 0;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.fuzzer = tls_handshake_fuzz_cert_len;
test.fuzz_ctx = i;
test.handshake_ok = false; test.client_err = 0; test.server_err = 0; test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case corrupting cert len (%d)\n", i);
err = test_one_case(&test);
ok(!err, "Test case fuzzing cert len (%d)", i);
test_log_end(err);
}
}
tls_handshake_trust_t trust_values[] = {
tls_handshake_trust_ok,
tls_handshake_trust_unknown,
tls_handshake_trust_unknown_root,
tls_handshake_trust_cert_expired,
tls_handshake_trust_cert_invalid,
};
int ntrust_values = sizeof(trust_values)/sizeof(trust_values[0]);
static tls_handshake_trust_t truster(intptr_t trust_ctx)
{
assert(trust_ctx<ntrust_values);
return trust_values[trust_ctx];
}
static void trust_tests(void)
{
tls_test_case test = {0,};
int err;
int i;
uint16_t cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
for(i=0; i<ntrust_values; i++)
{
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.server_trust = truster;
test.server_trust_ctx = i;
test.handshake_ok = (i==0); test.client_err = 0; test.server_err = 0; test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case trust (%d)\n", i);
err = test_one_case(&test);
ok(!err, "Test case trust (%d) - err=%d", i, err);
test_log_end(err);
}
}
static void client_auth_trust_tests(void)
{
tls_test_case test = {0,};
int err;
int i, j;
uint16_t cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
for(i=0; i<ntrust_values; i++)
{
for(j=0; j<2; j++)
{
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = (j) ? &g_client_cert : NULL;
test.client_key = (j) ? g_client_key : NULL;
test.request_client_auth = true;
test.client_trust = truster;
test.client_trust_ctx = i;
test.handshake_ok = (i==0); test.client_err = 0; test.server_err = 0; test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case client auth trust (%d:%d)\n", i, j);
err = test_one_case(&test);
ok(!err, "Test case client auth trust (%d:%d) - err=%d", i, j, err);
test_log_end(err);
}
}
}
extern SSLCertificate ec_cert;
static void cert_mismatch_test(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = 0;
test.server_certs = &ec_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.handshake_ok = false; test.client_err = 0; test.server_err = 0; test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case cert mismatch\n");
err = test_one_case(&test);
ok(!err, "Test case cert mismatch - err=%d", err);
test_log_end(err);
}
static uint8_t ocsp_response_data[] = {
0x30, 0x82, 0x01, 0x72, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x01, 0x6b, 0x30,
0x82, 0x01, 0x67, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
0x01, 0x01, 0x04, 0x82, 0x01, 0x58, 0x30, 0x82, 0x01, 0x54, 0x30, 0x81,
0xbe, 0xa1, 0x22, 0x30, 0x20, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x15, 0x63, 0x6f, 0x72, 0x65, 0x54, 0x4c, 0x53, 0x20,
0x43, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x28, 0x52, 0x53, 0x41,
0x29, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x34, 0x30, 0x38, 0x32, 0x30, 0x32,
0x31, 0x31, 0x33, 0x30, 0x37, 0x5a, 0x30, 0x62, 0x30, 0x60, 0x30, 0x3a,
0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,
0x14, 0x20, 0xd4, 0x96, 0xb3, 0xfb, 0xd1, 0xb8, 0x84, 0x3a, 0x38, 0x14,
0xdb, 0x33, 0xd1, 0x0d, 0xa8, 0xca, 0x96, 0xba, 0x13, 0x04, 0x14, 0xb2,
0x23, 0x1b, 0x0f, 0x2c, 0x5a, 0xa2, 0x1d, 0xeb, 0x96, 0x34, 0xa7, 0x6f,
0x9d, 0x97, 0x11, 0x81, 0x14, 0x61, 0xbb, 0x02, 0x01, 0x01, 0xa1, 0x11,
0x18, 0x0f, 0x32, 0x30, 0x31, 0x34, 0x30, 0x38, 0x32, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x34, 0x30,
0x38, 0x32, 0x30, 0x32, 0x31, 0x31, 0x33, 0x30, 0x37, 0x5a, 0xa1, 0x23,
0x30, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
0x30, 0x01, 0x02, 0x04, 0x12, 0x04, 0x10, 0x4c, 0xc5, 0x63, 0xf2, 0x0a,
0x84, 0x8c, 0x03, 0xa4, 0x0d, 0x97, 0xd1, 0xa2, 0xbb, 0x1e, 0xb2, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x1b, 0x21, 0xd7, 0x01, 0xde, 0xb8,
0x58, 0x4b, 0x79, 0x6a, 0xa3, 0x8b, 0xa7, 0xe0, 0xbd, 0xa8, 0xda, 0x58,
0x48, 0xbb, 0xa7, 0xcd, 0xf7, 0x91, 0x15, 0xb3, 0x38, 0x70, 0xd9, 0x43,
0x25, 0x72, 0x0e, 0xc3, 0x3d, 0xf9, 0xc7, 0x30, 0x2d, 0xb4, 0x9f, 0x1c,
0x4b, 0x62, 0x31, 0x48, 0xb4, 0x9f, 0x00, 0xbd, 0x57, 0xb6, 0xec, 0xda,
0xf0, 0xa2, 0x42, 0x61, 0xfc, 0xef, 0x73, 0xc5, 0x55, 0xc1, 0xf6, 0x72,
0x79, 0xcf, 0x55, 0x01, 0x09, 0xe4, 0xd2, 0xee, 0xbd, 0xa6, 0x08, 0xc6,
0x39, 0x3a, 0x17, 0x76, 0x98, 0xaa, 0x61, 0x82, 0xb9, 0x41, 0xe1, 0xbb,
0x4f, 0x67, 0x5e, 0x0b, 0x5e, 0xfa, 0x3c, 0x12, 0x15, 0xbe, 0x90, 0x8e,
0x29, 0xe6, 0x5c, 0x9b, 0xfc, 0xaf, 0x40, 0xa4, 0x31, 0xd7, 0xa4, 0xc6,
0x71, 0x22, 0x01, 0xfa, 0xb2, 0xcd, 0x6e, 0x1f, 0x26, 0xdb, 0xb1, 0xa3,
0xec, 0x43
};
static tls_buffer g_ocsp_response = {
.data = ocsp_response_data,
.length = sizeof(ocsp_response_data),
};
static uint8_t dummy_data[] = {
0x14, 0x20, 0xd4, 0x96, 0xb3, 0xfb, 0xd1, 0xb8, 0x84, 0x3a, 0x38, 0x14,
0x82, 0x01, 0x67, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
0x01, 0x01, 0x04, 0x82, 0x01, 0x58, 0x30, 0x82, 0x01, 0x54, 0x30, 0x81,
0xbe, 0xa1, 0x22, 0x30, 0x20, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x15, 0x63, 0x6f, 0x72, 0x65, 0x54, 0x4c, 0x53, 0x20,
0x30, 0x82, 0x01, 0x72, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x01, 0x6b, 0x30,
0x29, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x34, 0x30, 0x38, 0x32, 0x30, 0x32,
0x31, 0x31, 0x33, 0x30, 0x37, 0x5a, 0x30, 0x62, 0x30, 0x60, 0x30, 0x3a,
0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,
0x14, 0x20, 0xd4, 0x96, 0xb3, 0xfb, 0xd1, 0xb8, 0x84, 0x3a, 0x38, 0x14,
0xdb, 0x33, 0xd1, 0x0d, 0xa8, 0xca, 0x96, 0xba, 0x13, 0x04, 0x14, 0xb2,
0x23, 0x1b, 0x0f, 0x2c, 0x5a, 0xa2, 0x1d, 0xeb, 0x96, 0x34, 0xa7, 0x6f,
0x9d, 0x97, 0x11, 0x81, 0x14, 0x61, 0xbb, 0x02, 0x01, 0x01, 0xa1, 0x11,
};
static tls_buffer g_ocsp_request_extension = {
.data = dummy_data,
.length = sizeof(dummy_data),
};
static tls_buffer_list_t g_ocsp_responder_id_list = {
.next = NULL,
.buffer.data = dummy_data,
.buffer.length = sizeof(dummy_data),
};
static void ocsp_tests(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
tls_cache_empty(g_cache);
for(int i=0;i<4;i++) {
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.ocsp_response = &g_ocsp_response;
test.ocsp_request_extensions = &g_ocsp_request_extension;
test.ocsp_responder_id_list = &g_ocsp_responder_id_list;
test.client_ocsp_enable = i&0x1;
test.server_ocsp_enable = i&0x2;
test.allow_resumption = true;
test.session_id = i + 1;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test.is_session_resumption_proposed = false; test.is_session_resumed = false;
test_log_start();
test_printf("Test case oscp %d\n", i );
err = test_one_case(&test);
ok(!err, "Test case ocsp %d - err=%d", i, err);
test_log_end(err);
test.is_session_resumption_proposed = true; test.is_session_resumed = true;
test_log_start();
test_printf("Test case oscp %d (resumed)\n", i );
err = test_one_case(&test);
ok(!err, "Test case ocsp %d (resumed) - err=%d", i, err);
test_log_end(err);
}
}
static
uint8_t server_D_sct_data[] = {
0x00, 0xab, 0xa8, 0xb5, 0xb4, 0x7d, 0x00, 0x00, 0x1b, 0x46, 0x58, 0x28,
0xc4, 0x0a, 0xc7, 0x0b, 0x03, 0xf6, 0x91, 0x70, 0xa3, 0x5f, 0xed, 0xc8,
0x74, 0x40, 0x3c, 0xd0, 0x58, 0x1d, 0x3c, 0x8c, 0x16, 0x00, 0x00, 0x01,
0x47, 0xdc, 0x04, 0x70, 0x0e, 0x00, 0x00, 0x04, 0x03, 0x00, 0x46, 0x30,
0x44, 0x02, 0x20, 0x71, 0x55, 0x2f, 0x75, 0xa8, 0x3a, 0xfd, 0x01, 0x34,
0x44, 0xc7, 0x84, 0x71, 0x8f, 0x1e, 0xc2, 0x36, 0xe2, 0x08, 0x07, 0x92,
0x2b, 0x9f, 0x44, 0x0e, 0x84, 0x16, 0x08, 0xe0, 0xaf, 0xc5, 0xb9, 0x02,
0x20, 0x29, 0x3e, 0x0f, 0x63, 0x5c, 0xe7, 0x0a, 0xea, 0x1f, 0x96, 0x4a,
0x11, 0x86, 0x72, 0x06, 0xa5, 0x25, 0xc4, 0x5e, 0xf6, 0x92, 0xd8, 0x08,
0x98, 0x17, 0xba, 0xf2, 0xfe, 0x50, 0x62, 0x36, 0x29
};
static
uint8_t server_D_cert_data[] = {
0x30, 0x82, 0x02, 0xe4, 0x30, 0x82, 0x02, 0x4d, 0xa0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x01, 0x13, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x52, 0x31, 0x0b, 0x30,
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1a,
0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x63, 0x6f, 0x72,
0x65, 0x6f, 0x73, 0x2d, 0x63, 0x74, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20,
0x43, 0x41, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31,
0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75,
0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x30, 0x1e, 0x17, 0x0d, 0x31,
0x32, 0x30, 0x36, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
0x17, 0x0d, 0x32, 0x32, 0x30, 0x36, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x5a, 0x30, 0x72, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03,
0x55, 0x04, 0x0a, 0x0c, 0x0e, 0x63, 0x6f, 0x72, 0x65, 0x6f, 0x73, 0x2d,
0x63, 0x74, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x31, 0x13, 0x30, 0x11, 0x06,
0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f,
0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x18, 0x63,
0x6f, 0x72, 0x65, 0x6f, 0x73, 0x2d, 0x63, 0x74, 0x2d, 0x74, 0x65, 0x73,
0x74, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89,
0x02, 0x81, 0x81, 0x00, 0xba, 0x00, 0xc4, 0xfb, 0x3f, 0x9a, 0x86, 0x43,
0x1a, 0x26, 0x99, 0x9d, 0x19, 0x67, 0x27, 0xaa, 0x44, 0xd4, 0xba, 0x2b,
0xfe, 0x7b, 0x32, 0xe8, 0x2a, 0xc7, 0x89, 0x36, 0x41, 0xd7, 0xaf, 0xf4,
0x97, 0x4d, 0x41, 0x7b, 0xc7, 0x80, 0xba, 0x79, 0xab, 0x9c, 0xeb, 0xcc,
0x38, 0xb7, 0x83, 0xdf, 0x62, 0x7e, 0xaf, 0x6c, 0x32, 0x57, 0xc2, 0x41,
0xea, 0x73, 0xa9, 0x45, 0xf8, 0xbe, 0xc2, 0x26, 0x0f, 0x01, 0xec, 0x3b,
0x02, 0x24, 0x7d, 0x39, 0x5c, 0xa6, 0x9c, 0xdf, 0x4b, 0x1f, 0xd5, 0x4d,
0xd2, 0x5e, 0x9f, 0x09, 0x4c, 0x68, 0x11, 0xa3, 0x02, 0xb1, 0x65, 0x42,
0xef, 0x67, 0x25, 0x30, 0x93, 0x86, 0x6f, 0x37, 0x1c, 0x83, 0x62, 0xd1,
0x24, 0xfa, 0x89, 0x4d, 0x00, 0x8e, 0x77, 0x6a, 0xfd, 0x79, 0x85, 0x3e,
0x59, 0xed, 0x92, 0xdf, 0x8a, 0xa1, 0xca, 0xfd, 0xfe, 0x1b, 0xf7, 0x1f,
0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa9, 0x30, 0x81, 0xa6, 0x30,
0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xf4, 0x42,
0x90, 0xfd, 0x4c, 0xcd, 0x26, 0x10, 0x0b, 0xd7, 0x34, 0x22, 0xad, 0x23,
0x26, 0xa0, 0x6c, 0xaf, 0xaa, 0x6c, 0x30, 0x7a, 0x06, 0x03, 0x55, 0x1d,
0x23, 0x04, 0x73, 0x30, 0x71, 0x80, 0x14, 0xdc, 0x16, 0x44, 0x15, 0x3e,
0x53, 0x27, 0xd8, 0x68, 0x66, 0x41, 0x40, 0x88, 0x90, 0xe4, 0x4e, 0x0a,
0xda, 0x08, 0xa9, 0xa1, 0x56, 0xa4, 0x54, 0x30, 0x52, 0x31, 0x0b, 0x30,
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1a,
0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x63, 0x6f, 0x72,
0x65, 0x6f, 0x73, 0x2d, 0x63, 0x74, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20,
0x43, 0x41, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31,
0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75,
0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x82, 0x01, 0x01, 0x30, 0x09,
0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0d, 0x06,
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
0x03, 0x81, 0x81, 0x00, 0x7a, 0x06, 0xe3, 0x17, 0xca, 0xee, 0xe0, 0x67,
0x16, 0xfd, 0xf1, 0xad, 0x9f, 0xf8, 0xeb, 0xce, 0x03, 0x57, 0x7d, 0x90,
0x6c, 0x85, 0xe0, 0x43, 0x3f, 0xb4, 0x3a, 0x08, 0x63, 0xef, 0x79, 0xf6,
0xe1, 0xa3, 0x88, 0x32, 0xcf, 0x8f, 0x2f, 0xde, 0xd0, 0xc0, 0x92, 0x0b,
0x16, 0xe1, 0xd4, 0x49, 0xd5, 0xb2, 0x84, 0x2e, 0x87, 0xfa, 0x1b, 0x5b,
0x95, 0x51, 0x51, 0x0d, 0x29, 0x88, 0xd0, 0x8c, 0x10, 0x75, 0xe3, 0x78,
0xb3, 0x4e, 0x39, 0xc1, 0xe4, 0xd0, 0x22, 0xb7, 0x64, 0xbe, 0xc3, 0x9d,
0xff, 0x02, 0xc9, 0x66, 0xc3, 0x38, 0x4e, 0x88, 0xde, 0xa6, 0x75, 0x80,
0xb3, 0x17, 0xb9, 0xfe, 0xfb, 0x64, 0xec, 0x3b, 0x16, 0xcd, 0xf0, 0x0d,
0x15, 0xbf, 0x70, 0x42, 0xba, 0xe5, 0xec, 0x1d, 0x2f, 0xee, 0x0a, 0x2f,
0xd7, 0x37, 0x9d, 0xc6, 0x0b, 0x26, 0xf3, 0xfb, 0x13, 0x69, 0x9f, 0x09
};
static
uint8_t server_D_key_data[] = {
0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xba,
0x00, 0xc4, 0xfb, 0x3f, 0x9a, 0x86, 0x43, 0x1a, 0x26, 0x99, 0x9d, 0x19,
0x67, 0x27, 0xaa, 0x44, 0xd4, 0xba, 0x2b, 0xfe, 0x7b, 0x32, 0xe8, 0x2a,
0xc7, 0x89, 0x36, 0x41, 0xd7, 0xaf, 0xf4, 0x97, 0x4d, 0x41, 0x7b, 0xc7,
0x80, 0xba, 0x79, 0xab, 0x9c, 0xeb, 0xcc, 0x38, 0xb7, 0x83, 0xdf, 0x62,
0x7e, 0xaf, 0x6c, 0x32, 0x57, 0xc2, 0x41, 0xea, 0x73, 0xa9, 0x45, 0xf8,
0xbe, 0xc2, 0x26, 0x0f, 0x01, 0xec, 0x3b, 0x02, 0x24, 0x7d, 0x39, 0x5c,
0xa6, 0x9c, 0xdf, 0x4b, 0x1f, 0xd5, 0x4d, 0xd2, 0x5e, 0x9f, 0x09, 0x4c,
0x68, 0x11, 0xa3, 0x02, 0xb1, 0x65, 0x42, 0xef, 0x67, 0x25, 0x30, 0x93,
0x86, 0x6f, 0x37, 0x1c, 0x83, 0x62, 0xd1, 0x24, 0xfa, 0x89, 0x4d, 0x00,
0x8e, 0x77, 0x6a, 0xfd, 0x79, 0x85, 0x3e, 0x59, 0xed, 0x92, 0xdf, 0x8a,
0xa1, 0xca, 0xfd, 0xfe, 0x1b, 0xf7, 0x1f, 0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x81, 0x80, 0x21, 0x3f, 0xaf, 0xf6, 0x85, 0x99, 0x16, 0xb4, 0xfa,
0x00, 0xba, 0x66, 0xe5, 0xba, 0x95, 0xd1, 0x8e, 0xfa, 0x43, 0xc9, 0x47,
0x75, 0x38, 0x55, 0x5e, 0x08, 0x4b, 0x13, 0xc2, 0xd3, 0x4e, 0x65, 0xb7,
0x82, 0x1c, 0xd9, 0x86, 0x81, 0x11, 0x54, 0x5c, 0x83, 0xf1, 0x76, 0x91,
0x10, 0xe4, 0xe6, 0xd2, 0x91, 0x78, 0xc4, 0x2b, 0x7f, 0x9a, 0x7e, 0xf3,
0xec, 0xf6, 0xee, 0x46, 0x17, 0xbb, 0x56, 0x8a, 0x2b, 0x00, 0x0d, 0xd6,
0xc5, 0x6c, 0x03, 0x73, 0x36, 0xc7, 0x30, 0xd3, 0x79, 0xc7, 0xbd, 0x71,
0x17, 0x92, 0xde, 0x76, 0x72, 0x0b, 0xb6, 0xc1, 0xfe, 0x78, 0x4f, 0x4e,
0xac, 0x84, 0x25, 0xce, 0x5d, 0x15, 0x08, 0xb4, 0x3e, 0x26, 0xef, 0x3f,
0xfe, 0x09, 0x25, 0x31, 0x82, 0xd6, 0x1d, 0xb1, 0xd2, 0x5e, 0x9b, 0x4d,
0xd6, 0xfc, 0x1d, 0x8e, 0x9f, 0x40, 0xff, 0xc1, 0xba, 0x78, 0xe1, 0x02,
0x41, 0x00, 0xe6, 0x00, 0xa6, 0x26, 0xdd, 0x88, 0xe6, 0x72, 0x28, 0x1f,
0xc2, 0xb0, 0x87, 0xef, 0x72, 0x97, 0x32, 0x0c, 0xf2, 0xc0, 0xd9, 0x0c,
0x2b, 0x06, 0x7d, 0xbe, 0xcc, 0x09, 0x58, 0xa8, 0xe2, 0x5b, 0xaa, 0xcf,
0xf6, 0xb1, 0x67, 0x5a, 0x8b, 0x98, 0xa4, 0xed, 0x97, 0x51, 0xa7, 0x05,
0xf7, 0xc1, 0xb1, 0x38, 0xed, 0x4d, 0xce, 0x41, 0xf0, 0x3f, 0x9d, 0x46,
0x1f, 0x59, 0x39, 0x1a, 0xac, 0xb1, 0x02, 0x41, 0x00, 0xcf, 0x06, 0xf3,
0x53, 0xd3, 0x12, 0x2f, 0xae, 0x81, 0xd0, 0x3e, 0xd2, 0x3f, 0x3b, 0x3d,
0xd2, 0x61, 0xe2, 0xf8, 0x4e, 0x74, 0x00, 0xe1, 0xe5, 0x45, 0xa8, 0x88,
0xcb, 0xff, 0xf1, 0xb4, 0x90, 0xe4, 0xb7, 0x5b, 0xa8, 0xf8, 0xa4, 0x85,
0x5f, 0xfd, 0x2b, 0xb5, 0xd6, 0xd7, 0x8e, 0x0e, 0xac, 0x56, 0x31, 0x97,
0xec, 0xc6, 0xf8, 0xaa, 0x6a, 0x05, 0xf2, 0x32, 0x94, 0xdd, 0xf4, 0x94,
0xcf, 0x02, 0x41, 0x00, 0xd5, 0x55, 0xfc, 0xc7, 0x47, 0xec, 0xd7, 0x73,
0x43, 0x6c, 0x52, 0x35, 0x53, 0xa0, 0xf1, 0xf4, 0xf3, 0xe3, 0xb6, 0xb6,
0xd1, 0x9b, 0xcb, 0xbc, 0xb5, 0x9d, 0xe7, 0xbb, 0x33, 0x95, 0x52, 0x80,
0x1c, 0x2b, 0xd1, 0x72, 0x33, 0x9f, 0x74, 0xa4, 0x1d, 0x36, 0x93, 0x88,
0x95, 0x17, 0x9f, 0xfa, 0xf4, 0xdb, 0x0c, 0xa1, 0x82, 0x92, 0xfe, 0xb8,
0xc2, 0xb4, 0x6c, 0x17, 0x62, 0x34, 0x2f, 0xc1, 0x02, 0x41, 0x00, 0x89,
0xfb, 0x77, 0xf2, 0x46, 0x9b, 0xb8, 0x6b, 0xf6, 0xd9, 0x75, 0x05, 0x6c,
0x5f, 0x6f, 0xb4, 0xe8, 0xc8, 0xfd, 0xf6, 0x4c, 0x1a, 0xca, 0x74, 0xa5,
0x18, 0xcf, 0x14, 0x28, 0x62, 0x50, 0x96, 0xc1, 0xd9, 0xf3, 0x9d, 0x8b,
0x1b, 0x1c, 0x49, 0xfd, 0xd3, 0x44, 0x3f, 0x0d, 0x2c, 0x01, 0x5b, 0x9b,
0x97, 0x32, 0x4a, 0xfd, 0xd2, 0x7e, 0xc2, 0x6b, 0x74, 0x21, 0x82, 0x56,
0xec, 0xcc, 0xc1, 0x02, 0x41, 0x00, 0x92, 0x28, 0xeb, 0xba, 0xba, 0x6a,
0xd5, 0x85, 0x67, 0xfa, 0xc2, 0x2a, 0x28, 0x0a, 0x5a, 0x0c, 0xe3, 0x22,
0x73, 0xa0, 0xe6, 0xf7, 0xd9, 0x30, 0x23, 0x93, 0xf7, 0x2b, 0x70, 0x70,
0xd6, 0x8f, 0x4a, 0xf7, 0xc8, 0x0c, 0x07, 0x6c, 0x24, 0x0c, 0x15, 0xc7,
0x3d, 0x6f, 0xd0, 0xc2, 0x71, 0x0a, 0xc8, 0xa4, 0xe8, 0xd5, 0x5b, 0x41,
0x86, 0x36, 0x91, 0x8b, 0x1b, 0xfc, 0x7c, 0x10, 0x38, 0x06
};
static tls_buffer_list_t g_server_D_sct_list = {
.next = NULL,
.buffer.data = server_D_sct_data,
.buffer.length = sizeof(server_D_sct_data),
};
static SSLCertificate g_server_D_cert;
static tls_private_key_t g_server_D_key;
static void sct_tests(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
tls_cache_empty(g_cache);
for(int i=0;i<4;i++) {
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_D_cert;
test.server_key = g_server_D_key;
test.sct_enable = (i&1);
test.sct_list = (i&2)?&g_server_D_sct_list:NULL;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test.allow_resumption = true;
test.session_id = i + 1;
test.is_session_resumption_proposed = false; test.is_session_resumed = false;
test_log_start();
test_printf("Test case sct %d\n", i );
err = test_one_case(&test);
ok(!err, "Test case sct %d - err=%d", i, err);
test_log_end(err);
test.is_session_resumption_proposed = true; test.is_session_resumed = true;
test_log_start();
test_printf("Test case sct %d (resumed)\n", i );
err = test_one_case(&test);
ok(!err, "Test case sct %d (resumed) - err=%d", i, err);
test_log_end(err);
}
}
static void negotiated_version_tests(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
int actual_client_min, actual_client_max, actual_server_min, actual_server_max;
for(int i=0;i<nprotos;i++)
for(int j=0;j<nprotos;j++)
for(int k=0;k<nprotos;k++)
for(int l=0;l<nprotos;l++) {
test.client_protocol_min = protos[i];
test.client_protocol_max = protos[j];
test.server_protocol_min = protos[k];
test.server_protocol_max = protos[l];
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
actual_client_min = (test.client_protocol_min==0)?tls_protocol_version_TLS_1_0:test.client_protocol_min;
actual_server_min = (test.server_protocol_min==0)?tls_protocol_version_TLS_1_0:test.server_protocol_min;
actual_client_max = (test.client_protocol_max==0)?tls_protocol_version_TLS_1_2:test.client_protocol_max;
actual_server_max = (test.server_protocol_max==0)?tls_protocol_version_TLS_1_2:test.server_protocol_max;
if(actual_client_min>actual_client_max) actual_client_min = actual_client_max;
if(actual_server_min>actual_server_max) actual_server_min = actual_server_max;
if((actual_client_min>actual_server_max) || (actual_client_max<actual_server_min)) {
test.handshake_ok = false;
} else {
test.handshake_ok = true;
}
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = TLS_RSA_WITH_AES_128_CBC_SHA;
test.negotiated_version = (actual_client_max>actual_server_max)?actual_server_max:actual_client_max;
test_log_start();
test_printf("Test case: negotiated version (%d:%d, %d:%d)\n", i, j, k, l);
err = test_one_case(&test);
ok(!err, "Test case: negotiated version (%d:%d, %d:%d)", i, j, k, l);
test_log_end(err);
}
}
static void version_tolerance_tests(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
int tls_client_req_versions[] = {
0x0304, 0x0305, 0x03ff, 0x0400, 0x0401, 0x0501, 0x1010, };
for(int i=0;i<sizeof(tls_client_req_versions)/sizeof(tls_client_req_versions[0]);i++) {
test.client_protocol_max = tls_client_req_versions[i];
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = TLS_RSA_WITH_AES_128_CBC_SHA;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case: version intolerance version (%d)\n", i);
err = test_one_case(&test);
ok(!err, "Test case: version intolerance (%d)", i);
test_log_end(err);
}
}
static void dtls_tests(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
test.dtls = true;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.handshake_ok = true;
test.negotiated_ciphersuite = TLS_RSA_WITH_AES_128_CBC_SHA;
test.negotiated_version = tls_protocol_version_DTLS_1_0;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test_log_start();
test_printf("Test case: dtls\n");
err = test_one_case(&test);
ok(!err, "Test case: dtls");
test_log_end(err);
}
static void dtls_version_tolerance_tests(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
int client_req_versions[] = {
0xfefe, 0xfefd, 0xfdff, 0xf0f0, };
for(int i=0;i<sizeof(client_req_versions)/sizeof(client_req_versions[0]);i++) {
test.dtls = true;
test.client_protocol_max = client_req_versions[i];
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = TLS_RSA_WITH_AES_128_CBC_SHA;
test.negotiated_version = tls_protocol_version_DTLS_1_0;
test_log_start();
test_printf("Test case: version intolerance version (%d)\n", i);
err = test_one_case(&test);
ok(!err, "Test case: version intolerance (%d)", i);
test_log_end(err);
}
}
static void server_rsa_key_exchange_tests(void)
{
tls_test_case test = {0, };
int err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = 0;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.server_rsa_key_exchange = true;
test.handshake_ok = false; test.client_err = 0; test.server_err = 0; test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case server rsa key exchange\n");
err = test_one_case(&test);
ok(!err, "Test case server rsa key exchange - err=%d", err);
test_log_end(err);
}
static int tls_handshake_fuzz_server_hello(myFilterCtx_t *myCtx, const tls_buffer in, uint8_t content_type)
{
if((content_type==tls_record_type_Handshake) && (in.data[0]==tls_handshake_message_server_hello)) {
tls_buffer out;
int err;
out.data=malloc(in.length+16);
out.length=in.length+16;
if(out.data==NULL) return -1;
memset(out.data, 0, out.length);
memcpy(out.data, in.data, in.length);
err = send_to_peer(myCtx, out, content_type);
free(out.data);
return err;
} else {
return send_to_peer(myCtx, in, content_type);
}
}
static void zero_padding_tests(void)
{
tls_test_case test = {0,};
int err;
int i;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
for(i=0; i<1; i++)
{
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = 0;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.fuzzer = tls_handshake_fuzz_server_hello;
test.fuzz_ctx = i;
test.handshake_ok = true; test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case zero padding (%d)\n", i);
err = test_one_case(&test);
ok(!err, "Test case zero padding (%d)", i);
test_log_end(err);
}
}
static uint8_t client_hello_hostname[512] =
"0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF"
"0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF"
"0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF"
"0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF";
static void client_hello_size_test(void)
{
tls_test_case test = {0, };
int err;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
tls_buffer peer_hostname;
peer_hostname.data = client_hello_hostname;
for(int i=1; i<sizeof(client_hello_hostname); i++) {
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = 0;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
peer_hostname.length = i;
test.peer_hostname = &peer_hostname;
test.handshake_ok = true; test.client_err = 0; test.server_err = 0; test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case client hello size (%d)\n", i);
err = test_one_case(&test);
ok(!err, "Test case client hello size (%d) - err=%d", i, err);
test_log_end(err);
}
}
static void forget_pubkey_test(void)
{
uint16_t cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
tls_protocol_version pv = tls_protocol_version_TLS_1_2;
tls_test_case test = {0,};
int err;
test.client_protocol_min = pv;
test.client_protocol_max = pv;
test.server_protocol_min = pv;
test.server_protocol_max = pv;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = false;
test.session_id = 0;
test.forget_to_set_pubkey = true;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.handshake_ok = false;
test.client_err = 0;
test.server_err = -9838;
test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = pv;
test_log_start();
test_printf("Test case forget pubkey\n");
err = test_one_case(&test);
ok(!err, "Test case forget pubkey\"");
test_log_end(err);
}
static uint8_t dh_parameters_512_data[] = {
0x30, 0x46, 0x02, 0x41, 0x00, 0x85, 0xcd, 0xc1, 0x7e, 0x26, 0xeb, 0x37,
0x84, 0x13, 0xd0, 0x3b, 0x07, 0xc1, 0x57, 0x7d, 0xf3, 0x55, 0x8d, 0xa0,
0xc4, 0xa5, 0x03, 0xc4, 0x2c, 0xc6, 0xd5, 0xa6, 0x31, 0xcb, 0x68, 0xdf,
0x5d, 0x96, 0x20, 0x1a, 0x15, 0x57, 0x49, 0x7d, 0xd7, 0x51, 0x65, 0x6e,
0x37, 0xa8, 0xe3, 0xe9, 0xe1, 0x59, 0x2e, 0xd4, 0x57, 0x4a, 0xf0, 0xcb,
0x0e, 0x85, 0x07, 0xdd, 0x35, 0xa7, 0xe3, 0xc6, 0xbb, 0x02, 0x01, 0x02
};
static tls_buffer dh_parameters_512 = {
.data = dh_parameters_512_data,
.length = sizeof(dh_parameters_512_data),
};
static uint8_t dh_parameters_768_data[] = {
0x30, 0x66, 0x02, 0x61, 0x00, 0xe1, 0xa2, 0x50, 0xab, 0xb0, 0xdc, 0xef,
0xe1, 0x2f, 0xd9, 0xde, 0x59, 0x86, 0x24, 0x43, 0x3b, 0xf3, 0x40, 0x9d,
0x02, 0xcc, 0xe2, 0x70, 0x63, 0x46, 0x8d, 0x0f, 0xf3, 0x8a, 0xc6, 0xa0,
0x1d, 0x7b, 0x30, 0x83, 0x10, 0x48, 0x40, 0x28, 0xa4, 0x3e, 0xbe, 0x4d,
0xb6, 0xea, 0x90, 0x02, 0xae, 0x25, 0x93, 0xc0, 0xe8, 0x36, 0x5c, 0xc8,
0xc8, 0x0b, 0x04, 0xd5, 0x05, 0xac, 0x67, 0x24, 0x4b, 0xa9, 0x42, 0x5a,
0x03, 0x65, 0x4d, 0xd0, 0xc0, 0xbd, 0x78, 0x32, 0xd0, 0x8c, 0x0a, 0xf4,
0xbf, 0xd1, 0x61, 0x86, 0x13, 0x13, 0x3b, 0x83, 0xce, 0xbf, 0x3b, 0xbc,
0x8f, 0xf9, 0x4e, 0x50, 0xe3, 0x02, 0x01, 0x02
};
static tls_buffer dh_parameters_768 = {
.data = dh_parameters_768_data,
.length = sizeof(dh_parameters_768_data),
};
static uint8_t dh_parameters_1024_data[] = {
0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0xd5, 0x06, 0x69, 0xc6, 0xd4,
0x98, 0x2b, 0xe3, 0x49, 0xe2, 0xa1, 0x9b, 0x82, 0xaf, 0x3f, 0xaa, 0xc3,
0x86, 0x2a, 0x7a, 0xfa, 0x62, 0x12, 0x33, 0x45, 0x9f, 0x34, 0x57, 0xc6,
0x6c, 0x88, 0x81, 0xa6, 0x5d, 0xa3, 0x43, 0xe5, 0x4d, 0x87, 0x4f, 0x69,
0x3d, 0x2b, 0xc8, 0x18, 0xb6, 0xd7, 0x29, 0x53, 0x94, 0x0d, 0x73, 0x9b,
0x08, 0x22, 0x73, 0x84, 0x7b, 0x5a, 0x03, 0x2e, 0xfc, 0x10, 0x9b, 0x35,
0xc6, 0xa1, 0xca, 0x36, 0xd0, 0xcc, 0x3e, 0xa2, 0x04, 0x3a, 0x8a, 0xe8,
0x87, 0xe8, 0x60, 0x72, 0xee, 0x99, 0xf3, 0x04, 0x0a, 0xd8, 0x1a, 0xe6,
0xfc, 0xbc, 0xe1, 0xc5, 0x9d, 0x3a, 0xca, 0xf9, 0xfd, 0xbf, 0x58, 0xd3,
0x4d, 0xde, 0x8b, 0x4a, 0xb5, 0x37, 0x1e, 0x6d, 0xf4, 0x22, 0x0f, 0xb7,
0x48, 0x0a, 0xda, 0x82, 0x40, 0xc9, 0x55, 0x20, 0x01, 0x3b, 0x35, 0xb2,
0x94, 0x68, 0xab, 0x02, 0x01, 0x02
};
static tls_buffer dh_parameters_1024 = {
.data = dh_parameters_1024_data,
.length = sizeof(dh_parameters_1024_data),
};
static void min_dh_size_test(void)
{
tls_test_case test = {0, };
int err;
uint16_t cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
struct {
tls_buffer *params;
unsigned bits;
} dh_params[] = {
{ &dh_parameters_512, 512},
{ &dh_parameters_768, 768},
{ &dh_parameters_1024, 1024},
{ NULL, 2048},
};
unsigned n_dh_params = sizeof(dh_params)/sizeof(dh_params[0]);
unsigned min_dh_size[] = {
0, 512,
768,
1024,
2048,
};
unsigned n_min_dh_size = sizeof(min_dh_size)/sizeof(min_dh_size[0]);
for(int i=0; i<n_dh_params; i++) {
for(int j=0; j<n_min_dh_size; j++) {
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.dh_parameters = dh_params[i].params;
test.min_dh_size = min_dh_size[j];
if(dh_params[i].bits>=((min_dh_size[j]==0)?1024:min_dh_size[j]))
{
test.handshake_ok = true; test.client_err = 0; }
else
{
test.handshake_ok = false; test.client_err = -9850; }
test.server_err = 0; test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = tls_protocol_version_TLS_1_2;
test_log_start();
test_printf("Test case min dh size (%d, %d[%d])\n", i, j, min_dh_size[j]);
err = test_one_case(&test);
ok(!err, "Test case min dh size (%d, %d[%d]) - err=%d", i, j, min_dh_size[j], err);
test_log_end(err);
}}
}
static void config_tests(void)
{
tls_test_case test = {0,};
int err;
int i;
for(i=0; i<=tls_handshake_config_TLSv1_3DES_fallback; i++)
{
test.client_config = i;
test.server_config = i;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.handshake_ok = true;
test_log_start();
test_printf("Test case config (%d)\n", i);
err = test_one_case(&test);
ok(!err, "Test case config (%d)", i);
test_log_end(err);
}
}
uint16_t serverCurves[] = {
tls_curve_secp256r1,
tls_curve_secp384r1,
tls_curve_secp521r1
};
static int serverCurvesCount = sizeof(serverCurves)/sizeof(serverCurves[0]);
uint16_t ecCurves1[] = {
tls_curve_secp256r1,
tls_curve_secp384r1,
tls_curve_secp521r1
};
static int n_ecCurves1 = sizeof(ecCurves1)/sizeof(ecCurves1[0]);
uint16_t ecCurves2[] = {
tls_curve_secp384r1,
tls_curve_secp521r1
};
static int n_ecCurves2 = sizeof(ecCurves2)/sizeof(ecCurves2[0]);
uint16_t ecCurves3[] = {
tls_curve_sect193r1
};
static int n_ecCurves3 = sizeof(ecCurves3)/sizeof(ecCurves3[0]);
static void ec_curves_tests(const uint16_t *clientCurves, int clientCurvesCount, int negotiated_ec_curve)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_ecdsa_cert;
test.server_key = g_server_ecdsa_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.server_ec_curves = serverCurves;
test.num_server_ec_curves = serverCurvesCount;
test.client_ec_curves = clientCurves;
test.num_client_ec_curves = clientCurvesCount;
if (negotiated_ec_curve == tls_curve_none) {
test.handshake_ok = false;
} else {
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.certificate_requested = 0;
test.negotiated_ec_curve = negotiated_ec_curve;
}
test_log_start();
test_printf("Test case: negotiated ec curves \n");
err = test_one_case(&test);
ok(!err, "Test case: negotiated ec curves");
test_log_end(err);
}
static void ciphersuite_key_mismatch_test(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_ecdsa_cert;
test.server_key = g_server_ecdsa_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.handshake_ok = false;
test_log_start();
test_printf("Test case: ciphersuite_key_mismatch_test\n");
err = test_one_case(&test);
ok(!err, "Test case: ciphersuite_key_mismatch_test");
test_log_end(err);
}
static tls_signature_and_hash_algorithm sigAlgs[] = {
{tls_hash_algorithm_SHA1, tls_signature_algorithm_RSA},
{tls_hash_algorithm_SHA256, tls_signature_algorithm_RSA},
{tls_hash_algorithm_SHA384, tls_signature_algorithm_RSA},
{tls_hash_algorithm_SHA512, tls_signature_algorithm_RSA},
{tls_hash_algorithm_SHA1, tls_signature_algorithm_ECDSA},
{tls_hash_algorithm_SHA256, tls_signature_algorithm_ECDSA},
{tls_hash_algorithm_SHA384, tls_signature_algorithm_ECDSA},
{tls_hash_algorithm_SHA512, tls_signature_algorithm_ECDSA},
};
static int n_sigAlgs = sizeof(sigAlgs)/sizeof(sigAlgs[0]);
static void sigalgs_tests(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher;
for(int i=0;i<n_sigAlgs;i++)
{
switch(sigAlgs[i].signature) {
case tls_signature_algorithm_RSA:
cipher = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
break;
case tls_signature_algorithm_ECDSA:
cipher = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
test.server_certs = &g_server_ecdsa_cert;
test.server_key = g_server_ecdsa_key;
test.client_certs = &g_server_ecdsa_cert;
test.client_key = g_server_ecdsa_key;
break;
default:
assert(0);
break;
}
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_sigalgs = &sigAlgs[i];
test.num_server_sigalgs = 1;
test.client_sigalgs = &sigAlgs[i];
test.num_client_sigalgs = 1;
test.request_client_auth = true;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.certificate_requested = 1;
test_log_start();
test_printf("Test case: sigalgs (%d)\n", i);
err = test_one_case(&test);
ok(!err, "Test case: siglags (%d)", i);
test_log_end(err);
}
}
static void fallback_tests(void)
{
tls_test_case test = {0,};
int err;
uint16_t cipher = SSL_RSA_WITH_RC4_128_SHA;
for(int i=0;i<nprotos-1;i++)
for(int j=0;j<nprotos-1;j++) {
test.client_protocol_min = tls_protocol_version_SSL_3;
test.client_protocol_max = protos[i];
test.server_protocol_min = tls_protocol_version_SSL_3;
test.server_protocol_max = protos[j];
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.fallback = true;
if(test.client_protocol_max < test.server_protocol_max) {
test.handshake_ok = false;
} else {
test.handshake_ok = true;
}
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = SSL_RSA_WITH_RC4_128_SHA;
test_log_start();
test_printf("Test case: fallback (%d, %d)\n", i, j);
err = test_one_case(&test);
ok(!err, "Test case: fallback (%d, %d)", i, j);
test_log_end(err);
}
}
static void extended_master_secret_tests(void)
{
tls_test_case test = {0,};
int err;
int i, j;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
for (i = 0; i < 4; i++) {
for(j=1; j<nprotos; j++) {
test.client_protocol_min = protos[j];
test.client_protocol_max = protos[j];
test.server_protocol_min = protos[j];
test.server_protocol_max = protos[j];
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = true;
test.session_id = 0;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
test.client_extMS_enable = i&0x1;
test.server_extMS_enable = i&0x2;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false;
test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
test.negotiated_version = protos[j];
test_log_start();
test_printf("Test case extended master secret %d (%04x)\n", i, j );
err = test_one_case(&test);
ok(!err, "Test case extended master secret %d (%04x)- err=%d", i, j, err);
test_log_end(err);
}
}
}
static void extended_master_secret_resumption_tests(void)
{
tls_test_case test = {0,};
int err;
int i;
uint16_t cipher = TLS_RSA_WITH_AES_128_CBC_SHA;
test.client_protocol_min = tls_protocol_version_TLS_1_2;
test.client_protocol_max = tls_protocol_version_TLS_1_2;
test.server_protocol_min = tls_protocol_version_TLS_1_2;
test.server_protocol_max = tls_protocol_version_TLS_1_2;
test.ciphersuites = &cipher;
test.num_ciphersuites = 1;
test.allow_resumption = true;
test.server_certs = &g_server_cert;
test.server_key = g_server_key;
test.client_certs = &g_client_cert;
test.client_key = g_client_key;
for (i = 0; i < 2; i++) {
test.session_id = (cipher<<8 | i) + 1;
test.server_extMS_enable = true;
test.client_extMS_enable = i;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false; test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
if (test.client_extMS_enable)
test.is_session_resumption_proposed = false;
else
test.is_session_resumption_proposed = false;
test_log_start();
test_printf("Extended master secret Resumption - 1st connection client: %d server: 1\n", i);
err = test_one_case(&test);
ok(!err, "Extended master secret Resumption - 1st connection client: %d server: 1 - err=%d", i, err);
test_log_end(err);
test.is_session_resumed = false; test.client_extMS_enable = !i;
if (test.client_extMS_enable) {
test.handshake_ok = true;
test.is_session_resumption_proposed = true;
} else {
test.handshake_ok = false;
test.is_session_resumption_proposed = false;
}
test_log_start();
test_printf("Extended master secret Resumption - 2nd connection client: %d server: 1\n", !i);
err = test_one_case(&test);
ok(!err, "Extended master secret Resumption - 2nd connection client: %d server: 1 - err=%d", !i, err);
test_log_end(err);
}
for (i = 0; i < 2; i++) {
test.session_id = i+1;
test.client_extMS_enable = true;
test.server_extMS_enable = i;
test.handshake_ok = true;
test.client_err = 0;
test.server_err = 0;
test.is_session_resumed = false; test.certificate_requested = 0;
test.negotiated_ciphersuite = cipher;
if (test.server_extMS_enable)
test.is_session_resumption_proposed = false;
else
test.is_session_resumption_proposed = false;
test_log_start();
test_printf("Extended master secret Resumption - 1st connection client: 1 server: %d\n", i);
err = test_one_case(&test);
ok(!err, "Extended master secret Resumption - 1st connection client: 1 server: %d - err=%d", i, err);
test_log_end(err);
test.is_session_resumed = false; test.server_extMS_enable = !i;
if (test.server_extMS_enable) {
test.handshake_ok = true;
test.is_session_resumption_proposed = true;
} else {
test.handshake_ok = false;
test.is_session_resumption_proposed = false;
}
test_log_start();
test_printf("Extended master secret Resumption - 2nd connection client: 1 server: %d\n", !i);
err = test_one_case(&test);
ok(!err, "Extended master secret Resumption - 2nd connection client: 1 server: %d - err=%d", !i, err);
test_log_end(err);
}
}
int tls_02_self(int argc, char * const argv[])
{
plan_tests(5 + n_ssl_ciphers*nprotos*2 + n_anon_ciphers*nprotos + n_psk_ciphers*(nprotos-1) + n_gcm_ciphers*(nprotos-3)*2 + n_ecdhe_ciphers*(nprotos-1)*2 + n_ecanon_ciphers*(nprotos-1) + n_ssl_ciphers*nprotos*2 + n_anon_ciphers*nprotos*2 + n_psk_ciphers*(nprotos-1)*2 + n_gcm_ciphers*(nprotos-3)*2 + n_ecdhe_ciphers*(nprotos-1)*2 + n_ecanon_ciphers*(nprotos-1)*2 + 4 + 8 + ntrust_values*3 + nmessages*2 + 4 + 1 + 1 + 8 + 8 + nprotos*nprotos*nprotos*nprotos + 7 + 1 + 4 + 1 + 1 + sizeof(client_hello_hostname)-1 + 1 + 4 + 20 + 12 + 3 + 1 + n_sigAlgs + (nprotos-1)*(nprotos-1) + 4*(nprotos-1) + 8
);
int err;
err = init_server_keys(false,
Server1_Cert_rsa_rsa_der, Server1_Cert_rsa_rsa_der_len,
Server1_Key_rsa_der, Server1_Key_rsa_der_len,
&g_server_cert, &g_server_key);
ok(!err, "init server keys()");
if(err) return 0;
err = init_server_keys(false,
Server2_Cert_rsa_rsa_der, Server2_Cert_rsa_rsa_der_len,
Server2_Key_rsa_der, Server2_Key_rsa_der_len,
&g_client_cert, &g_client_key);
ok(!err, "init client keys()");
if(err) return 0;
err = init_server_keys(false,
server_D_cert_data, sizeof(server_D_cert_data),
server_D_key_data, sizeof(server_D_key_data),
&g_server_D_cert, &g_server_D_key);
ok(!err, "init server D keys()");
if(err) return 0;
err = init_server_keys(true,
eccert_der, eccert_der_len,
eckey_der, eckey_der_len,
&g_server_ecdsa_cert, &g_server_ecdsa_key);
ok(!err, "init server ECDSA keys()");
if(err) return 0;
g_cache = tls_cache_create();
ok(g_cache, "init session cache");
if(!g_cache) return 0;
good_tests(ssl_ciphers, n_ssl_ciphers, 0, false);
good_tests(ssl_ciphers, n_ssl_ciphers, 0, true);
good_tests(anon_ciphers, n_anon_ciphers, 0, false);
good_tests(psk_ciphers, n_psk_ciphers, 1, false);
good_tests(gcm_ciphers, n_gcm_ciphers, 3, false);
good_tests(gcm_ciphers, n_gcm_ciphers, 3, true);
good_tests(ecdhe_ciphers, n_ecdhe_ciphers, 1, false);
good_tests(ecdhe_ciphers, n_ecdhe_ciphers, 1, true);
good_tests(ecanon_ciphers, n_ecanon_ciphers, 1, false);
resumption_tests(ssl_ciphers, n_ssl_ciphers, 0);
resumption_tests(anon_ciphers, n_anon_ciphers, 0);
resumption_tests(psk_ciphers, n_psk_ciphers, 1);
resumption_tests(gcm_ciphers, n_gcm_ciphers, 3);
resumption_tests(ecdhe_ciphers, n_ecdhe_ciphers, 1);
resumption_tests(ecanon_ciphers, n_ecanon_ciphers, 1);
ciphersuites_tests();
renegotiation_tests();
trust_tests();
client_auth_trust_tests();
corrupted_message_len_tests();
corrupted_cert_len_tests();
goto_fail_test();
cert_mismatch_test();
ocsp_tests();
sct_tests();
negotiated_version_tests();
version_tolerance_tests();
dtls_tests();
dtls_version_tolerance_tests();
server_rsa_key_exchange_tests();
zero_padding_tests();
client_hello_size_test();
forget_pubkey_test();
resumption_mismatch_tests();
min_dh_size_test();
config_tests();
ec_curves_tests(ecCurves1, n_ecCurves1, tls_curve_secp256r1);
ec_curves_tests(ecCurves2, n_ecCurves2, tls_curve_secp384r1);
ec_curves_tests(ecCurves3, n_ecCurves3, tls_curve_none);
ciphersuite_key_mismatch_test();
sigalgs_tests();
fallback_tests();
extended_master_secret_tests();
extended_master_secret_resumption_tests();
clean_server_keys(g_server_key);
clean_server_keys(g_client_key);
clean_server_keys(g_server_D_key);
clean_server_keys(g_server_ecdsa_key);
tls_cache_destroy(g_cache);
return 0;
}