sec-updater: Use latest versions
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_hmac.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 /*
17 * Copyright (C) 2012 Aleksandr Grinberg
18 *
19 * Permission is hereby granted, free of charge, to any person obtaining a copy
20 * of this software and associated documentation files (the "Software"), to deal
21 * in the Software without restriction, including without limitation the rights
22 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 * copies of the Software, and to permit persons to whom the Software is
24 * furnished to do so, subject to the following conditions:
25 *
26 * The above copyright notice and this permission notice shall be included in
27 * all copies or substantial portions of the Software.
28 *
29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 * THE SOFTWARE.
36 */
37
38 #include <openssl/opensslconf.h>
39
40 #ifndef OPENSSL_NO_HMAC
41
42 #include <openssl/evp.h>
43 #include <openssl/hmac.h>
44
45 #include "openssl_hmac.h"
46
47 #include <crypto/mac.h>
48 #include <crypto/prfs/mac_prf.h>
49 #include <crypto/signers/mac_signer.h>
50
51 typedef struct private_mac_t private_mac_t;
52
53 /**
54 * Private data of a mac_t object.
55 */
56 struct private_mac_t {
57
58 /**
59 * Public interface
60 */
61 mac_t public;
62
63 /**
64 * Hasher to use
65 */
66 const EVP_MD *hasher;
67
68 /**
69 * Current HMAC context
70 */
71 HMAC_CTX *hmac;
72
73 #if OPENSSL_VERSION_NUMBER < 0x10100000L
74 /**
75 * Static context for OpenSSL < 1.1.0
76 */
77 HMAC_CTX hmac_ctx;
78 #endif
79 };
80
81 /**
82 * Resets the state with the given key, or only resets the internal state
83 * if key is chunk_empty.
84 */
85 static bool reset(private_mac_t *this, chunk_t key)
86 {
87 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
88 if (HMAC_Init_ex(this->hmac, key.ptr, key.len, this->hasher, NULL))
89 {
90 return TRUE;
91 }
92 return FALSE;
93 #else /* OPENSSL_VERSION_NUMBER < 1.0 */
94 HMAC_Init_ex(this->hmac, key.ptr, key.len, this->hasher, NULL);
95 return TRUE;
96 #endif
97 }
98
99 METHOD(mac_t, set_key, bool,
100 private_mac_t *this, chunk_t key)
101 {
102 if (!key.ptr)
103 { /* HMAC_Init_ex() won't reset the key if a NULL pointer is passed,
104 * use a lenghty string in case there is a limit in FIPS-mode */
105 key = chunk_from_str("00000000000000000000000000000000");
106 }
107 return reset(this, key);
108 }
109
110 METHOD(mac_t, get_mac, bool,
111 private_mac_t *this, chunk_t data, uint8_t *out)
112 {
113 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
114 if (!HMAC_Update(this->hmac, data.ptr, data.len))
115 {
116 return FALSE;
117 }
118 if (out == NULL)
119 {
120 return TRUE;
121 }
122 if (!HMAC_Final(this->hmac, out, NULL))
123 {
124 return FALSE;
125 }
126 #else /* OPENSSL_VERSION_NUMBER < 1.0 */
127 HMAC_Update(this->hmac, data.ptr, data.len);
128 if (out == NULL)
129 {
130 return TRUE;
131 }
132 HMAC_Final(this->hmac, out, NULL);
133 #endif
134 return reset(this, chunk_empty);
135 }
136
137 METHOD(mac_t, get_mac_size, size_t,
138 private_mac_t *this)
139 {
140 return EVP_MD_size(this->hasher);
141 }
142
143 METHOD(mac_t, destroy, void,
144 private_mac_t *this)
145 {
146 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
147 HMAC_CTX_free(this->hmac);
148 #else
149 HMAC_CTX_cleanup(&this->hmac_ctx);
150 #endif
151 free(this);
152 }
153
154 /*
155 * Create an OpenSSL-backed implementation of the mac_t interface
156 */
157 static mac_t *hmac_create(hash_algorithm_t algo)
158 {
159 private_mac_t *this;
160 char *name;
161
162 name = enum_to_name(hash_algorithm_short_names, algo);
163 if (!name)
164 {
165 return NULL;
166 }
167
168 INIT(this,
169 .public = {
170 .get_mac = _get_mac,
171 .get_mac_size = _get_mac_size,
172 .set_key = _set_key,
173 .destroy = _destroy,
174 },
175 .hasher = EVP_get_digestbyname(name),
176 );
177
178 if (!this->hasher)
179 {
180 free(this);
181 return NULL;
182 }
183
184 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
185 this->hmac = HMAC_CTX_new();
186 #else
187 HMAC_CTX_init(&this->hmac_ctx);
188 this->hmac = &this->hmac_ctx;
189 #endif
190
191 /* make sure the underlying hash algorithm is supported */
192 if (!set_key(this, chunk_empty))
193 {
194 destroy(this);
195 return NULL;
196 }
197 return &this->public;
198 }
199
200 /*
201 * Described in header
202 */
203 prf_t *openssl_hmac_prf_create(pseudo_random_function_t algo)
204 {
205 mac_t *hmac;
206
207 hmac = hmac_create(hasher_algorithm_from_prf(algo));
208 if (hmac)
209 {
210 return mac_prf_create(hmac);
211 }
212 return NULL;
213 }
214
215 /*
216 * Described in header
217 */
218 signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo)
219 {
220 mac_t *hmac;
221 size_t trunc;
222
223 hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc));
224 if (hmac)
225 {
226 return mac_signer_create(hmac, trunc);
227 }
228 return NULL;
229 }
230
231 #endif /* OPENSSL_NO_HMAC */