/** * utils.c * * Created on 2020-11-27 * @author: qyc * * @explain: */ #include #include #include #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; }