From 55401c13dd58e904558cd8db6230faab86d30d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s=20Guimar=C3=A3es?= Date: Tue, 23 Jul 2013 15:42:43 -0300 Subject: [PATCH] Truncated HMAC first part (protocol). Extension processing will be coded later. --- configure.ac | 15 +++++++++ cyassl/internal.h | 19 ++++++++---- cyassl/ssl.h | 9 ++++++ examples/client/client.c | 44 ++++++++++++++++++++++++++- src/internal.c | 3 ++ src/ssl.c | 20 ++++++++++++ src/tls.c | 66 ++++++++++++++++++++++++++++++++++++++++ tests/api.c | 32 ++++++++++++++++--- 8 files changed, 197 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index a6c720afb..95088eed2 100644 --- a/configure.ac +++ b/configure.ac @@ -1085,6 +1085,18 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_MAX_FRAGMENT" fi +# Truncated HMAC +AC_ARG_ENABLE([truncatedhmac], + [ --enable-truncatedhmac Enable Truncated HMAC (default: disabled)], + [ ENABLED_TRUNCATED_HMAC=$enableval ], + [ ENABLED_TRUNCATED_HMAC=no ] + ) + +if test "x$ENABLED_TRUNCATED_HMAC" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_TRUNCATED_HMAC" +fi + # TLS Extensions AC_ARG_ENABLE([tlsx], [ --enable-tlsx Enable all TLS Extensions (default: disabled)], @@ -1094,6 +1106,8 @@ AC_ARG_ENABLE([tlsx], if test "x$ENABLED_TLSX" = "xyes" then + ENABLED_SNI=yes + ENABLED_MAX_FRAGMENT=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT" fi @@ -1473,6 +1487,7 @@ echo " * Persistent cert cache: $ENABLED_SAVECERT" echo " * NTRU: $ENABLED_NTRU" echo " * SNI: $ENABLED_SNI" echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" +echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" echo " * All TLS Extensions: $ENABLED_TLSX" echo " * valgrind unit tests: $ENABLED_VALGRIND" echo " * LIBZ: $ENABLED_LIBZ" diff --git a/cyassl/internal.h b/cyassl/internal.h index 4a5132c84..1341ae416 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1122,16 +1122,12 @@ typedef struct CYASSL_DTLS_CTX { #ifdef HAVE_TLS_EXTENSIONS typedef enum { -#ifdef HAVE_SNI SERVER_NAME_INDICATION = 0, -#endif -#ifdef HAVE_MAX_FRAGMENT MAX_FRAGMENT_LENGTH = 1, -#endif /*CLIENT_CERTIFICATE_URL = 2, - TRUSTED_CA_KEYS = 3, + TRUSTED_CA_KEYS = 3,*/ TRUNCATED_HMAC = 4, - STATUS_REQUEST = 5, + /*STATUS_REQUEST = 5, SIGNATURE_ALGORITHMS = 13,*/ } TLSX_Type; @@ -1191,6 +1187,14 @@ CYASSL_LOCAL int TLSX_UseMaxFragment(TLSX** extensions, byte mfl); #endif /* HAVE_MAX_FRAGMENT */ +#ifdef HAVE_TRUNCATED_HMAC + +#define TRUNCATED_HMAC_SIZE 10 + +CYASSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions); + +#endif /* HAVE_TRUNCATED_HMAC */ + #endif /* HAVE_TLS_EXTENSIONS */ /* CyaSSL context type */ @@ -1813,6 +1817,9 @@ struct CYASSL { #ifdef HAVE_MAX_FRAGMENT word16 max_fragment; #endif +#ifdef HAVE_TRUNCATED_HMAC + byte truncated_hmac; +#endif #endif #ifdef HAVE_NETX NetX_Ctx nxCtx; /* NetX IO Context */ diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 88b6687ef..3a04211cb 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -1025,6 +1025,15 @@ CYASSL_API int CyaSSL_CTX_UseMaxFragment(CYASSL_CTX* ctx, unsigned char mfl); #endif /* NO_CYASSL_CLIENT */ #endif /* HAVE_MAX_FRAGMENT */ +#ifdef HAVE_TRUNCATED_HMAC +#ifndef NO_CYASSL_CLIENT + +CYASSL_API int CyaSSL_UseTruncatedHMAC(CYASSL* ssl); +CYASSL_API int CyaSSL_CTX_UseTruncatedHMAC(CYASSL_CTX* ctx); + +#endif /* NO_CYASSL_CLIENT */ +#endif /* HAVE_TRUNCATED_HMAC */ + #define CYASSL_CRL_MONITOR 0x01 /* monitor this dir flag */ #define CYASSL_CRL_START_MON 0x02 /* start monitoring flag */ diff --git a/examples/client/client.c b/examples/client/client.c index 632d872f8..cfc04d643 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -130,7 +130,15 @@ static void Usage(void) #ifdef SHOW_SIZES printf("-z Print structure sizes\n"); #endif +#ifdef HAVE_SNI printf("-S Use Host Name Indication\n"); +#endif +#ifdef HAVE_MAXFRAGMENT + printf("-L Use Maximum Fragment Length [1-5]\n"); +#endif +#ifdef HAVE_TRUNCATED_HMAC + printf("-T Use Truncated HMAC\n"); +#endif #ifdef HAVE_OCSP printf("-o Perform OCSP lookup on peer certificate\n"); printf("-O Perform OCSP lookup using as responder\n"); @@ -189,6 +197,13 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args) #ifdef HAVE_SNI char* sniHostName = NULL; #endif +#ifdef HAVE_MAX_FRAGMENT + byte maxFragment = 0; +#endif +#ifdef HAVE_TRUNCATED_HMAC + byte truncatedHMAC = 0; +#endif + #ifdef HAVE_OCSP int useOcsp = 0; @@ -213,7 +228,7 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args) StackTrap(); while ((ch = mygetopt(argc, argv, - "?gdusmNrtfxh:p:v:l:A:c:k:b:zS:oO:")) != -1) { + "?gdusmNrtfxh:p:v:l:A:c:k:b:zS:L:ToO:")) != -1) { switch (ch) { case '?' : Usage(); @@ -318,6 +333,23 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args) #endif break; + case 'L' : + #ifdef HAVE_MAX_FRAGMENT + maxFragment = atoi(myoptarg); + if (maxFragment < CYASSL_MFL_2_9 || + maxFragment > CYASSL_MFL_2_13) { + Usage(); + exit(MY_EX_USAGE); + } + #endif + break; + + case 'T' : + #ifdef HAVE_TRUNCATED_HMAC + truncatedHMAC = 1; + #endif + break; + case 'o' : #ifdef HAVE_OCSP useOcsp = 1; @@ -499,6 +531,16 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args) if (CyaSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName))) err_sys("UseSNI failed"); #endif +#ifdef HAVE_MAX_FRAGMENT + if (maxFragment) + if (CyaSSL_CTX_UseMaxFragment(ctx, maxFragment)) + err_sys("UseMaxFragment failed"); +#endif +#ifdef HAVE_TRUNCATED_HMAC + if (truncatedHMAC) + if (CyaSSL_CTX_UseTruncatedHMAC(ctx)) + err_sys("UseTruncatedHMAC failed"); +#endif if (benchmark) { /* time passed in number of connects give average */ diff --git a/src/internal.c b/src/internal.c index 59b3cb009..c2e48783c 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1459,6 +1459,9 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) #ifdef HAVE_MAX_FRAGMENT ssl->max_fragment = MAX_RECORD_SIZE; #endif +#ifdef HAVE_TRUNCATED_HMAC + ssl->truncated_hmac = 0; +#endif #endif ssl->rng = NULL; diff --git a/src/ssl.c b/src/ssl.c index 9a23cb051..0a1b2a06b 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -587,6 +587,26 @@ int CyaSSL_CTX_UseMaxFragment(CYASSL_CTX* ctx, byte mfl) #endif /* NO_CYASSL_CLIENT */ #endif /* HAVE_MAX_FRAGMENT */ +#ifdef HAVE_TRUNCATED_HMAC +#ifndef NO_CYASSL_CLIENT +int CyaSSL_UseTruncatedHMAC(CYASSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseTruncatedHMAC(&ssl->extensions); +} + +int CyaSSL_CTX_UseTruncatedHMAC(CYASSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseTruncatedHMAC(&ctx->extensions); +} +#endif /* NO_CYASSL_CLIENT */ +#endif /* HAVE_TRUNCATED_HMAC */ + #ifndef CYASSL_LEANPSK int CyaSSL_send(CYASSL* ssl, const void* data, int sz, int flags) { diff --git a/src/tls.c b/src/tls.c index cc8e51069..dedc0569e 100644 --- a/src/tls.c +++ b/src/tls.c @@ -955,6 +955,54 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl) #endif /* HAVE_MAX_FRAGMENT */ +#ifdef HAVE_TRUNCATED_HMAC + +int TLSX_UseTruncatedHMAC(TLSX** extensions) +{ + int ret = 0; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + if (!TLSX_Find(*extensions, TRUNCATED_HMAC)) + if ((ret = TLSX_Append(extensions, TRUNCATED_HMAC)) != 0) + return ret; + + return 0; +} + +static int TLSX_THM_Parse(CYASSL* ssl, byte* input, word16 length, + byte isRequest) +{ + if (length != 0 || input == NULL) + return INCOMPLETE_DATA; + +#ifndef NO_CYASSL_SERVER + if (isRequest) { + int r = TLSX_UseTruncatedHMAC(&ssl->extensions); + + if (r) return r; /* throw error */ + + TLSX_SetResponse(ssl, TRUNCATED_HMAC); + } +#endif + + ssl->truncated_hmac = 1; + +#error "TRUNCATED HMAC IS NOT FINISHED YET \ +(contact moises@wolfssl.com for more info)" + + return 0; +} + +#define THM_PARSE TLSX_THM_Parse + +#else + +#define THM_PARSE(a, b, c, d) 0 + +#endif /* HAVE_TRUNCATED_HMAC */ + TLSX* TLSX_Find(TLSX* list, TLSX_Type type) { TLSX* extension = list; @@ -980,6 +1028,10 @@ void TLSX_FreeAll(TLSX* list) case MAX_FRAGMENT_LENGTH: MFL_FREE_ALL(extension->data); break; + + case TRUNCATED_HMAC: + // Nothing to do. + break; } XFREE(extension, 0, DYNAMIC_TYPE_TLSX); @@ -1015,6 +1067,10 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) case MAX_FRAGMENT_LENGTH: length += MFL_GET_SIZE(extension->data); break; + + case TRUNCATED_HMAC: + // empty extension. + break; } TURN_ON(semaphore, extension->type); @@ -1055,6 +1111,10 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, offset += MFL_WRITE((byte *) extension->data, output + offset); break; + + case TRUNCATED_HMAC: + // empty extension. + break; } /* writing extension data length */ @@ -1215,6 +1275,12 @@ int TLSX_Parse(CYASSL* ssl, byte* input, word16 length, byte isRequest, ret = MFL_PARSE(ssl, input + offset, size, isRequest); break; + case TRUNCATED_HMAC: + CYASSL_MSG("Truncated HMAC extension received"); + + ret = THM_PARSE(ssl, input + offset, size, isRequest); + break; + case HELLO_EXT_SIG_ALGO: if (isRequest) { /* do not mess with offset inside the switch! */ diff --git a/tests/api.c b/tests/api.c index 1e3f0be95..140022461 100644 --- a/tests/api.c +++ b/tests/api.c @@ -47,14 +47,15 @@ static int test_client_CyaSSL_new(void); static int test_CyaSSL_read_write(void); #endif /* NO_RSA */ #endif /* NO_FILESYSTEM */ -#ifdef HAVE_TLS_EXTENSIONS #ifdef HAVE_SNI static void test_CyaSSL_UseSNI(void); #endif /* HAVE_SNI */ #ifdef HAVE_MAX_FRAGMENT static void test_CyaSSL_UseMaxFragment(void); #endif /* HAVE_MAX_FRAGMENT */ -#endif /* HAVE_TLS_EXTENSIONS */ +#ifdef HAVE_TRUNCATED_HMAC +static void test_CyaSSL_UseTruncatedHMAC(void); +#endif /* HAVE_TRUNCATED_HMAC */ /* test function helpers */ static int test_method(CYASSL_METHOD *method, const char *name); @@ -106,14 +107,15 @@ int ApiTest(void) test_CyaSSL_read_write(); #endif /* NO_RSA */ #endif /* NO_FILESYSTEM */ -#ifdef HAVE_TLS_EXTENSIONS #ifdef HAVE_SNI test_CyaSSL_UseSNI(); #endif /* HAVE_SNI */ #ifdef HAVE_MAX_FRAGMENT test_CyaSSL_UseMaxFragment(); #endif /* HAVE_MAX_FRAGMENT */ -#endif /* HAVE_TLS_EXTENSIONS */ +#ifdef HAVE_TRUNCATED_HMAC + test_CyaSSL_UseTruncatedHMAC(); +#endif /* HAVE_TRUNCATED_HMAC */ test_CyaSSL_Cleanup(); printf(" End API Tests\n"); @@ -425,6 +427,28 @@ static void test_CyaSSL_UseMaxFragment(void) } #endif /* HAVE_MAX_FRAGMENT */ +#ifdef HAVE_TRUNCATED_HMAC +static void test_CyaSSL_UseTruncatedHMAC(void) +{ + CYASSL_CTX *ctx = CyaSSL_CTX_new(CyaSSLv23_client_method()); + CYASSL *ssl = CyaSSL_new(ctx); + + AssertNotNull(ctx); + AssertNotNull(ssl); + + /* error cases */ + AssertIntNE(0, CyaSSL_CTX_UseTruncatedHMAC(NULL)); + AssertIntNE(0, CyaSSL_UseTruncatedHMAC(NULL)); + + /* success case */ + AssertIntEQ(0, CyaSSL_CTX_UseTruncatedHMAC(ctx)); + AssertIntEQ(0, CyaSSL_UseTruncatedHMAC(ssl)); + + CyaSSL_free(ssl); + CyaSSL_CTX_free(ctx); +} +#endif /* HAVE_TRUNCATED_HMAC */ + #endif /* HAVE_TLS_EXTENSIONS */ #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)