Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b

Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/hmac/openssl/hmac.c b/src/hmac/openssl/hmac.c
new file mode 100644
index 0000000..212567f
--- /dev/null
+++ b/src/hmac/openssl/hmac.c
@@ -0,0 +1,135 @@
+/**
+ * @file openssl/hmac.c  HMAC using OpenSSL
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+
+#include <openssl/hmac.h>
+#include <openssl/err.h>
+#include <re_types.h>
+#include <re_mem.h>
+#include <re_hmac.h>
+
+
+struct hmac {
+	HMAC_CTX *ctx;
+};
+
+
+static void destructor(void *arg)
+{
+	struct hmac *hmac = arg;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+	!defined(LIBRESSL_VERSION_NUMBER)
+
+	if (hmac->ctx)
+		HMAC_CTX_free(hmac->ctx);
+#else
+	if (hmac->ctx)
+		HMAC_CTX_cleanup(hmac->ctx);
+	mem_deref(hmac->ctx);
+#endif
+}
+
+
+int hmac_create(struct hmac **hmacp, enum hmac_hash hash,
+		const uint8_t *key, size_t key_len)
+{
+	struct hmac *hmac;
+	const EVP_MD *evp;
+	int err = 0;
+
+	if (!hmacp || !key || !key_len)
+		return EINVAL;
+
+	switch (hash) {
+
+	case HMAC_HASH_SHA1:
+		evp = EVP_sha1();
+		break;
+
+	case HMAC_HASH_SHA256:
+		evp = EVP_sha256();
+		break;
+
+	default:
+		return ENOTSUP;
+	}
+
+	hmac = mem_zalloc(sizeof(*hmac), destructor);
+	if (!hmac)
+		return ENOMEM;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+	!defined(LIBRESSL_VERSION_NUMBER)
+
+	hmac->ctx = HMAC_CTX_new();
+	if (!hmac->ctx) {
+		ERR_clear_error();
+		err = ENOMEM;
+		goto out;
+	}
+#else
+	hmac->ctx = mem_zalloc(sizeof(*hmac->ctx), NULL);
+	if (!hmac->ctx) {
+		err = ENOMEM;
+		goto out;
+	}
+
+	HMAC_CTX_init(hmac->ctx);
+#endif
+
+#if (OPENSSL_VERSION_NUMBER >= 0x00909000)
+	if (!HMAC_Init_ex(hmac->ctx, key, (int)key_len, evp, NULL)) {
+		ERR_clear_error();
+		err = EPROTO;
+	}
+#else
+	HMAC_Init_ex(hmac->ctx, key, (int)key_len, evp, NULL);
+#endif
+
+ out:
+	if (err)
+		mem_deref(hmac);
+	else
+		*hmacp = hmac;
+
+	return err;
+}
+
+
+int hmac_digest(struct hmac *hmac, uint8_t *md, size_t md_len,
+		const uint8_t *data, size_t data_len)
+{
+	unsigned int len = (unsigned int)md_len;
+
+	if (!hmac || !md || !md_len || !data || !data_len)
+		return EINVAL;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x00909000)
+	/* the HMAC context must be reset here */
+	if (!HMAC_Init_ex(hmac->ctx, 0, 0, 0, NULL))
+		goto error;
+
+	if (!HMAC_Update(hmac->ctx, data, (int)data_len))
+		goto error;
+	if (!HMAC_Final(hmac->ctx, md, &len))
+		goto error;
+
+	return 0;
+
+ error:
+	ERR_clear_error();
+	return EPROTO;
+
+#else
+	/* the HMAC context must be reset here */
+	HMAC_Init_ex(hmac->ctx, 0, 0, 0, NULL);
+
+	HMAC_Update(hmac->ctx, data, (int)data_len);
+	HMAC_Final(hmac->ctx, md, &len);
+
+	return 0;
+#endif
+}