]> pd.if.org Git - zpackage/blobdiff - crypto/hkdf.c
commit files needed for zpm-fetchurl
[zpackage] / crypto / hkdf.c
diff --git a/crypto/hkdf.c b/crypto/hkdf.c
new file mode 100644 (file)
index 0000000..4c601bc
--- /dev/null
@@ -0,0 +1,133 @@
+#define _POSIX_C_SOURCE 200809L
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include <errno.h>
+
+#include <tomcrypt.h>
+#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);
+}