Security hardening: Expose Build flags for Position Independed Execution (PIE)
[openssl.git] / test / quic_wire_test.c
index 07ce4e12faf5be45e9721aa848d3ed12c7e42219..69f4cf2977d764bee09f53a662836f9ed8cafa5a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -119,9 +119,17 @@ static int encode_case_3_dec(PACKET *pkt, ossl_ssize_t fail)
     if (!TEST_uint64_t_eq(total_ranges, peek_total_ranges))
         return 0;
 
-    if (!TEST_mem_eq(f.ack_ranges, f.num_ack_ranges * sizeof(OSSL_QUIC_ACK_RANGE),
+    if (!TEST_uint64_t_le(f.num_ack_ranges * sizeof(OSSL_QUIC_ACK_RANGE),
+                          SIZE_MAX)
+        || !TEST_uint64_t_le(encode_case_3_f.num_ack_ranges
+                             * sizeof(OSSL_QUIC_ACK_RANGE),
+                             SIZE_MAX))
+        return 0;
+
+    if (!TEST_mem_eq(f.ack_ranges,
+                     (size_t)f.num_ack_ranges * sizeof(OSSL_QUIC_ACK_RANGE),
                      encode_case_3_f.ack_ranges,
-                     encode_case_3_f.num_ack_ranges * sizeof(OSSL_QUIC_ACK_RANGE)))
+                     (size_t)encode_case_3_f.num_ack_ranges * sizeof(OSSL_QUIC_ACK_RANGE)))
         return 0;
 
     if (!TEST_uint64_t_eq(ossl_time2ticks(f.delay_time),
@@ -253,7 +261,7 @@ static int encode_case_6_dec(PACKET *pkt, ossl_ssize_t fail)
 {
     OSSL_QUIC_FRAME_CRYPTO f = {0};
 
-    if (!TEST_int_eq(ossl_quic_wire_decode_frame_crypto(pkt, &f), fail < 0))
+    if (!TEST_int_eq(ossl_quic_wire_decode_frame_crypto(pkt, 0, &f), fail < 0))
         return 0;
 
     if (fail >= 0)
@@ -262,7 +270,11 @@ static int encode_case_6_dec(PACKET *pkt, ossl_ssize_t fail)
     if (!TEST_uint64_t_eq(f.offset, 0x1234))
         return 0;
 
-    if (!TEST_mem_eq(f.data, f.len, encode_case_6_data, sizeof(encode_case_6_data)))
+    if (!TEST_uint64_t_le(f.len, SIZE_MAX))
+        return 0;
+
+    if (!TEST_mem_eq(f.data, (size_t)f.len,
+                     encode_case_6_data, sizeof(encode_case_6_data)))
         return 0;
 
     return 1;
@@ -346,13 +358,16 @@ static int encode_case_8_dec(PACKET *pkt, ossl_ssize_t fail)
          */
         return 1;
 
-    if (!TEST_int_eq(ossl_quic_wire_decode_frame_stream(pkt, &f), fail < 0))
+    if (!TEST_int_eq(ossl_quic_wire_decode_frame_stream(pkt, 0, &f), fail < 0))
         return 0;
 
     if (fail >= 0)
         return 1;
 
-    if (!TEST_mem_eq(f.data, f.len,
+    if (!TEST_uint64_t_le(f.len, SIZE_MAX))
+        return 0;
+
+    if (!TEST_mem_eq(f.data, (size_t)f.len,
                      encode_case_8_data, sizeof(encode_case_8_data)))
         return 0;
 
@@ -398,13 +413,16 @@ static int encode_case_9_dec(PACKET *pkt, ossl_ssize_t fail)
 {
     OSSL_QUIC_FRAME_STREAM f = {0};
 
-    if (!TEST_int_eq(ossl_quic_wire_decode_frame_stream(pkt, &f), fail < 0))
+    if (!TEST_int_eq(ossl_quic_wire_decode_frame_stream(pkt, 0, &f), fail < 0))
         return 0;
 
     if (fail >= 0)
         return 1;
 
-    if (!TEST_mem_eq(f.data, f.len,
+    if (!TEST_uint64_t_le(f.len, SIZE_MAX))
+        return 0;
+
+    if (!TEST_mem_eq(f.data, (size_t)f.len,
                      encode_case_9_data, sizeof(encode_case_9_data)))
         return 0;
 
@@ -515,23 +533,36 @@ static int encode_case_12_dec(PACKET *pkt, ossl_ssize_t fail)
 {
     uint64_t max_streams_1 = 0, max_streams_2 = 0,
             frame_type_1 = 0, frame_type_2 = 0;
+    int is_minimal = 1, success_if;
+
+    success_if = (fail < 0 || fail >= 1);
+    if (!TEST_int_eq(ossl_quic_wire_peek_frame_header(pkt, &frame_type_1,
+                                                      &is_minimal),
+                     success_if))
+        return 0;
 
-    if (!TEST_int_eq(ossl_quic_wire_peek_frame_header(pkt, &frame_type_1),
-                     fail < 0 || fail >= 1))
+    if (!TEST_true(!success_if || is_minimal))
         return 0;
 
+    success_if = (fail < 0 || fail >= 3);
     if (!TEST_int_eq(ossl_quic_wire_decode_frame_max_streams(pkt,
                                                              &max_streams_1),
-                     fail < 0 || fail >= 3))
+                     success_if))
         return 0;
 
-    if (!TEST_int_eq(ossl_quic_wire_peek_frame_header(pkt, &frame_type_2),
-                     fail < 0 || fail >= 4))
+    success_if = (fail < 0 || fail >= 4);
+    if (!TEST_int_eq(ossl_quic_wire_peek_frame_header(pkt, &frame_type_2,
+                                                      &is_minimal),
+                     success_if))
         return 0;
 
+    if (!TEST_true(!success_if || is_minimal))
+        return 0;
+
+    success_if = (fail < 0);
     if (!TEST_int_eq(ossl_quic_wire_decode_frame_max_streams(pkt,
                                                              &max_streams_2),
-                     fail < 0))
+                     success_if))
         return 0;
 
     if ((fail < 0 || fail >= 3)
@@ -645,18 +676,30 @@ static int encode_case_15_dec(PACKET *pkt, ossl_ssize_t fail)
 {
     uint64_t max_streams_1 = 0, max_streams_2 = 0,
             frame_type_1 = 0, frame_type_2 = 0;
+    int is_minimal = 1, success_if;
+
+    success_if = (fail < 0 || fail >= 1);
+    if (!TEST_int_eq(ossl_quic_wire_peek_frame_header(pkt, &frame_type_1,
+                                                      &is_minimal),
+                     success_if))
+        return 0;
 
-    if (!TEST_int_eq(ossl_quic_wire_peek_frame_header(pkt, &frame_type_1),
-                     fail < 0 || fail >= 1))
+    if (!TEST_true(!success_if || is_minimal))
         return 0;
 
+    success_if = (fail < 0 || fail >= 3);
     if (!TEST_int_eq(ossl_quic_wire_decode_frame_streams_blocked(pkt,
                                                                  &max_streams_1),
-                     fail < 0 || fail >= 3))
+                     success_if))
         return 0;
 
-    if (!TEST_int_eq(ossl_quic_wire_peek_frame_header(pkt, &frame_type_2),
-                     fail < 0 || fail >= 4))
+    success_if = (fail < 0 || fail >= 4);
+    if (!TEST_int_eq(ossl_quic_wire_peek_frame_header(pkt, &frame_type_2,
+                                                      &is_minimal),
+                     success_if))
+        return 0;
+
+    if (!TEST_true(!success_if || is_minimal))
         return 0;
 
     if (!TEST_int_eq(ossl_quic_wire_decode_frame_streams_blocked(pkt,
@@ -696,15 +739,17 @@ static const unsigned char encode_case_16_conn_id[] = {
 };
 
 static const OSSL_QUIC_FRAME_NEW_CONN_ID encode_case_16_f = {
-    0x1234,
     0x9781,
+    0x1234,
     {
         0x4,
         {0x33, 0x44, 0x55, 0x66}
     },
     {
-        0xde, 0x06, 0xcb, 0x76, 0x5d, 0xb1, 0xa7, 0x71,
-        0x78, 0x09, 0xbb, 0xe8, 0x50, 0x19, 0x12, 0x9a
+        {
+            0xde, 0x06, 0xcb, 0x76, 0x5d, 0xb1, 0xa7, 0x71,
+            0x78, 0x09, 0xbb, 0xe8, 0x50, 0x19, 0x12, 0x9a
+        }
     }
 };
 
@@ -727,10 +772,10 @@ static int encode_case_16_dec(PACKET *pkt, ossl_ssize_t fail)
     if (fail >= 0)
         return 1;
 
-    if (!TEST_uint64_t_eq(f.seq_num, 0x1234))
+    if (!TEST_uint64_t_eq(f.seq_num, 0x9781))
         return 0;
 
-    if (!TEST_uint64_t_eq(f.retire_prior_to, 0x9781))
+    if (!TEST_uint64_t_eq(f.retire_prior_to, 0x1234))
         return 0;
 
     if (!TEST_uint64_t_eq(f.conn_id.id_len, sizeof(encode_case_16_conn_id)))
@@ -740,16 +785,64 @@ static int encode_case_16_dec(PACKET *pkt, ossl_ssize_t fail)
                      encode_case_16_conn_id, sizeof(encode_case_16_conn_id)))
         return 0;
 
-    if (!TEST_mem_eq(f.stateless_reset_token,
-                     sizeof(f.stateless_reset_token),
-                     encode_case_16_f.stateless_reset_token,
-                     sizeof(encode_case_16_f.stateless_reset_token)))
+    if (!TEST_mem_eq(f.stateless_reset.token,
+                     sizeof(f.stateless_reset.token),
+                     encode_case_16_f.stateless_reset.token,
+                     sizeof(encode_case_16_f.stateless_reset.token)))
         return 0;
 
     return 1;
 }
 
 static const unsigned char encode_case_16_expect[] = {
+    0x18,                           /* Type */
+    0x80, 0x00, 0x97, 0x81,         /* Sequence Number */
+    0x52, 0x34,                     /* Retire Prior To */
+    0x04,                           /* Connection ID Length */
+    0x33, 0x44, 0x55, 0x66,         /* Connection ID */
+    0xde, 0x06, 0xcb, 0x76, 0x5d, 0xb1, 0xa7, 0x71, /* Stateless Reset Token */
+    0x78, 0x09, 0xbb, 0xe8, 0x50, 0x19, 0x12, 0x9a
+};
+
+/* 16b. NEW_CONNECTION_ID seq_num < retire_prior_to */
+static const OSSL_QUIC_FRAME_NEW_CONN_ID encode_case_16b_f = {
+    0x1234,
+    0x9781,
+    {
+        0x4,
+        {0x33, 0x44, 0x55, 0x66}
+    },
+    {
+        {
+            0xde, 0x06, 0xcb, 0x76, 0x5d, 0xb1, 0xa7, 0x71,
+            0x78, 0x09, 0xbb, 0xe8, 0x50, 0x19, 0x12, 0x9a
+        }
+    }
+};
+
+static int encode_case_16b_enc(WPACKET *pkt)
+{
+    if (!TEST_int_eq(ossl_quic_wire_encode_frame_new_conn_id(pkt,
+                                                             &encode_case_16b_f), 1))
+        return 0;
+
+    return 1;
+}
+
+static int encode_case_16b_dec(PACKET *pkt, ossl_ssize_t fail)
+{
+    OSSL_QUIC_FRAME_NEW_CONN_ID f = {0};
+
+    if (!TEST_int_eq(ossl_quic_wire_decode_frame_new_conn_id(pkt, &f), 0))
+        return 0;
+
+    if (!TEST_true(PACKET_forward(pkt, PACKET_remaining(pkt))))
+        return 0;
+
+    return 1;
+}
+
+static const unsigned char encode_case_16b_expect[] = {
     0x18,                           /* Type */
     0x52, 0x34,                     /* Sequence Number */
     0x80, 0x00, 0x97, 0x81,         /* Retire Prior To */
@@ -868,7 +961,7 @@ static const OSSL_QUIC_FRAME_CONN_CLOSE encode_case_20_f = {
     0,
     0x1234,
     0x9781,
-    encode_case_20_reason,
+    (char *)encode_case_20_reason,
     sizeof(encode_case_20_reason)
 };
 
@@ -1119,6 +1212,7 @@ static const struct encode_test_case encode_cases[] = {
     ENCODE_CASE(14)
     ENCODE_CASE(15)
     ENCODE_CASE(16)
+    ENCODE_CASE(16b)
     ENCODE_CASE(17)
     ENCODE_CASE(18)
     ENCODE_CASE(19)
@@ -1419,10 +1513,133 @@ err:
     return testresult;
 }
 
+/* RFC 9001 s. A.4 */
+static const QUIC_CONN_ID retry_orig_dcid = {
+    8, { 0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08 }
+};
+
+static const unsigned char retry_encoded[] = {
+  0xff,                                                 /* Long Header, Retry */
+  0x00, 0x00, 0x00, 0x01,                               /* Version 1 */
+  0x00,                                                 /* DCID */
+  0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5, /* SCID */
+
+  /* Retry Token */
+  0x74, 0x6f, 0x6b, 0x65, 0x6e,
+
+  /* Retry Integrity Tag */
+  0x04, 0xa2, 0x65, 0xba, 0x2e, 0xff, 0x4d, 0x82, 0x90, 0x58, 0xfb, 0x3f, 0x0f,
+  0x24, 0x96, 0xba
+};
+
+static int test_wire_retry_integrity_tag(void)
+{
+    int testresult = 0;
+    PACKET pkt = {0};
+    QUIC_PKT_HDR hdr = {0};
+    unsigned char got_tag[QUIC_RETRY_INTEGRITY_TAG_LEN] = {0};
+
+    if (!TEST_true(PACKET_buf_init(&pkt, retry_encoded, sizeof(retry_encoded))))
+        goto err;
+
+    if (!TEST_true(ossl_quic_wire_decode_pkt_hdr(&pkt, 0, 0, 0, &hdr, NULL)))
+        goto err;
+
+    if (!TEST_int_eq(hdr.type, QUIC_PKT_TYPE_RETRY))
+        goto err;
+
+    if (!TEST_true(ossl_quic_calculate_retry_integrity_tag(NULL, NULL, &hdr,
+                                                           &retry_orig_dcid,
+                                                           got_tag)))
+        goto err;
+
+    if (!TEST_mem_eq(got_tag, sizeof(got_tag),
+                     retry_encoded + sizeof(retry_encoded)
+                        - QUIC_RETRY_INTEGRITY_TAG_LEN,
+                     QUIC_RETRY_INTEGRITY_TAG_LEN))
+        goto err;
+
+    if (!TEST_true(ossl_quic_validate_retry_integrity_tag(NULL, NULL, &hdr,
+                                                          &retry_orig_dcid)))
+        goto err;
+
+    testresult = 1;
+err:
+    return testresult;
+}
+
+/* is_minimal=0 test */
+static const unsigned char non_minimal_1[] = {
+    0x40, 0x00,
+};
+
+static const unsigned char non_minimal_2[] = {
+    0x40, 0x3F,
+};
+
+static const unsigned char non_minimal_3[] = {
+    0x80, 0x00, 0x00, 0x00,
+};
+
+static const unsigned char non_minimal_4[] = {
+    0x80, 0x00, 0x3F, 0xFF,
+};
+
+static const unsigned char non_minimal_5[] = {
+    0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char non_minimal_6[] = {
+    0xC0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF
+};
+
+static const unsigned char *const non_minimal[] = {
+    non_minimal_1,
+    non_minimal_2,
+    non_minimal_3,
+    non_minimal_4,
+    non_minimal_5,
+    non_minimal_6,
+};
+
+static const size_t non_minimal_len[] = {
+    OSSL_NELEM(non_minimal_1),
+    OSSL_NELEM(non_minimal_2),
+    OSSL_NELEM(non_minimal_3),
+    OSSL_NELEM(non_minimal_4),
+    OSSL_NELEM(non_minimal_5),
+    OSSL_NELEM(non_minimal_6),
+};
+
+static int test_wire_minimal(int idx)
+{
+    int testresult = 0;
+    int is_minimal;
+    uint64_t frame_type;
+    PACKET pkt;
+
+    if (!TEST_true(PACKET_buf_init(&pkt, non_minimal[idx],
+                                   non_minimal_len[idx])))
+        goto err;
+
+    if (!TEST_true(ossl_quic_wire_peek_frame_header(&pkt, &frame_type,
+                                                    &is_minimal)))
+        goto err;
+
+    if (!TEST_false(is_minimal))
+        goto err;
+
+    testresult = 1;
+err:
+    return testresult;
+}
+
 int setup_tests(void)
 {
     ADD_ALL_TESTS(test_wire_encode,     OSSL_NELEM(encode_cases));
     ADD_ALL_TESTS(test_wire_ack,        OSSL_NELEM(ack_cases));
     ADD_ALL_TESTS(test_wire_pkt_hdr_pn, OSSL_NELEM(pn_tests));
+    ADD_TEST(test_wire_retry_integrity_tag);
+    ADD_ALL_TESTS(test_wire_minimal,    OSSL_NELEM(non_minimal_len));
     return 1;
 }