summaryrefslogtreecommitdiff
path: root/src/utils.cpp
diff options
context:
space:
mode:
author刘学利 <[email protected]>2021-08-23 11:15:11 +0000
committer刘学利 <[email protected]>2021-08-23 11:15:11 +0000
commitf68700112e61d6b920799a0cad54e1c2fe539b6e (patch)
tree2471cc1f228b0c847c0633309ed9d1ec17bd2179 /src/utils.cpp
parent13ba53b5a9a6d11f4349f6b2ec0997db1d08283a (diff)
TSG-7298: QUIC解析层支持解析quic-ietf加密SNI
Diffstat (limited to 'src/utils.cpp')
-rw-r--r--src/utils.cpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/utils.cpp b/src/utils.cpp
new file mode 100644
index 0000000..9af0ffa
--- /dev/null
+++ b/src/utils.cpp
@@ -0,0 +1,136 @@
+/**
+ * utils.c
+ *
+ * Created on 2020-11-27
+ * @author: qyc
+ *
+ * @explain:
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+#include "wsgcrypt.h"
+#include "pint.h"
+
+/*
+ * Computes HKDF-Expand-Label(Secret, Label, Hash(context_value), Length) with a
+ * custom label prefix. If "context_hash" is NULL, then an empty context is
+ * used. Otherwise it must have the same length as the hash algorithm output.
+ */
+static gboolean tls13_hkdf_expand_label_context(int md, const StringInfo *secret, const char *label_prefix, const char *label, const guint8 *context_hash, guint8 context_length, guint16 out_len, guchar **out)
+{
+ /* RFC 8446 Section 7.1:
+ * HKDF-Expand-Label(Secret, Label, Context, Length) =
+ * HKDF-Expand(Secret, HkdfLabel, Length)
+ * struct {
+ * uint16 length = Length;
+ * opaque label<7..255> = "tls13 " + Label; // "tls13 " is label prefix.
+ * opaque context<0..255> = Context;
+ * } HkdfLabel;
+ *
+ * RFC 5869 HMAC-based Extract-and-Expand Key Derivation Function (HKDF):
+ * HKDF-Expand(PRK, info, L) -> OKM
+ */
+ gcry_error_t err;
+ const guint label_prefix_length = (guint)strlen(label_prefix);
+ const guint label_length = (guint)strlen(label);
+
+ // Some sanity checks
+ g_assert(label_length > 0 && label_prefix_length + label_length <= 255);
+
+ // info = HkdfLabel { length, label, context }
+ GByteArray *info = g_byte_array_new();
+ const guint16 length = g_htons(out_len);
+ g_byte_array_append(info, (const guint8 *)&length, sizeof(length));
+
+ const guint8 label_vector_length = label_prefix_length + label_length;
+ g_byte_array_append(info, &label_vector_length, 1);
+ g_byte_array_append(info, (const guint8 *)label_prefix, label_prefix_length);
+ g_byte_array_append(info, (const guint8 *)label, label_length);
+
+ g_byte_array_append(info, &context_length, 1);
+ if (context_length)
+ g_byte_array_append(info, context_hash, context_length);
+
+ *out = (guchar *)g_malloc(out_len);
+ err = hkdf_expand(md, secret->data, secret->data_len, info->data, info->len, *out, out_len);
+ g_byte_array_free(info, TRUE);
+
+ if (err) {
+ printf("%s failed %d: %s\n", G_STRFUNC, md, gcry_strerror(err));
+ g_free(*out);
+ *out = NULL;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean tls13_hkdf_expand_label(int md, const StringInfo *secret, const char *label_prefix, const char *label, guint16 out_len, guchar **out)
+{
+ return tls13_hkdf_expand_label_context(md, secret, label_prefix, label, NULL, 0, out_len, out);
+}
+
+static guint8 tvb_get_guint8(const char *tvb, const gint offset)
+{
+ const guint8 *ptr;
+
+ ptr = (guint8 *)tvb + offset;
+ return *ptr;
+}
+
+static guint16 tvb_get_ntohs(const char *tvb, const gint offset)
+{
+ const guint8 *ptr;
+
+ ptr = (guint8 *)tvb + offset;
+ return pntoh16(ptr);
+}
+
+static guint32 tvb_get_ntohl(const char *tvb, const gint offset)
+{
+ const guint8 *ptr;
+
+ ptr = (guint8 *)tvb + offset;
+ return pntoh32(ptr);
+}
+
+static guint64 tvb_get_ntoh64(const char *tvb, const gint offset)
+{
+ const guint8 *ptr;
+
+ ptr = (guint8 *)tvb + offset;
+ return pntoh64(ptr);
+}
+
+guint tvb_get_varint(const char *tvb, guint offset, guint maxlen, guint64 *value, const guint encoding)
+{
+ *value = 0;
+
+ if (encoding & ENC_VARINT_QUIC) {
+ // calculate variable length
+ *value = tvb_get_guint8(tvb, offset);
+ switch((*value) >> 6) {
+ case 0: /* 0b00 => 1 byte length (6 bits Usable) */
+ (*value) &= 0x3F;
+ return 1;
+ case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
+ *value = tvb_get_ntohs(tvb, offset) & 0x3FFF;
+ return 2;
+ case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
+ *value = tvb_get_ntohl(tvb, offset) & 0x3FFFFFFF;
+ return 4;
+ case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
+ *value = tvb_get_ntoh64(tvb, offset) & G_GUINT64_CONSTANT(0x3FFFFFFFFFFFFFFF);
+ return 8;
+ default: /* No Possible */
+ g_assert_not_reached();
+ break;
+ }
+ }
+
+ // 10 bytes scanned, but no bytes' msb is zero
+ return 0;
+}