Use libtasn1 v2.4.
[gnutls.git] / lib / gnutls_hash_int.c
blobebbf4bc4807951cf6450487a83ca6444babeb85e
1 /*
2 * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2008, 2010 Free Software
3 * Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GNUTLS.
9 * The GNUTLS library 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,
22 * USA
26 /* This file handles all the internal functions that cope with hashes
27 * and HMACs.
30 #include <gnutls_int.h>
31 #include <gnutls_hash_int.h>
32 #include <gnutls_errors.h>
34 static int
35 digest_length (gnutls_digest_algorithm_t algo)
37 switch (algo)
39 case GNUTLS_DIG_NULL:
40 return 0;
41 case GNUTLS_DIG_MD5:
42 case GNUTLS_DIG_MD2:
43 return 16;
44 case GNUTLS_DIG_SHA1:
45 case GNUTLS_DIG_RMD160:
46 return 20;
47 case GNUTLS_DIG_SHA256:
48 return 32;
49 case GNUTLS_DIG_SHA384:
50 return 48;
51 case GNUTLS_DIG_SHA512:
52 return 64;
53 case GNUTLS_DIG_SHA224:
54 return 28;
55 default:
56 gnutls_assert ();
57 return GNUTLS_E_INTERNAL_ERROR;
61 int
62 _gnutls_hash_init (digest_hd_st * dig, gnutls_digest_algorithm_t algorithm)
64 int result;
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);
72 if (cc != NULL)
74 dig->registered = 1;
75 dig->hd.rh.cc = cc;
76 if (cc->init (algorithm, &dig->hd.rh.ctx) < 0)
78 gnutls_assert ();
79 return GNUTLS_E_HASH_FAILED;
81 dig->active = 1;
82 return 0;
85 dig->registered = 0;
87 result = _gnutls_digest_ops.init (algorithm, &dig->hd.gc);
88 if (result < 0)
90 gnutls_assert ();
91 return result;
94 dig->active = 1;
95 return 0;
98 /* returns the output size of the given hash/mac algorithm
101 _gnutls_hash_get_algo_len (gnutls_digest_algorithm_t algorithm)
103 return digest_length (algorithm);
107 _gnutls_hash (digest_hd_st * handle, const void *text, size_t textlen)
109 if (textlen > 0)
111 if (handle->registered)
113 return handle->hd.rh.cc->hash (handle->hd.rh.ctx, text, textlen);
115 return _gnutls_digest_ops.hash (handle->hd.gc, text, textlen);
117 return 0;
121 _gnutls_hash_copy (digest_hd_st * dst, digest_hd_st * src)
123 int result;
125 memset (dst, 0, sizeof (*dst));
126 dst->algorithm = src->algorithm;
127 dst->registered = src->registered;
128 dst->active = 1;
130 if (src->registered)
132 dst->hd.rh.cc = src->hd.rh.cc;
133 return src->hd.rh.cc->copy (&dst->hd.rh.ctx, src->hd.rh.ctx);
136 result = _gnutls_digest_ops.copy (&dst->hd.gc, src->hd.gc);
137 if (result < 0)
139 gnutls_assert ();
140 return result;
143 return 0;
146 /* when the current output is needed without calling deinit
148 void
149 _gnutls_hash_output (digest_hd_st * handle, void *digest)
151 size_t maclen;
153 maclen = _gnutls_hash_get_algo_len (handle->algorithm);
155 if (handle->registered && handle->hd.rh.ctx != NULL)
157 if (digest != NULL)
158 handle->hd.rh.cc->output (handle->hd.rh.ctx, digest, maclen);
159 return;
162 if (digest != NULL)
164 _gnutls_digest_ops.output (handle->hd.gc, digest, maclen);
168 void
169 _gnutls_hash_deinit (digest_hd_st * handle, void *digest)
171 if (handle->active != 1)
173 return;
176 if (digest != NULL)
177 _gnutls_hash_output (handle, digest);
179 handle->active = 0;
181 if (handle->registered && handle->hd.rh.ctx != NULL)
183 handle->hd.rh.cc->deinit (handle->hd.rh.ctx);
184 return;
187 _gnutls_digest_ops.deinit (handle->hd.gc);
191 _gnutls_hash_fast (gnutls_digest_algorithm_t algorithm,
192 const void *text, size_t textlen, void *digest)
194 digest_hd_st dig;
195 int ret;
197 ret = _gnutls_hash_init (&dig, algorithm);
198 if (ret < 0)
200 gnutls_assert ();
201 return ret;
204 ret = _gnutls_hash (&dig, text, textlen);
205 if (ret < 0)
207 gnutls_assert ();
208 _gnutls_hash_deinit (&dig, NULL);
209 return ret;
212 _gnutls_hash_deinit (&dig, digest);
213 return 0;
217 /* HMAC interface */
220 _gnutls_hmac_get_algo_len (gnutls_mac_algorithm_t algorithm)
222 return digest_length (algorithm);
226 _gnutls_hmac_fast (gnutls_mac_algorithm_t algorithm, const void *key,
227 int keylen, const void *text, size_t textlen, void *digest)
229 digest_hd_st dig;
230 int ret;
232 ret = _gnutls_hmac_init (&dig, algorithm, key, keylen);
233 if (ret < 0)
235 gnutls_assert ();
236 return ret;
239 ret = _gnutls_hmac (&dig, text, textlen);
240 if (ret < 0)
242 gnutls_assert ();
243 _gnutls_hmac_deinit (&dig, NULL);
244 return ret;
247 _gnutls_hmac_deinit (&dig, digest);
248 return 0;
252 _gnutls_hmac_init (digest_hd_st * dig, gnutls_mac_algorithm_t algorithm,
253 const void *key, int keylen)
255 int result;
256 const gnutls_crypto_mac_st *cc = NULL;
258 dig->algorithm = algorithm;
259 dig->key = key;
260 dig->keysize = keylen;
262 /* check if a digest has been registered
264 cc = _gnutls_get_crypto_mac (algorithm);
265 if (cc != NULL)
267 dig->registered = 1;
269 dig->hd.rh.cc = cc;
270 if (cc->init (algorithm, &dig->hd.rh.ctx) < 0)
272 gnutls_assert ();
273 return GNUTLS_E_HASH_FAILED;
276 if (cc->setkey (dig->hd.rh.ctx, key, keylen) < 0)
278 gnutls_assert ();
279 cc->deinit (dig->hd.rh.ctx);
280 return GNUTLS_E_HASH_FAILED;
283 dig->active = 1;
284 return 0;
287 dig->registered = 0;
289 result = _gnutls_mac_ops.init (algorithm, &dig->hd.gc);
290 if (result < 0)
292 gnutls_assert ();
293 return result;
296 _gnutls_mac_ops.setkey (dig->hd.gc, key, keylen);
298 dig->active = 1;
299 return 0;
303 _gnutls_hmac (digest_hd_st * handle, const void *text, size_t textlen)
305 if (textlen > 0)
307 if (handle->registered)
309 return handle->hd.rh.cc->hash (handle->hd.rh.ctx, text, textlen);
311 return _gnutls_mac_ops.hash (handle->hd.gc, text, textlen);
313 return 0;
316 void
317 _gnutls_hmac_output (digest_hd_st * handle, void *digest)
319 int maclen;
321 maclen = _gnutls_hmac_get_algo_len (handle->algorithm);
323 if (handle->registered && handle->hd.rh.ctx != NULL)
325 if (digest != NULL)
326 handle->hd.rh.cc->output (handle->hd.rh.ctx, digest, maclen);
327 return;
330 if (digest != NULL)
332 _gnutls_mac_ops.output (handle->hd.gc, digest, maclen);
336 void
337 _gnutls_hmac_deinit (digest_hd_st * handle, void *digest)
339 if (handle->active != 1)
341 return;
344 if (digest)
345 _gnutls_hmac_output (handle, digest);
347 handle->active = 0;
348 if (handle->registered && handle->hd.rh.ctx != NULL)
350 handle->hd.rh.cc->deinit (handle->hd.rh.ctx);
351 return;
354 _gnutls_mac_ops.deinit (handle->hd.gc);
357 inline static int
358 get_padsize (gnutls_mac_algorithm_t algorithm)
360 switch (algorithm)
362 case GNUTLS_MAC_MD5:
363 return 48;
364 case GNUTLS_MAC_SHA1:
365 return 40;
366 default:
367 return 0;
372 /* Special functions for SSL3 MAC
376 _gnutls_mac_init_ssl3 (digest_hd_st * ret, gnutls_mac_algorithm_t algorithm,
377 void *key, int keylen)
379 opaque ipad[48];
380 int padsize, result;
382 padsize = get_padsize (algorithm);
383 if (padsize == 0)
385 gnutls_assert ();
386 return GNUTLS_E_HASH_FAILED;
389 memset (ipad, 0x36, padsize);
391 result = _gnutls_hash_init (ret, algorithm);
392 if (result < 0)
394 gnutls_assert ();
395 return result;
398 ret->key = key;
399 ret->keysize = keylen;
401 if (keylen > 0)
402 _gnutls_hash (ret, key, keylen);
403 _gnutls_hash (ret, ipad, padsize);
405 return 0;
408 void
409 _gnutls_mac_deinit_ssl3 (digest_hd_st * handle, void *digest)
411 opaque ret[MAX_HASH_SIZE];
412 digest_hd_st td;
413 opaque opad[48];
414 int padsize;
415 int block, rc;
417 padsize = get_padsize (handle->algorithm);
418 if (padsize == 0)
420 gnutls_assert ();
421 _gnutls_hash_deinit (handle, NULL);
422 return;
425 memset (opad, 0x5C, padsize);
427 rc = _gnutls_hash_init (&td, handle->algorithm);
428 if (rc < 0)
430 gnutls_assert ();
431 _gnutls_hash_deinit (handle, NULL);
432 return;
435 if (handle->keysize > 0)
436 _gnutls_hash (&td, handle->key, handle->keysize);
438 _gnutls_hash (&td, opad, padsize);
439 block = _gnutls_hmac_get_algo_len (handle->algorithm);
440 _gnutls_hash_deinit (handle, ret); /* get the previous hash */
441 _gnutls_hash (&td, ret, block);
443 _gnutls_hash_deinit (&td, digest);
445 return;
448 void
449 _gnutls_mac_deinit_ssl3_handshake (digest_hd_st * handle,
450 void *digest, opaque * key,
451 uint32_t key_size)
453 opaque ret[MAX_HASH_SIZE];
454 digest_hd_st td;
455 opaque opad[48];
456 opaque ipad[48];
457 int padsize;
458 int block, rc;
460 padsize = get_padsize (handle->algorithm);
461 if (padsize == 0)
463 gnutls_assert ();
464 return;
467 memset (opad, 0x5C, padsize);
468 memset (ipad, 0x36, padsize);
470 rc = _gnutls_hash_init (&td, handle->algorithm);
471 if (rc < 0)
473 gnutls_assert ();
474 return;
477 if (key_size > 0)
478 _gnutls_hash (&td, key, key_size);
480 _gnutls_hash (&td, opad, padsize);
481 block = _gnutls_hmac_get_algo_len (handle->algorithm);
483 if (key_size > 0)
484 _gnutls_hash (handle, key, key_size);
485 _gnutls_hash (handle, ipad, padsize);
486 _gnutls_hash_deinit (handle, ret); /* get the previous hash */
488 _gnutls_hash (&td, ret, block);
490 _gnutls_hash_deinit (&td, digest);
492 return;
495 static int
496 ssl3_sha (int i, opaque * secret, int secret_len,
497 opaque * rnd, int rnd_len, void *digest)
499 int j, ret;
500 opaque text1[26];
502 digest_hd_st td;
504 for (j = 0; j < i + 1; j++)
506 text1[j] = 65 + i; /* A==65 */
509 ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
510 if (ret < 0)
512 gnutls_assert ();
513 return ret;
516 _gnutls_hash (&td, text1, i + 1);
517 _gnutls_hash (&td, secret, secret_len);
518 _gnutls_hash (&td, rnd, rnd_len);
520 _gnutls_hash_deinit (&td, digest);
521 return 0;
524 static int
525 ssl3_md5 (int i, opaque * secret, int secret_len,
526 opaque * rnd, int rnd_len, void *digest)
528 opaque tmp[MAX_HASH_SIZE];
529 digest_hd_st td;
530 int ret;
532 ret = _gnutls_hash_init (&td, GNUTLS_MAC_MD5);
533 if (ret < 0)
535 gnutls_assert ();
536 return ret;
539 _gnutls_hash (&td, secret, secret_len);
541 ret = ssl3_sha (i, secret, secret_len, rnd, rnd_len, tmp);
542 if (ret < 0)
544 gnutls_assert ();
545 _gnutls_hash_deinit (&td, digest);
546 return ret;
549 _gnutls_hash (&td, tmp, _gnutls_hash_get_algo_len (GNUTLS_MAC_SHA1));
551 _gnutls_hash_deinit (&td, digest);
552 return 0;
556 _gnutls_ssl3_hash_md5 (const void *first, int first_len,
557 const void *second, int second_len,
558 int ret_len, opaque * ret)
560 opaque digest[MAX_HASH_SIZE];
561 digest_hd_st td;
562 int block = _gnutls_hash_get_algo_len (GNUTLS_MAC_MD5);
563 int rc;
565 rc = _gnutls_hash_init (&td, GNUTLS_MAC_MD5);
566 if (rc < 0)
568 gnutls_assert ();
569 return rc;
572 _gnutls_hash (&td, first, first_len);
573 _gnutls_hash (&td, second, second_len);
575 _gnutls_hash_deinit (&td, digest);
577 if (ret_len > block)
579 gnutls_assert ();
580 return GNUTLS_E_INTERNAL_ERROR;
583 memcpy (ret, digest, ret_len);
585 return 0;
590 _gnutls_ssl3_generate_random (void *secret, int secret_len,
591 void *rnd, int rnd_len,
592 int ret_bytes, opaque * ret)
594 int i = 0, copy, output_bytes;
595 opaque digest[MAX_HASH_SIZE];
596 int block = _gnutls_hash_get_algo_len (GNUTLS_MAC_MD5);
597 int result, times;
599 output_bytes = 0;
602 output_bytes += block;
604 while (output_bytes < ret_bytes);
606 times = output_bytes / block;
608 for (i = 0; i < times; i++)
611 result = ssl3_md5 (i, secret, secret_len, rnd, rnd_len, digest);
612 if (result < 0)
614 gnutls_assert ();
615 return result;
618 if ((1 + i) * block < ret_bytes)
620 copy = block;
622 else
624 copy = ret_bytes - (i) * block;
627 memcpy (&ret[i * block], digest, copy);
630 return 0;