diff --git a/include/re_hmac.h b/include/re_hmac.h index 0f660c9..13fa68c 100644 --- a/include/re_hmac.h +++ b/include/re_hmac.h @@ -11,3 +11,15 @@ void hmac_sha1(const uint8_t *k, /* secret key */ size_t ld, /* length of data in bytes */ uint8_t* out, /* output buffer, at least "t" bytes */ size_t t); + + +enum hmac_hash { + HMAC_SHA1 +}; + +struct hmac; + +int hmac_create(struct hmac **hmacp, enum hmac_hash hash, + const uint8_t *key, size_t key_len); +int hmac_digest(struct hmac *hmac, uint8_t *md, size_t md_len, + const uint8_t *data, size_t data_len); diff --git a/src/hmac/hmac.c b/src/hmac/hmac.c new file mode 100644 index 0000000..5a916c5 --- /dev/null +++ b/src/hmac/hmac.c @@ -0,0 +1,63 @@ +/** + * @file hmac.c HMAC-SHA1 + * + * Copyright (C) 2010 Creytiv.com + */ +#include +#include +#include +#include +#include + + +struct hmac { + uint8_t key[SHA_DIGEST_LENGTH]; + size_t key_len; +}; + + +static void destructor(void *arg) +{ + struct hmac *hmac = arg; + + memset(hmac, 0, sizeof(*hmac)); +} + + +int hmac_create(struct hmac **hmacp, enum hmac_hash hash, + const uint8_t *key, size_t key_len) +{ + struct hmac *hmac; + + if (!hmacp || !key || !key_len) + return EINVAL; + + if (hash != HMAC_SHA1) + return ENOTSUP; + + if (key_len > SHA_DIGEST_LENGTH) + return EINVAL; + + hmac = mem_zalloc(sizeof(*hmac), destructor); + if (!hmac) + return ENOMEM; + + memcpy(hmac->key, key, key_len); + hmac->key_len = key_len; + + *hmacp = hmac; + + return 0; +} + + +int hmac_digest(struct hmac *hmac, uint8_t *md, size_t md_len, + const uint8_t *data, size_t data_len) +{ + if (!hmac || !md || !md_len || !data || !data_len) + return EINVAL; + + hmac_sha1(hmac->key, hmac->key_len, data, data_len, md, md_len); + + return 0; +} diff --git a/src/hmac/mod.mk b/src/hmac/mod.mk index 405aa70..1679fb3 100644 --- a/src/hmac/mod.mk +++ b/src/hmac/mod.mk @@ -5,3 +5,9 @@ # SRCS += hmac/hmac_sha1.c + +ifneq ($(USE_OPENSSL),) +SRCS += hmac/openssl/hmac.c +else +SRCS += hmac/hmac.c +endif diff --git a/src/hmac/openssl/hmac.c b/src/hmac/openssl/hmac.c new file mode 100644 index 0000000..53c1e76 --- /dev/null +++ b/src/hmac/openssl/hmac.c @@ -0,0 +1,86 @@ +/** + * @file openssl/hmac.c HMAC using OpenSSL + * + * Copyright (C) 2010 Creytiv.com + */ + +#include +#include +#include +#include + + +struct hmac { + HMAC_CTX ctx; +}; + + +static void destructor(void *arg) +{ + struct hmac *hmac = arg; + + HMAC_CTX_cleanup(&hmac->ctx); +} + + +int hmac_create(struct hmac **hmacp, enum hmac_hash hash, + const uint8_t *key, size_t key_len) +{ + struct hmac *hmac; + int err = 0; + + if (!hmacp || !key || !key_len) + return EINVAL; + + if (hash != HMAC_SHA1) + return ENOTSUP; + + hmac = mem_zalloc(sizeof(*hmac), destructor); + if (!hmac) + return ENOMEM; + + HMAC_CTX_init(&hmac->ctx); + +#if (OPENSSL_VERSION_NUMBER >= 0x00909000) + if (!HMAC_Init_ex(&hmac->ctx, key, (int)key_len, EVP_sha1(), NULL)) + err = EPROTO; +#else + HMAC_Init_ex(&hmac->ctx, key, (int)key_len, EVP_sha1(), NULL); +#endif + + 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)) + return EPROTO; + + if (!HMAC_Update(&hmac->ctx, data, (int)data_len)) + return EPROTO; + if (!HMAC_Final(&hmac->ctx, md, &len)) + 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); +#endif + + return 0; +}