Merge pull request #5585 from icing/groups-key-share

wolfSSL_set1_curves_list(), wolfSSL_CTX_set1_curves_list() improvements.
This commit is contained in:
JacobBarthelmeh 2022-09-13 10:36:25 -06:00 committed by GitHub
commit 12ec2272d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 148 additions and 35 deletions

View File

@ -33926,20 +33926,34 @@ int wolfSSL_curve_is_disabled(WOLFSSL* ssl, word16 curve_id)
defined(HAVE_CURVE25519) || defined(HAVE_CURVE448))
static int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names)
{
int idx, start = 0, len;
int idx, start = 0, len, i, ret = WOLFSSL_FAILURE;
word16 curve;
word32 disabled;
char name[MAX_CURVE_NAME_SZ];
byte groups_len = 0;
#ifdef WOLFSSL_SMALL_STACK
void *heap = ssl? ssl->heap : ctx->heap;
int *groups;
#else
int groups[WOLFSSL_MAX_GROUP_COUNT];
#endif
#ifdef WOLFSSL_SMALL_STACK
groups = (int*)XMALLOC(sizeof(int)*WOLFSSL_MAX_GROUP_COUNT,
heap, DYNAMIC_TYPE_TMP_BUFFER);
if (groups == NULL) {
ret = MEMORY_E;
goto leave;
}
#endif
/* Disable all curves so that only the ones the user wants are enabled. */
disabled = 0xFFFFFFFFUL;
for (idx = 1; names[idx-1] != '\0'; idx++) {
if (names[idx] != ':' && names[idx] != '\0')
continue;
len = idx - start;
if (len > MAX_CURVE_NAME_SZ - 1)
return WOLFSSL_FAILURE;
goto leave;
XMEMCPY(name, names + start, len);
name[len] = 0;
@ -33974,25 +33988,25 @@ static int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names)
#endif
else {
#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
int ret;
int nret;
const ecc_set_type *eccSet;
ret = wc_ecc_get_curve_idx_from_name(name);
if (ret < 0) {
nret = wc_ecc_get_curve_idx_from_name(name);
if (nret < 0) {
WOLFSSL_MSG("Could not find name in set");
return WOLFSSL_FAILURE;
goto leave;
}
eccSet = wc_ecc_get_curve_params(ret);
if (eccSet == NULL) {
WOLFSSL_MSG("NULL set returned");
return WOLFSSL_FAILURE;
goto leave;
}
curve = GetCurveByOID(eccSet->oidSum);
#else
WOLFSSL_MSG("API not present to search farther using name");
return WOLFSSL_FAILURE;
goto leave;
#endif
}
@ -34000,32 +34014,71 @@ static int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names)
/* shift left more than size of ctx->disabledCurves causes static
* analysis report */
WOLFSSL_MSG("curve value is too large for upcoming shift");
return WOLFSSL_FAILURE;
goto leave;
}
#if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT)
for (i = 0; i < groups_len; ++i) {
if (groups[i] == curve) {
/* silently drop duplicates */
break;
}
}
if (i >= groups_len) {
if (groups_len >= WOLFSSL_MAX_GROUP_COUNT) {
WOLFSSL_MSG_EX("setting %d or more supported "
"curves is not permitted", groups_len);
goto leave;
}
groups[groups_len++] = (int)curve;
}
start = idx + 1;
}
/* Disable all curves so that only the ones the user wants are enabled. */
disabled = 0xFFFFFFFFUL;
for (i = 0; i < groups_len; ++i) {
/* Switch the bit to off and therefore is enabled. */
curve = (word16)groups[i];
disabled &= ~(1U << curve);
#ifdef HAVE_SUPPORTED_CURVES
#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_OLD_SET_CURVES_LIST)
/* using the wolfSSL API to set the groups, this will populate
* (ssl|ctx)->groups and reset any TLSX_SUPPORTED_GROUPS.
* The order in (ssl|ctx)->groups will then be respected
* when TLSX_KEY_SHARE needs to be established */
if ((ssl && wolfSSL_set_groups(ssl, groups, groups_len)
!= WOLFSSL_SUCCESS)
|| (ctx && wolfSSL_CTX_set_groups(ctx, groups, groups_len)
!= WOLFSSL_SUCCESS)) {
WOLFSSL_MSG("Unable to set supported curve");
goto leave;
}
#elif !defined(NO_WOLFSSL_CLIENT)
/* set the supported curve so client TLS extension contains only the
* desired curves */
if ((ssl
&& wolfSSL_UseSupportedCurve(ssl, curve) != WOLFSSL_SUCCESS)
|| (ctx
&& wolfSSL_CTX_UseSupportedCurve(ctx, curve) != WOLFSSL_SUCCESS)) {
if ((ssl && wolfSSL_UseSupportedCurve(ssl, curve) != WOLFSSL_SUCCESS)
|| (ctx && wolfSSL_CTX_UseSupportedCurve(ctx, curve)
!= WOLFSSL_SUCCESS)) {
WOLFSSL_MSG("Unable to set supported curve");
return WOLFSSL_FAILURE;
goto leave;
}
#endif
/* Switch the bit to off and therefore is enabled. */
disabled &= ~(1U << curve);
start = idx + 1;
#endif /* HAVE_SUPPORTED_CURVES */
}
if (ssl)
ssl->disabledCurves = disabled;
else
ctx->disabledCurves = disabled;
ret = WOLFSSL_SUCCESS;
return WOLFSSL_SUCCESS;
leave:
#ifdef WOLFSSL_SMALL_STACK
if (groups)
XFREE((void*)groups, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names)

View File

@ -949,20 +949,26 @@ static int QuicConversation_start(QuicConversation *conv, const byte *data,
return ret;
}
static int QuicConversation_step(QuicConversation *conv)
static int QuicConversation_step(QuicConversation *conv, int may_fail)
{
int n;
if (!conv->started) {
AssertTrue(wolfSSL_connect(conv->client->ssl) != WOLFSSL_SUCCESS);
AssertIntEQ(SSL_ERROR_WANT_READ, wolfSSL_get_error(conv->client->ssl, 0));
n = wolfSSL_connect(conv->client->ssl);
if (n != WOLFSSL_SUCCESS
&& wolfSSL_get_error(conv->client->ssl, 0) != SSL_ERROR_WANT_READ) {
if (may_fail) return 0;
AssertIntEQ(SSL_ERROR_WANT_READ, wolfSSL_get_error(conv->client->ssl, 0));
}
conv->started = 1;
}
if (conv->server->output.len > 0) {
QuicTestContext_forward(conv->server, conv->client, conv->rec_log, sizeof(conv->rec_log));
n = wolfSSL_quic_read_write(conv->client->ssl);
if (n != WOLFSSL_SUCCESS) {
AssertIntEQ(wolfSSL_get_error(conv->client->ssl, 0), SSL_ERROR_WANT_READ);
if (n != WOLFSSL_SUCCESS
&& wolfSSL_get_error(conv->client->ssl, 0) != SSL_ERROR_WANT_READ) {
if (may_fail) return 0;
AssertIntEQ(SSL_ERROR_WANT_READ, wolfSSL_get_error(conv->client->ssl, 0));
}
return 1;
}
@ -976,7 +982,10 @@ static int QuicConversation_step(QuicConversation *conv)
(int)(sizeof(conv->early_data) - conv->early_data_len),
&written);
if (n < 0) {
AssertIntEQ(wolfSSL_get_error(conv->server->ssl, 0), SSL_ERROR_WANT_READ);
if (wolfSSL_get_error(conv->server->ssl, 0) != SSL_ERROR_WANT_READ) {
if (may_fail) return 0;
AssertIntEQ(wolfSSL_get_error(conv->server->ssl, 0), SSL_ERROR_WANT_READ);
}
}
else if (n > 0) {
conv->early_data_len += n;
@ -988,7 +997,9 @@ static int QuicConversation_step(QuicConversation *conv)
#endif /* WOLFSSL_EARLY_DATA */
{
n = wolfSSL_quic_read_write(conv->server->ssl);
if (n != WOLFSSL_SUCCESS) {
if (n != WOLFSSL_SUCCESS
&& wolfSSL_get_error(conv->server->ssl, 0) != SSL_ERROR_WANT_READ) {
if (may_fail) return 0;
AssertIntEQ(wolfSSL_get_error(conv->server->ssl, 0), SSL_ERROR_WANT_READ);
}
}
@ -1004,7 +1015,7 @@ static void QuicConversation_do(QuicConversation *conv)
}
while (1) {
if (!QuicConversation_step(conv)) {
if (!QuicConversation_step(conv, 0)) {
int c_err = wolfSSL_get_error(conv->client->ssl, 0);
int s_err = wolfSSL_get_error(conv->server->ssl, 0);
if (c_err == 0 && s_err == 0) {
@ -1018,6 +1029,22 @@ static void QuicConversation_do(QuicConversation *conv)
}
}
static void QuicConversation_fail(QuicConversation *conv)
{
if (!conv->started) {
QuicConversation_start(conv, NULL, 0, NULL);
}
while (1) {
if (!QuicConversation_step(conv, 1)) {
int c_err = wolfSSL_get_error(conv->client->ssl, 0);
int s_err = wolfSSL_get_error(conv->server->ssl, 0);
AssertTrue(c_err != 0 || s_err != 0);
break;
}
}
}
static int test_quic_client_hello(int verbose) {
WOLFSSL_CTX *ctx;
int ret = 0;
@ -1089,14 +1116,14 @@ static int test_quic_server_hello(int verbose) {
/* connect */
QuicConversation_init(&conv, &tclient, &tserver);
QuicConversation_step(&conv);
QuicConversation_step(&conv, 0);
/* check established/missing secrets */
check_secrets(&tserver, wolfssl_encryption_initial, 0, 0);
check_secrets(&tserver, wolfssl_encryption_handshake, 32, 32);
check_secrets(&tserver, wolfssl_encryption_application, 32, 32);
check_secrets(&tclient, wolfssl_encryption_handshake, 0, 0);
/* feed the server data to the client */
QuicConversation_step(&conv);
QuicConversation_step(&conv, 0);
/* client has generated handshake secret */
check_secrets(&tclient, wolfssl_encryption_handshake, 32, 32);
/* continue the handshake till done */
@ -1166,8 +1193,9 @@ static int test_quic_key_share(int verbose) {
QuicTestContext_free(&tclient);
QuicTestContext_free(&tserver);
/* setup & handshake, restricted groups, will trigger a
* HelloRetryRequest(ServerHello) and a new ClientHello */
/* setup & handshake, restricted groups. KEY_SHARE should use
* the first configured group. */
/*If that is supported by the server, expect a smooth handshake.*/
QuicTestContext_init(&tclient, ctx_c, "client", verbose);
QuicTestContext_init(&tserver, ctx_s, "server", verbose);
AssertTrue(wolfSSL_set1_curves_list(tclient.ssl, "X25519:P-256")
@ -1176,11 +1204,43 @@ static int test_quic_key_share(int verbose) {
== WOLFSSL_SUCCESS);
QuicConversation_init(&conv, &tclient, &tserver);
QuicConversation_do(&conv);
AssertStrEQ(conv.rec_log,
"ClientHello:ServerHello:EncryptedExtension:"
"Certificate:CertificateVerify:Finished:Finished:SessionTicket");
QuicTestContext_free(&tclient);
QuicTestContext_free(&tserver);
printf(" test_quic_key_share: priority ok\n");
/* If group is not supported by server, expect HelloRetry */
QuicTestContext_init(&tclient, ctx_c, "client", verbose);
QuicTestContext_init(&tserver, ctx_s, "server", verbose);
AssertTrue(wolfSSL_set1_curves_list(tclient.ssl, "X25519:P-256")
== WOLFSSL_SUCCESS);
AssertTrue(wolfSSL_set1_curves_list(tserver.ssl, "P-256")
== WOLFSSL_SUCCESS);
QuicConversation_init(&conv, &tclient, &tserver);
QuicConversation_do(&conv);
AssertStrEQ(conv.rec_log,
"ClientHello:ServerHello:ClientHello:ServerHello:EncryptedExtension:"
"Certificate:CertificateVerify:Finished:Finished:SessionTicket");
QuicTestContext_free(&tclient);
QuicTestContext_free(&tserver);
printf(" test_quic_key_share: retry ok\n");
/* If no group overlap, expect failure */
QuicTestContext_init(&tclient, ctx_c, "client", verbose);
QuicTestContext_init(&tserver, ctx_s, "server", verbose);
AssertTrue(wolfSSL_set1_curves_list(tclient.ssl, "P-256")
== WOLFSSL_SUCCESS);
AssertTrue(wolfSSL_set1_curves_list(tserver.ssl, "X25519")
== WOLFSSL_SUCCESS);
QuicConversation_init(&conv, &tclient, &tserver);
QuicConversation_fail(&conv);
AssertIntEQ(wolfSSL_get_error(tserver.ssl, 0), SSL_ERROR_WANT_READ);
AssertIntEQ(wolfSSL_get_error(tclient.ssl, 0), BAD_KEY_SHARE_DATA);
QuicTestContext_free(&tclient);
QuicTestContext_free(&tserver);
printf(" test_quic_key_share: no match ok\n");
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
@ -1476,7 +1536,7 @@ int QuicTest(void)
if ((ret = test_quic_key_share(verbose)) != 0) goto leave;
if ((ret = test_quic_resumption(verbose)) != 0) goto leave;
#ifdef WOLFSSL_EARLY_DATA
if ((ret = test_quic_early_data(verbose || 1)) != 0) goto leave;
if ((ret = test_quic_early_data(verbose)) != 0) goto leave;
#endif /* WOLFSSL_EARLY_DATA */
if ((ret = test_quic_session_export(verbose)) != 0) goto leave;
#endif /* HAVE_SESSION_TICKET */