]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
QUIC Wire Encoding: Support Retry Integrity Tag Calculation
authorHugo Landau <hlandau@openssl.org>
Mon, 31 Oct 2022 15:15:26 +0000 (15:15 +0000)
committerHugo Landau <hlandau@openssl.org>
Fri, 13 Jan 2023 13:20:10 +0000 (13:20 +0000)
This adds support for calculating and verifying retry integrity tags. In
order to support this, an 'unused' field is added to the QUIC packet
header structure so we can ensure that the serialization of the header
is bit-for-bit identical to what was decoded.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19703)

include/internal/quic_wire_pkt.h
ssl/quic/quic_wire_pkt.c
test/quic_record_test.c
test/quic_record_test_util.h
test/quic_wire_test.c

index 34e95ba7b6869f065533d8d580b7d49181b66d79..daf1785591657f71c45da3db018656d16a980e16 100644 (file)
@@ -322,6 +322,14 @@ typedef struct quic_pkt_hdr_st {
      */
     unsigned int    fixed       :1;
 
+    /*
+     * The unused bits in the low 4 bits of a Retry packet header's first byte.
+     * This is used to ensure that Retry packets have the same bit-for-bit
+     * representation in their header when decoding and encoding them again.
+     * This is necessary to validate Retry packet headers.
+     */
+    unsigned int    unused      :4;
+
     /* [L] Version field. Valid if (type != 1RTT). */
     uint32_t        version;
 
@@ -537,4 +545,51 @@ int ossl_quic_wire_determine_pn_len(QUIC_PN pn, QUIC_PN largest_acked);
 int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
                                      unsigned char *enc_pn,
                                      size_t enc_pn_len);
+
+/*
+ * Retry Integrity Tags
+ * ====================
+ */
+
+#define QUIC_RETRY_INTEGRITY_TAG_LEN    16
+
+/*
+ * Validate a retry integrity tag. Returns 1 if the tag is valid.
+ *
+ * Must be called on a hdr with a type of QUIC_PKT_TYPE_RETRY with a valid data
+ * pointer.
+ *
+ * client_initial_dcid must be the original DCID used by the client in its first
+ * Initial packet, as this is used to calculate the Retry Integrity Tag.
+ *
+ * Returns 0 if the tag is invalid, if called on any other type of packet or if
+ * the body is too short.
+ */
+int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
+                                           const char *propq,
+                                           const QUIC_PKT_HDR *hdr,
+                                           const QUIC_CONN_ID *client_initial_dcid);
+
+/*
+ * Calculates a retry integrity tag. Returns 0 on error, for example if hdr does
+ * not have a type of QUIC_PKT_TYPE_RETRY.
+ *
+ * client_initial_dcid must be the original DCID used by the client in its first
+ * Initial packet, as this is used to calculate the Retry Integrity Tag.
+ *
+ * tag must point to a buffer of QUIC_RETRY_INTEGRITY_TAG_LEN bytes in size.
+ *
+ * Note that hdr->data must point to the Retry packet body, and hdr->len must
+ * include the space for the Retry Integrity Tag. (This means that you can
+ * easily fill in a tag in a Retry packet you are generating by calling this
+ * function and passing (hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN) as
+ * the tag argument.) This function fails if hdr->len is too short to contain a
+ * Retry Integrity Tag.
+ */
+int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
+                                            const char *propq,
+                                            const QUIC_PKT_HDR *hdr,
+                                            const QUIC_CONN_ID *client_initial_dcid,
+                                            unsigned char *tag);
+
 #endif
index a4fdc7bf53008d8b22f0e6c0db008cadafd4ba06..de3466daa2129890fddd696039cd5da4176ee091 100644 (file)
@@ -181,6 +181,7 @@ int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt,
         return 0;
 
     hdr->partial = partial;
+    hdr->unused  = 0;
 
     if ((b0 & 0x80) == 0) {
         /* Short header. */
@@ -353,6 +354,9 @@ int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt,
                 /* Retry packets are always fully decoded. */
                 hdr->partial    = 0;
 
+                /* Unused bits in Retry header. */
+                hdr->unused     = b0 & 0x0f;
+
                 /* Fields not used in Retry packets. */
                 memset(hdr->pn, 0, sizeof(hdr->pn));
 
@@ -490,6 +494,8 @@ int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt,
             b0 |= 0x40; /* fixed */
         if (ossl_quic_pkt_type_has_pn(hdr->type))
             b0 |= hdr->pn_len - 1;
+        if (hdr->type == QUIC_PKT_TYPE_RETRY)
+            b0 |= hdr->unused;
 
         if (!WPACKET_put_bytes_u8(pkt, b0)
             || !WPACKET_put_bytes_u32(pkt, hdr->version)
@@ -503,7 +509,7 @@ int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt,
 
         if (hdr->type == QUIC_PKT_TYPE_VERSION_NEG
             || hdr->type == QUIC_PKT_TYPE_RETRY) {
-            if (!WPACKET_reserve_bytes(pkt, hdr->len, NULL))
+            if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
                 return 0;
 
             return 1;
@@ -521,7 +527,7 @@ int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt,
             return 0;
     }
 
-    if (!WPACKET_reserve_bytes(pkt, hdr->len, NULL))
+    if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
         return 0;
 
     off_sample = off_pn + 4;
@@ -745,3 +751,125 @@ int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
 
     return 1;
 }
+
+int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
+                                           const char *propq,
+                                           const QUIC_PKT_HDR *hdr,
+                                           const QUIC_CONN_ID *client_initial_dcid)
+{
+    unsigned char expected_tag[QUIC_RETRY_INTEGRITY_TAG_LEN];
+    const unsigned char *actual_tag;
+
+    if (hdr == NULL || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN)
+        return 0;
+
+    if (!ossl_quic_calculate_retry_integrity_tag(libctx, propq,
+                                                 hdr, client_initial_dcid,
+                                                 expected_tag))
+        return 0;
+
+    actual_tag = hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN;
+
+    return !CRYPTO_memcmp(expected_tag, actual_tag,
+                          QUIC_RETRY_INTEGRITY_TAG_LEN);
+}
+
+/* RFC 9001 s. 5.8 */
+static const unsigned char retry_integrity_key[] = {
+    0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a,
+    0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e
+};
+
+static const unsigned char retry_integrity_nonce[] = {
+    0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2,
+    0x23, 0x98, 0x25, 0xbb
+};
+
+int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
+                                            const char *propq,
+                                            const QUIC_PKT_HDR *hdr,
+                                            const QUIC_CONN_ID *client_initial_dcid,
+                                            unsigned char *tag)
+{
+    EVP_CIPHER *cipher = NULL;
+    EVP_CIPHER_CTX *cctx = NULL;
+    int ok = 0, l = 0, l2 = 0, wpkt_valid = 0;
+    WPACKET wpkt;
+    /* Worst case length of the Retry Psuedo-Packet header is 68 bytes. */
+    unsigned char buf[128];
+    QUIC_PKT_HDR hdr2;
+    size_t hdr_enc_len = 0;
+
+    if (hdr->type != QUIC_PKT_TYPE_RETRY || hdr->version == 0
+        || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN
+        || hdr->data == NULL
+        || client_initial_dcid == NULL || tag == NULL
+        || client_initial_dcid->id_len > QUIC_MAX_CONN_ID_LEN)
+        goto err;
+
+    /*
+     * Do not reserve packet body in WPACKET. Retry packet header
+     * does not contain a Length field so this does not affect
+     * the serialized packet header.
+     */
+    hdr2 = *hdr;
+    hdr2.len = 0;
+
+    /* Assemble retry psuedo-packet. */
+    if (!WPACKET_init_static_len(&wpkt, buf, sizeof(buf), 0))
+        goto err;
+
+    wpkt_valid = 1;
+
+    /* Prepend original DCID to the packet. */
+    if (!WPACKET_put_bytes_u8(&wpkt, client_initial_dcid->id_len)
+        || !WPACKET_memcpy(&wpkt, client_initial_dcid->id,
+                           client_initial_dcid->id_len))
+        goto err;
+
+    /* Encode main retry header. */
+    if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, hdr2.dst_conn_id.id_len,
+                                       &hdr2, NULL))
+        goto err;
+
+    if (!WPACKET_get_total_written(&wpkt, &hdr_enc_len))
+        return 0;
+
+    /* Create and initialise cipher context. */
+    if ((cipher = EVP_CIPHER_fetch(libctx, "AES-128-GCM", propq)) == NULL)
+        goto err;
+
+    if ((cctx = EVP_CIPHER_CTX_new()) == NULL)
+        goto err;
+
+    if (!EVP_CipherInit_ex(cctx, cipher, NULL,
+                           retry_integrity_key, retry_integrity_nonce, /*enc=*/1))
+        goto err;
+
+    /* Feed packet header as AAD data. */
+    if (EVP_CipherUpdate(cctx, NULL, &l, buf, hdr_enc_len) != 1)
+        return 0;
+
+    /* Feed packet body as AAD data. */
+    if (EVP_CipherUpdate(cctx, NULL, &l, hdr->data,
+                         hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN) != 1)
+        return 0;
+
+    /* Finalise and get tag. */
+    if (EVP_CipherFinal_ex(cctx, NULL, &l2) != 1)
+        return 0;
+
+    if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG,
+                            QUIC_RETRY_INTEGRITY_TAG_LEN,
+                            tag) != 1)
+        return 0;
+
+    ok = 1;
+err:
+    EVP_CIPHER_free(cipher);
+    EVP_CIPHER_CTX_free(cctx);
+    if (wpkt_valid)
+        WPACKET_finish(&wpkt);
+
+    return ok;
+}
index f02abb25b8af3aaca2096d435f98e3732b824412..1664cd2afcabe88df9142c5ddd9dc4824a728ca4 100644 (file)
@@ -150,7 +150,7 @@ static const QUIC_CONN_ID rx_script_1_dcid = {
 
 static const QUIC_PKT_HDR rx_script_1_expect_hdr = {
     QUIC_PKT_TYPE_INITIAL,
-    0, 0, 2, 0, 1, 1, { 0, {0} },
+    0, 0, 2, 0, 1, 0, 1, { 0, {0} },
     { 8, {0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5 } },
     { 0, 1, 0, 0 },
     NULL, 0,
@@ -186,7 +186,7 @@ static const unsigned char rx_script_2_body[] = {
 
 static const QUIC_PKT_HDR rx_script_2_expect_hdr = {
     QUIC_PKT_TYPE_1RTT,
-    0, 0, 3, 0, 1, 0, {0, {0}}, {0, {0}},
+    0, 0, 3, 0, 1, 0, 0, {0, {0}}, {0, {0}},
     {0x00, 0xbf, 0xf4, 0x00},
     NULL, 0,
     1, NULL
@@ -222,6 +222,7 @@ static const QUIC_PKT_HDR rx_script_3_expect_hdr = {
     0,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},                                   /* DCID */
     {12, {0x35, 0x3c, 0x1b, 0x97, 0xca, 0xf8,   /* SCID */
@@ -274,6 +275,7 @@ static const QUIC_PKT_HDR rx_script_4_expect_hdr = {
     0,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     1,          /* Version */
     {0, {0}},                           /* DCID */
     {4, {0xad, 0x15, 0x3f, 0xae}},      /* SCID */
@@ -455,6 +457,7 @@ static const QUIC_PKT_HDR rx_script_5a_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     1,          /* Version */
     {0, {0}},                           /* DCID */
     {4, {0x83, 0xd0, 0x0a, 0x27}},      /* SCID */
@@ -511,6 +514,7 @@ static const QUIC_PKT_HDR rx_script_5b_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     1,          /* Version */
     {0, {0}},                           /* DCID */
     {4, {0x83, 0xd0, 0x0a, 0x27}},      /* SCID */
@@ -584,6 +588,7 @@ static const QUIC_PKT_HDR rx_script_5c_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},                           /* DCID */
     {0, {0}},                           /* SCID */
@@ -818,6 +823,7 @@ static const QUIC_PKT_HDR rx_script_6a_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     1,          /* Version */
     {0, {0}},                           /* DCID */
     {4, {0x36, 0xf4, 0x75, 0x2d}},      /* SCID */
@@ -872,6 +878,7 @@ static const QUIC_PKT_HDR rx_script_6b_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     1,          /* Version */
     {0, {0}},                           /* DCID */
     {4, {0x36, 0xf4, 0x75, 0x2d}},      /* SCID */
@@ -946,6 +953,7 @@ static const QUIC_PKT_HDR rx_script_6c_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},                           /* DCID */
     {0, {0}},                           /* SCID */
@@ -1174,6 +1182,7 @@ static const QUIC_PKT_HDR rx_script_7a_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     1,          /* Version */
     {0, {0}},                           /* DCID */
     {4, {0x03, 0x45, 0x0c, 0x7a}},      /* SCID */
@@ -1229,6 +1238,7 @@ static const QUIC_PKT_HDR rx_script_7b_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     1,          /* Version */
     {0, {0}},                           /* DCID */
     {4, {0x03, 0x45, 0x0c, 0x7a}},      /* SCID */
@@ -1302,6 +1312,7 @@ static const QUIC_PKT_HDR rx_script_7c_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},                           /* DCID */
     {0, {0}},                           /* SCID */
@@ -1402,6 +1413,7 @@ static const QUIC_PKT_HDR rx_script_8a_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},   /* DCID */
     {0, {0}},   /* SCID */
@@ -1433,6 +1445,7 @@ static const QUIC_PKT_HDR rx_script_8b_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},   /* DCID */
     {0, {0}},   /* SCID */
@@ -1463,6 +1476,7 @@ static const QUIC_PKT_HDR rx_script_8c_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},   /* DCID */
     {0, {0}},   /* SCID */
@@ -1494,6 +1508,7 @@ static const QUIC_PKT_HDR rx_script_8d_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},   /* DCID */
     {0, {0}},   /* SCID */
@@ -1525,6 +1540,7 @@ static const QUIC_PKT_HDR rx_script_8e_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},   /* DCID */
     {0, {0}},   /* SCID */
@@ -1553,6 +1569,7 @@ static const QUIC_PKT_HDR rx_script_8f_expect_hdr = {
     2,          /* PN Length */
     0,          /* Partial */
     1,          /* Fixed */
+    0,          /* Unused */
     0,          /* Version */
     {0, {0}},   /* DCID */
     {0, {0}},   /* SCID */
@@ -1969,6 +1986,7 @@ static const struct pkt_hdr_test pkt_hdr_test_1 = {
         2,                      /* PN length */
         0,                      /* partial */
         1,                      /* fixed */
+        0,                      /* unused */
         1,                      /* version */
         { 0, {0} },             /* DCID */
         { 8, {0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5 } }, /* SCID */
@@ -2015,6 +2033,7 @@ static const struct pkt_hdr_test pkt_hdr_test_2 = {
         2,                      /* PN length */
         0,                      /* partial */
         1,                      /* fixed */
+        0,                      /* unused */
         1,                      /* version */
         { 0, {0} },             /* DCID */
         { 8, {0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5 } }, /* SCID */
@@ -2062,6 +2081,7 @@ static const struct pkt_hdr_test pkt_hdr_test_3 = {
         2,                      /* PN length */
         0,                      /* partial */
         1,                      /* fixed */
+        0,                      /* unused */
         1,                      /* version */
         { 3, {0x70, 0x71, 0x72} },                                /* DCID */
         { 8, {0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5 } }, /* SCID */
@@ -2103,6 +2123,7 @@ static const struct pkt_hdr_test pkt_hdr_test_4 = {
         1,                      /* PN length */
         0,                      /* partial */
         1,                      /* fixed */
+        0,                      /* unused */
         1,                      /* version */
         { 3, {0x70, 0x71, 0x72} },                                /* DCID */
         { 8, {0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5 } }, /* SCID */
@@ -2143,7 +2164,8 @@ static const struct pkt_hdr_test pkt_hdr_test_5 = {
         0,                          /* key phase */
         1,                          /* PN length */
         0,                          /* partial */
-        1,                      /* fixed */
+        1,                          /* fixed */
+        0,                          /* unused */
         1,                          /* version */
         { 3, {0x70, 0x71, 0x72} },                                /* DCID */
         { 8, {0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5 } }, /* SCID */
@@ -2183,6 +2205,7 @@ static const struct pkt_hdr_test pkt_hdr_test_6 = {
         0,                          /* PN length */
         0,                          /* partial */
         1,                          /* fixed */
+        0,                          /* unused */
         1,                          /* version */
         { 3, {0x70, 0x71, 0x72} },                                /* DCID */
         { 8, {0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5 } }, /* SCID */
@@ -2218,6 +2241,7 @@ static const struct pkt_hdr_test pkt_hdr_test_7 = {
         3,                          /* PN length */
         0,                          /* partial */
         1,                          /* fixed */
+        0,                          /* unused */
         0,                          /* version */
         { 3, {0x70, 0x71, 0x72} },  /* DCID */
         { 0, {0} },                 /* SCID */
@@ -2253,6 +2277,7 @@ static const struct pkt_hdr_test pkt_hdr_test_8 = {
         3,                          /* PN length */
         0,                          /* partial */
         1,                          /* fixed */
+        0,                          /* unused */
         0,                          /* version */
         { 3, {0x70, 0x71, 0x72} },  /* DCID */
         { 0, {0} },                 /* SCID */
@@ -2288,6 +2313,7 @@ static const struct pkt_hdr_test pkt_hdr_test_9 = {
         3,                          /* PN length */
         0,                          /* partial */
         1,                          /* fixed */
+        0,                          /* unused */
         0,                          /* version */
         { 3, {0x70, 0x71, 0x72} },  /* DCID */
         { 0, {0} },                 /* SCID */
@@ -2329,6 +2355,7 @@ static const struct pkt_hdr_test pkt_hdr_test_10 = {
         4,                          /* PN length */
         0,                          /* partial */
         1,                          /* fixed */
+        0,                          /* unused */
         1,                          /* version */
         { 3, {0x70, 0x71, 0x72} },                                /* DCID */
         { 8, {0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5 } }, /* SCID */
@@ -2364,6 +2391,7 @@ static const struct pkt_hdr_test pkt_hdr_test_11 = {
         4,                          /* PN length */
         0,                          /* partial */
         1,                          /* fixed */
+        0,                          /* unused */
         0,                          /* version */
         { 3, {0x70, 0x71, 0x72} },  /* DCID */
         { 0, {0} },                 /* SCID */
@@ -2398,6 +2426,7 @@ static const struct pkt_hdr_test pkt_hdr_test_12 = {
         0,                          /* PN length */
         0,                          /* partial */
         1,                          /* fixed */
+        0,                          /* unused */
         0,                          /* version */
         { 3, {0x70, 0x71, 0x72} },  /* DCID */
         { 2, {0x81, 0x82} },        /* SCID */
@@ -2432,6 +2461,7 @@ static const struct pkt_hdr_test pkt_hdr_test_13 = {
         0,                          /* PN length */
         0,                          /* partial */
         0,                          /* fixed */
+        0,                          /* unused */
         0,                          /* version */
         { 3, {0x70, 0x71, 0x72} },  /* DCID */
         { 2, {0x81, 0x82} },        /* SCID */
@@ -2964,6 +2994,7 @@ static QUIC_PKT_HDR tx_script_1_hdr = {
     4,                          /* PN length */
     0,                          /* partial */
     0,                          /* fixed */
+    0,                          /* unused */
     1,                          /* version */
     {8, {0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08}}, /* DCID */
     { 0, {0} },                 /* SCID */
@@ -3027,6 +3058,7 @@ static QUIC_PKT_HDR tx_script_2_hdr = {
     2,                          /* PN length */
     0,                          /* partial */
     0,                          /* fixed */
+    0,                          /* unused */
     1,                          /* version */
     { 0, {0} },                 /* DCID */
     {8, {0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5}}, /* SCID */
@@ -3077,6 +3109,7 @@ static QUIC_PKT_HDR tx_script_3_hdr = {
     3,                          /* PN length */
     0,                          /* partial */
     0,                          /* fixed */
+    0,                          /* unused */
     0,                          /* version */
     { 0, {0} },                 /* DCID */
     { 0, {0} },                 /* SCID */
@@ -3133,6 +3166,7 @@ static QUIC_PKT_HDR tx_script_4a_hdr = {
     2,                          /* PN length */
     0,                          /* partial */
     0,                          /* fixed */
+    0,                          /* unused */
     0,                          /* version */
     { 4, {0x6e, 0x4e, 0xbd, 0x49} }, /* DCID */
     { 0, {0} },                 /* SCID */
@@ -3175,6 +3209,7 @@ static QUIC_PKT_HDR tx_script_4b_hdr = {
     2,                          /* PN length */
     0,                          /* partial */
     0,                          /* fixed */
+    0,                          /* unused */
     0,                          /* version */
     { 4, {0x6e, 0x4e, 0xbd, 0x49} }, /* DCID */
     { 0, {0} },                 /* SCID */
@@ -3217,6 +3252,7 @@ static QUIC_PKT_HDR tx_script_4c_hdr = {
     2,                          /* PN length */
     0,                          /* partial */
     0,                          /* fixed */
+    0,                          /* unused */
     0,                          /* version */
     { 4, {0x6e, 0x4e, 0xbd, 0x49} }, /* DCID */
     { 0, {0} },                 /* SCID */
@@ -3286,6 +3322,7 @@ static QUIC_PKT_HDR tx_script_5_hdr = {
     0,                          /* PN length */
     0,                          /* partial */
     0,                          /* fixed */
+    0,                          /* unused */
     1,                          /* version */
     { 0, {0} },                 /* DCID */
     { 4, {0xa9, 0x20, 0xcc, 0xc2} },   /* SCID */
@@ -3336,6 +3373,7 @@ static QUIC_PKT_HDR tx_script_6_hdr = {
     0,                          /* PN length */
     0,                          /* partial */
     0,                          /* fixed */
+    0,                          /* unused */
     0,                          /* version */
     { 0, {0} },                 /* DCID */
     { 12, {0x35, 0x3c, 0x1b, 0x97, 0xca, 0xf8, 0x99,
index 51d5db8a6ea630e56a7dc0fd74ede4a3f968de2e..2dc0951f2ef5f9eb3befa484836ca5c830f4001f 100644 (file)
@@ -27,6 +27,7 @@ static int cmp_pkt_hdr(const QUIC_PKT_HDR *a, const QUIC_PKT_HDR *b,
         || !TEST_int_eq(a->pn_len, b->pn_len)
         || !TEST_int_eq(a->partial, b->partial)
         || !TEST_int_eq(a->fixed, b->fixed)
+        || !TEST_int_eq(a->unused, b->unused)
         || !TEST_uint_eq(a->version, b->version)
         || !TEST_true(ossl_quic_conn_id_eq(&a->dst_conn_id, &b->dst_conn_id))
         || !TEST_true(ossl_quic_conn_id_eq(&a->src_conn_id, &b->src_conn_id))
index 325e322694f04109dff2b9c4ce295160635c5338..ceb273e7b6d13bd510f3a9f22e9bdab51a159419 100644 (file)
@@ -1437,10 +1437,66 @@ 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, &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;
+}
+
 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);
     return 1;
 }