crypto/x86_64cpuid.pl: fix typo in Knights Landing detection.
[openssl.git] / test / sslapitest.c
index 7a2f9a410e16f60530b8aaaea2f3ab9b2466cce5..ea68f0be697c9dd68a7104dd81875f620af988d4 100644 (file)
@@ -1536,10 +1536,10 @@ static int test_early_data_read_write(int idx)
 }
 
 /*
- * Test that a server attempting to read early data can handle a connection
- * from a client where the early data is not acceptable.
+ * Helper function to test that a server attempting to read early data can
+ * handle a connection from a client where the early data should be skipped.
  */
-static int test_early_data_skip(int idx)
+static int early_data_skip_helper(int hrr, int idx)
 {
     SSL_CTX *cctx = NULL, *sctx = NULL;
     SSL *clientssl = NULL, *serverssl = NULL;
@@ -1552,13 +1552,19 @@ static int test_early_data_skip(int idx)
                                         &serverssl, &sess, idx)))
         goto end;
 
-    /*
-     * Deliberately corrupt the creation time. We take 20 seconds off the time.
-     * It could be any value as long as it is not within tolerance. This should
-     * mean the ticket is rejected.
-     */
-    if (!TEST_true(SSL_SESSION_set_time(sess, time(NULL) - 20)))
-        goto end;
+    if (hrr) {
+        /* Force an HRR to occur */
+        if (!TEST_true(SSL_set1_groups_list(serverssl, "P-256")))
+            goto end;
+    } else {
+        /*
+         * Deliberately corrupt the creation time. We take 20 seconds off the
+         * time. It could be any value as long as it is not within tolerance.
+         * This should mean the ticket is rejected.
+         */
+        if (!TEST_true(SSL_SESSION_set_time(sess, time(NULL) - 20)))
+            goto end;
+    }
 
     /* Write some early data */
     if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
@@ -1575,6 +1581,18 @@ static int test_early_data_skip(int idx)
                             SSL_EARLY_DATA_REJECTED))
         goto end;
 
+    if (hrr) {
+        /*
+         * Finish off the handshake. We perform the same writes and reads as
+         * further down but we expect them to fail due to the incomplete
+         * handshake.
+         */
+        if (!TEST_false(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written))
+                || !TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf),
+                               &readbytes)))
+            goto end;
+    }
+
     /* Should be able to send normal data despite rejection of early data */
     if (!TEST_true(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written))
             || !TEST_size_t_eq(written, strlen(MSG2))
@@ -1595,6 +1613,24 @@ static int test_early_data_skip(int idx)
     return testresult;
 }
 
+/*
+ * Test that a server attempting to read early data can handle a connection
+ * from a client where the early data is not acceptable.
+ */
+static int test_early_data_skip(int idx)
+{
+    return early_data_skip_helper(0, idx);
+}
+
+/*
+ * Test that a server attempting to read early data can handle a connection
+ * from a client where an HRR occurs.
+ */
+static int test_early_data_skip_hrr(int idx)
+{
+    return early_data_skip_helper(1, idx);
+}
+
 /*
  * Test that a server attempting to read early data can handle a connection
  * from a client that doesn't send any.
@@ -1938,19 +1974,23 @@ static int find_session_cb_cnt = 0;
 static int use_session_cb(SSL *ssl, const EVP_MD *md, const unsigned char **id,
                           size_t *idlen, SSL_SESSION **sess)
 {
-    use_session_cb_cnt++;
-
-    /* The first call should always have a NULL md */
-    if (use_session_cb_cnt == 1 && md != NULL)
-        return 0;
+    switch (++use_session_cb_cnt) {
+    case 1:
+        /* The first call should always have a NULL md */
+        if (md != NULL)
+            return 0;
+        break;
 
-    /* The second call should always have an md */
-    if (use_session_cb_cnt == 2 && md == NULL)
-        return 0;
+    case 2:
+        /* The second call should always have an md */
+        if (md == NULL)
+            return 0;
+        break;
 
-    /* We should only be called a maximum of twice */
-    if (use_session_cb_cnt == 3)
+    default:
+        /* We should only be called a maximum of twice */
         return 0;
+    }
 
     if (psk != NULL)
         SSL_SESSION_up_ref(psk);
@@ -1998,7 +2038,8 @@ static int test_tls13_psk(void)
     const unsigned char key[] = {
         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
         0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+        0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
     };
     int testresult = 0;
 
@@ -2482,6 +2523,186 @@ static int test_serverinfo(int tst)
     return testresult;
 }
 
+/*
+ * Test that SSL_export_keying_material() produces expected results. There are
+ * no test vectors so all we do is test that both sides of the communication
+ * produce the same results for different protocol versions.
+ */
+static int test_export_key_mat(int tst)
+{
+    int testresult = 0;
+    SSL_CTX *cctx = NULL, *sctx = NULL, *sctx2 = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    const char label[] = "test label";
+    const unsigned char context[] = "context";
+    const unsigned char *emptycontext = NULL;
+    unsigned char ckeymat1[80], ckeymat2[80], ckeymat3[80];
+    unsigned char skeymat1[80], skeymat2[80], skeymat3[80];
+    const int protocols[] = {
+        TLS1_VERSION,
+        TLS1_1_VERSION,
+        TLS1_2_VERSION,
+        TLS1_3_VERSION
+    };
+
+#ifdef OPENSSL_NO_TLS1
+    if (tst == 0)
+        return 1;
+#endif
+#ifdef OPENSSL_NO_TLS1_1
+    if (tst == 1)
+        return 1;
+#endif
+#ifdef OPENSSL_NO_TLS1_2
+    if (tst == 2)
+        return 1;
+#endif
+#ifdef OPENSSL_NO_TLS1_3
+    if (tst == 3)
+        return 1;
+#endif
+    if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
+                                       TLS_client_method(), &sctx,
+                                       &cctx, cert, privkey)))
+        goto end;
+
+    OPENSSL_assert(tst >= 0 && (size_t)tst < OSSL_NELEM(protocols));
+    SSL_CTX_set_max_proto_version(cctx, protocols[tst]);
+    SSL_CTX_set_min_proto_version(cctx, protocols[tst]);
+
+    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
+                                      NULL))
+            || !TEST_true(create_ssl_connection(serverssl, clientssl,
+                                                SSL_ERROR_NONE)))
+        goto end;
+
+    if (!TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat1,
+                                                sizeof(ckeymat1), label,
+                                                sizeof(label) - 1, context,
+                                                sizeof(context) - 1, 1), 1)
+            || !TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat2,
+                                                       sizeof(ckeymat2), label,
+                                                       sizeof(label) - 1,
+                                                       emptycontext,
+                                                       0, 1), 1)
+            || !TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat3,
+                                                       sizeof(ckeymat3), label,
+                                                       sizeof(label) - 1,
+                                                       NULL, 0, 0), 1)
+            || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat1,
+                                                       sizeof(skeymat1), label,
+                                                       sizeof(label) - 1,
+                                                       context,
+                                                       sizeof(context) -1, 1),
+                            1)
+            || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat2,
+                                                       sizeof(skeymat2), label,
+                                                       sizeof(label) - 1,
+                                                       emptycontext,
+                                                       0, 1), 1)
+            || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat3,
+                                                       sizeof(skeymat3), label,
+                                                       sizeof(label) - 1,
+                                                       NULL, 0, 0), 1)
+               /*
+                * Check that both sides created the same key material with the
+                * same context.
+                */
+            || !TEST_mem_eq(ckeymat1, sizeof(ckeymat1), skeymat1,
+                            sizeof(skeymat1))
+               /*
+                * Check that both sides created the same key material with an
+                * empty context.
+                */
+            || !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), skeymat2,
+                            sizeof(skeymat2))
+               /*
+                * Check that both sides created the same key material without a
+                * context.
+                */
+            || !TEST_mem_eq(ckeymat3, sizeof(ckeymat3), skeymat3,
+                            sizeof(skeymat3))
+               /* Different contexts should produce different results */
+            || !TEST_mem_ne(ckeymat1, sizeof(ckeymat1), ckeymat2,
+                            sizeof(ckeymat2)))
+        goto end;
+
+    /*
+     * Check that an empty context and no context produce different results in
+     * protocols less than TLSv1.3. In TLSv1.3 they should be the same.
+     */
+    if ((tst != 3 && !TEST_mem_ne(ckeymat2, sizeof(ckeymat2), ckeymat3,
+                                  sizeof(ckeymat3)))
+            || (tst ==3 && !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), ckeymat3,
+                                        sizeof(ckeymat3))))
+        goto end;
+
+    testresult = 1;
+
+ end:
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx2);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+
+static int test_ssl_clear(int idx)
+{
+    SSL_CTX *cctx = NULL, *sctx = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    int testresult = 0;
+
+#ifdef OPENSSL_NO_TLS1_2
+    if (idx == 1)
+        return 1;
+#endif
+
+    /* Create an initial connection */
+    if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
+                                       TLS_client_method(), &sctx,
+                                       &cctx, cert, privkey))
+            || (idx == 1
+                && !TEST_true(SSL_CTX_set_max_proto_version(cctx,
+                                                            TLS1_2_VERSION)))
+            || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
+                                          &clientssl, NULL, NULL))
+            || !TEST_true(create_ssl_connection(serverssl, clientssl,
+                                                SSL_ERROR_NONE)))
+        goto end;
+
+    SSL_shutdown(clientssl);
+    SSL_shutdown(serverssl);
+    SSL_free(serverssl);
+    serverssl = NULL;
+
+    /* Clear clientssl - we're going to reuse the object */
+    if (!TEST_true(SSL_clear(clientssl)))
+        goto end;
+
+    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+                                             NULL, NULL))
+            || !TEST_true(create_ssl_connection(serverssl, clientssl,
+                                                SSL_ERROR_NONE))
+            || !TEST_true(SSL_session_reused(clientssl)))
+        goto end;
+
+    SSL_shutdown(clientssl);
+    SSL_shutdown(serverssl);
+
+    testresult = 1;
+
+ end:
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+
 int test_main(int argc, char *argv[])
 {
     int testresult = 1;
@@ -2521,6 +2742,7 @@ int test_main(int argc, char *argv[])
 #ifndef OPENSSL_NO_TLS1_3
     ADD_ALL_TESTS(test_early_data_read_write, 2);
     ADD_ALL_TESTS(test_early_data_skip, 2);
+    ADD_ALL_TESTS(test_early_data_skip_hrr, 2);
     ADD_ALL_TESTS(test_early_data_not_sent, 2);
     ADD_ALL_TESTS(test_early_data_not_expected, 2);
 # ifndef OPENSSL_NO_TLS1_2
@@ -2535,6 +2757,8 @@ int test_main(int argc, char *argv[])
     ADD_ALL_TESTS(test_custom_exts, 3);
 #endif
     ADD_ALL_TESTS(test_serverinfo, 8);
+    ADD_ALL_TESTS(test_export_key_mat, 4);
+    ADD_ALL_TESTS(test_ssl_clear, 2);
 
     testresult = run_tests(argv[0]);