}
#endif
+static int full_early_callback(SSL *s, int *al, void *arg)
+{
+ int *ctr = arg;
+ const unsigned char *p;
+ /* We only configure two ciphers, but the SCSV is added automatically. */
+#ifdef OPENSSL_NO_EC
+ const unsigned char expected_ciphers[] = {0x00, 0x9d, 0x00, 0xff};
+#else
+ const unsigned char expected_ciphers[] = {0x00, 0x9d, 0xc0,
+ 0x2c, 0x00, 0xff};
+#endif
+ size_t len;
+
+ /* Make sure we can defer processing and get called back. */
+ if ((*ctr)++ == 0)
+ return -1;
+
+ len = SSL_early_get0_ciphers(s, &p);
+ if (len != sizeof(expected_ciphers) ||
+ memcmp(p, expected_ciphers, len) != 0) {
+ printf("Early callback expected ciphers mismatch\n");
+ return 0;
+ }
+ len = SSL_early_get0_compression_methods(s, &p);
+ if (len != 1 || *p != 0) {
+ printf("Early callback expected comperssion methods mismatch\n");
+ return 0;
+ }
+ return 1;
+}
+
+static int test_early_cb(void) {
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testctr = 0, testresult = 0;
+
+ if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), &sctx,
+ &cctx, cert, privkey)) {
+ printf("Unable to create SSL_CTX pair\n");
+ goto end;
+ }
+
+ SSL_CTX_set_early_cb(sctx, full_early_callback, &testctr);
+ /* The gimpy cipher list we configure can't do TLS 1.3. */
+ SSL_CTX_set_max_proto_version(cctx, TLS1_2_VERSION);
+ if (!SSL_CTX_set_cipher_list(cctx,
+ "AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384")) {
+ printf("Failed to set cipher list\n");
+ goto end;
+ }
+
+ if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) {
+ printf("Unable to create SSL objects\n");
+ goto end;
+ }
+
+ if (create_ssl_connection(serverssl, clientssl, SSL_ERROR_WANT_EARLY)) {
+ printf("Creating SSL connection succeeded with async early return\n");
+ goto end;
+ }
+
+ /* Passing a -1 literal is a hack since the real value was lost. */
+ if (SSL_get_error(serverssl, -1) != SSL_ERROR_WANT_EARLY) {
+ printf("Early callback failed to make state SSL_ERROR_WANT_EARLY\n");
+ goto end;
+ }
+
+ if (!create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) {
+ printf("Restarting SSL connection failed\n");
+ goto end;
+ }
+
+ testresult = 1;
+
+end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+
+ return testresult;
+}
+
static int execute_test_large_message(const SSL_METHOD *smeth,
const SSL_METHOD *cmeth, int read_ahead)
{
#ifndef OPENSSL_NO_TLS1_3
ADD_TEST(test_keylog_no_master_key);
#endif
+ ADD_TEST(test_early_cb);
testresult = run_tests(argv[0]);