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 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 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>
30 #include <algorithms.h>
33 int _gnutls_hash_init(digest_hd_st * dig, const mac_entry_st * e)
36 const gnutls_crypto_digest_st *cc = NULL;
40 if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
41 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
45 /* check if a digest has been registered
47 cc = _gnutls_get_crypto_digest((gnutls_digest_algorithm_t)e->id);
48 if (cc != NULL && cc->init) {
49 if (cc->init((gnutls_digest_algorithm_t)e->id, &dig->handle) < 0) {
51 return GNUTLS_E_HASH_FAILED;
55 dig->output = cc->output;
56 dig->deinit = cc->deinit;
61 result = _gnutls_digest_ops.init((gnutls_digest_algorithm_t)e->id, &dig->handle);
67 dig->hash = _gnutls_digest_ops.hash;
68 dig->output = _gnutls_digest_ops.output;
69 dig->deinit = _gnutls_digest_ops.deinit;
74 /* Returns true(non-zero) or false(0) if the
75 * provided hash exists
77 int _gnutls_digest_exists(gnutls_digest_algorithm_t algo)
79 const gnutls_crypto_digest_st *cc = NULL;
81 cc = _gnutls_get_crypto_digest(algo);
85 return _gnutls_digest_ops.exists(algo);
88 void _gnutls_hash_deinit(digest_hd_st * handle, void *digest)
90 if (handle->handle == NULL) {
95 _gnutls_hash_output(handle, digest);
97 handle->deinit(handle->handle);
98 handle->handle = NULL;
102 _gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,
103 const void *text, size_t textlen, void *digest)
106 const gnutls_crypto_digest_st *cc = NULL;
110 /* check if a digest has been registered
112 cc = _gnutls_get_crypto_digest(algorithm);
114 if (cc->fast(algorithm, text, textlen, digest) < 0) {
116 return GNUTLS_E_HASH_FAILED;
122 ret = _gnutls_digest_ops.fast(algorithm, text, textlen, digest);
135 _gnutls_mac_fast(gnutls_mac_algorithm_t algorithm, const void *key,
136 int keylen, const void *text, size_t textlen,
140 const gnutls_crypto_mac_st *cc = NULL;
144 /* check if a digest has been registered
146 cc = _gnutls_get_crypto_mac(algorithm);
149 fast(algorithm, NULL, 0, key, keylen, text, textlen,
152 return GNUTLS_E_HASH_FAILED;
159 _gnutls_mac_ops.fast(algorithm, NULL, 0, key, keylen, text,
170 /* Returns true(non-zero) or false(0) if the
171 * provided hash exists
173 int _gnutls_mac_exists(gnutls_mac_algorithm_t algo)
175 const gnutls_crypto_mac_st *cc = NULL;
177 cc = _gnutls_get_crypto_mac(algo);
181 return _gnutls_mac_ops.exists(algo);
185 _gnutls_mac_init(mac_hd_st * mac, const mac_entry_st * e,
186 const void *key, int keylen)
189 const gnutls_crypto_mac_st *cc = NULL;
193 if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
194 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
197 mac->mac_len = _gnutls_mac_get_algo_len(e);
199 /* check if a digest has been registered
201 cc = _gnutls_get_crypto_mac(e->id);
202 if (cc != NULL && cc->init != NULL) {
203 if (cc->init(e->id, &mac->handle) < 0) {
205 return GNUTLS_E_HASH_FAILED;
208 if (cc->setkey(mac->handle, key, keylen) < 0) {
210 cc->deinit(mac->handle);
211 return GNUTLS_E_HASH_FAILED;
214 mac->hash = cc->hash;
215 mac->setnonce = cc->setnonce;
216 mac->output = cc->output;
217 mac->deinit = cc->deinit;
222 result = _gnutls_mac_ops.init(e->id, &mac->handle);
228 mac->hash = _gnutls_mac_ops.hash;
229 mac->setnonce = _gnutls_mac_ops.setnonce;
230 mac->output = _gnutls_mac_ops.output;
231 mac->deinit = _gnutls_mac_ops.deinit;
233 if (_gnutls_mac_ops.setkey(mac->handle, key, keylen) < 0) {
235 mac->deinit(mac->handle);
236 return GNUTLS_E_HASH_FAILED;
242 void _gnutls_mac_deinit(mac_hd_st * handle, void *digest)
244 if (handle->handle == NULL) {
249 _gnutls_mac_output(handle, digest);
251 handle->deinit(handle->handle);
252 handle->handle = NULL;
255 inline static int get_padsize(gnutls_mac_algorithm_t algorithm)
260 case GNUTLS_MAC_SHA1:
267 /* Special functions for SSL3 MAC
271 _gnutls_mac_init_ssl3(digest_hd_st * ret, const mac_entry_st * e,
272 void *key, int keylen)
279 padsize = get_padsize(e->id);
282 return GNUTLS_E_HASH_FAILED;
285 memset(ipad, 0x36, padsize);
287 result = _gnutls_hash_init(ret, e);
294 ret->keysize = keylen;
297 _gnutls_hash(ret, key, keylen);
298 _gnutls_hash(ret, ipad, padsize);
303 int _gnutls_mac_output_ssl3(digest_hd_st * handle, void *digest)
305 uint8_t ret[MAX_HASH_SIZE];
311 padsize = get_padsize(handle->e->id);
314 return GNUTLS_E_INTERNAL_ERROR;
317 memset(opad, 0x5C, padsize);
319 rc = _gnutls_hash_init(&td, handle->e);
325 if (handle->keysize > 0)
326 _gnutls_hash(&td, handle->key, handle->keysize);
328 _gnutls_hash(&td, opad, padsize);
329 block = _gnutls_mac_get_algo_len(handle->e);
330 _gnutls_hash_output(handle, ret); /* get the previous hash */
331 _gnutls_hash(&td, ret, block);
333 _gnutls_hash_deinit(&td, digest);
336 memset(opad, 0x36, padsize);
338 if (handle->keysize > 0)
339 _gnutls_hash(handle, handle->key, handle->keysize);
340 _gnutls_hash(handle, opad, padsize);
345 int _gnutls_mac_deinit_ssl3(digest_hd_st * handle, void *digest)
350 ret = _gnutls_mac_output_ssl3(handle, digest);
351 _gnutls_hash_deinit(handle, NULL);
357 _gnutls_mac_deinit_ssl3_handshake(digest_hd_st * handle,
358 void *digest, uint8_t * key,
361 uint8_t ret[MAX_HASH_SIZE];
368 padsize = get_padsize(handle->e->id);
371 rc = GNUTLS_E_INTERNAL_ERROR;
375 memset(opad, 0x5C, padsize);
376 memset(ipad, 0x36, padsize);
378 rc = _gnutls_hash_init(&td, handle->e);
385 _gnutls_hash(&td, key, key_size);
387 _gnutls_hash(&td, opad, padsize);
388 block = _gnutls_mac_get_algo_len(handle->e);
391 _gnutls_hash(handle, key, key_size);
392 _gnutls_hash(handle, ipad, padsize);
393 _gnutls_hash_deinit(handle, ret); /* get the previous hash */
395 _gnutls_hash(&td, ret, block);
397 _gnutls_hash_deinit(&td, digest);
402 _gnutls_hash_deinit(handle, NULL);
407 ssl3_sha(int i, uint8_t * secret, int secret_len,
408 uint8_t * rnd, int rnd_len, void *digest)
415 for (j = 0; j < i + 1; j++) {
416 text1[j] = 65 + i; /* A==65 */
419 ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1));
425 _gnutls_hash(&td, text1, i + 1);
426 _gnutls_hash(&td, secret, secret_len);
427 _gnutls_hash(&td, rnd, rnd_len);
429 _gnutls_hash_deinit(&td, digest);
433 #define SHA1_DIGEST_OUTPUT 20
434 #define MD5_DIGEST_OUTPUT 16
437 ssl3_md5(int i, uint8_t * secret, int secret_len,
438 uint8_t * rnd, int rnd_len, void *digest)
440 uint8_t tmp[MAX_HASH_SIZE];
444 ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
450 _gnutls_hash(&td, secret, secret_len);
452 ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp);
455 _gnutls_hash_deinit(&td, digest);
459 _gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT);
461 _gnutls_hash_deinit(&td, digest);
466 _gnutls_ssl3_hash_md5(const void *first, int first_len,
467 const void *second, int second_len,
468 int ret_len, uint8_t * ret)
470 uint8_t digest[MAX_HASH_SIZE];
472 int block = MD5_DIGEST_OUTPUT;
475 rc = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
481 _gnutls_hash(&td, first, first_len);
482 _gnutls_hash(&td, second, second_len);
484 _gnutls_hash_deinit(&td, digest);
486 if (ret_len > block) {
488 return GNUTLS_E_INTERNAL_ERROR;
491 memcpy(ret, digest, ret_len);
498 _gnutls_ssl3_generate_random(void *secret, int secret_len,
499 void *rnd, int rnd_len,
500 int ret_bytes, uint8_t * ret)
502 int i = 0, copy, output_bytes;
503 uint8_t digest[MAX_HASH_SIZE];
504 int block = MD5_DIGEST_OUTPUT;
509 output_bytes += block;
511 while (output_bytes < ret_bytes);
513 times = output_bytes / block;
515 for (i = 0; i < times; i++) {
518 ssl3_md5(i, secret, secret_len, rnd, rnd_len, digest);
524 if ((1 + i) * block < ret_bytes) {
527 copy = ret_bytes - (i) * block;
530 memcpy(&ret[i * block], digest, copy);