]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Refactored OpenSSL based HMAC implementation
authorTobias Brunner <tobias@strongswan.org>
Thu, 21 Jun 2012 11:10:26 +0000 (13:10 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 25 Jun 2012 14:35:06 +0000 (16:35 +0200)
src/libstrongswan/plugins/openssl/Makefile.am
src/libstrongswan/plugins/openssl/openssl_hmac.c [new file with mode: 0644]
src/libstrongswan/plugins/openssl/openssl_hmac.h [new file with mode: 0644]
src/libstrongswan/plugins/openssl/openssl_hmac_prf.c
src/libstrongswan/plugins/openssl/openssl_hmac_signer.c

index 26443e3e3526d6b3849b80c6475a1221c2a834d1..0a4586982b02737e0ee122312b1897fd7c63cf7b 100644 (file)
@@ -24,6 +24,7 @@ libstrongswan_openssl_la_SOURCES = \
        openssl_x509.c openssl_x509.h \
        openssl_crl.c openssl_crl.h \
        openssl_rng.c openssl_rng.h \
+       openssl_hmac.c openssl_hmac.h \
        openssl_hmac_prf.c openssl_hmac_prf.h \
        openssl_hmac_signer.c openssl_hmac_signer.h
 
diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c
new file mode 100644 (file)
index 0000000..fa88238
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/*
+ * Copyright (C) 2012 Aleksandr Grinberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+#include "openssl_hmac.h"
+
+typedef struct private_openssl_hmac_t private_openssl_hmac_t;
+
+/**
+ * Private data of a openssl_hmac_t object.
+ */
+struct private_openssl_hmac_t {
+
+       /**
+        * Public interface
+        */
+       openssl_hmac_t public;
+
+       /**
+        * Hasher to use
+        */
+       const EVP_MD *hasher;
+
+       /**
+        * Current HMAC context
+        */
+       HMAC_CTX hmac;
+
+       /**
+        * Key
+        */
+       chunk_t key;
+};
+
+/**
+ * Resets HMAC context
+ */
+static void reset(private_openssl_hmac_t *this)
+{
+       HMAC_Init_ex(&this->hmac, this->key.ptr, this->key.len, this->hasher, NULL);
+}
+
+METHOD(openssl_hmac_t, get_mac, void,
+       private_openssl_hmac_t *this, chunk_t data, u_int8_t *out)
+{
+       if (out == NULL)
+       {
+               HMAC_Update(&this->hmac, data.ptr, data.len);
+       }
+       else
+       {
+               HMAC_Update(&this->hmac, data.ptr, data.len);
+               HMAC_Final(&this->hmac, out, NULL);
+               reset(this);
+       }
+}
+
+METHOD(openssl_hmac_t, allocate_mac, void,
+       private_openssl_hmac_t *this, chunk_t data, chunk_t *out)
+{
+       if (out == NULL)
+       {
+               get_mac(this, data, NULL);
+       }
+       else
+       {
+               *out = chunk_alloc(EVP_MD_size(this->hasher));
+               get_mac(this, data, out->ptr);
+       }
+}
+
+METHOD(openssl_hmac_t, get_block_size, size_t,
+       private_openssl_hmac_t *this)
+{
+       return EVP_MD_size(this->hasher);
+}
+
+METHOD(openssl_hmac_t, set_key, void,
+       private_openssl_hmac_t *this, chunk_t key)
+{
+       chunk_clear(&this->key);
+       this->key = chunk_clone(key);
+       reset(this);
+}
+
+METHOD(openssl_hmac_t, destroy, void,
+       private_openssl_hmac_t *this)
+{
+       HMAC_CTX_cleanup(&this->hmac);
+       chunk_clear(&this->key);
+       free(this);
+}
+
+/*
+ * Described in header
+ */
+openssl_hmac_t *openssl_hmac_create(hash_algorithm_t algo)
+{
+       private_openssl_hmac_t *this;
+
+       INIT(this,
+               .public = {
+                       .get_mac = _get_mac,
+                       .allocate_mac = _allocate_mac,
+                       .get_block_size = _get_block_size,
+                       .set_key = _set_key,
+                       .destroy = _destroy,
+               },
+       );
+
+       switch (algo)
+       {
+               case HASH_MD5:
+                       this->hasher = EVP_get_digestbyname("md5");
+                       break;
+               case HASH_SHA1:
+                       this->hasher = EVP_get_digestbyname("sha1");
+                       break;
+               case HASH_SHA256:
+                       this->hasher = EVP_get_digestbyname("sha256");
+                       break;
+               case HASH_SHA384:
+                       this->hasher = EVP_get_digestbyname("sha384");
+                       break;
+               case HASH_SHA512:
+                       this->hasher = EVP_get_digestbyname("sha512");
+                       break;
+               default:
+                       break;
+       }
+
+       if (!this->hasher)
+       {
+               free(this);
+               return NULL;
+       }
+
+       HMAC_CTX_init(&this->hmac);
+
+       return &this->public;
+}
diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.h b/src/libstrongswan/plugins/openssl/openssl_hmac.h
new file mode 100644 (file)
index 0000000..175513c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup openssl_hmac openssl_hmac
+ * @{ @ingroup openssl_p
+ */
+
+#ifndef OPENSSL_HMAC_H_
+#define OPENSSL_HMAC_H_
+
+typedef struct openssl_hmac_t openssl_hmac_t;
+
+#include <crypto/hashers/hasher.h>
+
+/**
+ * Simple wrapper around OpenSSL's functions to calculate HMAC message
+ * authentication codes
+ */
+struct openssl_hmac_t {
+
+       /**
+        * Generate message authentication code.
+        *
+        * If out is NULL, no result is given back.  A next call will
+        * append the data to already supplied data.  If out is not NULL,
+        * the mac of all apended data is calculated, written to out and the
+        * internal state is reset.
+        *
+        * @param data          chunk of data to authenticate
+        * @param out           pointer where the generated bytes will be written
+        */
+       void (*get_mac)(openssl_hmac_t *this, chunk_t data, u_int8_t *out);
+
+       /**
+        * Generates message authentication code and allocates memory for it.
+        *
+        * If out is NULL, no result is given back.  A next call will
+        * append the data to already supplied data.  If out is not NULL,
+        * the mac of all apended data is calculated, returned in out and the
+        * internal state is reset;
+        *
+        * @param data          chunk of data to authenticate
+        * @param out           chunk which will hold generated bytes
+        */
+       void (*allocate_mac)(openssl_hmac_t *this, chunk_t data, chunk_t *out);
+
+       /**
+        * Get the size of the resulting MAC.
+        *
+        * @return                      block size in bytes
+        */
+       size_t (*get_block_size)(openssl_hmac_t *this);
+
+       /**
+        * Set the key to be used for the HMAC.
+        *
+        * Any key length is accepted.
+        *
+        * @param key           key to set
+        */
+       void (*set_key)(openssl_hmac_t *this, chunk_t key);
+
+       /**
+        * Destroys an openssl_hmac_t object.
+        */
+       void (*destroy)(openssl_hmac_t *this);
+};
+
+/**
+ * Creates a new openssl_hmac_t object.
+ *
+ * @param algo                 hash algorithm to use
+ * @return                             openssl_hmac_t object, NULL if not supported
+ */
+openssl_hmac_t *openssl_hmac_create(hash_algorithm_t algo);
+
+#endif /** OPENSSL_HMAC_H_ @}*/
index 874a0968700f86bc51fa4fa3a736607c06d86f5e..fc2285c05a10681167b4de48334355ea970f2346 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
 /*
  * Copyright (C) 2012 Aleksandr Grinberg
  *
@@ -20,9 +35,8 @@
  * THE SOFTWARE.
  */
 
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
 
+#include "openssl_hmac.h"
 #include "openssl_hmac_prf.h"
 
 typedef struct private_openssl_hmac_prf_t private_openssl_hmac_prf_t;
@@ -38,84 +52,46 @@ struct private_openssl_hmac_prf_t {
        openssl_hmac_prf_t public;
 
        /**
-        * Hasher to use
+        * OpenSSL based HMAC implementation
         */
-       const EVP_MD *hasher;
-
-       /**
-        * Current HMAC context
-        */
-       HMAC_CTX hmac;
-
-       /**
-        * Key stored for reuse
-        */
-       chunk_t key;
+       openssl_hmac_t *hmac;
 };
 
 METHOD(prf_t, get_block_size, size_t,
        private_openssl_hmac_prf_t *this)
 {
-       return EVP_MD_size(this->hasher);
+       return this->hmac->get_block_size(this->hmac);
 }
 
 METHOD(prf_t, get_key_size, size_t,
        private_openssl_hmac_prf_t *this)
 {
        /* for HMAC prfs, IKEv2 uses block size as key size */
-       return EVP_MD_size(this->hasher);
-}
-
-/**
- * Resets HMAC context
- */
-static void reset(private_openssl_hmac_prf_t *this)
-{
-       HMAC_Init_ex(&this->hmac, this->key.ptr, this->key.len, this->hasher, NULL);
+       return this->hmac->get_block_size(this->hmac);
 }
 
 METHOD(prf_t, get_bytes, void,
        private_openssl_hmac_prf_t *this, chunk_t seed, u_int8_t *out)
 {
-       if (out == NULL)
-       {
-               HMAC_Update(&this->hmac, seed.ptr, seed.len);
-       }
-       else
-       {
-               HMAC_Update(&this->hmac, seed.ptr, seed.len);
-               HMAC_Final(&this->hmac, out, NULL);
-               reset(this);
-       }
+       this->hmac->get_mac(this->hmac, seed, out);
 }
 
 METHOD(prf_t, allocate_bytes, void,
        private_openssl_hmac_prf_t *this, chunk_t seed, chunk_t *out)
 {
-       if (out == NULL)
-       {
-               get_bytes(this, seed, NULL);
-       }
-       else
-       {
-               *out = chunk_alloc(EVP_MD_size(this->hasher));
-               get_bytes(this, seed, out->ptr);
-       }
+       this->hmac->allocate_mac(this->hmac, seed, out);
 }
 
 METHOD(prf_t, set_key, void,
        private_openssl_hmac_prf_t *this, chunk_t key)
 {
-       chunk_clear(&this->key);
-       this->key = chunk_clone(key);
-       reset(this);
+       this->hmac->set_key(this->hmac, key);
 }
 
 METHOD(prf_t, destroy, void,
        private_openssl_hmac_prf_t *this)
 {
-       HMAC_CTX_cleanup(&this->hmac);
-       chunk_clear(&this->key);
+       this->hmac->destroy(this->hmac);
        free(this);
 }
 
@@ -125,48 +101,46 @@ METHOD(prf_t, destroy, void,
 openssl_hmac_prf_t *openssl_hmac_prf_create(pseudo_random_function_t algo)
 {
        private_openssl_hmac_prf_t *this;
-
-       INIT(this,
-               .public = {
-                       .prf = {
-                               .get_bytes = _get_bytes,
-                               .allocate_bytes = _allocate_bytes,
-                               .get_block_size = _get_block_size,
-                               .get_key_size = _get_key_size,
-                               .set_key = _set_key,
-                               .destroy = _destroy,
-                       },
-               },
-       );
+       openssl_hmac_t *hmac = NULL;
 
        switch (algo)
        {
                case PRF_HMAC_MD5:
-                       this->hasher = EVP_get_digestbyname("md5");
+                       hmac = openssl_hmac_create(HASH_MD5);
                        break;
                case PRF_HMAC_SHA1:
-                       this->hasher = EVP_get_digestbyname("sha1");
+                       hmac = openssl_hmac_create(HASH_SHA1);
                        break;
                case PRF_HMAC_SHA2_256:
-                       this->hasher = EVP_get_digestbyname("sha256");
+                       hmac = openssl_hmac_create(HASH_SHA256);
                        break;
                case PRF_HMAC_SHA2_384:
-                       this->hasher = EVP_get_digestbyname("sha384");
+                       hmac = openssl_hmac_create(HASH_SHA384);
                        break;
                case PRF_HMAC_SHA2_512:
-                       this->hasher = EVP_get_digestbyname("sha512");
+                       hmac = openssl_hmac_create(HASH_SHA512);
                        break;
                default:
                        break;
        }
-
-       if (!this->hasher)
+       if (!hmac)
        {
-               free(this);
                return NULL;
        }
 
-       HMAC_CTX_init(&this->hmac);
+       INIT(this,
+               .public = {
+                       .prf = {
+                               .get_bytes = _get_bytes,
+                               .allocate_bytes = _allocate_bytes,
+                               .get_block_size = _get_block_size,
+                               .get_key_size = _get_key_size,
+                               .set_key = _set_key,
+                               .destroy = _destroy,
+                       },
+               },
+               .hmac = hmac,
+       );
 
        return &this->public;
 }
index e31047b239c7dda088a7af2b0ebd638a67dbdb25..3c2a89035b7ce73caeee4bf2e73b8474f45ba653 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
 /*
  * Copyright (C) 2012 Aleksandr Grinberg
  *
@@ -20,9 +35,7 @@
  * THE SOFTWARE.
  */
 
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-
+#include "openssl_hmac.h"
 #include "openssl_hmac_signer.h"
 
 typedef struct private_openssl_hmac_signer_t private_openssl_hmac_signer_t;
@@ -38,19 +51,9 @@ struct private_openssl_hmac_signer_t {
        openssl_hmac_signer_t public;
 
        /**
-        * Hasher to use
-        */
-       const EVP_MD *hasher;
-
-       /**
-        * Current HMAC context
+        * OpenSSL based HMAC implementation
         */
-       HMAC_CTX hmac;
-
-       /**
-        * Key stored for reuse
-        */
-       chunk_t key;
+       openssl_hmac_t *hmac;
 
        /**
         * Signature truncation length
@@ -67,60 +70,38 @@ METHOD(signer_t, get_block_size, size_t,
 METHOD(signer_t, get_key_size, size_t,
        private_openssl_hmac_signer_t *this)
 {
-       return this->key.len;
-}
-
-/**
- * Resets HMAC context
- */
-static void reset(private_openssl_hmac_signer_t *this)
-{
-       HMAC_Init_ex(&this->hmac, this->key.ptr, this->key.len, this->hasher, NULL);
-}
-
-static void get_bytes(private_openssl_hmac_signer_t *this, chunk_t seed,
-                                         u_int8_t *out)
-{
-       if (out == NULL)
-       {
-               HMAC_Update(&this->hmac, seed.ptr, seed.len);
-       }
-       else
-       {
-               HMAC_Update(&this->hmac, seed.ptr, seed.len);
-               HMAC_Final(&this->hmac, out, NULL);
-               reset(this);
-       }
+       return this->hmac->get_block_size(this->hmac);
 }
 
 METHOD(signer_t, get_signature, void,
-       private_openssl_hmac_signer_t *this, chunk_t seed, u_int8_t *out)
+       private_openssl_hmac_signer_t *this, chunk_t data, u_int8_t *out)
 {
        if (out == NULL)
        {
-               get_bytes(this, seed, NULL);
+               this->hmac->get_mac(this->hmac, data, NULL);
        }
        else
        {
-               u_int8_t mac[this->key.len];
+               u_int8_t mac[this->hmac->get_block_size(this->hmac)];
 
-               get_bytes(this, seed, mac);
+               this->hmac->get_mac(this->hmac, data, mac);
                memcpy(out, mac, this->trunc);
        }
 }
 
 METHOD(signer_t, allocate_signature,void,
-       private_openssl_hmac_signer_t *this, chunk_t seed, chunk_t *out)
+       private_openssl_hmac_signer_t *this, chunk_t data, chunk_t *out)
 {
        if (out == NULL)
        {
-               get_bytes(this, seed, NULL);
+               this->hmac->get_mac(this->hmac, data, NULL);
        }
        else
        {
-               u_int8_t mac[this->key.len];
+               u_int8_t mac[this->hmac->get_block_size(this->hmac)];
+
+               this->hmac->get_mac(this->hmac, data, mac);
 
-               get_bytes(this, seed, mac);
                *out = chunk_alloc(this->trunc);
                memcpy(out->ptr, mac, this->trunc);
        }
@@ -129,9 +110,9 @@ METHOD(signer_t, allocate_signature,void,
 METHOD(signer_t, verify_signature, bool,
        private_openssl_hmac_signer_t *this, chunk_t seed, chunk_t signature)
 {
-       u_int8_t mac[this->key.len];
+       u_int8_t mac[this->hmac->get_block_size(this->hmac)];
 
-       get_bytes(this, seed, mac);
+       this->hmac->get_mac(this->hmac, seed, mac);
 
        if (signature.len != this->trunc)
        {
@@ -143,16 +124,13 @@ METHOD(signer_t, verify_signature, bool,
 METHOD(signer_t, set_key, void,
        private_openssl_hmac_signer_t *this, chunk_t key)
 {
-       chunk_clear(&this->key);
-       this->key = chunk_clone(key);
-       reset(this);
+       this->hmac->set_key(this->hmac, key);
 }
 
 METHOD(signer_t, destroy, void,
        private_openssl_hmac_signer_t *this)
 {
-       HMAC_CTX_cleanup(&this->hmac);
-       chunk_clear(&this->key);
+       this->hmac->destroy(this->hmac);
        free(this);
 }
 
@@ -162,85 +140,74 @@ METHOD(signer_t, destroy, void,
 openssl_hmac_signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo)
 {
        private_openssl_hmac_signer_t *this;
-
-       INIT(this,
-               .public = {
-                       .signer = {
-                               .get_signature = _get_signature,
-                               .allocate_signature = _allocate_signature,
-                               .verify_signature = _verify_signature,
-                               .get_block_size = _get_block_size,
-                               .get_key_size = _get_key_size,
-                               .set_key = _set_key,
-                               .destroy = _destroy,
-                       },
-               },
-       );
+       openssl_hmac_t *hmac = NULL;
+       size_t trunc = 0;
 
        switch (algo)
        {
                case AUTH_HMAC_MD5_96:
-                       this->hasher = EVP_get_digestbyname("md5");
-                       this->key.len = 16;
-                       this->trunc = 12;
+                       hmac = openssl_hmac_create(HASH_MD5);
+                       trunc = 12;
                        break;
                case AUTH_HMAC_MD5_128:
-                       this->hasher = EVP_get_digestbyname("md5");
-                       this->key.len = 16;
-                       this->trunc = 16;
+                       hmac = openssl_hmac_create(HASH_MD5);
+                       trunc = 16;
                        break;
                case AUTH_HMAC_SHA1_96:
-                       this->hasher = EVP_get_digestbyname("sha1");
-                       this->key.len = 20;
-                       this->trunc = 12;
+                       hmac = openssl_hmac_create(HASH_SHA1);
+                       trunc = 12;
                        break;
                case AUTH_HMAC_SHA1_128:
-                       this->hasher = EVP_get_digestbyname("sha1");
-                       this->key.len = 20;
-                       this->trunc = 16;
+                       hmac = openssl_hmac_create(HASH_SHA1);
+                       trunc = 16;
                        break;
                case AUTH_HMAC_SHA1_160:
-                       this->hasher = EVP_get_digestbyname("sha1");
-                       this->key.len = 20;
-                       this->trunc = 20;
+                       hmac = openssl_hmac_create(HASH_SHA1);
+                       trunc = 20;
                        break;
                case AUTH_HMAC_SHA2_256_128:
-                       this->hasher = EVP_get_digestbyname("sha256");
-                       this->key.len = 32;
-                       this->trunc = 16;
+                       hmac = openssl_hmac_create(HASH_SHA256);
+                       trunc = 16;
                        break;
                case AUTH_HMAC_SHA2_256_256:
-                       this->hasher = EVP_get_digestbyname("sha256");
-                       this->key.len = 32;
-                       this->trunc = 32;
+                       hmac = openssl_hmac_create(HASH_SHA256);
+                       trunc = 32;
                        break;
                case AUTH_HMAC_SHA2_384_192:
-                       this->hasher = EVP_get_digestbyname("sha384");
-                       this->key.len = 48;
-                       this->trunc = 24;
+                       hmac = openssl_hmac_create(HASH_SHA384);
+                       trunc = 24;
                        break;
                case AUTH_HMAC_SHA2_384_384:
-                       this->hasher = EVP_get_digestbyname("sha384");
-                       this->key.len = 48;
-                       this->trunc = 48;
+                       hmac = openssl_hmac_create(HASH_SHA384);
+                       trunc = 48;
                        break;
                case AUTH_HMAC_SHA2_512_256:
-                       this->hasher = EVP_get_digestbyname("sha512");
-                       this->key.len = 64;
-                       this->trunc = 32;
+                       hmac = openssl_hmac_create(HASH_SHA512);
+                       trunc = 32;
                        break;
                default:
                        break;
        }
-
-       if (!this->hasher)
+       if (!hmac)
        {
-               /* hash is not available */
-               free(this);
                return NULL;
        }
 
-       HMAC_CTX_init(&this->hmac);
+       INIT(this,
+               .public = {
+                       .signer = {
+                               .get_signature = _get_signature,
+                               .allocate_signature = _allocate_signature,
+                               .verify_signature = _verify_signature,
+                               .get_block_size = _get_block_size,
+                               .get_key_size = _get_key_size,
+                               .set_key = _set_key,
+                               .destroy = _destroy,
+                       },
+               },
+               .hmac = hmac,
+               .trunc = trunc,
+       );
 
        return &this->public;
 }