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 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,
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
);
76 if (cc
->init (algorithm
, &dig
->hd
.rh
.ctx
) < 0)
79 return GNUTLS_E_HASH_FAILED
;
87 result
= _gnutls_digest_ops
.init (algorithm
, &dig
->hd
.gc
);
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
)
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
);
121 _gnutls_hash_copy (digest_hd_st
* dst
, digest_hd_st
* src
)
125 memset (dst
, 0, sizeof (*dst
));
126 dst
->algorithm
= src
->algorithm
;
127 dst
->registered
= 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
);
146 /* when the current output is needed without calling deinit
149 _gnutls_hash_output (digest_hd_st
* handle
, void *digest
)
153 maclen
= _gnutls_hash_get_algo_len (handle
->algorithm
);
155 if (handle
->registered
&& handle
->hd
.rh
.ctx
!= NULL
)
158 handle
->hd
.rh
.cc
->output (handle
->hd
.rh
.ctx
, digest
, maclen
);
164 _gnutls_digest_ops
.output (handle
->hd
.gc
, digest
, maclen
);
169 _gnutls_hash_deinit (digest_hd_st
* handle
, void *digest
)
171 if (handle
->active
!= 1)
177 _gnutls_hash_output (handle
, digest
);
181 if (handle
->registered
&& handle
->hd
.rh
.ctx
!= NULL
)
183 handle
->hd
.rh
.cc
->deinit (handle
->hd
.rh
.ctx
);
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
)
197 ret
= _gnutls_hash_init (&dig
, algorithm
);
204 ret
= _gnutls_hash (&dig
, text
, textlen
);
208 _gnutls_hash_deinit (&dig
, NULL
);
212 _gnutls_hash_deinit (&dig
, digest
);
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
)
232 ret
= _gnutls_hmac_init (&dig
, algorithm
, key
, keylen
);
239 ret
= _gnutls_hmac (&dig
, text
, textlen
);
243 _gnutls_hmac_deinit (&dig
, NULL
);
247 _gnutls_hmac_deinit (&dig
, digest
);
252 _gnutls_hmac_init (digest_hd_st
* dig
, gnutls_mac_algorithm_t algorithm
,
253 const void *key
, int keylen
)
256 const gnutls_crypto_mac_st
*cc
= NULL
;
258 dig
->algorithm
= algorithm
;
260 dig
->keysize
= keylen
;
262 /* check if a digest has been registered
264 cc
= _gnutls_get_crypto_mac (algorithm
);
270 if (cc
->init (algorithm
, &dig
->hd
.rh
.ctx
) < 0)
273 return GNUTLS_E_HASH_FAILED
;
276 if (cc
->setkey (dig
->hd
.rh
.ctx
, key
, keylen
) < 0)
279 cc
->deinit (dig
->hd
.rh
.ctx
);
280 return GNUTLS_E_HASH_FAILED
;
289 result
= _gnutls_mac_ops
.init (algorithm
, &dig
->hd
.gc
);
296 _gnutls_mac_ops
.setkey (dig
->hd
.gc
, key
, keylen
);
303 _gnutls_hmac (digest_hd_st
* handle
, const void *text
, size_t textlen
)
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
);
317 _gnutls_hmac_output (digest_hd_st
* handle
, void *digest
)
321 maclen
= _gnutls_hmac_get_algo_len (handle
->algorithm
);
323 if (handle
->registered
&& handle
->hd
.rh
.ctx
!= NULL
)
326 handle
->hd
.rh
.cc
->output (handle
->hd
.rh
.ctx
, digest
, maclen
);
332 _gnutls_mac_ops
.output (handle
->hd
.gc
, digest
, maclen
);
337 _gnutls_hmac_deinit (digest_hd_st
* handle
, void *digest
)
339 if (handle
->active
!= 1)
345 _gnutls_hmac_output (handle
, digest
);
348 if (handle
->registered
&& handle
->hd
.rh
.ctx
!= NULL
)
350 handle
->hd
.rh
.cc
->deinit (handle
->hd
.rh
.ctx
);
354 _gnutls_mac_ops
.deinit (handle
->hd
.gc
);
358 get_padsize (gnutls_mac_algorithm_t algorithm
)
364 case GNUTLS_MAC_SHA1
:
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
)
382 padsize
= get_padsize (algorithm
);
386 return GNUTLS_E_HASH_FAILED
;
389 memset (ipad
, 0x36, padsize
);
391 result
= _gnutls_hash_init (ret
, algorithm
);
399 ret
->keysize
= keylen
;
402 _gnutls_hash (ret
, key
, keylen
);
403 _gnutls_hash (ret
, ipad
, padsize
);
409 _gnutls_mac_deinit_ssl3 (digest_hd_st
* handle
, void *digest
)
411 opaque ret
[MAX_HASH_SIZE
];
417 padsize
= get_padsize (handle
->algorithm
);
421 _gnutls_hash_deinit (handle
, NULL
);
425 memset (opad
, 0x5C, padsize
);
427 rc
= _gnutls_hash_init (&td
, handle
->algorithm
);
431 _gnutls_hash_deinit (handle
, NULL
);
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
);
449 _gnutls_mac_deinit_ssl3_handshake (digest_hd_st
* handle
,
450 void *digest
, opaque
* key
,
453 opaque ret
[MAX_HASH_SIZE
];
460 padsize
= get_padsize (handle
->algorithm
);
467 memset (opad
, 0x5C, padsize
);
468 memset (ipad
, 0x36, padsize
);
470 rc
= _gnutls_hash_init (&td
, handle
->algorithm
);
478 _gnutls_hash (&td
, key
, key_size
);
480 _gnutls_hash (&td
, opad
, padsize
);
481 block
= _gnutls_hmac_get_algo_len (handle
->algorithm
);
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
);
496 ssl3_sha (int i
, opaque
* secret
, int secret_len
,
497 opaque
* rnd
, int rnd_len
, void *digest
)
504 for (j
= 0; j
< i
+ 1; j
++)
506 text1
[j
] = 65 + i
; /* A==65 */
509 ret
= _gnutls_hash_init (&td
, GNUTLS_MAC_SHA1
);
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
);
525 ssl3_md5 (int i
, opaque
* secret
, int secret_len
,
526 opaque
* rnd
, int rnd_len
, void *digest
)
528 opaque tmp
[MAX_HASH_SIZE
];
532 ret
= _gnutls_hash_init (&td
, GNUTLS_MAC_MD5
);
539 _gnutls_hash (&td
, secret
, secret_len
);
541 ret
= ssl3_sha (i
, secret
, secret_len
, rnd
, rnd_len
, tmp
);
545 _gnutls_hash_deinit (&td
, digest
);
549 _gnutls_hash (&td
, tmp
, _gnutls_hash_get_algo_len (GNUTLS_MAC_SHA1
));
551 _gnutls_hash_deinit (&td
, digest
);
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
];
562 int block
= _gnutls_hash_get_algo_len (GNUTLS_MAC_MD5
);
565 rc
= _gnutls_hash_init (&td
, GNUTLS_MAC_MD5
);
572 _gnutls_hash (&td
, first
, first_len
);
573 _gnutls_hash (&td
, second
, second_len
);
575 _gnutls_hash_deinit (&td
, digest
);
580 return GNUTLS_E_INTERNAL_ERROR
;
583 memcpy (ret
, digest
, ret_len
);
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
);
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
);
618 if ((1 + i
) * block
< ret_bytes
)
624 copy
= ret_bytes
- (i
) * block
;
627 memcpy (&ret
[i
* block
], digest
, copy
);