1 /*
2  * Copyright (C) 2000-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>
20  *
21  */
22 
23 /* This file handles all the internal functions that cope with hashes
24  * and HMACs.
25  */
26 
27 #include "gnutls_int.h"
28 #include <hash_int.h>
29 #include "errors.h"
30 #include <algorithms.h>
31 #include <fips.h>
32 
_gnutls_hash_init(digest_hd_st * dig,const mac_entry_st * e)33 int _gnutls_hash_init(digest_hd_st * dig, const mac_entry_st * e)
34 {
35 	int result;
36 	const gnutls_crypto_digest_st *cc = NULL;
37 
38 	FAIL_IF_LIB_ERROR;
39 
40 	if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
41 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
42 
43 	dig->e = e;
44 
45 	/* check if a digest has been registered
46 	 */
47 	cc = _gnutls_get_crypto_digest((gnutls_digest_algorithm_t)e->id);
48 	if (cc != NULL && cc->init) {
49 		if (cc->init((gnutls_digest_algorithm_t)e->id, &dig->handle) < 0) {
50 			gnutls_assert();
51 			return GNUTLS_E_HASH_FAILED;
52 		}
53 
54 		dig->hash = cc->hash;
55 		dig->output = cc->output;
56 		dig->deinit = cc->deinit;
57 		dig->copy = cc->copy;
58 
59 		return 0;
60 	}
61 
62 	result = _gnutls_digest_ops.init((gnutls_digest_algorithm_t)e->id, &dig->handle);
63 	if (result < 0) {
64 		gnutls_assert();
65 		return result;
66 	}
67 
68 	dig->hash = _gnutls_digest_ops.hash;
69 	dig->output = _gnutls_digest_ops.output;
70 	dig->deinit = _gnutls_digest_ops.deinit;
71 	dig->copy = _gnutls_digest_ops.copy;
72 
73 	return 0;
74 }
75 
76 /* Returns true(non-zero) or false(0) if the
77  * provided hash exists
78  */
_gnutls_digest_exists(gnutls_digest_algorithm_t algo)79 int _gnutls_digest_exists(gnutls_digest_algorithm_t algo)
80 {
81 	const gnutls_crypto_digest_st *cc = NULL;
82 
83 	if (is_mac_algo_forbidden(DIG_TO_MAC(algo)))
84 		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
85 
86 	cc = _gnutls_get_crypto_digest(algo);
87 	if (cc != NULL)
88 		return 1;
89 
90 	return _gnutls_digest_ops.exists(algo);
91 }
92 
_gnutls_hash_copy(const digest_hd_st * handle,digest_hd_st * dst)93 int _gnutls_hash_copy(const digest_hd_st * handle, digest_hd_st * dst)
94 {
95 	if (handle->copy == NULL)
96 		return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
97 
98 	*dst = *handle; /* copy data */
99 	dst->handle = handle->copy(handle->handle);
100 
101 	if (dst->handle == NULL)
102 		return GNUTLS_E_HASH_FAILED;
103 
104 	return 0;
105 }
106 
_gnutls_hash_deinit(digest_hd_st * handle,void * digest)107 void _gnutls_hash_deinit(digest_hd_st * handle, void *digest)
108 {
109 	if (handle->handle == NULL) {
110 		return;
111 	}
112 
113 	if (digest != NULL)
114 		_gnutls_hash_output(handle, digest);
115 
116 	handle->deinit(handle->handle);
117 	handle->handle = NULL;
118 }
119 
120 int
_gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,const void * text,size_t textlen,void * digest)121 _gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,
122 		  const void *text, size_t textlen, void *digest)
123 {
124 	int ret;
125 	const gnutls_crypto_digest_st *cc = NULL;
126 
127 	FAIL_IF_LIB_ERROR;
128 
129 	/* check if a digest has been registered
130 	 */
131 	cc = _gnutls_get_crypto_digest(algorithm);
132 	if (cc != NULL) {
133 		if (cc->fast(algorithm, text, textlen, digest) < 0) {
134 			gnutls_assert();
135 			return GNUTLS_E_HASH_FAILED;
136 		}
137 
138 		return 0;
139 	}
140 
141 	ret = _gnutls_digest_ops.fast(algorithm, text, textlen, digest);
142 	if (ret < 0) {
143 		gnutls_assert();
144 		return ret;
145 	}
146 
147 	return 0;
148 }
149 
150 
151 /* HMAC interface */
152 
153 int
_gnutls_mac_fast(gnutls_mac_algorithm_t algorithm,const void * key,int keylen,const void * text,size_t textlen,void * digest)154 _gnutls_mac_fast(gnutls_mac_algorithm_t algorithm, const void *key,
155 		 int keylen, const void *text, size_t textlen,
156 		 void *digest)
157 {
158 	int ret;
159 	const gnutls_crypto_mac_st *cc = NULL;
160 
161 	FAIL_IF_LIB_ERROR;
162 
163 	/* check if a digest has been registered
164 	 */
165 	cc = _gnutls_get_crypto_mac(algorithm);
166 	if (cc != NULL) {
167 		if (cc->
168 		    fast(algorithm, NULL, 0, key, keylen, text, textlen,
169 			 digest) < 0) {
170 			gnutls_assert();
171 			return GNUTLS_E_HASH_FAILED;
172 		}
173 
174 		return 0;
175 	}
176 
177 	ret =
178 	    _gnutls_mac_ops.fast(algorithm, NULL, 0, key, keylen, text,
179 				 textlen, digest);
180 	if (ret < 0) {
181 		gnutls_assert();
182 		return ret;
183 	}
184 
185 	return 0;
186 
187 }
188 
189 /* Returns true(non-zero) or false(0) if the
190  * provided hash exists
191  */
_gnutls_mac_exists(gnutls_mac_algorithm_t algo)192 int _gnutls_mac_exists(gnutls_mac_algorithm_t algo)
193 {
194 	const gnutls_crypto_mac_st *cc = NULL;
195 
196 	/* exceptionally it exists, as it is not a real MAC */
197 	if (algo == GNUTLS_MAC_AEAD)
198 		return 1;
199 
200 	if (is_mac_algo_forbidden(algo))
201 		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
202 
203 	cc = _gnutls_get_crypto_mac(algo);
204 	if (cc != NULL)
205 		return 1;
206 
207 	return _gnutls_mac_ops.exists(algo);
208 }
209 
210 int
_gnutls_mac_init(mac_hd_st * mac,const mac_entry_st * e,const void * key,int keylen)211 _gnutls_mac_init(mac_hd_st * mac, const mac_entry_st * e,
212 		 const void *key, int keylen)
213 {
214 	int result;
215 	const gnutls_crypto_mac_st *cc = NULL;
216 
217 	FAIL_IF_LIB_ERROR;
218 
219 	if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
220 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
221 
222 	mac->e = e;
223 	mac->mac_len = _gnutls_mac_get_algo_len(e);
224 
225 	/* check if a digest has been registered
226 	 */
227 	cc = _gnutls_get_crypto_mac(e->id);
228 	if (cc != NULL && cc->init != NULL) {
229 		if (cc->init(e->id, &mac->handle) < 0) {
230 			gnutls_assert();
231 			return GNUTLS_E_HASH_FAILED;
232 		}
233 
234 		if (cc->setkey(mac->handle, key, keylen) < 0) {
235 			gnutls_assert();
236 			cc->deinit(mac->handle);
237 			return GNUTLS_E_HASH_FAILED;
238 		}
239 
240 		mac->hash = cc->hash;
241 		mac->setnonce = cc->setnonce;
242 		mac->output = cc->output;
243 		mac->deinit = cc->deinit;
244 		mac->copy = cc->copy;
245 
246 		return 0;
247 	}
248 
249 	result = _gnutls_mac_ops.init(e->id, &mac->handle);
250 	if (result < 0) {
251 		gnutls_assert();
252 		return result;
253 	}
254 
255 	mac->hash = _gnutls_mac_ops.hash;
256 	mac->setnonce = _gnutls_mac_ops.setnonce;
257 	mac->output = _gnutls_mac_ops.output;
258 	mac->deinit = _gnutls_mac_ops.deinit;
259 	mac->copy = _gnutls_mac_ops.copy;
260 
261 	if (_gnutls_mac_ops.setkey(mac->handle, key, keylen) < 0) {
262 		gnutls_assert();
263 		mac->deinit(mac->handle);
264 		return GNUTLS_E_HASH_FAILED;
265 	}
266 
267 	return 0;
268 }
269 
_gnutls_mac_copy(const mac_hd_st * handle,mac_hd_st * dst)270 int _gnutls_mac_copy(const mac_hd_st * handle, mac_hd_st * dst)
271 {
272 	if (handle->copy == NULL)
273 		return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
274 
275 	*dst = *handle; /* copy data */
276 	dst->handle = handle->copy(handle->handle);
277 
278 	if (dst->handle == NULL)
279 		return GNUTLS_E_HASH_FAILED;
280 
281 	return 0;
282 }
283 
_gnutls_mac_deinit(mac_hd_st * handle,void * digest)284 void _gnutls_mac_deinit(mac_hd_st * handle, void *digest)
285 {
286 	if (handle->handle == NULL) {
287 		return;
288 	}
289 
290 	if (digest)
291 		_gnutls_mac_output(handle, digest);
292 
293 	handle->deinit(handle->handle);
294 	handle->handle = NULL;
295 }
296 
297 #ifdef ENABLE_SSL3
get_padsize(gnutls_mac_algorithm_t algorithm)298 inline static int get_padsize(gnutls_mac_algorithm_t algorithm)
299 {
300 	switch (algorithm) {
301 	case GNUTLS_MAC_MD5:
302 		return 48;
303 	case GNUTLS_MAC_SHA1:
304 		return 40;
305 	default:
306 		return 0;
307 	}
308 }
309 
310 /* Special functions for SSL3 MAC
311  */
312 
313 int
_gnutls_mac_init_ssl3(digest_hd_st * ret,const mac_entry_st * e,void * key,int keylen)314 _gnutls_mac_init_ssl3(digest_hd_st * ret, const mac_entry_st * e,
315 		      void *key, int keylen)
316 {
317 	uint8_t ipad[48];
318 	int padsize, result;
319 
320 	FAIL_IF_LIB_ERROR;
321 
322 	padsize = get_padsize(e->id);
323 	if (padsize == 0) {
324 		gnutls_assert();
325 		return GNUTLS_E_HASH_FAILED;
326 	}
327 
328 	memset(ipad, 0x36, padsize);
329 
330 	result = _gnutls_hash_init(ret, e);
331 	if (result < 0) {
332 		gnutls_assert();
333 		return result;
334 	}
335 
336 	ret->key = key;
337 	ret->keysize = keylen;
338 
339 	if (keylen > 0)
340 		_gnutls_hash(ret, key, keylen);
341 	_gnutls_hash(ret, ipad, padsize);
342 
343 	return 0;
344 }
345 
_gnutls_mac_output_ssl3(digest_hd_st * handle,void * digest)346 int _gnutls_mac_output_ssl3(digest_hd_st * handle, void *digest)
347 {
348 	uint8_t ret[MAX_HASH_SIZE];
349 	digest_hd_st td;
350 	uint8_t opad[48];
351 	int padsize;
352 	int block, rc;
353 
354 	padsize = get_padsize(handle->e->id);
355 	if (padsize == 0) {
356 		gnutls_assert();
357 		return GNUTLS_E_INTERNAL_ERROR;
358 	}
359 
360 	memset(opad, 0x5C, padsize);
361 
362 	rc = _gnutls_hash_init(&td, handle->e);
363 	if (rc < 0) {
364 		gnutls_assert();
365 		return rc;
366 	}
367 
368 	if (handle->keysize > 0)
369 		_gnutls_hash(&td, handle->key, handle->keysize);
370 
371 	_gnutls_hash(&td, opad, padsize);
372 	block = _gnutls_mac_get_algo_len(handle->e);
373 	_gnutls_hash_output(handle, ret);	/* get the previous hash */
374 	_gnutls_hash(&td, ret, block);
375 
376 	_gnutls_hash_deinit(&td, digest);
377 
378 	/* reset handle */
379 	memset(opad, 0x36, padsize);
380 
381 	if (handle->keysize > 0)
382 		_gnutls_hash(handle, handle->key, handle->keysize);
383 	_gnutls_hash(handle, opad, padsize);
384 
385 	return 0;
386 }
387 
_gnutls_mac_deinit_ssl3(digest_hd_st * handle,void * digest)388 int _gnutls_mac_deinit_ssl3(digest_hd_st * handle, void *digest)
389 {
390 	int ret = 0;
391 
392 	if (digest != NULL)
393 		ret = _gnutls_mac_output_ssl3(handle, digest);
394 	_gnutls_hash_deinit(handle, NULL);
395 
396 	return ret;
397 }
398 
399 int
_gnutls_mac_deinit_ssl3_handshake(digest_hd_st * handle,void * digest,uint8_t * key,uint32_t key_size)400 _gnutls_mac_deinit_ssl3_handshake(digest_hd_st * handle,
401 				  void *digest, uint8_t * key,
402 				  uint32_t key_size)
403 {
404 	uint8_t ret[MAX_HASH_SIZE];
405 	digest_hd_st td;
406 	uint8_t opad[48];
407 	uint8_t ipad[48];
408 	int padsize;
409 	int block, rc;
410 
411 	padsize = get_padsize(handle->e->id);
412 	if (padsize == 0) {
413 		gnutls_assert();
414 		rc = GNUTLS_E_INTERNAL_ERROR;
415 		goto cleanup;
416 	}
417 
418 	memset(opad, 0x5C, padsize);
419 	memset(ipad, 0x36, padsize);
420 
421 	rc = _gnutls_hash_init(&td, handle->e);
422 	if (rc < 0) {
423 		gnutls_assert();
424 		goto cleanup;
425 	}
426 
427 	if (key_size > 0)
428 		_gnutls_hash(&td, key, key_size);
429 
430 	_gnutls_hash(&td, opad, padsize);
431 	block = _gnutls_mac_get_algo_len(handle->e);
432 
433 	if (key_size > 0)
434 		_gnutls_hash(handle, key, key_size);
435 	_gnutls_hash(handle, ipad, padsize);
436 	_gnutls_hash_deinit(handle, ret);	/* get the previous hash */
437 
438 	_gnutls_hash(&td, ret, block);
439 
440 	_gnutls_hash_deinit(&td, digest);
441 
442 	return 0;
443 
444       cleanup:
445 	_gnutls_hash_deinit(handle, NULL);
446 	return rc;
447 }
448 
449 static int
ssl3_sha(int i,uint8_t * secret,int secret_len,uint8_t * rnd,int rnd_len,void * digest)450 ssl3_sha(int i, uint8_t * secret, int secret_len,
451 	 uint8_t * rnd, int rnd_len, void *digest)
452 {
453 	int j, ret;
454 	uint8_t text1[26];
455 
456 	digest_hd_st td;
457 
458 	for (j = 0; j < i + 1; j++) {
459 		text1[j] = 65 + i;	/* A==65 */
460 	}
461 
462 	ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1));
463 	if (ret < 0) {
464 		gnutls_assert();
465 		return ret;
466 	}
467 
468 	_gnutls_hash(&td, text1, i + 1);
469 	_gnutls_hash(&td, secret, secret_len);
470 	_gnutls_hash(&td, rnd, rnd_len);
471 
472 	_gnutls_hash_deinit(&td, digest);
473 	return 0;
474 }
475 
476 #define SHA1_DIGEST_OUTPUT 20
477 #define MD5_DIGEST_OUTPUT 16
478 
479 static int
ssl3_md5(int i,uint8_t * secret,int secret_len,uint8_t * rnd,int rnd_len,void * digest)480 ssl3_md5(int i, uint8_t * secret, int secret_len,
481 	 uint8_t * rnd, int rnd_len, void *digest)
482 {
483 	uint8_t tmp[MAX_HASH_SIZE];
484 	digest_hd_st td;
485 	int ret;
486 
487 	ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
488 	if (ret < 0) {
489 		gnutls_assert();
490 		return ret;
491 	}
492 
493 	_gnutls_hash(&td, secret, secret_len);
494 
495 	ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp);
496 	if (ret < 0) {
497 		gnutls_assert();
498 		_gnutls_hash_deinit(&td, digest);
499 		return ret;
500 	}
501 
502 	_gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT);
503 
504 	_gnutls_hash_deinit(&td, digest);
505 	return 0;
506 }
507 
508 int
_gnutls_ssl3_generate_random(void * secret,int secret_len,void * rnd,int rnd_len,int ret_bytes,uint8_t * ret)509 _gnutls_ssl3_generate_random(void *secret, int secret_len,
510 			     void *rnd, int rnd_len,
511 			     int ret_bytes, uint8_t * ret)
512 {
513 	int i = 0, copy, output_bytes;
514 	uint8_t digest[MAX_HASH_SIZE];
515 	int block = MD5_DIGEST_OUTPUT;
516 	int result, times;
517 
518 	output_bytes = 0;
519 	do {
520 		output_bytes += block;
521 	}
522 	while (output_bytes < ret_bytes);
523 
524 	times = output_bytes / block;
525 
526 	for (i = 0; i < times; i++) {
527 
528 		result =
529 		    ssl3_md5(i, secret, secret_len, rnd, rnd_len, digest);
530 		if (result < 0) {
531 			gnutls_assert();
532 			return result;
533 		}
534 
535 		if ((1 + i) * block < ret_bytes) {
536 			copy = block;
537 		} else {
538 			copy = ret_bytes - (i) * block;
539 		}
540 
541 		memcpy(&ret[i * block], digest, copy);
542 	}
543 
544 	return 0;
545 }
546 
547 #endif
548