added dtls message retry

This commit is contained in:
John Safranek 2012-09-14 09:35:34 -07:00
parent 97ca8439a4
commit 56ee2eaba8
7 changed files with 212 additions and 11 deletions

View File

@ -218,7 +218,8 @@ enum {
DYNAMIC_TYPE_ALTNAME = 29,
DYNAMIC_TYPE_SUITES = 30,
DYNAMIC_TYPE_CIPHER = 31,
DYNAMIC_TYPE_RNG = 32
DYNAMIC_TYPE_RNG = 32,
DYNAMIC_TYPE_DTLS_POOL = 33
};
/* stack protection */

View File

@ -398,6 +398,7 @@ enum Misc {
DTLS_RECORD_EXTRA = 8, /* diff from normal */
DTLS_HANDSHAKE_SEQ_SZ = 2, /* handshake header sequence number */
DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */
DTLS_POOL_SZ = 5, /* buffers to hold in the retry pool */
FINISHED_LABEL_SZ = 15, /* TLS finished label size */
TLS_FINISHED_SZ = 12, /* TLS has a shorter size */
@ -445,6 +446,7 @@ enum Misc {
CLIENT_HELLO_FIRST = 35, /* Protocol + RAN_LEN + sizeof(id_len) */
MAX_SUITE_NAME = 48, /* maximum length of cipher suite string */
DEFAULT_TIMEOUT = 500, /* default resumption timeout in seconds */
DTLS_DEFAULT_TIMEOUT = 1, /* default timeout for DTLS receive */
MAX_PSK_ID_LEN = 128, /* max psk identity/hint supported */
MAX_PSK_KEY_LEN = 64, /* max psk key supported */
@ -1210,6 +1212,13 @@ typedef struct DtlsRecordLayerHeader {
} DtlsRecordLayerHeader;
typedef struct DtlsPool {
buffer buf[DTLS_POOL_SZ];
int used;
byte pool[MAX_MTU*DTLS_POOL_SZ];
} DtlsPool;
/* CyaSSL ssl type */
struct CYASSL {
CYASSL_CTX* ctx;
@ -1274,6 +1283,7 @@ struct CYASSL {
#endif
#ifdef CYASSL_DTLS
int dtls_timeout;
DtlsPool* dtls_pool;
#endif
#ifdef CYASSL_CALLBACKS
HandShakeInfo handShakeInfo; /* info saved during handshake */
@ -1479,6 +1489,12 @@ CYASSL_LOCAL void BuildTlsFinished(CYASSL* ssl, Hashes* hashes,
#endif
#endif /* NO_CYASSL_SERVER */
#ifdef CYASSL_DTLS
CYASSL_LOCAL int DtlsPoolInit(CYASSL*);
CYASSL_LOCAL void DtlsPoolSave(CYASSL*, const byte*, int);
CYASSL_LOCAL int DtlsPoolSend(CYASSL*);
CYASSL_LOCAL void DtlsPoolReset(CYASSL*);
#endif /* CYASSL_DTLS */
#ifndef NO_TLS

View File

@ -216,6 +216,10 @@ CYASSL_API long CyaSSL_CTX_set_session_cache_mode(CYASSL_CTX*, long);
CYASSL_API int CyaSSL_CTX_set_cipher_list(CYASSL_CTX*, const char*);
CYASSL_API int CyaSSL_set_cipher_list(CYASSL*, const char*);
/* Nonblocking DTLS helper functions */
CYASSL_API int CyaSSL_dtls_get_current_timeout(CYASSL* ssl);
CYASSL_API int CyaSSL_dtls_got_timeout(CYASSL* ssl);
CYASSL_API int CyaSSL_ERR_GET_REASON(int err);
CYASSL_API char* CyaSSL_ERR_error_string(unsigned long,char*);
CYASSL_API void CyaSSL_ERR_error_string_n(unsigned long e, char* buf,

View File

@ -292,6 +292,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#endif
#ifdef NON_BLOCKING
CyaSSL_using_nonblock(ssl);
tcp_set_nonblocking(&clientfd);
NonBlockingSSL_Accept(ssl);
#else

View File

@ -981,7 +981,8 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
ssl->keys.dtls_peer_epoch = 0;
ssl->keys.dtls_expected_peer_epoch = 0;
ssl->arrays.cookieSz = 0;
ssl->dtls_timeout = 2;
ssl->dtls_timeout = DTLS_DEFAULT_TIMEOUT;
ssl->dtls_pool = NULL;
#endif
ssl->keys.encryptionOn = 0; /* initially off */
ssl->keys.decryptedCur = 0; /* initially off */
@ -1135,6 +1136,8 @@ void SSL_ResourceFree(CYASSL* ssl)
#ifdef CYASSL_DTLS
if (ssl->buffers.dtlsHandshake.buffer != NULL)
XFREE(ssl->buffers.dtlsHandshake.buffer, ssl->heap, DYNAMIC_TYPE_NONE);
if (ssl->dtls_pool != NULL)
XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_NONE);
#endif
#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
XFREE(ssl->peerCert.derCert.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
@ -1172,6 +1175,14 @@ void FreeHandshakeResources(CYASSL* ssl)
XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
ssl->rng = NULL;
}
#ifdef CYASSL_DTLS
/* DTLS_POOL */
if (ssl->options.dtls && ssl->dtls_pool != NULL) {
XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
ssl->dtls_pool = NULL;
}
#endif
}
@ -1183,6 +1194,87 @@ void FreeSSL(CYASSL* ssl)
}
#ifdef CYASSL_DTLS
int DtlsPoolInit(CYASSL* ssl)
{
if (ssl->dtls_pool == NULL) {
DtlsPool *pool = (DtlsPool*)XMALLOC(sizeof(DtlsPool),
ssl->heap, DYNAMIC_TYPE_DTLS_POOL);
if (pool == NULL) {
CYASSL_MSG("DTLS Buffer Pool Memory error");
return MEMORY_E;
}
else {
int i;
for (i = 0; i < DTLS_POOL_SZ; i++) {
pool->buf[i].length = 0;
pool->buf[i].buffer = pool->pool + (MAX_MTU * i);
}
pool->used = 0;
ssl->dtls_pool = pool;
}
}
return 0;
}
void DtlsPoolSave(CYASSL* ssl, const byte *src, int sz)
{
DtlsPool *pool = ssl->dtls_pool;
if (pool != NULL && pool->used < DTLS_POOL_SZ) {
buffer *buf = &pool->buf[pool->used];
XMEMCPY(buf->buffer, src, sz);
buf->length = (word32)sz;
pool->used++;
}
}
void DtlsPoolReset(CYASSL* ssl)
{
if (ssl->dtls_pool != NULL) {
ssl->dtls_pool->used = 0;
ssl->dtls_timeout = DTLS_DEFAULT_TIMEOUT;
}
}
int DtlsPoolSend(CYASSL* ssl)
{
DtlsPool *pool = ssl->dtls_pool;
if (pool != NULL && pool->used > 0) {
int i;
for (i = 0; i < pool->used; i++) {
int sendResult;
buffer* buf = &pool->buf[i];
DtlsRecordLayerHeader* dtls = (DtlsRecordLayerHeader*)buf->buffer;
if (dtls->type == change_cipher_spec) {
ssl->keys.dtls_epoch++;
ssl->keys.dtls_sequence_number = 0;
}
c16toa(ssl->keys.dtls_epoch, dtls->epoch);
c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number);
XMEMCPY(ssl->buffers.outputBuffer.buffer, buf->buffer, buf->length);
ssl->buffers.outputBuffer.idx = 0;
ssl->buffers.outputBuffer.length = buf->length;
sendResult = SendBuffered(ssl);
if (sendResult < 0) {
return sendResult;
}
}
}
return 0;
}
#endif
ProtocolVersion MakeSSLv3(void)
{
ProtocolVersion pv;
@ -1438,9 +1530,11 @@ retry:
ssl->options.isClosed = 1;
return -1;
#ifdef CYASSL_DTLS
case IO_ERR_TIMEOUT:
/* XXX More than retry. Need to resend. */
DtlsPoolSend(ssl);
goto retry;
#endif
default:
return recvd;
@ -3014,6 +3108,7 @@ int ProcessReply(CYASSL* ssl)
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolReset(ssl);
ssl->keys.dtls_expected_peer_epoch++;
ssl->keys.dtls_expected_peer_sequence_number = 0;
}
@ -3120,6 +3215,11 @@ int SendChangeCipher(CYASSL* ssl)
output[idx] = 1; /* turn it on */
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, sendSz);
}
#endif
#ifdef CYASSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("ChangeCipher", &ssl->handShakeInfo);
if (ssl->toInfoOn)
@ -3318,8 +3418,14 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz,
XMEMCPY(output + idx, input, inSz);
idx += inSz;
if (type == handshake)
if (type == handshake) {
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, headerSz+inSz);
}
#endif
HashOutput(ssl, output, headerSz + inSz, ivSz);
}
if (ssl->specs.cipher_type != aead) {
ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0);
idx += digestSz;
@ -3389,6 +3495,11 @@ int SendFinished(CYASSL* ssl)
else
BuildFinished(ssl, &ssl->verifyHashes, client);
}
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, sendSz);
}
#endif
#ifdef CYASSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
@ -3467,6 +3578,11 @@ int SendCertificate(CYASSL* ssl)
i += ssl->buffers.certChain.length; */
}
}
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, sendSz);
}
#endif
HashOutput(ssl, output, sendSz, 0);
#ifdef CYASSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
@ -3536,6 +3652,11 @@ int SendCertificateRequest(CYASSL* ssl)
/* if add more to output, adjust i
i += REQ_HEADER_SZ; */
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, sendSz);
}
#endif
HashOutput(ssl, output, sendSz, 0);
#ifdef CYASSL_CALLBACKS
@ -4797,6 +4918,11 @@ int SetCipherList(Suites* s, const char* list)
output[idx++] = ecc_dsa_sa_algo;
}
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, sendSz);
}
#endif
HashOutput(ssl, output, sendSz, 0);
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
@ -4824,6 +4950,11 @@ int SetCipherList(Suites* s, const char* list)
if (ssl->hsInfoOn) AddPacketName("HelloVerifyRequest",
&ssl->handShakeInfo);
if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
#endif
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolReset(ssl);
}
#endif
XMEMCPY(&pv, input + *inOutIdx, sizeof(pv));
*inOutIdx += sizeof(pv);
@ -4937,7 +5068,11 @@ int SetCipherList(Suites* s, const char* list)
ssl->options.resuming = 0; /* server denied resumption try */
}
}
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolReset(ssl);
}
#endif
return SetCipherSpecs(ssl);
}
@ -5391,7 +5526,11 @@ int SetCipherList(Suites* s, const char* list)
XMEMCPY(output + idx, encSecret, encSz);
/* if add more to output, adjust idx
idx += encSz; */
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, sendSz);
}
#endif
HashOutput(ssl, output, sendSz, 0);
#ifdef CYASSL_CALLBACKS
@ -5527,8 +5666,10 @@ int SetCipherList(Suites* s, const char* list)
sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length +
extraSz + VERIFY_HEADER;
#ifdef CYASSL_DTLS
if (ssl->options.dtls)
if (ssl->options.dtls) {
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
DtlsPoolSave(ssl, output, sendSz);
}
#endif
HashOutput(ssl, output, sendSz, 0);
}
@ -5631,6 +5772,11 @@ int SetCipherList(Suites* s, const char* list)
output[idx++] = NO_COMPRESSION;
ssl->buffers.outputBuffer.length += sendSz;
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, sendSz);
}
#endif
HashOutput(ssl, output, sendSz, 0);
#ifdef CYASSL_CALLBACKS
@ -6091,6 +6237,11 @@ int SetCipherList(Suites* s, const char* list)
}
}
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, sendSz);
}
#endif
HashOutput(ssl, output, sendSz, 0);
#ifdef CYASSL_CALLBACKS
@ -6943,6 +7094,11 @@ int SetCipherList(Suites* s, const char* list)
AddHeaders(output, 0, server_hello_done, ssl);
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
DtlsPoolSave(ssl, output, sendSz);
}
#endif
HashOutput(ssl, output, sendSz, 0);
#ifdef CYASSL_CALLBACKS
if (ssl->hsInfoOn)

View File

@ -143,7 +143,7 @@ int EmbedReceive(CYASSL *ssl, char *buf, int sz, void *ctx)
#ifdef CYASSL_DTLS
if (ssl->options.dtls
&& !ssl->options.usingNonblock && ssl->dtls_timeout != 0) {
#if USE_WINDOWS_API
#ifdef USE_WINDOWS_API
DWORD timeout = ssl->dtls_timeout;
#else
struct timeval timeout = {ssl->dtls_timeout, 0};

View File

@ -2219,19 +2219,30 @@ int CyaSSL_dtls_get_current_timeout(CYASSL* ssl)
#ifdef CYASSL_DTLS
return ssl->dtls_timeout;
#else
return 0;
return SSL_NOT_IMPLEMENTED;
#endif
}
void CyaSSL_dtls_got_timeout(CYASSL* ssl)
int CyaSSL_dtls_got_timeout(CYASSL* ssl)
{
int result = SSL_NOT_IMPLEMENTED;
(void)ssl;
#ifdef CYASSL_DTLS
if (ssl->dtls_timeout < 64)
if (ssl->dtls_timeout < 64) {
ssl->dtls_timeout *= 2;
if (DtlsPoolSend(ssl) < 0)
result = SSL_FATAL_ERROR;
else
result = SSL_SUCCESS;
}
else {
result = SSL_FATAL_ERROR;
}
#endif
return result;
}
@ -2285,6 +2296,12 @@ void CyaSSL_dtls_got_timeout(CYASSL* ssl)
ssl->options.dtls = 1;
ssl->options.tls = 1;
ssl->options.tls1_1 = 1;
if (DtlsPoolInit(ssl) != 0) {
ssl->error = MEMORY_ERROR;
CYASSL_ERROR(ssl->error);
return SSL_FATAL_ERROR;
}
}
#endif
@ -2535,6 +2552,12 @@ void CyaSSL_dtls_got_timeout(CYASSL* ssl)
ssl->options.dtls = 1;
ssl->options.tls = 1;
ssl->options.tls1_1 = 1;
if (DtlsPoolInit(ssl) != 0) {
ssl->error = MEMORY_ERROR;
CYASSL_ERROR(ssl->error);
return SSL_FATAL_ERROR;
}
}
#endif