X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=crypto%2Fhkdf.c;fp=crypto%2Fhkdf.c;h=4c601bc7f443e9af07df087044b5e1bcd14cafca;hb=66bc25938679f1d6a1d1200f329093d82a5e99b4;hp=0000000000000000000000000000000000000000;hpb=a52ee0733f420ca20224049260d6fc5cf7d8f621;p=zpackage diff --git a/crypto/hkdf.c b/crypto/hkdf.c new file mode 100644 index 0000000..4c601bc --- /dev/null +++ b/crypto/hkdf.c @@ -0,0 +1,133 @@ +#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); +}