corrected copyright notices
[gnutls.git] / lib / gnutls_hash_int.c
blob740e13b0862341cc67e0ef954656f8f312e252dc
1 /*
2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
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 3 of
11 * the License, or (at your option) any later version.
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.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* This file handles all the internal functions that cope with hashes
24 * and HMACs.
27 #include <gnutls_int.h>
28 #include <gnutls_hash_int.h>
29 #include <gnutls_errors.h>
31 static size_t
32 digest_length (int algo)
34 switch (algo)
36 case GNUTLS_DIG_NULL:
37 case GNUTLS_MAC_AEAD:
38 return 0;
39 case GNUTLS_DIG_MD5:
40 case GNUTLS_DIG_MD2:
41 return 16;
42 case GNUTLS_DIG_SHA1:
43 case GNUTLS_DIG_RMD160:
44 return 20;
45 case GNUTLS_DIG_SHA256:
46 return 32;
47 case GNUTLS_DIG_SHA384:
48 return 48;
49 case GNUTLS_DIG_SHA512:
50 return 64;
51 case GNUTLS_DIG_SHA224:
52 return 28;
53 default:
54 gnutls_assert ();
55 return GNUTLS_E_INTERNAL_ERROR;
60 int
61 _gnutls_hash_init (digest_hd_st * dig, gnutls_digest_algorithm_t algorithm)
63 int result;
64 const gnutls_crypto_digest_st *cc = NULL;
66 dig->algorithm = algorithm;
68 /* check if a digest has been registered
70 cc = _gnutls_get_crypto_digest (algorithm);
71 if (cc != NULL && cc->init)
73 if (cc->init (algorithm, &dig->handle) < 0)
75 gnutls_assert ();
76 return GNUTLS_E_HASH_FAILED;
79 dig->hash = cc->hash;
80 dig->reset = cc->reset;
81 dig->output = cc->output;
82 dig->deinit = cc->deinit;
84 return 0;
87 result = _gnutls_digest_ops.init (algorithm, &dig->handle);
88 if (result < 0)
90 gnutls_assert ();
91 return result;
94 dig->hash = _gnutls_digest_ops.hash;
95 dig->reset = _gnutls_digest_ops.reset;
96 dig->output = _gnutls_digest_ops.output;
97 dig->deinit = _gnutls_digest_ops.deinit;
99 return 0;
102 void
103 _gnutls_hash_deinit (digest_hd_st * handle, void *digest)
105 if (handle->handle == NULL)
107 return;
110 if (digest != NULL)
111 _gnutls_hash_output (handle, digest);
113 handle->deinit (handle->handle);
114 handle->handle = NULL;
117 /* returns the output size of the given hash/mac algorithm
119 size_t
120 _gnutls_hash_get_algo_len (gnutls_digest_algorithm_t algorithm)
122 return digest_length (algorithm);
126 _gnutls_hash_fast (gnutls_digest_algorithm_t algorithm,
127 const void *text, size_t textlen, void *digest)
129 int ret;
130 const gnutls_crypto_digest_st *cc = NULL;
132 /* check if a digest has been registered
134 cc = _gnutls_get_crypto_digest (algorithm);
135 if (cc != NULL)
137 if (cc->fast (algorithm, text, textlen, digest) < 0)
139 gnutls_assert ();
140 return GNUTLS_E_HASH_FAILED;
143 return 0;
146 ret = _gnutls_digest_ops.fast (algorithm, text, textlen, digest);
147 if (ret < 0)
149 gnutls_assert ();
150 return ret;
153 return 0;
157 /* HMAC interface */
160 _gnutls_hmac_fast (gnutls_mac_algorithm_t algorithm, const void *key,
161 int keylen, const void *text, size_t textlen, void *digest)
163 int ret;
164 const gnutls_crypto_mac_st *cc = NULL;
166 /* check if a digest has been registered
168 cc = _gnutls_get_crypto_mac (algorithm);
169 if (cc != NULL)
171 if (cc->fast (algorithm, key, keylen, text, textlen, digest) < 0)
173 gnutls_assert ();
174 return GNUTLS_E_HASH_FAILED;
177 return 0;
180 ret = _gnutls_mac_ops.fast (algorithm, key, keylen, text, textlen, digest);
181 if (ret < 0)
183 gnutls_assert ();
184 return ret;
187 return 0;
191 /* Returns true(non-zero) or false(0) if the
192 * provided hash exists
194 int _gnutls_hmac_exists(gnutls_mac_algorithm_t algo)
196 const gnutls_crypto_mac_st *cc = NULL;
198 cc = _gnutls_get_crypto_mac (algo);
199 if (cc != NULL) return 1;
201 return _gnutls_mac_ops.exists (algo);
205 _gnutls_hmac_init (digest_hd_st * dig, gnutls_mac_algorithm_t algorithm,
206 const void *key, int keylen)
208 int result;
209 const gnutls_crypto_mac_st *cc = NULL;
211 dig->algorithm = (gnutls_digest_algorithm_t)algorithm;
212 dig->key = key;
213 dig->keysize = keylen;
215 /* check if a digest has been registered
217 cc = _gnutls_get_crypto_mac (algorithm);
218 if (cc != NULL && cc->init != NULL)
220 if (cc->init (algorithm, &dig->handle) < 0)
222 gnutls_assert ();
223 return GNUTLS_E_HASH_FAILED;
226 if (cc->setkey (dig->handle, key, keylen) < 0)
228 gnutls_assert ();
229 cc->deinit (dig->handle);
230 return GNUTLS_E_HASH_FAILED;
233 dig->hash = cc->hash;
234 dig->output = cc->output;
235 dig->deinit = cc->deinit;
236 dig->reset = cc->reset;
238 return 0;
241 result = _gnutls_mac_ops.init (algorithm, &dig->handle);
242 if (result < 0)
244 gnutls_assert ();
245 return result;
248 dig->hash = _gnutls_mac_ops.hash;
249 dig->output = _gnutls_mac_ops.output;
250 dig->deinit = _gnutls_mac_ops.deinit;
251 dig->reset = _gnutls_mac_ops.reset;
253 if (_gnutls_mac_ops.setkey (dig->handle, key, keylen) < 0)
255 gnutls_assert();
256 dig->deinit(dig->handle);
257 return GNUTLS_E_HASH_FAILED;
260 return 0;
263 void
264 _gnutls_hmac_deinit (digest_hd_st * handle, void *digest)
266 if (handle->handle == NULL)
268 return;
271 if (digest)
272 _gnutls_hmac_output (handle, digest);
274 handle->deinit (handle->handle);
275 handle->handle = NULL;
278 inline static int
279 get_padsize (gnutls_digest_algorithm_t algorithm)
281 switch (algorithm)
283 case GNUTLS_DIG_MD5:
284 return 48;
285 case GNUTLS_DIG_SHA1:
286 return 40;
287 default:
288 return 0;
292 /* Special functions for SSL3 MAC
296 _gnutls_mac_init_ssl3 (digest_hd_st * ret, gnutls_mac_algorithm_t algorithm,
297 void *key, int keylen)
299 uint8_t ipad[48];
300 int padsize, result;
302 padsize = get_padsize ((gnutls_digest_algorithm_t)algorithm);
303 if (padsize == 0)
305 gnutls_assert ();
306 return GNUTLS_E_HASH_FAILED;
309 memset (ipad, 0x36, padsize);
311 result = _gnutls_hash_init (ret, (gnutls_digest_algorithm_t)algorithm);
312 if (result < 0)
314 gnutls_assert ();
315 return result;
318 ret->key = key;
319 ret->keysize = keylen;
321 if (keylen > 0)
322 _gnutls_hash (ret, key, keylen);
323 _gnutls_hash (ret, ipad, padsize);
325 return 0;
328 void
329 _gnutls_mac_reset_ssl3 (digest_hd_st * handle)
331 uint8_t ipad[48];
332 int padsize;
334 padsize = get_padsize (handle->algorithm);
336 memset (ipad, 0x36, padsize);
338 _gnutls_hash_reset(handle);
340 if (handle->keysize > 0)
341 _gnutls_hash (handle, handle->key, handle->keysize);
342 _gnutls_hash (handle, ipad, padsize);
344 return;
347 int
348 _gnutls_mac_output_ssl3 (digest_hd_st * handle, void *digest)
350 uint8_t ret[MAX_HASH_SIZE];
351 digest_hd_st td;
352 uint8_t opad[48];
353 int padsize;
354 int block, rc;
356 padsize = get_padsize (handle->algorithm);
357 if (padsize == 0)
359 gnutls_assert ();
360 return GNUTLS_E_INTERNAL_ERROR;
363 memset (opad, 0x5C, padsize);
365 rc = _gnutls_hash_init (&td, handle->algorithm);
366 if (rc < 0)
368 gnutls_assert ();
369 return rc;
372 if (handle->keysize > 0)
373 _gnutls_hash (&td, handle->key, handle->keysize);
375 _gnutls_hash (&td, opad, padsize);
376 block = _gnutls_hmac_get_algo_len (handle->algorithm);
377 _gnutls_hash_output (handle, ret); /* get the previous hash */
378 _gnutls_hash (&td, ret, block);
380 _gnutls_hash_deinit (&td, digest);
382 return 0;
386 _gnutls_mac_deinit_ssl3 (digest_hd_st * handle, void *digest)
388 int ret = 0;
390 if (digest != NULL) ret = _gnutls_mac_output_ssl3(handle, digest);
391 _gnutls_hash_deinit(handle, NULL);
393 return ret;
397 _gnutls_mac_deinit_ssl3_handshake (digest_hd_st * handle,
398 void *digest, uint8_t * key,
399 uint32_t key_size)
401 uint8_t ret[MAX_HASH_SIZE];
402 digest_hd_st td;
403 uint8_t opad[48];
404 uint8_t ipad[48];
405 int padsize;
406 int block, rc;
408 padsize = get_padsize (handle->algorithm);
409 if (padsize == 0)
411 gnutls_assert ();
412 rc = GNUTLS_E_INTERNAL_ERROR;
413 goto cleanup;
416 memset (opad, 0x5C, padsize);
417 memset (ipad, 0x36, padsize);
419 rc = _gnutls_hash_init (&td, handle->algorithm);
420 if (rc < 0)
422 gnutls_assert ();
423 goto cleanup;
426 if (key_size > 0)
427 _gnutls_hash (&td, key, key_size);
429 _gnutls_hash (&td, opad, padsize);
430 block = _gnutls_hmac_get_algo_len (handle->algorithm);
432 if (key_size > 0)
433 _gnutls_hash (handle, key, key_size);
434 _gnutls_hash (handle, ipad, padsize);
435 _gnutls_hash_deinit (handle, ret); /* get the previous hash */
437 _gnutls_hash (&td, ret, block);
439 _gnutls_hash_deinit (&td, digest);
441 return 0;
443 cleanup:
444 _gnutls_hash_deinit(handle, NULL);
445 return rc;
448 static int
449 ssl3_sha (int i, uint8_t * secret, int secret_len,
450 uint8_t * rnd, int rnd_len, void *digest)
452 int j, ret;
453 uint8_t text1[26];
455 digest_hd_st td;
457 for (j = 0; j < i + 1; j++)
459 text1[j] = 65 + i; /* A==65 */
462 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
463 if (ret < 0)
465 gnutls_assert ();
466 return ret;
469 _gnutls_hash (&td, text1, i + 1);
470 _gnutls_hash (&td, secret, secret_len);
471 _gnutls_hash (&td, rnd, rnd_len);
473 _gnutls_hash_deinit (&td, digest);
474 return 0;
477 #define SHA1_DIGEST_OUTPUT 20
478 #define MD5_DIGEST_OUTPUT 16
480 static int
481 ssl3_md5 (int i, uint8_t * secret, int secret_len,
482 uint8_t * rnd, int rnd_len, void *digest)
484 uint8_t tmp[MAX_HASH_SIZE];
485 digest_hd_st td;
486 int ret;
488 ret = _gnutls_hash_init (&td, GNUTLS_MAC_MD5);
489 if (ret < 0)
491 gnutls_assert ();
492 return ret;
495 _gnutls_hash (&td, secret, secret_len);
497 ret = ssl3_sha (i, secret, secret_len, rnd, rnd_len, tmp);
498 if (ret < 0)
500 gnutls_assert ();
501 _gnutls_hash_deinit (&td, digest);
502 return ret;
505 _gnutls_hash (&td, tmp, SHA1_DIGEST_OUTPUT);
507 _gnutls_hash_deinit (&td, digest);
508 return 0;
512 _gnutls_ssl3_hash_md5 (const void *first, int first_len,
513 const void *second, int second_len,
514 int ret_len, uint8_t * ret)
516 uint8_t digest[MAX_HASH_SIZE];
517 digest_hd_st td;
518 int block = MD5_DIGEST_OUTPUT;
519 int rc;
521 rc = _gnutls_hash_init (&td, GNUTLS_MAC_MD5);
522 if (rc < 0)
524 gnutls_assert ();
525 return rc;
528 _gnutls_hash (&td, first, first_len);
529 _gnutls_hash (&td, second, second_len);
531 _gnutls_hash_deinit (&td, digest);
533 if (ret_len > block)
535 gnutls_assert ();
536 return GNUTLS_E_INTERNAL_ERROR;
539 memcpy (ret, digest, ret_len);
541 return 0;
546 _gnutls_ssl3_generate_random (void *secret, int secret_len,
547 void *rnd, int rnd_len,
548 int ret_bytes, uint8_t * ret)
550 int i = 0, copy, output_bytes;
551 uint8_t digest[MAX_HASH_SIZE];
552 int block = MD5_DIGEST_OUTPUT;
553 int result, times;
555 output_bytes = 0;
558 output_bytes += block;
560 while (output_bytes < ret_bytes);
562 times = output_bytes / block;
564 for (i = 0; i < times; i++)
567 result = ssl3_md5 (i, secret, secret_len, rnd, rnd_len, digest);
568 if (result < 0)
570 gnutls_assert ();
571 return result;
574 if ((1 + i) * block < ret_bytes)
576 copy = block;
578 else
580 copy = ret_bytes - (i) * block;
583 memcpy (&ret[i * block], digest, copy);
586 return 0;