From bdd640e7e63d5ea3ff0af9a63261a252949b71c5 Mon Sep 17 00:00:00 2001
From: James M Snell <jasnell@gmail.com>
Date: Sun, 5 Jan 2020 13:27:19 -0800
Subject: [PATCH] Additional crypto helper function

* `ngtcp2_crypto_generate_stateless_reset_token` - Used to generate
  a stateless reset token as an HKDF extraction using the CID and
  a token secret as input.
---
 crypto/includes/ngtcp2/ngtcp2_crypto.h | 15 +++++++++++++++
 crypto/shared.c                        | 23 +++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/crypto/includes/ngtcp2/ngtcp2_crypto.h b/crypto/includes/ngtcp2/ngtcp2_crypto.h
index 99d2f687..1368c368 100644
--- a/crypto/includes/ngtcp2/ngtcp2_crypto.h
+++ b/crypto/includes/ngtcp2/ngtcp2_crypto.h
@@ -492,6 +492,21 @@ NGTCP2_EXTERN int
 ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls,
                                           ngtcp2_crypto_side side);
 
+/**
+ * @function
+ *
+ *  `ngtcp2_crypto_generate_stateless_reset_token` generates a
+ *  stateless reset token using HKDF extraction with |md| using the
+ *  given |cid| and static key |secret| as input.  The token will be
+ *  written to the buffer pointed by |token| and it must have a
+ *  capacity of at least NGTCP2_STATELESS_RESET_TOKENLEN bytes.
+ *
+ * This function returns 0 if it succeeds, or -1.
+ */
+NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token(
+    uint8_t *token, const ngtcp2_crypto_md *md, const uint8_t *secret,
+    size_t secretlen, const ngtcp2_cid *cid);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/crypto/shared.c b/crypto/shared.c
index 9d5feb60..f12736ce 100644
--- a/crypto/shared.c
+++ b/crypto/shared.c
@@ -25,6 +25,7 @@
 #include "shared.h"
 
 #include <string.h>
+#include <assert.h>
 
 #include "ngtcp2_macro.h"
 
@@ -419,3 +420,25 @@ int ngtcp2_crypto_update_key_cb(ngtcp2_conn *conn, uint8_t *rx_secret,
   }
   return 0;
 }
+
+int ngtcp2_crypto_generate_stateless_reset_token(uint8_t *token,
+                                                 const ngtcp2_crypto_md *md,
+                                                 const uint8_t *secret,
+                                                 size_t secretlen,
+                                                 const ngtcp2_cid *cid) {
+  uint8_t buf[64];
+  int rv;
+
+  assert(ngtcp2_crypto_md_hashlen(md) <= sizeof(buf));
+  assert(NGTCP2_STATELESS_RESET_TOKENLEN <= sizeof(buf));
+
+  rv = ngtcp2_crypto_hkdf_extract(buf, md, secret, secretlen, cid->data,
+                                  cid->datalen);
+  if (rv != 0) {
+    return -1;
+  }
+
+  memcpy(token, buf, NGTCP2_STATELESS_RESET_TOKENLEN);
+
+  return 0;
+}
-- 
GitLab