]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/openssl/openssl_hmac.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libstrongswan / plugins / openssl / openssl_hmac.c
CommitLineData
8391c1d0
TB
1/*
2 * Copyright (C) 2012 Tobias Brunner
19ef2aec
TB
3 *
4 * Copyright (C) secunet Security Networks AG
8391c1d0
TB
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17/*
18 * Copyright (C) 2012 Aleksandr Grinberg
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining a copy
21 * of this software and associated documentation files (the "Software"), to deal
22 * in the Software without restriction, including without limitation the rights
23 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 * copies of the Software, and to permit persons to whom the Software is
25 * furnished to do so, subject to the following conditions:
26 *
27 * The above copyright notice and this permission notice shall be included in
28 * all copies or substantial portions of the Software.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 * THE SOFTWARE.
37 */
38
a3a190b7
TB
39#include <openssl/opensslconf.h>
40
41#ifndef OPENSSL_NO_HMAC
42
8391c1d0
TB
43#include <openssl/evp.h>
44#include <openssl/hmac.h>
45
db0c53c2
TB
46#if OPENSSL_VERSION_NUMBER >= 0x30000000L
47#include <openssl/core_names.h>
48#endif
49
8391c1d0
TB
50#include "openssl_hmac.h"
51
c4a3c967
TB
52#include <crypto/mac.h>
53#include <crypto/prfs/mac_prf.h>
54#include <crypto/signers/mac_signer.h>
73d032e4 55
c4a3c967 56typedef struct private_mac_t private_mac_t;
8391c1d0
TB
57
58/**
c4a3c967 59 * Private data of a mac_t object.
8391c1d0 60 */
c4a3c967 61struct private_mac_t {
8391c1d0
TB
62
63 /**
64 * Public interface
65 */
c4a3c967 66 mac_t public;
8391c1d0 67
db0c53c2
TB
68#if OPENSSL_VERSION_NUMBER >= 0x30000000L
69 /**
70 * HMAC context
71 */
72 EVP_MAC_CTX *hmac;
73
74 /**
75 * Base context because EVP_MAC_init() does not reset the internal state if
76 * no key is passed, so the above is a copy that's replaced with every
77 * reset that does not change the key
78 */
79 EVP_MAC_CTX *hmac_base;
80#else
8391c1d0
TB
81 /**
82 * Hasher to use
83 */
84 const EVP_MD *hasher;
85
86 /**
87 * Current HMAC context
88 */
97b1a27f 89 HMAC_CTX *hmac;
db0c53c2 90#endif
97b1a27f
TB
91
92#if OPENSSL_VERSION_NUMBER < 0x10100000L
93 /**
94 * Static context for OpenSSL < 1.1.0
95 */
96 HMAC_CTX hmac_ctx;
97#endif
8391c1d0
TB
98};
99
6a440f83
TB
100/**
101 * Resets the state with the given key, or only resets the internal state
102 * if key is chunk_empty.
103 */
104static bool reset(private_mac_t *this, chunk_t key)
8391c1d0 105{
db0c53c2
TB
106#if OPENSSL_VERSION_NUMBER >= 0x30000000L
107 if (!key.len || EVP_MAC_init(this->hmac_base, key.ptr, key.len, NULL))
108 {
109 EVP_MAC_CTX_free(this->hmac);
110 this->hmac = EVP_MAC_CTX_dup(this->hmac_base);
111 return TRUE;
112 }
113#else
97b1a27f 114 if (HMAC_Init_ex(this->hmac, key.ptr, key.len, this->hasher, NULL))
c2906c8f 115 {
c2906c8f
MW
116 return TRUE;
117 }
082b0d72 118#endif
db0c53c2 119 return FALSE;
8391c1d0
TB
120}
121
6a440f83
TB
122METHOD(mac_t, set_key, bool,
123 private_mac_t *this, chunk_t key)
124{
125 if (!key.ptr)
64b28172 126 { /* HMAC_Init_ex() won't reset the key if a NULL pointer is passed,
627eaa22 127 * use a lengthy string in case there is a limit in FIPS-mode */
64b28172 128 key = chunk_from_str("00000000000000000000000000000000");
6a440f83 129 }
db0c53c2
TB
130 if (!reset(this, key))
131 {
132 return FALSE;
133 }
134 return TRUE;
135}
136
137METHOD(mac_t, get_mac_size, size_t,
138 private_mac_t *this)
139{
140#if OPENSSL_VERSION_NUMBER >= 0x30000000L
141 return EVP_MAC_CTX_get_mac_size(this->hmac);
142#else
143 return EVP_MD_size(this->hasher);
144#endif
6a440f83
TB
145}
146
27e1eabb 147METHOD(mac_t, get_mac, bool,
b12c53ce 148 private_mac_t *this, chunk_t data, uint8_t *out)
8391c1d0 149{
db0c53c2
TB
150#if OPENSSL_VERSION_NUMBER >= 0x30000000L
151 if (!EVP_MAC_update(this->hmac, data.ptr, data.len))
152 {
153 return FALSE;
154 }
155#else
97b1a27f 156 if (!HMAC_Update(this->hmac, data.ptr, data.len))
082b0d72
MW
157 {
158 return FALSE;
159 }
db0c53c2
TB
160#endif
161 if (!out)
8391c1d0 162 {
082b0d72 163 return TRUE;
8391c1d0 164 }
db0c53c2
TB
165#if OPENSSL_VERSION_NUMBER >= 0x30000000L
166 if (!EVP_MAC_final(this->hmac, out, NULL, get_mac_size(this)))
082b0d72
MW
167 {
168 return FALSE;
169 }
db0c53c2
TB
170#else
171 if (!HMAC_Final(this->hmac, out, NULL))
082b0d72 172 {
db0c53c2 173 return FALSE;
082b0d72 174 }
082b0d72 175#endif
6a440f83 176 return reset(this, chunk_empty);
8391c1d0
TB
177}
178
c4a3c967
TB
179METHOD(mac_t, destroy, void,
180 private_mac_t *this)
8391c1d0 181{
db0c53c2
TB
182#if OPENSSL_VERSION_NUMBER >= 0x30000000L
183 EVP_MAC_CTX_free(this->hmac_base);
184 EVP_MAC_CTX_free(this->hmac);
185#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
97b1a27f
TB
186 HMAC_CTX_free(this->hmac);
187#else
188 HMAC_CTX_cleanup(&this->hmac_ctx);
189#endif
8391c1d0
TB
190 free(this);
191}
192
193/*
c4a3c967 194 * Create an OpenSSL-backed implementation of the mac_t interface
8391c1d0 195 */
c4a3c967 196static mac_t *hmac_create(hash_algorithm_t algo)
8391c1d0 197{
c4a3c967 198 private_mac_t *this;
610f90a8
MW
199 char *name;
200
201 name = enum_to_name(hash_algorithm_short_names, algo);
202 if (!name)
203 {
204 return NULL;
205 }
8391c1d0
TB
206
207 INIT(this,
208 .public = {
209 .get_mac = _get_mac,
73d032e4 210 .get_mac_size = _get_mac_size,
8391c1d0
TB
211 .set_key = _set_key,
212 .destroy = _destroy,
213 },
214 );
215
db0c53c2
TB
216#if OPENSSL_VERSION_NUMBER >= 0x30000000L
217 OSSL_PARAM params[] = {
218 OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, name, 0),
219 OSSL_PARAM_END,
220 };
221 EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
222
223 if (!mac)
224 {
225 free(this);
226 return NULL;
227 }
228 this->hmac_base = EVP_MAC_CTX_new(mac);
229 EVP_MAC_free(mac);
230 if (!this->hmac_base || !EVP_MAC_CTX_set_params(this->hmac_base, params))
231 {
232 free(this);
233 return NULL;
234 }
235#else /* OPENSSL_VERSION_NUMBER */
236 this->hasher = EVP_get_digestbyname(name);
8391c1d0
TB
237 if (!this->hasher)
238 {
239 free(this);
240 return NULL;
241 }
97b1a27f
TB
242#if OPENSSL_VERSION_NUMBER >= 0x10100000L
243 this->hmac = HMAC_CTX_new();
244#else
245 HMAC_CTX_init(&this->hmac_ctx);
246 this->hmac = &this->hmac_ctx;
247#endif
db0c53c2 248#endif /* OPENSSL_VERSION_NUMBER */
8391c1d0 249
6b347d52 250 /* make sure the underlying hash algorithm is supported */
64b28172 251 if (!set_key(this, chunk_empty))
6b347d52
TB
252 {
253 destroy(this);
254 return NULL;
255 }
8391c1d0
TB
256 return &this->public;
257}
73d032e4
TB
258
259/*
260 * Described in header
261 */
262prf_t *openssl_hmac_prf_create(pseudo_random_function_t algo)
263{
c4a3c967 264 mac_t *hmac;
73d032e4 265
228d096e 266 hmac = hmac_create(hasher_algorithm_from_prf(algo));
73d032e4
TB
267 if (hmac)
268 {
c4a3c967 269 return mac_prf_create(hmac);
73d032e4
TB
270 }
271 return NULL;
272}
273
274/*
275 * Described in header
276 */
277signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo)
278{
c4a3c967 279 mac_t *hmac;
228d096e 280 size_t trunc;
73d032e4 281
228d096e 282 hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc));
73d032e4
TB
283 if (hmac)
284 {
c4a3c967 285 return mac_signer_create(hmac, trunc);
73d032e4
TB
286 }
287 return NULL;
288}
289
a3a190b7 290#endif /* OPENSSL_NO_HMAC */