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
27 #include <gnutls_int.h>
28 #include <gnutls_hash_int.h>
29 #include <gnutls_errors.h>
32 digest_length (int algo
)
43 case GNUTLS_DIG_RMD160
:
45 case GNUTLS_DIG_SHA256
:
47 case GNUTLS_DIG_SHA384
:
49 case GNUTLS_DIG_SHA512
:
51 case GNUTLS_DIG_SHA224
:
55 return GNUTLS_E_INTERNAL_ERROR
;
61 _gnutls_hash_init (digest_hd_st
* dig
, gnutls_digest_algorithm_t algorithm
)
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)
76 return GNUTLS_E_HASH_FAILED
;
80 dig
->reset
= cc
->reset
;
81 dig
->output
= cc
->output
;
82 dig
->deinit
= cc
->deinit
;
87 result
= _gnutls_digest_ops
.init (algorithm
, &dig
->handle
);
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
;
103 _gnutls_hash_deinit (digest_hd_st
* handle
, void *digest
)
105 if (handle
->handle
== 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
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
)
130 const gnutls_crypto_digest_st
*cc
= NULL
;
132 /* check if a digest has been registered
134 cc
= _gnutls_get_crypto_digest (algorithm
);
137 if (cc
->fast (algorithm
, text
, textlen
, digest
) < 0)
140 return GNUTLS_E_HASH_FAILED
;
146 ret
= _gnutls_digest_ops
.fast (algorithm
, text
, textlen
, digest
);
160 _gnutls_hmac_fast (gnutls_mac_algorithm_t algorithm
, const void *key
,
161 int keylen
, const void *text
, size_t textlen
, void *digest
)
164 const gnutls_crypto_mac_st
*cc
= NULL
;
166 /* check if a digest has been registered
168 cc
= _gnutls_get_crypto_mac (algorithm
);
171 if (cc
->fast (algorithm
, key
, keylen
, text
, textlen
, digest
) < 0)
174 return GNUTLS_E_HASH_FAILED
;
180 ret
= _gnutls_mac_ops
.fast (algorithm
, key
, keylen
, text
, textlen
, digest
);
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
)
209 const gnutls_crypto_mac_st
*cc
= NULL
;
211 dig
->algorithm
= (gnutls_digest_algorithm_t
)algorithm
;
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)
223 return GNUTLS_E_HASH_FAILED
;
226 if (cc
->setkey (dig
->handle
, key
, keylen
) < 0)
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
;
241 result
= _gnutls_mac_ops
.init (algorithm
, &dig
->handle
);
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)
256 dig
->deinit(dig
->handle
);
257 return GNUTLS_E_HASH_FAILED
;
264 _gnutls_hmac_deinit (digest_hd_st
* handle
, void *digest
)
266 if (handle
->handle
== NULL
)
272 _gnutls_hmac_output (handle
, digest
);
274 handle
->deinit (handle
->handle
);
275 handle
->handle
= NULL
;
279 get_padsize (gnutls_digest_algorithm_t algorithm
)
285 case GNUTLS_DIG_SHA1
:
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
)
302 padsize
= get_padsize ((gnutls_digest_algorithm_t
)algorithm
);
306 return GNUTLS_E_HASH_FAILED
;
309 memset (ipad
, 0x36, padsize
);
311 result
= _gnutls_hash_init (ret
, (gnutls_digest_algorithm_t
)algorithm
);
319 ret
->keysize
= keylen
;
322 _gnutls_hash (ret
, key
, keylen
);
323 _gnutls_hash (ret
, ipad
, padsize
);
329 _gnutls_mac_reset_ssl3 (digest_hd_st
* handle
)
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
);
348 _gnutls_mac_output_ssl3 (digest_hd_st
* handle
, void *digest
)
350 uint8_t ret
[MAX_HASH_SIZE
];
356 padsize
= get_padsize (handle
->algorithm
);
360 return GNUTLS_E_INTERNAL_ERROR
;
363 memset (opad
, 0x5C, padsize
);
365 rc
= _gnutls_hash_init (&td
, handle
->algorithm
);
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
);
386 _gnutls_mac_deinit_ssl3 (digest_hd_st
* handle
, void *digest
)
390 if (digest
!= NULL
) ret
= _gnutls_mac_output_ssl3(handle
, digest
);
391 _gnutls_hash_deinit(handle
, NULL
);
397 _gnutls_mac_deinit_ssl3_handshake (digest_hd_st
* handle
,
398 void *digest
, uint8_t * key
,
401 uint8_t ret
[MAX_HASH_SIZE
];
408 padsize
= get_padsize (handle
->algorithm
);
412 rc
= GNUTLS_E_INTERNAL_ERROR
;
416 memset (opad
, 0x5C, padsize
);
417 memset (ipad
, 0x36, padsize
);
419 rc
= _gnutls_hash_init (&td
, handle
->algorithm
);
427 _gnutls_hash (&td
, key
, key_size
);
429 _gnutls_hash (&td
, opad
, padsize
);
430 block
= _gnutls_hmac_get_algo_len (handle
->algorithm
);
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
);
444 _gnutls_hash_deinit(handle
, NULL
);
449 ssl3_sha (int i
, uint8_t * secret
, int secret_len
,
450 uint8_t * rnd
, int rnd_len
, void *digest
)
457 for (j
= 0; j
< i
+ 1; j
++)
459 text1
[j
] = 65 + i
; /* A==65 */
462 ret
= _gnutls_hash_init (&td
, GNUTLS_MAC_SHA1
);
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
);
477 #define SHA1_DIGEST_OUTPUT 20
478 #define MD5_DIGEST_OUTPUT 16
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
];
488 ret
= _gnutls_hash_init (&td
, GNUTLS_MAC_MD5
);
495 _gnutls_hash (&td
, secret
, secret_len
);
497 ret
= ssl3_sha (i
, secret
, secret_len
, rnd
, rnd_len
, tmp
);
501 _gnutls_hash_deinit (&td
, digest
);
505 _gnutls_hash (&td
, tmp
, SHA1_DIGEST_OUTPUT
);
507 _gnutls_hash_deinit (&td
, digest
);
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
];
518 int block
= MD5_DIGEST_OUTPUT
;
521 rc
= _gnutls_hash_init (&td
, GNUTLS_MAC_MD5
);
528 _gnutls_hash (&td
, first
, first_len
);
529 _gnutls_hash (&td
, second
, second_len
);
531 _gnutls_hash_deinit (&td
, digest
);
536 return GNUTLS_E_INTERNAL_ERROR
;
539 memcpy (ret
, digest
, ret_len
);
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
;
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
);
574 if ((1 + i
) * block
< ret_bytes
)
580 copy
= ret_bytes
- (i
) * block
;
583 memcpy (&ret
[i
* block
], digest
, copy
);