From 4feedb72cc6a72cf63fc430da486b15a4ce4df62 Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Thu, 20 May 2021 19:14:35 +0900 Subject: [PATCH] simulate set_ciphersuites comp. API --- src/ssl.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++- tests/api.c | 16 +++++ 2 files changed, 195 insertions(+), 2 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 579e13fcc..34b9cd45f 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -11943,6 +11943,153 @@ static int wolfSSL_remove_ciphers(char* list, int sz, const char* toRemove) return totalSz; } +/* */ +/* build enabled cipher list w/ TLS13 or w/o TLS13 suites */ +/* @param ctx a pointer to WOLFSSL_CTX structure */ +/* @param suites currently enabled suites */ +/* @param onlytlsv13suites flag whether correcting w/ TLS13 suites */ +/* or w/o TLS13 suties */ +/* @param list suites list that user wants to update */ +/* @return suites list on successs, otherwise NULL */ +static char* buildEnabledCipherList(WOLFSSL_CTX* ctx, Suites* suites, + int onlytlsv13suites, const char* list) +{ + int idx = 0; + int listsz = 0; + int len = 0; + int ianasz = 0; + const char* enabledcs = NULL; + char* locallist = NULL; + char* head = NULL; + byte cipherSuite0; + byte cipherSuite; + + /* sanity check */ + if (ctx == NULL || suites == NULL || list == NULL) + return NULL; + + if (!suites->setSuites) + return NULL; + + listsz = XSTRLEN(list); + + /* calculate necessary buffer length */ + for(idx = 0; idx < suites->suiteSz; idx++) { + + cipherSuite0 = suites->suites[idx]; + cipherSuite = suites->suites[++idx]; + + if (onlytlsv13suites && cipherSuite0 == TLS13_BYTE) { + enabledcs = GetCipherNameInternal(cipherSuite0, cipherSuite); + } else if (!onlytlsv13suites && cipherSuite0 != TLS13_BYTE) { + enabledcs = GetCipherNameInternal(cipherSuite0, cipherSuite); + } else + continue; + + if (XSTRNCMP(enabledcs, "None", XSTRLEN(enabledcs)) != 0) { + len += XSTRLEN(enabledcs) + 2; + } + } + + len += listsz + 1; + + /* build string */ + if (len > 0) { + locallist = (char*)XMALLOC(len, ctx->heap, + DYNAMIC_TYPE_TMP_BUFFER); + /* sanity check */ + if (!locallist) + return NULL; + + XMEMSET(locallist, 0, len); + + head = locallist; + + for(idx = 0; idx < suites->suiteSz; idx++) { + cipherSuite0 = suites->suites[idx]; + cipherSuite = suites->suites[++idx]; + + if (onlytlsv13suites && cipherSuite0 == TLS13_BYTE) { + enabledcs = GetCipherNameInternal(cipherSuite0, cipherSuite); + } else if (!onlytlsv13suites && cipherSuite0 != TLS13_BYTE) { + enabledcs = GetCipherNameInternal(cipherSuite0, cipherSuite); + } else + continue; + + ianasz = (int)XSTRLEN(enabledcs); + if (ianasz + 1 < len) { + XSTRNCPY(locallist, enabledcs, len); + locallist += ianasz; + + *locallist++ = ':'; + *locallist = 0; + len -= ianasz + 1; + } + else{ + XFREE(locallist, ctx-heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + } + XSTRNCPY(locallist, list, len); + locallist += listsz; + *locallist = 0; + + return head; + } else + return NULL; +} + +/* */ +/* check if the list has TLS13 and pre-TLS13 suites */ +/* @param list cipher suite list that user want to set */ +/* @return mixed: 0, only pre-TLS13: 1, only TLS13: 2 */ +static int CheckcipherList(const char* list) +{ + int findTLSv13Suites = 0; + int findbeforeSuites = 0; + const int suiteSz = GetCipherNamesSize(); + const CipherSuiteInfo* names = GetCipherNames(); + + char* next = (char*)list; + + do { + char* current = next; + char name[MAX_SUITE_NAME + 1]; + int i; + word32 length; + + next = XSTRSTR(next, ":"); + length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /* last */ + : (word32)(next - current)); + XSTRNCPY(name, current, length); + name[(length == sizeof(name)) ? length - 1 : length] = 0; + + for (i = 0; i < suiteSz; i++) { + if (XSTRNCMP(name, names[i].name, sizeof(name)) == 0) + { + if (names[i].cipherSuite0 == TLS13_BYTE) { + /* TLSv13 suite */ + findTLSv13Suites = 1; + break; + } else { + findbeforeSuites = 1; + break; + } + } + } + + if (findTLSv13Suites == 1 && findbeforeSuites == 1) + /* list has mixed suites */ + return 0; + } while (next++); /* ++ needed to skip ':' */ + + if (findTLSv13Suites == 0 && findbeforeSuites == 1) + return 1;/* only before TLSv13 sutes */ + else if (findTLSv13Suites == 1 && findbeforeSuites == 0) + return 2;/* only TLSv13 suties */ + else + return 0;/* handle as mixed */ +} /* parse some bulk lists like !eNULL / !aNULL * @@ -11957,7 +12104,10 @@ static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, Suites* suites, const CipherSuiteInfo* names = GetCipherNames(); char* localList = NULL; int sz = 0; - + int listattribute = 0; + char* buildcipherList = NULL; + int onlytls13suites = 0; + if (suites == NULL || list == NULL) { WOLFSSL_MSG("NULL argument"); return WOLFSSL_FAILURE; @@ -12006,8 +12156,35 @@ static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, Suites* suites, return (ret)? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } else { - return (SetCipherList(ctx, suites, list)) ? WOLFSSL_SUCCESS : + + listattribute = CheckcipherList(list); + + if (listattribute == 0) { + /* list has mixed(pre-TLSv13 and TLSv13) suites */ + /* update cipher suites the same as before */ + return (SetCipherList(ctx, suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + } else if (listattribute == 1) { + /* list has only pre-TLSv13 suites. Only update before TLSv13 suites.*/ + onlytls13suites = 1; + } else if (listattribute == 2) { + /* list has only TLSv13 suites. Only update TLv13 suites */ + /* simulate set_ciphersuites() comatibility layer API */ + onlytls13suites = 0; + } + + buildcipherList = buildEnabledCipherList(ctx, ctx->suites, + onlytls13suites, list); + + if (buildcipherList) { + + ret = SetCipherList(ctx, suites, buildcipherList); + XFREE(buildcipherList, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + else + ret = SetCipherList(ctx, suites, list); + + return ret; } } diff --git a/tests/api.c b/tests/api.c index ad2ad6dc1..3f415fe51 100644 --- a/tests/api.c +++ b/tests/api.c @@ -756,6 +756,14 @@ static void test_for_double_Free(void) AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); AssertTrue(wolfSSL_CTX_set_cipher_list(ctx, optionsCiphers)); +#ifdef WOLFSSL_TLS13 + /* only update TLSv13 suites */ + AssertTrue(wolfSSL_CTX_set_cipher_list(ctx, "TLS13-AES256-GCM-SHA384")); +#endif +#ifndef WOLFSSL_NO_TLS12 + /* only update pre-TLSv13 suites */ + AssertTrue(wolfSSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-GCM-SHA256")); +#endif AssertNotNull(ssl = wolfSSL_new(ctx)); wolfSSL_CTX_free(ctx); wolfSSL_free(ssl); @@ -773,6 +781,14 @@ static void test_for_double_Free(void) AssertNotNull(ssl); /* test setting ciphers at SSL level */ AssertTrue(wolfSSL_set_cipher_list(ssl, optionsCiphers)); +#ifdef WOLFSSL_TLS13 + /* only update TLSv13 suites */ + AssertTrue(wolfSSL_set_cipher_list(ssl, "TLS13-AES256-GCM-SHA384")); +#endif +#ifndef WOLFSSL_NO_TLS12 + /* only update pre-TLSv13 suites */ + AssertTrue(wolfSSL_set_cipher_list(ssl, "ECDHE-RSA-AES128-GCM-SHA256")); +#endif wolfSSL_CTX_free(ctx); wolfSSL_free(ssl); }