2 * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2008, 2010 Free Software
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* This file handles all the internal functions that cope with hashes
30 #include <gnutls_int.h>
31 #include <gnutls_hash_int.h>
32 #include <gnutls_errors.h>
35 digest_length (gnutls_digest_algorithm_t algo)
45 case GNUTLS_DIG_RMD160:
47 case GNUTLS_DIG_SHA256:
49 case GNUTLS_DIG_SHA384:
51 case GNUTLS_DIG_SHA512:
53 case GNUTLS_DIG_SHA224:
57 return GNUTLS_E_INTERNAL_ERROR;
62 _gnutls_hash_init (digest_hd_st * dig, gnutls_digest_algorithm_t algorithm)
65 const gnutls_crypto_digest_st *cc = NULL;
67 dig->algorithm = algorithm;
69 /* check if a digest has been registered
71 cc = _gnutls_get_crypto_digest (algorithm);
74 if (cc->init (algorithm, &dig->handle) < 0)
77 return GNUTLS_E_HASH_FAILED;
82 dig->output = cc->output;
83 dig->deinit = cc->deinit;
88 result = _gnutls_digest_ops.init (algorithm, &dig->handle);
95 dig->hash = _gnutls_digest_ops.hash;
96 dig->copy = _gnutls_digest_ops.copy;
97 dig->output = _gnutls_digest_ops.output;
98 dig->deinit = _gnutls_digest_ops.deinit;
103 /* returns the output size of the given hash/mac algorithm
106 _gnutls_hash_get_algo_len (gnutls_digest_algorithm_t algorithm)
108 return digest_length (algorithm);
112 _gnutls_hash (digest_hd_st * handle, const void *text, size_t textlen)
116 handle->hash (handle->handle, text, textlen);
122 _gnutls_hash_copy (digest_hd_st * dst, digest_hd_st * src)
125 memset (dst, 0, sizeof (*dst));
126 dst->algorithm = src->algorithm;
128 dst->hash = src->hash;
129 dst->copy = src->copy;
130 dst->output = src->output;
131 dst->deinit = src->deinit;
133 return src->copy (&dst->handle, src->handle);
136 /* when the current output is needed without calling deinit
139 _gnutls_hash_output (digest_hd_st * handle, void *digest)
143 maclen = _gnutls_hash_get_algo_len (handle->algorithm);
147 handle->output (handle->handle, digest, maclen);
152 _gnutls_hash_deinit (digest_hd_st * handle, void *digest)
154 if (handle->handle == NULL)
160 _gnutls_hash_output (handle, digest);
162 handle->deinit (handle->handle);
163 handle->handle = NULL;
167 _gnutls_hash_fast (gnutls_digest_algorithm_t algorithm,
168 const void *text, size_t textlen, void *digest)
173 ret = _gnutls_hash_init (&dig, algorithm);
180 ret = _gnutls_hash (&dig, text, textlen);
184 _gnutls_hash_deinit (&dig, NULL);
188 _gnutls_hash_deinit (&dig, digest);
196 _gnutls_hmac_get_algo_len (gnutls_mac_algorithm_t algorithm)
198 return digest_length (algorithm);
202 _gnutls_hmac_fast (gnutls_mac_algorithm_t algorithm, const void *key,
203 int keylen, const void *text, size_t textlen, void *digest)
208 ret = _gnutls_hmac_init (&dig, algorithm, key, keylen);
215 ret = _gnutls_hmac (&dig, text, textlen);
219 _gnutls_hmac_deinit (&dig, NULL);
223 _gnutls_hmac_deinit (&dig, digest);
228 _gnutls_hmac_init (digest_hd_st * dig, gnutls_mac_algorithm_t algorithm,
229 const void *key, int keylen)
232 const gnutls_crypto_mac_st *cc = NULL;
234 dig->algorithm = algorithm;
236 dig->keysize = keylen;
238 /* check if a digest has been registered
240 cc = _gnutls_get_crypto_mac (algorithm);
243 if (cc->init (algorithm, &dig->handle) < 0)
246 return GNUTLS_E_HASH_FAILED;
249 if (cc->setkey (dig->handle, key, keylen) < 0)
252 cc->deinit (dig->handle);
253 return GNUTLS_E_HASH_FAILED;
256 dig->hash = cc->hash;
257 dig->output = cc->output;
258 dig->deinit = cc->deinit;
263 result = _gnutls_mac_ops.init (algorithm, &dig->handle);
270 dig->hash = _gnutls_mac_ops.hash;
271 dig->output = _gnutls_mac_ops.output;
272 dig->deinit = _gnutls_mac_ops.deinit;
274 if (_gnutls_mac_ops.setkey (dig->handle, key, keylen) < 0)
277 dig->deinit(dig->handle);
278 return GNUTLS_E_HASH_FAILED;
285 _gnutls_hmac (digest_hd_st * handle, const void *text, size_t textlen)
289 return handle->hash (handle->handle, text, textlen);
295 _gnutls_hmac_output (digest_hd_st * handle, void *digest)
299 maclen = _gnutls_hmac_get_algo_len (handle->algorithm);
303 handle->output (handle->handle, digest, maclen);
308 _gnutls_hmac_deinit (digest_hd_st * handle, void *digest)
310 if (handle->handle == NULL)
316 _gnutls_hmac_output (handle, digest);
318 handle->deinit (handle->handle);
319 handle->handle = NULL;
323 get_padsize (gnutls_mac_algorithm_t algorithm)
329 case GNUTLS_MAC_SHA1:
337 /* Special functions for SSL3 MAC
341 _gnutls_mac_init_ssl3 (digest_hd_st * ret, gnutls_mac_algorithm_t algorithm,
342 void *key, int keylen)
347 padsize = get_padsize (algorithm);
351 return GNUTLS_E_HASH_FAILED;
354 memset (ipad, 0x36, padsize);
356 result = _gnutls_hash_init (ret, algorithm);
364 ret->keysize = keylen;
367 _gnutls_hash (ret, key, keylen);
368 _gnutls_hash (ret, ipad, padsize);
374 _gnutls_mac_deinit_ssl3 (digest_hd_st * handle, void *digest)
376 opaque ret[MAX_HASH_SIZE];
382 padsize = get_padsize (handle->algorithm);
386 _gnutls_hash_deinit (handle, NULL);
390 memset (opad, 0x5C, padsize);
392 rc = _gnutls_hash_init (&td, handle->algorithm);
396 _gnutls_hash_deinit (handle, NULL);
400 if (handle->keysize > 0)
401 _gnutls_hash (&td, handle->key, handle->keysize);
403 _gnutls_hash (&td, opad, padsize);
404 block = _gnutls_hmac_get_algo_len (handle->algorithm);
405 _gnutls_hash_deinit (handle, ret); /* get the previous hash */
406 _gnutls_hash (&td, ret, block);
408 _gnutls_hash_deinit (&td, digest);
414 _gnutls_mac_deinit_ssl3_handshake (digest_hd_st * handle,
415 void *digest, opaque * key,
418 opaque ret[MAX_HASH_SIZE];
425 padsize = get_padsize (handle->algorithm);
432 memset (opad, 0x5C, padsize);
433 memset (ipad, 0x36, padsize);
435 rc = _gnutls_hash_init (&td, handle->algorithm);
443 _gnutls_hash (&td, key, key_size);
445 _gnutls_hash (&td, opad, padsize);
446 block = _gnutls_hmac_get_algo_len (handle->algorithm);
449 _gnutls_hash (handle, key, key_size);
450 _gnutls_hash (handle, ipad, padsize);
451 _gnutls_hash_deinit (handle, ret); /* get the previous hash */
453 _gnutls_hash (&td, ret, block);
455 _gnutls_hash_deinit (&td, digest);
461 ssl3_sha (int i, opaque * secret, int secret_len,
462 opaque * rnd, int rnd_len, void *digest)
469 for (j = 0; j < i + 1; j++)
471 text1[j] = 65 + i; /* A==65 */
474 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
481 _gnutls_hash (&td, text1, i + 1);
482 _gnutls_hash (&td, secret, secret_len);
483 _gnutls_hash (&td, rnd, rnd_len);
485 _gnutls_hash_deinit (&td, digest);
490 ssl3_md5 (int i, opaque * secret, int secret_len,
491 opaque * rnd, int rnd_len, void *digest)
493 opaque tmp[MAX_HASH_SIZE];
497 ret = _gnutls_hash_init (&td, GNUTLS_MAC_MD5);
504 _gnutls_hash (&td, secret, secret_len);
506 ret = ssl3_sha (i, secret, secret_len, rnd, rnd_len, tmp);
510 _gnutls_hash_deinit (&td, digest);
514 _gnutls_hash (&td, tmp, _gnutls_hash_get_algo_len (GNUTLS_MAC_SHA1));
516 _gnutls_hash_deinit (&td, digest);
521 _gnutls_ssl3_hash_md5 (const void *first, int first_len,
522 const void *second, int second_len,
523 int ret_len, opaque * ret)
525 opaque digest[MAX_HASH_SIZE];
527 int block = _gnutls_hash_get_algo_len (GNUTLS_MAC_MD5);
530 rc = _gnutls_hash_init (&td, GNUTLS_MAC_MD5);
537 _gnutls_hash (&td, first, first_len);
538 _gnutls_hash (&td, second, second_len);
540 _gnutls_hash_deinit (&td, digest);
545 return GNUTLS_E_INTERNAL_ERROR;
548 memcpy (ret, digest, ret_len);
555 _gnutls_ssl3_generate_random (void *secret, int secret_len,
556 void *rnd, int rnd_len,
557 int ret_bytes, opaque * ret)
559 int i = 0, copy, output_bytes;
560 opaque digest[MAX_HASH_SIZE];
561 int block = _gnutls_hash_get_algo_len (GNUTLS_MAC_MD5);
567 output_bytes += block;
569 while (output_bytes < ret_bytes);
571 times = output_bytes / block;
573 for (i = 0; i < times; i++)
576 result = ssl3_md5 (i, secret, secret_len, rnd, rnd_len, digest);
583 if ((1 + i) * block < ret_bytes)
589 copy = ret_bytes - (i) * block;
592 memcpy (&ret[i * block], digest, copy);