2 * Copyright (C) 2000, 2001, 2004, 2005, 2007 Free Software Foundation
4 * Author: Nikos Mavroyanopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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 2.1 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25 /* This file handles all the internal functions that cope with hashes
29 #include <gnutls_int.h>
30 #include <gnutls_hash_int.h>
31 #include <gnutls_errors.h>
33 static inline Gc_hash
_gnutls_mac2gc (gnutls_mac_algorithm_t mac
)
43 case GNUTLS_MAC_SHA256
:
46 case GNUTLS_MAC_SHA384
:
49 case GNUTLS_MAC_SHA512
:
55 case GNUTLS_MAC_RMD160
:
69 _gnutls_hash_init (gnutls_mac_algorithm_t algorithm
)
74 ret
= gnutls_malloc (sizeof (mac_hd_st
));
78 return GNUTLS_HASH_FAILED
;
81 ret
->algorithm
= algorithm
;
83 result
= gc_hash_open (_gnutls_mac2gc (algorithm
), 0, &ret
->handle
);
88 ret
= GNUTLS_HASH_FAILED
;
95 _gnutls_hash_get_algo_len (gnutls_mac_algorithm_t algorithm
)
99 ret
= gc_hash_digest_length (_gnutls_mac2gc (algorithm
));
106 _gnutls_hash (GNUTLS_HASH_HANDLE handle
, const void *text
, size_t textlen
)
109 gc_hash_write (handle
->handle
, textlen
, text
);
114 _gnutls_hash_copy (GNUTLS_HASH_HANDLE handle
)
116 GNUTLS_HASH_HANDLE ret
;
119 ret
= gnutls_malloc (sizeof (mac_hd_st
));
122 return GNUTLS_HASH_FAILED
;
124 ret
->algorithm
= handle
->algorithm
;
125 ret
->key
= NULL
; /* it's a hash anyway */
128 result
= gc_hash_clone (handle
->handle
, &ret
->handle
);
133 return GNUTLS_HASH_FAILED
;
140 _gnutls_hash_deinit (GNUTLS_HASH_HANDLE handle
, void *digest
)
145 maclen
= _gnutls_hash_get_algo_len (handle
->algorithm
);
147 mac
= gc_hash_read (handle
->handle
);
149 memcpy (digest
, mac
, maclen
);
151 gc_hash_close (handle
->handle
);
153 gnutls_free (handle
);
158 _gnutls_hmac_init (gnutls_mac_algorithm_t algorithm
,
159 const void *key
, int keylen
)
164 ret
= gnutls_malloc (sizeof (mac_hd_st
));
166 return GNUTLS_MAC_FAILED
;
168 result
= gc_hash_open (_gnutls_mac2gc (algorithm
), GC_HMAC
, &ret
->handle
);
172 return GNUTLS_MAC_FAILED
;
175 gc_hash_hmac_setkey (ret
->handle
, keylen
, key
);
177 ret
->algorithm
= algorithm
;
179 ret
->keysize
= keylen
;
185 _gnutls_hmac_deinit (mac_hd_t handle
, void *digest
)
190 maclen
= _gnutls_hash_get_algo_len (handle
->algorithm
);
192 mac
= gc_hash_read (handle
->handle
);
195 memcpy (digest
, mac
, maclen
);
197 gc_hash_close (handle
->handle
);
199 gnutls_free (handle
);
203 get_padsize (gnutls_mac_algorithm_t algorithm
)
209 case GNUTLS_MAC_SHA1
:
217 _gnutls_mac_init_ssl3 (gnutls_mac_algorithm_t algorithm
, void *key
,
224 padsize
= get_padsize (algorithm
);
228 return GNUTLS_MAC_FAILED
;
231 memset (ipad
, 0x36, padsize
);
233 ret
= _gnutls_hash_init (algorithm
);
234 if (ret
!= GNUTLS_HASH_FAILED
)
237 ret
->keysize
= keylen
;
240 _gnutls_hash (ret
, key
, keylen
);
241 _gnutls_hash (ret
, ipad
, padsize
);
248 _gnutls_mac_deinit_ssl3 (mac_hd_t handle
, void *digest
)
250 opaque ret
[MAX_HASH_SIZE
];
256 padsize
= get_padsize (handle
->algorithm
);
263 memset (opad
, 0x5C, padsize
);
265 td
= _gnutls_hash_init (handle
->algorithm
);
266 if (td
!= GNUTLS_MAC_FAILED
)
268 if (handle
->keysize
> 0)
269 _gnutls_hash (td
, handle
->key
, handle
->keysize
);
271 _gnutls_hash (td
, opad
, padsize
);
272 block
= _gnutls_hmac_get_algo_len (handle
->algorithm
);
273 _gnutls_hash_deinit (handle
, ret
); /* get the previous hash */
274 _gnutls_hash (td
, ret
, block
);
276 _gnutls_hash_deinit (td
, digest
);
281 _gnutls_mac_deinit_ssl3_handshake (mac_hd_t handle
,
282 void *digest
, opaque
* key
,
285 opaque ret
[MAX_HASH_SIZE
];
292 padsize
= get_padsize (handle
->algorithm
);
299 memset (opad
, 0x5C, padsize
);
300 memset (ipad
, 0x36, padsize
);
302 td
= _gnutls_hash_init (handle
->algorithm
);
303 if (td
!= GNUTLS_HASH_FAILED
)
306 _gnutls_hash (td
, key
, key_size
);
308 _gnutls_hash (td
, opad
, padsize
);
309 block
= _gnutls_hmac_get_algo_len (handle
->algorithm
);
312 _gnutls_hash (handle
, key
, key_size
);
313 _gnutls_hash (handle
, ipad
, padsize
);
314 _gnutls_hash_deinit (handle
, ret
); /* get the previous hash */
316 _gnutls_hash (td
, ret
, block
);
318 _gnutls_hash_deinit (td
, digest
);
323 ssl3_sha (int i
, opaque
* secret
, int secret_len
,
324 opaque
* rnd
, int rnd_len
, void *digest
)
329 GNUTLS_HASH_HANDLE td
;
331 for (j
= 0; j
< i
+ 1; j
++)
333 text1
[j
] = 65 + i
; /* A==65 */
336 td
= _gnutls_hash_init (GNUTLS_MAC_SHA1
);
340 return GNUTLS_E_HASH_FAILED
;
343 _gnutls_hash (td
, text1
, i
+ 1);
344 _gnutls_hash (td
, secret
, secret_len
);
345 _gnutls_hash (td
, rnd
, rnd_len
);
347 _gnutls_hash_deinit (td
, digest
);
352 ssl3_md5 (int i
, opaque
* secret
, int secret_len
,
353 opaque
* rnd
, int rnd_len
, void *digest
)
355 opaque tmp
[MAX_HASH_SIZE
];
359 td
= _gnutls_hash_init (GNUTLS_MAC_MD5
);
363 return GNUTLS_E_HASH_FAILED
;
366 _gnutls_hash (td
, secret
, secret_len
);
368 ret
= ssl3_sha (i
, secret
, secret_len
, rnd
, rnd_len
, tmp
);
372 _gnutls_hash_deinit (td
, digest
);
376 _gnutls_hash (td
, tmp
, _gnutls_hash_get_algo_len (GNUTLS_MAC_SHA1
));
378 _gnutls_hash_deinit (td
, digest
);
383 _gnutls_ssl3_hash_md5 (void *first
, int first_len
,
384 void *second
, int second_len
, int ret_len
,
387 opaque digest
[MAX_HASH_SIZE
];
389 int block
= _gnutls_hash_get_algo_len (GNUTLS_MAC_MD5
);
391 td
= _gnutls_hash_init (GNUTLS_MAC_MD5
);
395 return GNUTLS_E_HASH_FAILED
;
398 _gnutls_hash (td
, first
, first_len
);
399 _gnutls_hash (td
, second
, second_len
);
401 _gnutls_hash_deinit (td
, digest
);
406 return GNUTLS_E_INTERNAL_ERROR
;
409 memcpy (ret
, digest
, ret_len
);
416 _gnutls_ssl3_generate_random (void *secret
, int secret_len
,
417 void *rnd
, int rnd_len
,
418 int ret_bytes
, opaque
* ret
)
420 int i
= 0, copy
, output_bytes
;
421 opaque digest
[MAX_HASH_SIZE
];
422 int block
= _gnutls_hash_get_algo_len (GNUTLS_MAC_MD5
);
428 output_bytes
+= block
;
430 while (output_bytes
< ret_bytes
);
432 times
= output_bytes
/ block
;
434 for (i
= 0; i
< times
; i
++)
437 result
= ssl3_md5 (i
, secret
, secret_len
, rnd
, rnd_len
, digest
);
444 if ((1 + i
) * block
< ret_bytes
)
450 copy
= ret_bytes
- (i
) * block
;
453 memcpy (&ret
[i
* block
], digest
, copy
);