Branch data Line data Source code
1 : : /**
2 : : * \file lib/fko_hmac.c
3 : : *
4 : : * \brief Provide HMAC support to SPA communications
5 : : */
6 : :
7 : : /* Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
8 : : * Copyright (C) 2009-2015 fwknop developers and contributors. For a full
9 : : * list of contributors, see the file 'CREDITS'.
10 : : *
11 : : * License (GNU General Public License):
12 : : *
13 : : * This program is free software; you can redistribute it and/or
14 : : * modify it under the terms of the GNU General Public License
15 : : * as published by the Free Software Foundation; either version 2
16 : : * of the License, or (at your option) any later version.
17 : : *
18 : : * This program is distributed in the hope that it will be useful,
19 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : : * GNU General Public License for more details.
22 : : *
23 : : * You should have received a copy of the GNU General Public License
24 : : * along with this program; if not, write to the Free Software
25 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 : : * USA
27 : : *
28 : : *****************************************************************************
29 : : */
30 : : #include "fko_common.h"
31 : : #include "fko.h"
32 : : #include "cipher_funcs.h"
33 : : #include "hmac.h"
34 : : #include "base64.h"
35 : :
36 : : int
37 : 768146 : fko_verify_hmac(fko_ctx_t ctx,
38 : : const char * const hmac_key, const int hmac_key_len)
39 : : {
40 : 768146 : char *hmac_digest_from_data = NULL;
41 : 768146 : char *tbuf = NULL;
42 : 768146 : int res = FKO_SUCCESS;
43 : 768146 : int hmac_b64_digest_len = 0, zero_free_rv = FKO_SUCCESS;
44 : :
45 : : /* Must be initialized
46 : : */
47 [ + + ][ + - ]: 768146 : if(!CTX_INITIALIZED(ctx))
48 : : return(FKO_ERROR_CTX_NOT_INITIALIZED);
49 : :
50 [ + - ]: 768086 : if(hmac_key == NULL)
51 : : return(FKO_ERROR_INVALID_DATA);
52 : :
53 [ + - ]: 768086 : if (! is_valid_encoded_msg_len(ctx->encrypted_msg_len))
54 : : return(FKO_ERROR_INVALID_DATA_HMAC_MSGLEN_VALIDFAIL);
55 : :
56 [ + + ]: 768086 : if(hmac_key_len < 0 || hmac_key_len > MAX_DIGEST_BLOCK_LEN)
57 : : return(FKO_ERROR_INVALID_HMAC_KEY_LEN);
58 : :
59 [ + + ]: 768085 : if(ctx->hmac_type == FKO_HMAC_MD5)
60 : : hmac_b64_digest_len = MD5_B64_LEN;
61 [ + + ]: 768079 : else if(ctx->hmac_type == FKO_HMAC_SHA1)
62 : : hmac_b64_digest_len = SHA1_B64_LEN;
63 [ + + ]: 768058 : else if(ctx->hmac_type == FKO_HMAC_SHA256)
64 : : hmac_b64_digest_len = SHA256_B64_LEN;
65 [ + + ]: 17 : else if(ctx->hmac_type == FKO_HMAC_SHA384)
66 : : hmac_b64_digest_len = SHA384_B64_LEN;
67 [ + + ]: 11 : else if(ctx->hmac_type == FKO_HMAC_SHA512)
68 : : hmac_b64_digest_len = SHA512_B64_LEN;
69 [ + + ]: 2 : else if(ctx->hmac_type == FKO_HMAC_SHA3_256)
70 : : hmac_b64_digest_len = SHA3_256_B64_LEN;
71 [ + - ]: 1 : else if(ctx->hmac_type == FKO_HMAC_SHA3_512)
72 : : hmac_b64_digest_len = SHA3_512_B64_LEN;
73 : : else
74 : : return(FKO_ERROR_UNSUPPORTED_HMAC_MODE);
75 : :
76 [ + + ]: 768085 : if((ctx->encrypted_msg_len - hmac_b64_digest_len)
77 : : < MIN_SPA_ENCODED_MSG_SIZE)
78 : : return(FKO_ERROR_INVALID_DATA_HMAC_ENCMSGLEN_VALIDFAIL);
79 : :
80 : : /* Get digest value
81 : : */
82 : 1536150 : hmac_digest_from_data = strndup((ctx->encrypted_msg
83 : 768075 : + ctx->encrypted_msg_len - hmac_b64_digest_len),
84 : : hmac_b64_digest_len);
85 : :
86 [ + - ]: 768075 : if(hmac_digest_from_data == NULL)
87 : : return(FKO_ERROR_MEMORY_ALLOCATION);
88 : :
89 : : /* Now we chop the HMAC digest off of the encrypted msg
90 : : */
91 : 768075 : tbuf = strndup(ctx->encrypted_msg,
92 : : ctx->encrypted_msg_len - hmac_b64_digest_len);
93 : :
94 [ - + ]: 768075 : if(tbuf == NULL)
95 : : {
96 [ # # ]: 0 : if(zero_free(hmac_digest_from_data, strnlen(hmac_digest_from_data,
97 : : MAX_SPA_ENCODED_MSG_SIZE)) == FKO_SUCCESS)
98 : : return(FKO_ERROR_MEMORY_ALLOCATION);
99 : : else
100 : 0 : return(FKO_ERROR_ZERO_OUT_DATA);
101 : : }
102 : :
103 [ + + ]: 768075 : if(zero_free(ctx->encrypted_msg, ctx->encrypted_msg_len) != FKO_SUCCESS)
104 : 2 : zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
105 : :
106 : 768075 : ctx->encrypted_msg = tbuf;
107 : 768075 : ctx->encrypted_msg_len -= hmac_b64_digest_len;
108 : :
109 [ + + ]: 768075 : if(ctx->encryption_mode == FKO_ENC_MODE_ASYMMETRIC)
110 : : {
111 : : /* See if we need to add the "hQ" string to the front of the
112 : : * encrypted data.
113 : : */
114 [ + - ]: 24 : if(! ctx->added_gpg_prefix)
115 : : {
116 : 24 : res = add_gpg_prefix(ctx);
117 : : }
118 : : }
119 : : else
120 : : {
121 : : /* See if we need to add the "Salted__" string to the front of the
122 : : * encrypted data.
123 : : */
124 [ + + ]: 768051 : if(! ctx->added_salted_str)
125 : : {
126 : 768043 : res = add_salted_str(ctx);
127 : : }
128 : : }
129 : :
130 [ + + ]: 768075 : if (res != FKO_SUCCESS)
131 : : {
132 [ - + ]: 30 : if(zero_free(hmac_digest_from_data, strnlen(hmac_digest_from_data,
133 : : MAX_SPA_ENCODED_MSG_SIZE)) != FKO_SUCCESS)
134 : 0 : zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
135 : :
136 [ - + ]: 30 : if(zero_free_rv == FKO_SUCCESS)
137 : : return(res);
138 : : else
139 : 0 : return(zero_free_rv);
140 : : }
141 : :
142 : : /* Calculate the HMAC from the encrypted data and then
143 : : * compare
144 : : */
145 : 768045 : res = fko_set_spa_hmac_type(ctx, ctx->hmac_type);
146 [ + - ]: 768045 : if(res == FKO_SUCCESS)
147 : : {
148 : 768045 : res = fko_set_spa_hmac(ctx, hmac_key, hmac_key_len);
149 : :
150 [ + + ]: 768045 : if(res == FKO_SUCCESS)
151 : : {
152 [ + + ]: 768002 : if(constant_runtime_cmp(hmac_digest_from_data,
153 : 768002 : ctx->msg_hmac, hmac_b64_digest_len) != 0)
154 : : {
155 : 2121 : res = FKO_ERROR_INVALID_DATA_HMAC_COMPAREFAIL;
156 : : }
157 : : }
158 : : }
159 : :
160 [ + + ]: 768045 : if(zero_free(hmac_digest_from_data, strnlen(hmac_digest_from_data,
161 : : MAX_SPA_ENCODED_MSG_SIZE)) != FKO_SUCCESS)
162 : 2 : zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
163 : :
164 [ + + ]: 768045 : if(res == FKO_SUCCESS)
165 : : return(zero_free_rv);
166 : : else
167 : 2164 : return(res);
168 : : }
169 : :
170 : : /* Return the fko HMAC data
171 : : */
172 : : int
173 : 3924 : fko_get_spa_hmac(fko_ctx_t ctx, char **hmac_data)
174 : : {
175 : : /* Must be initialized
176 : : */
177 [ + + ][ + - ]: 3924 : if(!CTX_INITIALIZED(ctx))
178 : : return(FKO_ERROR_CTX_NOT_INITIALIZED);
179 : :
180 [ + + ]: 3772 : if(hmac_data == NULL)
181 : : return(FKO_ERROR_INVALID_DATA);
182 : :
183 : 3704 : *hmac_data = ctx->msg_hmac;
184 : :
185 : 3704 : return(FKO_SUCCESS);
186 : : }
187 : :
188 : : /* Set the HMAC type
189 : : */
190 : : int
191 : 2405335 : fko_set_spa_hmac_type(fko_ctx_t ctx, const short hmac_type)
192 : : {
193 : : #if HAVE_LIBFIU
194 [ + + ]: 2405335 : fiu_return_on("fko_set_spa_hmac_type_init",
195 : : FKO_ERROR_CTX_NOT_INITIALIZED);
196 : : #endif
197 : :
198 : : /* Must be initialized
199 : : */
200 [ + + ][ + - ]: 2405334 : if(!CTX_INITIALIZED(ctx))
201 : : return(FKO_ERROR_CTX_NOT_INITIALIZED);
202 : :
203 : : #if HAVE_LIBFIU
204 [ + + ]: 2404480 : fiu_return_on("fko_set_spa_hmac_type_val",
205 : : FKO_ERROR_INVALID_DATA_HMAC_TYPE_VALIDFAIL);
206 : : #endif
207 : :
208 [ + + ]: 2404479 : if(hmac_type < 0 || hmac_type >= FKO_LAST_HMAC_MODE)
209 : : return(FKO_ERROR_INVALID_DATA_HMAC_TYPE_VALIDFAIL);
210 : :
211 : 2400436 : ctx->hmac_type = hmac_type;
212 : :
213 : 2400436 : ctx->state |= FKO_HMAC_MODE_MODIFIED;
214 : :
215 : 2400436 : return(FKO_SUCCESS);
216 : : }
217 : :
218 : : /* Return the fko HMAC type
219 : : */
220 : : int
221 : 5617 : fko_get_spa_hmac_type(fko_ctx_t ctx, short *hmac_type)
222 : : {
223 : : /* Must be initialized
224 : : */
225 [ + + ][ + - ]: 5617 : if(!CTX_INITIALIZED(ctx))
226 : : return(FKO_ERROR_CTX_NOT_INITIALIZED);
227 : :
228 [ + + ]: 5045 : if(hmac_type == NULL)
229 : : return(FKO_ERROR_INVALID_DATA);
230 : :
231 : 4977 : *hmac_type = ctx->hmac_type;
232 : :
233 : 4977 : return(FKO_SUCCESS);
234 : : }
235 : :
236 : 1522942 : int fko_set_spa_hmac(fko_ctx_t ctx,
237 : : const char * const hmac_key, const int hmac_key_len)
238 : : {
239 : 1522942 : unsigned char hmac[SHA512_DIGEST_STR_LEN] = {0};
240 : 1522942 : char *hmac_base64 = NULL;
241 : 1522942 : int hmac_digest_str_len = 0;
242 : 1522942 : int hmac_digest_len = 0;
243 : 1522942 : int res = FKO_ERROR_UNKNOWN ;
244 : :
245 : : /* Must be initialized
246 : : */
247 [ + + ][ + - ]: 1522942 : if(!CTX_INITIALIZED(ctx))
248 : : return(FKO_ERROR_CTX_NOT_INITIALIZED);
249 : :
250 [ + + ]: 1522934 : if(hmac_key == NULL)
251 : : return(FKO_ERROR_INVALID_DATA);
252 : :
253 [ + + ]: 1522910 : if(hmac_key_len < 0 || hmac_key_len > MAX_DIGEST_BLOCK_LEN)
254 : : return(FKO_ERROR_INVALID_HMAC_KEY_LEN);
255 : :
256 [ + + ]: 1522856 : if(ctx->hmac_type == FKO_HMAC_MD5)
257 : : {
258 : 51 : res = hmac_md5(ctx->encrypted_msg,
259 : 51 : ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len);
260 : :
261 : 51 : hmac_digest_len = MD5_DIGEST_LEN;
262 : 51 : hmac_digest_str_len = MD5_DIGEST_STR_LEN;
263 : : }
264 [ + + ]: 1522805 : else if(ctx->hmac_type == FKO_HMAC_SHA1)
265 : : {
266 : 89 : res = hmac_sha1(ctx->encrypted_msg,
267 : 89 : ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len);
268 : :
269 : 89 : hmac_digest_len = SHA1_DIGEST_LEN;
270 : 89 : hmac_digest_str_len = SHA1_DIGEST_STR_LEN;
271 : : }
272 [ + + ]: 1522716 : else if(ctx->hmac_type == FKO_HMAC_SHA256)
273 : : {
274 : 1522596 : res = hmac_sha256(ctx->encrypted_msg,
275 : 1522596 : ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len);
276 : :
277 : 1522596 : hmac_digest_len = SHA256_DIGEST_LEN;
278 : 1522596 : hmac_digest_str_len = SHA256_DIGEST_STR_LEN;
279 : : }
280 [ + + ]: 120 : else if(ctx->hmac_type == FKO_HMAC_SHA384)
281 : : {
282 : 51 : res = hmac_sha384(ctx->encrypted_msg,
283 : 51 : ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len);
284 : :
285 : 51 : hmac_digest_len = SHA384_DIGEST_LEN;
286 : 51 : hmac_digest_str_len = SHA384_DIGEST_STR_LEN;
287 : : }
288 [ + + ]: 69 : else if(ctx->hmac_type == FKO_HMAC_SHA512)
289 : : {
290 : 57 : res = hmac_sha512(ctx->encrypted_msg,
291 : 57 : ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len);
292 : :
293 : 57 : hmac_digest_len = SHA512_DIGEST_LEN;
294 : 57 : hmac_digest_str_len = SHA512_DIGEST_STR_LEN;
295 : : }
296 [ + + ]: 12 : else if(ctx->hmac_type == FKO_HMAC_SHA3_256)
297 : : {
298 : 2 : res = hmac_sha3_256(ctx->encrypted_msg,
299 : 2 : ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len);
300 : 2 : hmac_digest_len = SHA3_256_DIGEST_LEN;
301 : 2 : hmac_digest_str_len = SHA3_256_DIGEST_STR_LEN;
302 : :
303 : : }
304 [ + - ]: 10 : else if(ctx->hmac_type == FKO_HMAC_SHA3_512)
305 : : {
306 : 10 : res = hmac_sha3_512(ctx->encrypted_msg,
307 : 10 : ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len);
308 : 10 : hmac_digest_len = SHA3_512_DIGEST_LEN;
309 : 10 : hmac_digest_str_len = SHA3_512_DIGEST_STR_LEN;
310 : :
311 : : }
312 : :
313 [ + + ]: 1522856 : if (res != FKO_SUCCESS)
314 : : return res;
315 : :
316 : 1522835 : hmac_base64 = calloc(1, MD_HEX_SIZE(hmac_digest_len)+1);
317 [ + + ]: 1522835 : if (hmac_base64 == NULL)
318 : : return(FKO_ERROR_MEMORY_ALLOCATION);
319 : :
320 : 1522813 : b64_encode(hmac, hmac_base64, hmac_digest_len);
321 : 1522813 : strip_b64_eq(hmac_base64);
322 : :
323 [ + + ]: 1522813 : if(ctx->msg_hmac != NULL)
324 : 2623 : free(ctx->msg_hmac);
325 : :
326 : 1522813 : ctx->msg_hmac = strdup(hmac_base64);
327 : :
328 : 1522813 : free(hmac_base64);
329 : :
330 [ + - ]: 1522813 : if(ctx->msg_hmac == NULL)
331 : : return(FKO_ERROR_MEMORY_ALLOCATION);
332 : :
333 : 1522813 : ctx->msg_hmac_len = strnlen(ctx->msg_hmac, hmac_digest_str_len);
334 : :
335 [ + - ]: 1522813 : switch(ctx->msg_hmac_len)
336 : : {
337 : : case MD5_B64_LEN:
338 : : break;
339 : : case SHA1_B64_LEN:
340 : : break;
341 : : case SHA256_B64_LEN:
342 : : break;
343 : : case SHA384_B64_LEN:
344 : : break;
345 : : case SHA512_B64_LEN:
346 : : break;
347 : : default:
348 : : return(FKO_ERROR_INVALID_DATA_HMAC_LEN_VALIDFAIL);
349 : : }
350 : :
351 : 1522813 : return FKO_SUCCESS;
352 : : }
353 : :
354 : : /***EOF***/
|