From 591e1fc772860b60aba0538077627d8a5879e442 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 6 Mar 2013 23:02:33 -0800 Subject: [PATCH] DTLSv1.2, fixed DTLS socket timeout --- cyassl/internal.h | 2 ++ cyassl/openssl/ssl.h | 2 ++ cyassl/ssl.h | 2 ++ src/internal.c | 22 +++++++++++++--- src/io.c | 14 ++-------- src/ssl.c | 62 ++++++++++++++++++++++++++++++++++++-------- 6 files changed, 77 insertions(+), 27 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index bc0e0ecc1..af9005ff7 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -452,6 +452,7 @@ enum Misc { DTLS_MAJOR = 0xfe, /* DTLS major version number */ DTLS_MINOR = 0xff, /* DTLS minor version number */ + DTLSv1_2_MINOR = 0xfd, /* DTLS minor version number */ SSLv3_MAJOR = 3, /* SSLv3 and TLSv1+ major version number */ SSLv3_MINOR = 0, /* TLSv1 minor version number */ TLSv1_MINOR = 1, /* TLSv1 minor version number */ @@ -655,6 +656,7 @@ CYASSL_LOCAL ProtocolVersion MakeTLSv1_2(void); #ifdef CYASSL_DTLS CYASSL_LOCAL ProtocolVersion MakeDTLSv1(void); + CYASSL_LOCAL ProtocolVersion MakeDTLSv1_2(void); #endif diff --git a/cyassl/openssl/ssl.h b/cyassl/openssl/ssl.h index b5070d18f..840954f00 100644 --- a/cyassl/openssl/ssl.h +++ b/cyassl/openssl/ssl.h @@ -92,6 +92,8 @@ typedef CYASSL_X509_STORE_CTX X509_STORE_CTX; #ifdef CYASSL_DTLS #define DTLSv1_client_method CyaDTLSv1_client_method #define DTLSv1_server_method CyaDTLSv1_server_method + #define DTLSv1_2_client_method CyaDTLSv1_2_client_method + #define DTLSv1_2_server_method CyaDTLSv1_2_server_method #endif diff --git a/cyassl/ssl.h b/cyassl/ssl.h index f9876fb23..f30dc7af8 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -149,6 +149,8 @@ CYASSL_API CYASSL_METHOD *CyaTLSv1_2_client_method(void); #ifdef CYASSL_DTLS CYASSL_API CYASSL_METHOD *CyaDTLSv1_client_method(void); CYASSL_API CYASSL_METHOD *CyaDTLSv1_server_method(void); + CYASSL_API CYASSL_METHOD *CyaDTLSv1_2_client_method(void); + CYASSL_API CYASSL_METHOD *CyaDTLSv1_2_server_method(void); #endif #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) diff --git a/src/internal.c b/src/internal.c index b58dee1c0..60ef85b85 100644 --- a/src/internal.c +++ b/src/internal.c @@ -123,6 +123,8 @@ int IsAtLeastTLSv1_2(const CYASSL* ssl) { if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR) return 1; + if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR) + return 1; return 0; } @@ -357,7 +359,7 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method) ctx->CBIOSend = EmbedSend; #ifdef CYASSL_DTLS if (method->version.major == DTLS_MAJOR - && method->version.minor == DTLS_MINOR) { + && method->version.minor >= DTLSv1_2_MINOR) { ctx->CBIORecv = EmbedReceiveFrom; ctx->CBIOSend = EmbedSendTo; } @@ -591,8 +593,10 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveRSA, byte havePSK, } #ifdef CYASSL_DTLS - if (pv.major == DTLS_MAJOR && pv.minor == DTLS_MINOR) - tls = 1; + if (pv.major == DTLS_MAJOR) { + tls = 1; + tls1_2 = pv.minor <= DTLSv1_2_MINOR; + } #endif #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA @@ -1299,7 +1303,8 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->heap = ctx->heap; /* defaults to self */ ssl->options.tls = 0; ssl->options.tls1_1 = 0; - if (ssl->version.major == DTLS_MAJOR && ssl->version.minor == DTLS_MINOR) + if (ssl->version.major == DTLS_MAJOR + && ssl->version.minor >= DTLSv1_2_MINOR) ssl->options.dtls = 1; else ssl->options.dtls = 0; @@ -1951,6 +1956,15 @@ ProtocolVersion MakeDTLSv1(void) return pv; } +ProtocolVersion MakeDTLSv1_2(void) +{ + ProtocolVersion pv; + pv.major = DTLS_MAJOR; + pv.minor = DTLSv1_2_MINOR; + + return pv; +} + #endif /* CYASSL_DTLS */ diff --git a/src/io.c b/src/io.c index 624f5742c..e6ceaa19e 100644 --- a/src/io.c +++ b/src/io.c @@ -136,16 +136,6 @@ #endif -#ifdef CYASSL_DTLS - /* sizeof(struct timeval) will pass uninit bytes to setsockopt if padded */ - #ifdef USE_WINDOWS_API - #define TIMEVAL_BYTES sizeof(timeout) - #else - #define TIMEVAL_BYTES sizeof(timeout.tv_sec) + sizeof(timeout.tv_usec) - #endif -#endif - - /* Translates return codes returned from * send() and recv() if need be. */ @@ -201,7 +191,7 @@ int EmbedReceive(CYASSL *ssl, char *buf, int sz, void *ctx) struct timeval timeout = {dtls_timeout, 0}; #endif if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, - TIMEVAL_BYTES) != 0) { + sizeof(timeout)) != 0) { CYASSL_MSG("setsockopt rcvtimeo failed"); } } @@ -329,7 +319,7 @@ int EmbedReceiveFrom(CYASSL *ssl, char *buf, int sz, void *ctx) struct timeval timeout = { dtls_timeout, 0 }; #endif if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, - TIMEVAL_BYTES) != 0) { + sizeof(timeout)) != 0) { CYASSL_MSG("setsockopt rcvtimeo failed"); } } diff --git a/src/ssl.c b/src/ssl.c index f89b004d0..bd0f6fc6a 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2562,6 +2562,17 @@ int CyaSSL_dtls_got_timeout(CYASSL* ssl) InitSSL_Method(method, MakeDTLSv1()); return method; } + + CYASSL_METHOD* CyaDTLSv1_2_client_method(void) + { + CYASSL_METHOD* method = + (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + CYASSL_ENTER("DTLSv1_2_client_method"); + if (method) + InitSSL_Method(method, MakeDTLSv1_2()); + return method; + } #endif @@ -2583,7 +2594,7 @@ int CyaSSL_dtls_got_timeout(CYASSL* ssl) #ifdef CYASSL_DTLS if (ssl->version.major == DTLS_MAJOR && - ssl->version.minor == DTLS_MINOR) { + ssl->version.minor >= DTLSv1_2_MINOR) { ssl->options.dtls = 1; ssl->options.tls = 1; ssl->options.tls1_1 = 1; @@ -2656,10 +2667,14 @@ int CyaSSL_dtls_got_timeout(CYASSL* ssl) /* re-init hashes, exclude first hello and verify request */ InitMd5(&ssl->hashMd5); InitSha(&ssl->hashSha); - #ifndef NO_SHA256 - if (IsAtLeastTLSv1_2(ssl)) + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 InitSha256(&ssl->hashSha256); - #endif + #endif + #ifdef CYASSL_SHA384 + InitSha384(&ssl->hashSha384); + #endif + } if ( (ssl->error = SendClientHello(ssl)) != 0) { CYASSL_ERROR(ssl->error); return SSL_FATAL_ERROR; @@ -2799,6 +2814,19 @@ int CyaSSL_dtls_got_timeout(CYASSL* ssl) } return method; } + + CYASSL_METHOD* CyaDTLSv1_2_server_method(void) + { + CYASSL_METHOD* method = + (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + CYASSL_ENTER("DTLSv1_2_server_method"); + if (method) { + InitSSL_Method(method, MakeDTLSv1_2()); + method->side = SERVER_END; + } + return method; + } #endif @@ -2846,7 +2874,7 @@ int CyaSSL_dtls_got_timeout(CYASSL* ssl) #ifdef CYASSL_DTLS if (ssl->version.major == DTLS_MAJOR && - ssl->version.minor == DTLS_MINOR) { + ssl->version.minor >= DTLSv1_2_MINOR) { ssl->options.dtls = 1; ssl->options.tls = 1; ssl->options.tls1_1 = 1; @@ -2900,10 +2928,14 @@ int CyaSSL_dtls_got_timeout(CYASSL* ssl) /* re-init hashes, exclude first hello and verify request */ InitMd5(&ssl->hashMd5); InitSha(&ssl->hashSha); - #ifndef NO_SHA256 - if (IsAtLeastTLSv1_2(ssl)) - InitSha256(&ssl->hashSha256); - #endif + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 + InitSha256(&ssl->hashSha256); + #endif + #ifdef CYASSL_SHA384 + InitSha384(&ssl->hashSha384); + #endif + } while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) if ( (ssl->error = ProcessReply(ssl)) < 0) { @@ -5415,8 +5447,16 @@ int CyaSSL_set_compression(CYASSL* ssl) return "unknown"; } } - else if (ssl->version.major == DTLS_MAJOR) - return "DTLS"; + else if (ssl->version.major == DTLS_MAJOR) { + switch (ssl->version.minor) { + case DTLS_MINOR : + return "DTLS"; + case DTLSv1_2_MINOR : + return "DTLSv1.2"; + default: + return "unknown"; + } + } return "unknown"; }