Support void return values in OpenSSL 0.9.8 HMAC functions
[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 METHOD(mac_t, set_key, bool,
71 private_mac_t *this, chunk_t key)
72 {
73 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
74 return HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL);
75 #else /* OPENSSL_VERSION_NUMBER < 1.0 */
76 HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL);
77 return TRUE;
78 #endif
79 }
80
81 METHOD(mac_t, get_mac, bool,
82 private_mac_t *this, chunk_t data, u_int8_t *out)
83 {
84 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
85 if (!HMAC_Update(&this->hmac, data.ptr, data.len))
86 {
87 return FALSE;
88 }
89 if (out == NULL)
90 {
91 return TRUE;
92 }
93 if (!HMAC_Final(&this->hmac, out, NULL))
94 {
95 return FALSE;
96 }
97 #else /* OPENSSL_VERSION_NUMBER < 1.0 */
98 HMAC_Update(&this->hmac, data.ptr, data.len);
99 if (out == NULL)
100 {
101 return TRUE;
102 }
103 HMAC_Final(&this->hmac, out, NULL);
104 #endif
105 return set_key(this, chunk_empty);
106 }
107
108 METHOD(mac_t, get_mac_size, size_t,
109 private_mac_t *this)
110 {
111 return EVP_MD_size(this->hasher);
112 }
113
114 METHOD(mac_t, destroy, void,
115 private_mac_t *this)
116 {
117 HMAC_CTX_cleanup(&this->hmac);
118 free(this);
119 }
120
121 /*
122 * Create an OpenSSL-backed implementation of the mac_t interface
123 */
124 static mac_t *hmac_create(hash_algorithm_t algo)
125 {
126 private_mac_t *this;
127
128 INIT(this,
129 .public = {
130 .get_mac = _get_mac,
131 .get_mac_size = _get_mac_size,
132 .set_key = _set_key,
133 .destroy = _destroy,
134 },
135 );
136
137 switch (algo)
138 {
139 case HASH_MD5:
140 this->hasher = EVP_get_digestbyname("md5");
141 break;
142 case HASH_SHA1:
143 this->hasher = EVP_get_digestbyname("sha1");
144 break;
145 case HASH_SHA256:
146 this->hasher = EVP_get_digestbyname("sha256");
147 break;
148 case HASH_SHA384:
149 this->hasher = EVP_get_digestbyname("sha384");
150 break;
151 case HASH_SHA512:
152 this->hasher = EVP_get_digestbyname("sha512");
153 break;
154 default:
155 break;
156 }
157
158 if (!this->hasher)
159 {
160 free(this);
161 return NULL;
162 }
163
164 HMAC_CTX_init(&this->hmac);
165 if (!set_key(this, chunk_empty))
166 {
167 destroy(this);
168 return NULL;
169 }
170
171 return &this->public;
172 }
173
174 /*
175 * Described in header
176 */
177 prf_t *openssl_hmac_prf_create(pseudo_random_function_t algo)
178 {
179 mac_t *hmac;
180
181 hmac = hmac_create(hasher_algorithm_from_prf(algo));
182 if (hmac)
183 {
184 return mac_prf_create(hmac);
185 }
186 return NULL;
187 }
188
189 /*
190 * Described in header
191 */
192 signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo)
193 {
194 mac_t *hmac;
195 size_t trunc;
196
197 hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc));
198 if (hmac)
199 {
200 return mac_signer_create(hmac, trunc);
201 }
202 return NULL;
203 }
204