--- /dev/null
+/*
+* Copyright 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
+* in the file LICENSE in the source distribution or at
+* https://www.openssl.org/source/license.html
+*/
+
+#ifndef OSSL_INTERNAL_QUIC_SRT_GEN_H
+# define OSSL_INTERNAL_QUIC_SRT_GEN_H
+# pragma once
+
+# include "internal/e_os.h"
+# include "internal/time.h"
+# include "internal/quic_types.h"
+# include "internal/quic_wire.h"
+
+# ifndef OPENSSL_NO_QUIC
+
+/*
+ * QUIC Stateless Reset Token Generator
+ * ====================================
+ *
+ * This generates 16-byte QUIC Stateless Reset Tokens given a secret symmetric
+ * key and a DCID. Because the output is deterministic with regards to these
+ * inputs, assuming the same key is used between invocations of a process, we
+ * are able to generate the same stateless reset token in a subsequent process,
+ * thereby allowing us to achieve stateless reset of a peer which still thinks
+ * it is connected to a past process at the same UDP address.
+ */
+typedef struct quic_srt_gen_st QUIC_SRT_GEN;
+
+/*
+ * Create a new stateless reset token generator using the given key as input.
+ * The key may be of arbitrary length.
+ *
+ * The caller is responsible for performing domain separation with regards to
+ * the key; i.e., the caller is responsible for ensuring the key is never used
+ * in any other context.
+ */
+QUIC_SRT_GEN *ossl_quic_srt_gen_new(OSSL_LIB_CTX *libctx, const char *propq,
+ const unsigned char *key, size_t key_len);
+
+/* Free the stateless reset token generator. No-op if srt_gen is NULL. */
+void ossl_quic_srt_gen_free(QUIC_SRT_GEN *srt_gen);
+
+/*
+ * Calculates a token using the given DCID and writes it to *token. Returns 0 on
+ * failure.
+ */
+int ossl_quic_srt_gen_calculate_token(QUIC_SRT_GEN *srt_gen,
+ const QUIC_CONN_ID *dcid,
+ QUIC_STATELESS_RESET_TOKEN *token);
+
+# endif
+#endif
SOURCE[$LIBSSL]=quic_tls.c
SOURCE[$LIBSSL]=quic_thread_assist.c
SOURCE[$LIBSSL]=quic_trace.c
-SOURCE[$LIBSSL]=quic_srtm.c
+SOURCE[$LIBSSL]=quic_srtm.c quic_srt_gen.c
--- /dev/null
+/*
+ * Copyright 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#include "internal/quic_srt_gen.h"
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+
+struct quic_srt_gen_st {
+ EVP_MAC *mac;
+ EVP_MAC_CTX *mac_ctx;
+};
+
+/*
+ * Simple HMAC-SHA256-based stateless reset token generator.
+ */
+
+QUIC_SRT_GEN *ossl_quic_srt_gen_new(OSSL_LIB_CTX *libctx, const char *propq,
+ const unsigned char *key, size_t key_len)
+{
+ QUIC_SRT_GEN *srt_gen;
+ OSSL_PARAM params[3], *p = params;
+
+ if ((srt_gen = OPENSSL_zalloc(sizeof(*srt_gen))) == NULL)
+ return NULL;
+
+ if ((srt_gen->mac = EVP_MAC_fetch(libctx, "HMAC", propq)) == NULL)
+ goto err;
+
+ if ((srt_gen->mac_ctx = EVP_MAC_CTX_new(srt_gen->mac)) == NULL)
+ goto err;
+
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, "SHA256", 7);
+ if (propq != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,
+ (char *)propq, 0);
+ *p++ = OSSL_PARAM_construct_end();
+
+ if (!EVP_MAC_init(srt_gen->mac_ctx, key, key_len, params))
+ goto err;
+
+ return srt_gen;
+
+err:
+ ossl_quic_srt_gen_free(srt_gen);
+ return NULL;
+}
+
+void ossl_quic_srt_gen_free(QUIC_SRT_GEN *srt_gen)
+{
+ if (srt_gen == NULL)
+ return;
+
+ EVP_MAC_CTX_free(srt_gen->mac_ctx);
+ EVP_MAC_free(srt_gen->mac);
+ OPENSSL_free(srt_gen);
+}
+
+int ossl_quic_srt_gen_calculate_token(QUIC_SRT_GEN *srt_gen,
+ const QUIC_CONN_ID *dcid,
+ QUIC_STATELESS_RESET_TOKEN *token)
+{
+ size_t outl = 0;
+ unsigned char mac[32];
+
+ if (!EVP_MAC_init(srt_gen->mac_ctx, NULL, 0, NULL))
+ return 0;
+
+ if (!EVP_MAC_update(srt_gen->mac_ctx, (const unsigned char *)dcid->id,
+ dcid->id_len))
+ return 0;
+
+ if (!EVP_MAC_final(srt_gen->mac_ctx, mac, &outl, sizeof(mac))
+ || outl != sizeof(mac))
+ return 0;
+
+ memcpy(token, mac, sizeof(*token));
+ return 1;
+}
IF[{- !$disabled{quic} -}]
PROGRAMS{noinst}=priority_queue_test event_queue_test quicfaultstest quicapitest \
- quic_newcid_test
+ quic_newcid_test quic_srt_gen_test
ENDIF
IF[{- !$disabled{comp} && (!$disabled{brotli} || !$disabled{zstd} || !$disabled{zlib}) -}]
SOURCE[quic_newcid_test]=quic_newcid_test.c helpers/ssltestlib.c $QUICTESTHELPERS
INCLUDE[quic_newcid_test]=../include ../apps/include ..
DEPEND[quic_newcid_test]=../libcrypto.a ../libssl.a libtestutil.a
+
+ SOURCE[quic_srt_gen_test]=quic_srt_gen_test.c helpers/ssltestlib.c $QUICTESTHELPERS
+ INCLUDE[quic_srt_gen_test]=../include ../apps/include ..
+ DEPEND[quic_srt_gen_test]=../libcrypto.a ../libssl.a libtestutil.a
ENDIF
SOURCE[dhtest]=dhtest.c
--- /dev/null
+/*
+ * Copyright 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+#include "internal/quic_srt_gen.h"
+
+#include "testutil.h"
+#include "testutil/output.h"
+
+struct test_case {
+ const unsigned char *key;
+ size_t key_len;
+ QUIC_CONN_ID dcid;
+ QUIC_STATELESS_RESET_TOKEN expected;
+};
+
+static const unsigned char key_1[] = { 0x01, 0x02, 0x03 };
+
+static const unsigned char key_2[] = {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const struct test_case tests[] = {
+ {
+ key_1, sizeof(key_1), { 2, { 0x55, 0x66 } },
+ {{ 0x02,0x9e,0x8f,0x3d,0x1e,0xa9,0x06,0x23,0xb2,0x43,0xd2,0x19,0x59,0x8a,0xa1,0x66 }}
+ },
+ {
+ key_2, sizeof(key_2), { 0, { 0 } },
+ {{ 0x93,0x10,0x2f,0xc7,0xaf,0x9d,0x9b,0x28,0x3f,0x84,0x95,0x6b,0xa3,0xdc,0x07,0x6b }}
+ },
+ {
+ key_2, sizeof(key_2),
+ { 20, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } },
+ {{ 0x9a,0x98,0x98,0x61,0xbe,0xfd,0xe3,0x05,0x45,0xac,0x66,0xcf,0x3b,0x58,0xfb,0xab }}
+ }
+};
+
+static int test_srt_gen(int idx)
+{
+ int testresult = 0;
+ const struct test_case *t = &tests[idx];
+ QUIC_SRT_GEN *srt_gen = NULL;
+ QUIC_STATELESS_RESET_TOKEN token;
+ size_t i;
+
+ if (!TEST_ptr(srt_gen = ossl_quic_srt_gen_new(NULL, NULL,
+ t->key, t->key_len)))
+ goto err;
+
+ for (i = 0; i < 2; ++i) {
+ memset(&token, 0xff, sizeof(token));
+
+ if (!TEST_true(ossl_quic_srt_gen_calculate_token(srt_gen, &t->dcid,
+ &token)))
+ goto err;
+
+ if (!TEST_mem_eq(&token, sizeof(token),
+ &t->expected, sizeof(t->expected)))
+ goto err;
+ }
+
+ testresult = 1;
+err:
+ ossl_quic_srt_gen_free(srt_gen);
+ return testresult;
+}
+
+int setup_tests(void)
+{
+ ADD_ALL_TESTS(test_srt_gen, OSSL_NELEM(tests));
+ return 1;
+}
--- /dev/null
+#! /usr/bin/env perl
+# 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
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use OpenSSL::Test qw/:DEFAULT/;
+use OpenSSL::Test::Utils;
+
+setup("test_quic_srt_gen");
+
+plan skip_all => "QUIC protocol is not supported by this OpenSSL build"
+ if disabled('quic');
+
+plan tests => 1;
+
+ok(run(test(["quic_srt_gen_test"])));