summaryrefslogtreecommitdiff
path: root/src/wsgcrypt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wsgcrypt.cpp')
-rw-r--r--src/wsgcrypt.cpp69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/wsgcrypt.cpp b/src/wsgcrypt.cpp
new file mode 100644
index 0000000..c6b89a5
--- /dev/null
+++ b/src/wsgcrypt.cpp
@@ -0,0 +1,69 @@
+/**
+ * wsgcrypt.c
+ *
+ * Created on 2020-11-26
+ * @author: qyc
+ *
+ * @explain:
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wsgcrypt.h"
+
+gcry_error_t ws_hmac_buffer(int algo, void *digest, const void *buffer, size_t length, const void *key, size_t keylen)
+{
+ gcry_md_hd_t hmac_handle;
+ gcry_error_t result = gcry_md_open(&hmac_handle, algo, GCRY_MD_FLAG_HMAC);
+ if (result) {
+ return result;
+ }
+ result = gcry_md_setkey(hmac_handle, key, keylen);
+ if (result) {
+ gcry_md_close(hmac_handle);
+ return result;
+ }
+ gcry_md_write(hmac_handle, buffer, length);
+ memcpy(digest, gcry_md_read(hmac_handle, 0), gcry_md_get_algo_dlen(algo));
+ gcry_md_close(hmac_handle);
+ return GPG_ERR_NO_ERROR;
+}
+
+gcry_error_t hkdf_expand(int hashalgo, const guint8 *prk, guint prk_len, const guint8 *info, guint info_len, guint8 *out, guint out_len)
+{
+ // Current maximum hash output size: 48 bytes for SHA-384.
+ guchar lastoutput[48];
+ gcry_md_hd_t h;
+ gcry_error_t err;
+ const guint hash_len = gcry_md_get_algo_dlen(hashalgo);
+
+ // Some sanity checks
+ if (!(out_len > 0 && out_len <= 255 * hash_len) || !(hash_len > 0 && hash_len <= sizeof(lastoutput)))
+ return GPG_ERR_INV_ARG;
+
+ err = gcry_md_open(&h, hashalgo, GCRY_MD_FLAG_HMAC);
+ if (err)
+ return err;
+
+ guint offset;
+ for (offset = 0; offset < out_len; offset += hash_len) {
+ gcry_md_reset(h);
+ // Set PRK
+ gcry_md_setkey(h, prk, prk_len);
+ if (offset > 0)
+ // T(1..N)
+ gcry_md_write(h, lastoutput, hash_len);
+ // info
+ gcry_md_write(h, info, info_len);
+ // constant 0x01..N
+ gcry_md_putc(h, (guint8)(offset / hash_len + 1));
+
+ memcpy(lastoutput, gcry_md_read(h, hashalgo), hash_len);
+ memcpy(out + offset, lastoutput, MIN(hash_len, out_len - offset));
+ }
+
+ gcry_md_close(h);
+
+ return 0;
+}