Resetting OpenSSL HMAC with NULL key reuses existing key
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_hmac.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * 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/evp.h>
39 #include <openssl/hmac.h>
40
41 #include "openssl_hmac.h"
42
43 #include <crypto/mac.h>
44 #include <crypto/prfs/mac_prf.h>
45 #include <crypto/signers/mac_signer.h>
46
47 typedef struct private_mac_t private_mac_t;
48
49 /**
50 * Private data of a mac_t object.
51 */
52 struct private_mac_t {
53
54 /**
55 * Public interface
56 */
57 mac_t public;
58
59 /**
60 * Hasher to use
61 */
62 const EVP_MD *hasher;
63
64 /**
65 * Current HMAC context
66 */
67 HMAC_CTX hmac;
68 };
69
70 /**
71 * Resets HMAC context
72 */
73 static bool reset(private_mac_t *this)
74 {
75 return HMAC_Init_ex(&this->hmac, NULL, 0, this->hasher, NULL);
76 }
77
78 METHOD(mac_t, get_mac, bool,
79 private_mac_t *this, chunk_t data, u_int8_t *out)
80 {
81 if (out == NULL)
82 {
83 return HMAC_Update(&this->hmac, data.ptr, data.len);
84 }
85 return HMAC_Update(&this->hmac, data.ptr, data.len) &&
86 HMAC_Final(&this->hmac, out, NULL) &&
87 reset(this);
88 }
89
90 METHOD(mac_t, get_mac_size, size_t,
91 private_mac_t *this)
92 {
93 return EVP_MD_size(this->hasher);
94 }
95
96 METHOD(mac_t, set_key, bool,
97 private_mac_t *this, chunk_t key)
98 {
99 return HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL);
100 }
101
102 METHOD(mac_t, destroy, void,
103 private_mac_t *this)
104 {
105 HMAC_CTX_cleanup(&this->hmac);
106 free(this);
107 }
108
109 /*
110 * Create an OpenSSL-backed implementation of the mac_t interface
111 */
112 static mac_t *hmac_create(hash_algorithm_t algo)
113 {
114 private_mac_t *this;
115
116 INIT(this,
117 .public = {
118 .get_mac = _get_mac,
119 .get_mac_size = _get_mac_size,
120 .set_key = _set_key,
121 .destroy = _destroy,
122 },
123 );
124
125 switch (algo)
126 {
127 case HASH_MD5:
128 this->hasher = EVP_get_digestbyname("md5");
129 break;
130 case HASH_SHA1:
131 this->hasher = EVP_get_digestbyname("sha1");
132 break;
133 case HASH_SHA256:
134 this->hasher = EVP_get_digestbyname("sha256");
135 break;
136 case HASH_SHA384:
137 this->hasher = EVP_get_digestbyname("sha384");
138 break;
139 case HASH_SHA512:
140 this->hasher = EVP_get_digestbyname("sha512");
141 break;
142 default:
143 break;
144 }
145
146 if (!this->hasher)
147 {
148 free(this);
149 return NULL;
150 }
151
152 HMAC_CTX_init(&this->hmac);
153 if (!HMAC_Init_ex(&this->hmac, NULL, 0, this->hasher, NULL))
154 {
155 destroy(this);
156 return NULL;
157 }
158
159 return &this->public;
160 }
161
162 /*
163 * Described in header
164 */
165 prf_t *openssl_hmac_prf_create(pseudo_random_function_t algo)
166 {
167 mac_t *hmac;
168
169 hmac = hmac_create(hasher_algorithm_from_prf(algo));
170 if (hmac)
171 {
172 return mac_prf_create(hmac);
173 }
174 return NULL;
175 }
176
177 /*
178 * Described in header
179 */
180 signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo)
181 {
182 mac_t *hmac;
183 size_t trunc;
184
185 hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc));
186 if (hmac)
187 {
188 return mac_signer_create(hmac, trunc);
189 }
190 return NULL;
191 }
192
193