return testresult;
}
+# if !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_DH)
+static int set_ssl_groups(SSL *serverssl, SSL *clientssl, int clientmulti,
+ int isecdhe, int idx)
+{
+ int kexch_alg;
+ int *kexch_groups = &kexch_alg;
+ int numec, numff;
+
+ numec = OSSL_NELEM(ecdhe_kexch_groups);
+ numff = OSSL_NELEM(ffdhe_kexch_groups);
+ if (isecdhe)
+ kexch_alg = ecdhe_kexch_groups[idx];
+ else
+ kexch_alg = ffdhe_kexch_groups[idx];
+
+ if (clientmulti) {
+ if (!TEST_true(SSL_set1_groups(serverssl, kexch_groups, 1)))
+ return 0;
+ if (isecdhe) {
+ if (!TEST_true(SSL_set1_groups(clientssl, ecdhe_kexch_groups,
+ numec)))
+ return 0;
+ } else {
+ if (!TEST_true(SSL_set1_groups(clientssl, ffdhe_kexch_groups,
+ numff)))
+ return 0;
+ }
+ } else {
+ if (!TEST_true(SSL_set1_groups(clientssl, kexch_groups, 1)))
+ return 0;
+ if (isecdhe) {
+ if (!TEST_true(SSL_set1_groups(serverssl, ecdhe_kexch_groups,
+ numec)))
+ return 0;
+ } else {
+ if (!TEST_true(SSL_set1_groups(serverssl, ffdhe_kexch_groups,
+ numff)))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*-
+ * Test the SSL_get_negotiated_group() API across a battery of scenarios.
+ * Run through both the ECDHE and FFDHE group lists used in the previous
+ * test, for both TLS 1.2 and TLS 1.3, negotiating each group in turn,
+ * confirming the expected result; then perform a resumption handshake
+ * while offering the same group list, and another resumption handshake
+ * offering a different group list. The returned value should be the
+ * negotiated group for the initial handshake; for TLS 1.3 resumption
+ * handshakes the returned value will be negotiated on the resumption
+ * handshake itself, but for TLS 1.2 resumption handshakes the value will
+ * be cached in the session from the original handshake, regardless of what
+ * was offered in the resumption ClientHello.
+ *
+ * Using E for the number of EC groups and F for the number of FF groups:
+ * E tests of ECDHE with TLS 1.3, client sends only one group
+ * F tests of FFDHE with TLS 1.3, client sends only one group
+ * E tests of ECDHE with TLS 1.2, client sends only one group
+ * F tests of FFDHE with TLS 1.2, client sends only one group
+ * E tests of ECDHE with TLS 1.3, server only has one group
+ * F tests of FFDHE with TLS 1.3, server only has one group
+ * E tests of ECDHE with TLS 1.2, server only has one group
+ * F tests of FFDHE with TLS 1.2, server only has one group
+ */
+static int test_negotiated_group(int idx)
+{
+ int clientmulti, istls13, isecdhe, numec, numff, numgroups;
+ int expectednid;
+ SSL_CTX *sctx = NULL, *cctx = NULL;
+ SSL *serverssl = NULL, *clientssl = NULL;
+ SSL_SESSION *origsess = NULL;
+ int testresult = 0;
+ int kexch_alg;
+ int max_version = TLS1_3_VERSION;
+
+ numec = OSSL_NELEM(ecdhe_kexch_groups);
+ numff = OSSL_NELEM(ffdhe_kexch_groups);
+ numgroups = numec + numff;
+ clientmulti = (idx < 2 * numgroups);
+ idx = idx % (2 * numgroups);
+ istls13 = (idx < numgroups);
+ idx = idx % numgroups;
+ isecdhe = (idx < numec);
+ if (!isecdhe)
+ idx -= numec;
+ /* Now 'idx' is an index into ecdhe_kexch_groups or ffdhe_kexch_groups */
+ if (isecdhe)
+ kexch_alg = ecdhe_kexch_groups[idx];
+ else
+ kexch_alg = ffdhe_kexch_groups[idx];
+ /* We expect nothing for the unimplemented TLS 1.2 FFDHE named groups */
+ if (!istls13 && !isecdhe)
+ expectednid = NID_undef;
+ else
+ expectednid = kexch_alg;
+
+ if (!istls13)
+ max_version = TLS1_2_VERSION;
+
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(), TLS1_VERSION,
+ max_version, &sctx, &cctx, cert,
+ privkey)))
+ goto end;
+
+ /*
+ * Force (EC)DHE ciphers for TLS 1.2.
+ * Be sure to enable auto tmp DH so that FFDHE can succeed.
+ */
+ if (!TEST_true(SSL_CTX_set_cipher_list(sctx,
+ TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ":"
+ TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256))
+ || !TEST_true(SSL_CTX_set_dh_auto(sctx, 1)))
+ goto end;
+ if (!TEST_true(SSL_CTX_set_cipher_list(cctx,
+ TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ":"
+ TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256)))
+ goto end;
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL)))
+ goto end;
+
+ if (!TEST_true(set_ssl_groups(serverssl, clientssl, clientmulti, isecdhe,
+ idx)))
+ goto end;
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
+ goto end;
+
+ /* Initial handshake; always the configured one */
+ if (!TEST_uint_eq(SSL_get_negotiated_group(clientssl), expectednid)
+ || !TEST_uint_eq(SSL_get_negotiated_group(serverssl), expectednid))
+ goto end;
+
+ if (!TEST_ptr((origsess = SSL_get1_session(clientssl))))
+ goto end;
+
+ SSL_shutdown(clientssl);
+ SSL_shutdown(serverssl);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ serverssl = clientssl = NULL;
+
+ /* First resumption attempt; use the same config as initial handshake */
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL))
+ || !TEST_true(SSL_set_session(clientssl, origsess))
+ || !TEST_true(set_ssl_groups(serverssl, clientssl, clientmulti,
+ isecdhe, idx)))
+ goto end;
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
+ || !TEST_true(SSL_session_reused(clientssl)))
+ goto end;
+
+ /* Still had better agree, since nothing changed... */
+ if (!TEST_uint_eq(SSL_get_negotiated_group(clientssl), expectednid)
+ || !TEST_uint_eq(SSL_get_negotiated_group(serverssl), expectednid))
+ goto end;
+
+ SSL_shutdown(clientssl);
+ SSL_shutdown(serverssl);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ serverssl = clientssl = NULL;
+
+ /*-
+ * Second resumption attempt
+ * The party that picks one group changes it, which we effectuate by
+ * changing 'idx' and updating what we expect.
+ */
+ if (idx == 0)
+ idx = 1;
+ else
+ idx--;
+ if (istls13) {
+ if (isecdhe)
+ expectednid = ecdhe_kexch_groups[idx];
+ else
+ expectednid = ffdhe_kexch_groups[idx];
+ /* Verify that we are changing what we expect. */
+ if (!TEST_int_ne(expectednid, kexch_alg))
+ goto end;
+ } else {
+ /* TLS 1.2 only supports named groups for ECDHE. */
+ if (isecdhe)
+ expectednid = kexch_alg;
+ else
+ expectednid = 0;
+ }
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL))
+ || !TEST_true(SSL_set_session(clientssl, origsess))
+ || !TEST_true(set_ssl_groups(serverssl, clientssl, clientmulti,
+ isecdhe, idx)))
+ goto end;
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))
+ || !TEST_true(SSL_session_reused(clientssl)))
+ goto end;
+
+ /* Check that we get what we expected */
+ if (!TEST_uint_eq(SSL_get_negotiated_group(clientssl), expectednid)
+ || !TEST_uint_eq(SSL_get_negotiated_group(serverssl), expectednid))
+ goto end;
+
+ testresult = 1;
+ end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ SSL_SESSION_free(origsess);
+ return testresult;
+}
+# endif /* !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_DH) */
+
/*
* Test TLSv1.3 Cipher Suite
* Test 0 = Set TLS1.3 cipher on context
# ifndef OPENSSL_NO_TLS1_2
/* Test with both TLSv1.3 and 1.2 versions */
ADD_ALL_TESTS(test_key_exchange, 14);
+# if !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_DH)
+ ADD_ALL_TESTS(test_negotiated_group,
+ 4 * (OSSL_NELEM(ecdhe_kexch_groups)
+ + OSSL_NELEM(ffdhe_kexch_groups)));
+# endif
# else
/* Test with only TLSv1.3 versions */
ADD_ALL_TESTS(test_key_exchange, 12);