#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tlse.h" int tls_hkdf_extract(unsigned int mac_length, unsigned char *output, unsigned int outlen, const unsigned char *salt, unsigned int salt_len, const unsigned char *ikm, unsigned char ikm_len) { int hash_idx; unsigned long dlen = outlen; unsigned char dummy_label[1] = { 0 }; if (!salt || salt_len == 0) { salt_len = 1; salt = dummy_label; } if (mac_length == TLS_SHA384_MAC_SIZE) { hash_idx = find_hash("sha384"); dlen = mac_length; } else { hash_idx = find_hash("sha256"); } hmac_memory(hash_idx, salt, salt_len, ikm, ikm_len, output, &dlen); return dlen; } static int make_hkdf_label(const char *label, unsigned char label_len, const unsigned char *data, unsigned char data_len, unsigned char *hkdflabel, unsigned short length, const char *prefix) { int prefix_len; *(unsigned short *) &hkdflabel[0] = htons(length); if (prefix) { prefix_len = strlen(prefix); memcpy(&hkdflabel[3], prefix, prefix_len); } else { memcpy(&hkdflabel[3], "tls13 ", 6); prefix_len = 6; } hkdflabel[2] = (unsigned char) prefix_len + label_len; memcpy(&hkdflabel[3 + prefix_len], label, label_len); hkdflabel[3 + prefix_len + label_len] = data_len; if (data_len) { memcpy(&hkdflabel[4 + prefix_len + label_len], data, data_len); } return 4 + prefix_len + label_len + data_len; } void tls_hkdf_expand(unsigned int mac_length, unsigned char *output, unsigned int outlen, const unsigned char *secret, unsigned int secret_len, const unsigned char *info, unsigned char info_len) { unsigned char digest_out[TLS_MAX_HASH_LEN]; unsigned long dlen = 32; int hash_idx; unsigned int i; unsigned char i2 = 0; unsigned int idx = 0; hmac_state hmac; unsigned int copylen; if (mac_length == TLS_SHA384_MAC_SIZE) { hash_idx = find_hash("sha384"); dlen = mac_length; } else { hash_idx = find_hash("sha256"); } while (outlen) { hmac_init(&hmac, hash_idx, secret, secret_len); if (i2) { hmac_process(&hmac, digest_out, dlen); } if (info && info_len) { hmac_process(&hmac, info, info_len); } i2++; hmac_process(&hmac, &i2, 1); hmac_done(&hmac, digest_out, &dlen); copylen = outlen; if (copylen > dlen) { copylen = (unsigned int) dlen; } for (i = 0; i < copylen; i++) { output[idx++] = digest_out[i]; outlen--; } } } void tls_hkdf_expand_label(unsigned int mac_length, unsigned char *output, unsigned int outlen, const unsigned char *secret, unsigned int secret_len, const char *label, unsigned char label_len, const unsigned char *data, unsigned char data_len) { unsigned char hkdf_label[512]; int len = make_hkdf_label(label, label_len, data, data_len, hkdf_label, outlen, NULL); tls_hkdf_expand(mac_length, output, outlen, secret, secret_len, hkdf_label, len); }