Version 1.7.10.
[gnutls.git] / lib / gnutls_hash_int.c
blobde655a6b03b579c6d491fe073ce3d6b6bba0e4ba
1 /*
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,
21 * USA
25 /* This file handles all the internal functions that cope with hashes
26 * and HMACs.
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)
35 switch (mac)
37 case GNUTLS_MAC_NULL:
38 return -1;
39 break;
40 case GNUTLS_MAC_SHA1:
41 return GC_SHA1;
42 break;
43 case GNUTLS_MAC_SHA256:
44 return GC_SHA256;
45 break;
46 case GNUTLS_MAC_SHA384:
47 return GC_SHA384;
48 break;
49 case GNUTLS_MAC_SHA512:
50 return GC_SHA512;
51 break;
52 case GNUTLS_MAC_MD5:
53 return GC_MD5;
54 break;
55 case GNUTLS_MAC_RMD160:
56 return GC_RMD160;
57 break;
58 case GNUTLS_MAC_MD2:
59 return GC_MD2;
60 break;
61 default:
62 gnutls_assert ();
63 return -1;
65 return -1;
68 GNUTLS_HASH_HANDLE
69 _gnutls_hash_init (gnutls_mac_algorithm_t algorithm)
71 mac_hd_t ret;
72 int result;
74 ret = gnutls_malloc (sizeof (mac_hd_st));
75 if (ret == NULL)
77 gnutls_assert ();
78 return GNUTLS_HASH_FAILED;
81 ret->algorithm = algorithm;
83 result = gc_hash_open (_gnutls_mac2gc (algorithm), 0, &ret->handle);
84 if (result)
86 gnutls_assert ();
87 gnutls_free (ret);
88 ret = GNUTLS_HASH_FAILED;
91 return ret;
94 int
95 _gnutls_hash_get_algo_len (gnutls_mac_algorithm_t algorithm)
97 int ret;
99 ret = gc_hash_digest_length (_gnutls_mac2gc (algorithm));
101 return ret;
106 _gnutls_hash (GNUTLS_HASH_HANDLE handle, const void *text, size_t textlen)
108 if (textlen > 0)
109 gc_hash_write (handle->handle, textlen, text);
110 return 0;
113 GNUTLS_HASH_HANDLE
114 _gnutls_hash_copy (GNUTLS_HASH_HANDLE handle)
116 GNUTLS_HASH_HANDLE ret;
117 int result;
119 ret = gnutls_malloc (sizeof (mac_hd_st));
121 if (ret == NULL)
122 return GNUTLS_HASH_FAILED;
124 ret->algorithm = handle->algorithm;
125 ret->key = NULL; /* it's a hash anyway */
126 ret->keysize = 0;
128 result = gc_hash_clone (handle->handle, &ret->handle);
130 if (result)
132 gnutls_free (ret);
133 return GNUTLS_HASH_FAILED;
136 return ret;
139 void
140 _gnutls_hash_deinit (GNUTLS_HASH_HANDLE handle, void *digest)
142 const opaque *mac;
143 int maclen;
145 maclen = _gnutls_hash_get_algo_len (handle->algorithm);
147 mac = gc_hash_read (handle->handle);
148 if (digest != NULL)
149 memcpy (digest, mac, maclen);
151 gc_hash_close (handle->handle);
153 gnutls_free (handle);
157 mac_hd_t
158 _gnutls_hmac_init (gnutls_mac_algorithm_t algorithm,
159 const void *key, int keylen)
161 mac_hd_t ret;
162 int result;
164 ret = gnutls_malloc (sizeof (mac_hd_st));
165 if (ret == NULL)
166 return GNUTLS_MAC_FAILED;
168 result = gc_hash_open (_gnutls_mac2gc (algorithm), GC_HMAC, &ret->handle);
169 if (result)
171 gnutls_free (ret);
172 return GNUTLS_MAC_FAILED;
175 gc_hash_hmac_setkey (ret->handle, keylen, key);
177 ret->algorithm = algorithm;
178 ret->key = key;
179 ret->keysize = keylen;
181 return ret;
184 void
185 _gnutls_hmac_deinit (mac_hd_t handle, void *digest)
187 const opaque *mac;
188 int maclen;
190 maclen = _gnutls_hash_get_algo_len (handle->algorithm);
192 mac = gc_hash_read (handle->handle);
194 if (digest != NULL)
195 memcpy (digest, mac, maclen);
197 gc_hash_close (handle->handle);
199 gnutls_free (handle);
202 inline static int
203 get_padsize (gnutls_mac_algorithm_t algorithm)
205 switch (algorithm)
207 case GNUTLS_MAC_MD5:
208 return 48;
209 case GNUTLS_MAC_SHA1:
210 return 40;
211 default:
212 return 0;
216 mac_hd_t
217 _gnutls_mac_init_ssl3 (gnutls_mac_algorithm_t algorithm, void *key,
218 int keylen)
220 mac_hd_t ret;
221 opaque ipad[48];
222 int padsize;
224 padsize = get_padsize (algorithm);
225 if (padsize == 0)
227 gnutls_assert ();
228 return GNUTLS_MAC_FAILED;
231 memset (ipad, 0x36, padsize);
233 ret = _gnutls_hash_init (algorithm);
234 if (ret != GNUTLS_HASH_FAILED)
236 ret->key = key;
237 ret->keysize = keylen;
239 if (keylen > 0)
240 _gnutls_hash (ret, key, keylen);
241 _gnutls_hash (ret, ipad, padsize);
244 return ret;
247 void
248 _gnutls_mac_deinit_ssl3 (mac_hd_t handle, void *digest)
250 opaque ret[MAX_HASH_SIZE];
251 mac_hd_t td;
252 opaque opad[48];
253 int padsize;
254 int block;
256 padsize = get_padsize (handle->algorithm);
257 if (padsize == 0)
259 gnutls_assert ();
260 return;
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);
280 void
281 _gnutls_mac_deinit_ssl3_handshake (mac_hd_t handle,
282 void *digest, opaque * key,
283 uint32_t key_size)
285 opaque ret[MAX_HASH_SIZE];
286 mac_hd_t td;
287 opaque opad[48];
288 opaque ipad[48];
289 int padsize;
290 int block;
292 padsize = get_padsize (handle->algorithm);
293 if (padsize == 0)
295 gnutls_assert ();
296 return;
299 memset (opad, 0x5C, padsize);
300 memset (ipad, 0x36, padsize);
302 td = _gnutls_hash_init (handle->algorithm);
303 if (td != GNUTLS_HASH_FAILED)
305 if (key_size > 0)
306 _gnutls_hash (td, key, key_size);
308 _gnutls_hash (td, opad, padsize);
309 block = _gnutls_hmac_get_algo_len (handle->algorithm);
311 if (key_size > 0)
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);
322 static int
323 ssl3_sha (int i, opaque * secret, int secret_len,
324 opaque * rnd, int rnd_len, void *digest)
326 int j;
327 opaque text1[26];
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);
337 if (td == NULL)
339 gnutls_assert ();
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);
348 return 0;
351 static int
352 ssl3_md5 (int i, opaque * secret, int secret_len,
353 opaque * rnd, int rnd_len, void *digest)
355 opaque tmp[MAX_HASH_SIZE];
356 mac_hd_t td;
357 int ret;
359 td = _gnutls_hash_init (GNUTLS_MAC_MD5);
360 if (td == NULL)
362 gnutls_assert ();
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);
369 if (ret < 0)
371 gnutls_assert ();
372 _gnutls_hash_deinit (td, digest);
373 return ret;
376 _gnutls_hash (td, tmp, _gnutls_hash_get_algo_len (GNUTLS_MAC_SHA1));
378 _gnutls_hash_deinit (td, digest);
379 return 0;
383 _gnutls_ssl3_hash_md5 (void *first, int first_len,
384 void *second, int second_len, int ret_len,
385 opaque * ret)
387 opaque digest[MAX_HASH_SIZE];
388 mac_hd_t td;
389 int block = _gnutls_hash_get_algo_len (GNUTLS_MAC_MD5);
391 td = _gnutls_hash_init (GNUTLS_MAC_MD5);
392 if (td == NULL)
394 gnutls_assert ();
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);
403 if (ret_len > block)
405 gnutls_assert ();
406 return GNUTLS_E_INTERNAL_ERROR;
409 memcpy (ret, digest, ret_len);
411 return 0;
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);
423 int result, times;
425 output_bytes = 0;
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);
438 if (result < 0)
440 gnutls_assert ();
441 return result;
444 if ((1 + i) * block < ret_bytes)
446 copy = block;
448 else
450 copy = ret_bytes - (i) * block;
453 memcpy (&ret[i * block], digest, copy);
456 return 0;