Line data Source code
1 : /*
2 : * Copyright (C) 2000-2012 Free Software Foundation, Inc.
3 : *
4 : * Author: Nikos Mavrogiannopoulos
5 : *
6 : * This file is part of GnuTLS.
7 : *
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.
12 : *
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.
17 : *
18 : * You should have received a copy of the GNU Lesser General Public License
19 : * along with this program. If not, see <https://www.gnu.org/licenses/>
20 : *
21 : */
22 :
23 : /* This file handles all the internal functions that cope with hashes
24 : * and HMACs.
25 : */
26 :
27 : #include "gnutls_int.h"
28 : #include <hash_int.h>
29 : #include "errors.h"
30 : #include <algorithms.h>
31 : #include <fips.h>
32 :
33 7474 : int _gnutls_hash_init(digest_hd_st * dig, const mac_entry_st * e)
34 : {
35 7474 : int result;
36 7474 : const gnutls_crypto_digest_st *cc = NULL;
37 :
38 7474 : FAIL_IF_LIB_ERROR;
39 :
40 7474 : if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
41 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
42 :
43 7474 : dig->e = e;
44 :
45 : /* check if a digest has been registered
46 : */
47 7474 : cc = _gnutls_get_crypto_digest((gnutls_digest_algorithm_t)e->id);
48 7474 : if (cc != NULL && cc->init) {
49 1212 : if (cc->init((gnutls_digest_algorithm_t)e->id, &dig->handle) < 0) {
50 0 : gnutls_assert();
51 0 : return GNUTLS_E_HASH_FAILED;
52 : }
53 :
54 1212 : dig->hash = cc->hash;
55 1212 : dig->output = cc->output;
56 1212 : dig->deinit = cc->deinit;
57 1212 : dig->copy = cc->copy;
58 :
59 1212 : return 0;
60 : }
61 :
62 6262 : result = _gnutls_digest_ops.init((gnutls_digest_algorithm_t)e->id, &dig->handle);
63 6262 : if (result < 0) {
64 0 : gnutls_assert();
65 0 : return result;
66 : }
67 :
68 6262 : dig->hash = _gnutls_digest_ops.hash;
69 6262 : dig->output = _gnutls_digest_ops.output;
70 6262 : dig->deinit = _gnutls_digest_ops.deinit;
71 6262 : dig->copy = _gnutls_digest_ops.copy;
72 :
73 6262 : return 0;
74 : }
75 :
76 : /* Returns true(non-zero) or false(0) if the
77 : * provided hash exists
78 : */
79 3434 : int _gnutls_digest_exists(gnutls_digest_algorithm_t algo)
80 : {
81 3434 : const gnutls_crypto_digest_st *cc = NULL;
82 :
83 3434 : if (is_mac_algo_forbidden(DIG_TO_MAC(algo)))
84 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
85 :
86 3434 : cc = _gnutls_get_crypto_digest(algo);
87 3434 : if (cc != NULL)
88 : return 1;
89 :
90 822 : return _gnutls_digest_ops.exists(algo);
91 : }
92 :
93 36 : int _gnutls_hash_copy(const digest_hd_st * handle, digest_hd_st * dst)
94 : {
95 36 : if (handle->copy == NULL)
96 4 : return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
97 :
98 32 : *dst = *handle; /* copy data */
99 32 : dst->handle = handle->copy(handle->handle);
100 :
101 32 : if (dst->handle == NULL)
102 0 : return GNUTLS_E_HASH_FAILED;
103 :
104 : return 0;
105 : }
106 :
107 7506 : void _gnutls_hash_deinit(digest_hd_st * handle, void *digest)
108 : {
109 7506 : if (handle->handle == NULL) {
110 : return;
111 : }
112 :
113 7506 : if (digest != NULL)
114 15008 : _gnutls_hash_output(handle, digest);
115 :
116 7506 : handle->deinit(handle->handle);
117 7506 : handle->handle = NULL;
118 : }
119 :
120 : int
121 958532 : _gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,
122 : const void *text, size_t textlen, void *digest)
123 : {
124 958532 : int ret;
125 958532 : const gnutls_crypto_digest_st *cc = NULL;
126 :
127 958532 : FAIL_IF_LIB_ERROR;
128 :
129 : /* check if a digest has been registered
130 : */
131 958532 : cc = _gnutls_get_crypto_digest(algorithm);
132 958532 : if (cc != NULL) {
133 906322 : if (cc->fast(algorithm, text, textlen, digest) < 0) {
134 0 : gnutls_assert();
135 0 : return GNUTLS_E_HASH_FAILED;
136 : }
137 :
138 : return 0;
139 : }
140 :
141 52210 : ret = _gnutls_digest_ops.fast(algorithm, text, textlen, digest);
142 52210 : if (ret < 0) {
143 0 : gnutls_assert();
144 0 : return ret;
145 : }
146 :
147 : return 0;
148 : }
149 :
150 :
151 : /* HMAC interface */
152 :
153 : int
154 26697 : _gnutls_mac_fast(gnutls_mac_algorithm_t algorithm, const void *key,
155 : int keylen, const void *text, size_t textlen,
156 : void *digest)
157 : {
158 26697 : int ret;
159 26697 : const gnutls_crypto_mac_st *cc = NULL;
160 :
161 26697 : FAIL_IF_LIB_ERROR;
162 :
163 : /* check if a digest has been registered
164 : */
165 26697 : cc = _gnutls_get_crypto_mac(algorithm);
166 26697 : if (cc != NULL) {
167 26675 : if (cc->
168 : fast(algorithm, NULL, 0, key, keylen, text, textlen,
169 : digest) < 0) {
170 0 : gnutls_assert();
171 0 : return GNUTLS_E_HASH_FAILED;
172 : }
173 :
174 : return 0;
175 : }
176 :
177 22 : ret =
178 22 : _gnutls_mac_ops.fast(algorithm, NULL, 0, key, keylen, text,
179 : textlen, digest);
180 22 : if (ret < 0) {
181 5 : gnutls_assert();
182 5 : return ret;
183 : }
184 :
185 : return 0;
186 :
187 : }
188 :
189 : /* Returns true(non-zero) or false(0) if the
190 : * provided hash exists
191 : */
192 8948 : int _gnutls_mac_exists(gnutls_mac_algorithm_t algo)
193 : {
194 8948 : const gnutls_crypto_mac_st *cc = NULL;
195 :
196 : /* exceptionally it exists, as it is not a real MAC */
197 8948 : if (algo == GNUTLS_MAC_AEAD)
198 : return 1;
199 :
200 8593 : if (is_mac_algo_forbidden(algo))
201 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
202 :
203 8593 : cc = _gnutls_get_crypto_mac(algo);
204 8593 : if (cc != NULL)
205 : return 1;
206 :
207 614 : return _gnutls_mac_ops.exists(algo);
208 : }
209 :
210 : int
211 17702 : _gnutls_mac_init(mac_hd_st * mac, const mac_entry_st * e,
212 : const void *key, int keylen)
213 : {
214 17702 : int result;
215 17702 : const gnutls_crypto_mac_st *cc = NULL;
216 :
217 17702 : FAIL_IF_LIB_ERROR;
218 :
219 17702 : if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
220 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
221 :
222 17702 : mac->e = e;
223 17702 : mac->mac_len = _gnutls_mac_get_algo_len(e);
224 :
225 : /* check if a digest has been registered
226 : */
227 17702 : cc = _gnutls_get_crypto_mac(e->id);
228 17702 : if (cc != NULL && cc->init != NULL) {
229 17443 : if (cc->init(e->id, &mac->handle) < 0) {
230 0 : gnutls_assert();
231 0 : return GNUTLS_E_HASH_FAILED;
232 : }
233 :
234 17443 : if (cc->setkey(mac->handle, key, keylen) < 0) {
235 0 : gnutls_assert();
236 0 : cc->deinit(mac->handle);
237 0 : return GNUTLS_E_HASH_FAILED;
238 : }
239 :
240 17443 : mac->hash = cc->hash;
241 17443 : mac->setnonce = cc->setnonce;
242 17443 : mac->output = cc->output;
243 17443 : mac->deinit = cc->deinit;
244 17443 : mac->copy = cc->copy;
245 17443 : mac->setkey = cc->setkey;
246 :
247 17443 : return 0;
248 : }
249 :
250 259 : result = _gnutls_mac_ops.init(e->id, &mac->handle);
251 259 : if (result < 0) {
252 0 : gnutls_assert();
253 0 : return result;
254 : }
255 :
256 259 : mac->hash = _gnutls_mac_ops.hash;
257 259 : mac->setnonce = _gnutls_mac_ops.setnonce;
258 259 : mac->output = _gnutls_mac_ops.output;
259 259 : mac->deinit = _gnutls_mac_ops.deinit;
260 259 : mac->copy = _gnutls_mac_ops.copy;
261 259 : mac->setkey = _gnutls_mac_ops.setkey;
262 :
263 259 : if (_gnutls_mac_ops.setkey(mac->handle, key, keylen) < 0) {
264 0 : gnutls_assert();
265 0 : mac->deinit(mac->handle);
266 0 : return GNUTLS_E_HASH_FAILED;
267 : }
268 :
269 : return 0;
270 : }
271 :
272 252 : int _gnutls_mac_copy(const mac_hd_st * handle, mac_hd_st * dst)
273 : {
274 252 : if (handle->copy == NULL)
275 2 : return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
276 :
277 250 : *dst = *handle; /* copy data */
278 250 : dst->handle = handle->copy(handle->handle);
279 :
280 250 : if (dst->handle == NULL)
281 0 : return GNUTLS_E_HASH_FAILED;
282 :
283 : return 0;
284 : }
285 :
286 17870 : void _gnutls_mac_deinit(mac_hd_st * handle, void *digest)
287 : {
288 17870 : if (handle->handle == NULL) {
289 : return;
290 : }
291 :
292 17870 : if (digest)
293 8802 : _gnutls_mac_output(handle, digest);
294 :
295 17870 : handle->deinit(handle->handle);
296 17870 : handle->handle = NULL;
297 : }
298 :
299 : #ifdef ENABLE_SSL3
300 : inline static int get_padsize(gnutls_mac_algorithm_t algorithm)
301 : {
302 : switch (algorithm) {
303 : case GNUTLS_MAC_MD5:
304 : return 48;
305 : case GNUTLS_MAC_SHA1:
306 : return 40;
307 : default:
308 : return 0;
309 : }
310 : }
311 :
312 : /* Special functions for SSL3 MAC
313 : */
314 :
315 : int
316 : _gnutls_mac_init_ssl3(digest_hd_st * ret, const mac_entry_st * e,
317 : void *key, int keylen)
318 : {
319 : uint8_t ipad[48];
320 : int padsize, result;
321 :
322 : FAIL_IF_LIB_ERROR;
323 :
324 : padsize = get_padsize(e->id);
325 : if (padsize == 0) {
326 : gnutls_assert();
327 : return GNUTLS_E_HASH_FAILED;
328 : }
329 :
330 : memset(ipad, 0x36, padsize);
331 :
332 : result = _gnutls_hash_init(ret, e);
333 : if (result < 0) {
334 : gnutls_assert();
335 : return result;
336 : }
337 :
338 : ret->key = key;
339 : ret->keysize = keylen;
340 :
341 : if (keylen > 0)
342 : _gnutls_hash(ret, key, keylen);
343 : _gnutls_hash(ret, ipad, padsize);
344 :
345 : return 0;
346 : }
347 :
348 : int _gnutls_mac_output_ssl3(digest_hd_st * handle, void *digest)
349 : {
350 : uint8_t ret[MAX_HASH_SIZE];
351 : digest_hd_st td;
352 : uint8_t opad[48];
353 : int padsize;
354 : int block, rc;
355 :
356 : padsize = get_padsize(handle->e->id);
357 : if (padsize == 0) {
358 : gnutls_assert();
359 : return GNUTLS_E_INTERNAL_ERROR;
360 : }
361 :
362 : memset(opad, 0x5C, padsize);
363 :
364 : rc = _gnutls_hash_init(&td, handle->e);
365 : if (rc < 0) {
366 : gnutls_assert();
367 : return rc;
368 : }
369 :
370 : if (handle->keysize > 0)
371 : _gnutls_hash(&td, handle->key, handle->keysize);
372 :
373 : _gnutls_hash(&td, opad, padsize);
374 : block = _gnutls_mac_get_algo_len(handle->e);
375 : _gnutls_hash_output(handle, ret); /* get the previous hash */
376 : _gnutls_hash(&td, ret, block);
377 :
378 : _gnutls_hash_deinit(&td, digest);
379 :
380 : /* reset handle */
381 : memset(opad, 0x36, padsize);
382 :
383 : if (handle->keysize > 0)
384 : _gnutls_hash(handle, handle->key, handle->keysize);
385 : _gnutls_hash(handle, opad, padsize);
386 :
387 : return 0;
388 : }
389 :
390 : int _gnutls_mac_deinit_ssl3(digest_hd_st * handle, void *digest)
391 : {
392 : int ret = 0;
393 :
394 : if (digest != NULL)
395 : ret = _gnutls_mac_output_ssl3(handle, digest);
396 : _gnutls_hash_deinit(handle, NULL);
397 :
398 : return ret;
399 : }
400 :
401 : int
402 : _gnutls_mac_deinit_ssl3_handshake(digest_hd_st * handle,
403 : void *digest, uint8_t * key,
404 : uint32_t key_size)
405 : {
406 : uint8_t ret[MAX_HASH_SIZE];
407 : digest_hd_st td;
408 : uint8_t opad[48];
409 : uint8_t ipad[48];
410 : int padsize;
411 : int block, rc;
412 :
413 : padsize = get_padsize(handle->e->id);
414 : if (padsize == 0) {
415 : gnutls_assert();
416 : rc = GNUTLS_E_INTERNAL_ERROR;
417 : goto cleanup;
418 : }
419 :
420 : memset(opad, 0x5C, padsize);
421 : memset(ipad, 0x36, padsize);
422 :
423 : rc = _gnutls_hash_init(&td, handle->e);
424 : if (rc < 0) {
425 : gnutls_assert();
426 : goto cleanup;
427 : }
428 :
429 : if (key_size > 0)
430 : _gnutls_hash(&td, key, key_size);
431 :
432 : _gnutls_hash(&td, opad, padsize);
433 : block = _gnutls_mac_get_algo_len(handle->e);
434 :
435 : if (key_size > 0)
436 : _gnutls_hash(handle, key, key_size);
437 : _gnutls_hash(handle, ipad, padsize);
438 : _gnutls_hash_deinit(handle, ret); /* get the previous hash */
439 :
440 : _gnutls_hash(&td, ret, block);
441 :
442 : _gnutls_hash_deinit(&td, digest);
443 :
444 : return 0;
445 :
446 : cleanup:
447 : _gnutls_hash_deinit(handle, NULL);
448 : return rc;
449 : }
450 :
451 : static int
452 : ssl3_sha(int i, uint8_t * secret, int secret_len,
453 : uint8_t * rnd, int rnd_len, void *digest)
454 : {
455 : int j, ret;
456 : uint8_t text1[26];
457 :
458 : digest_hd_st td;
459 :
460 : for (j = 0; j < i + 1; j++) {
461 : text1[j] = 65 + i; /* A==65 */
462 : }
463 :
464 : ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1));
465 : if (ret < 0) {
466 : gnutls_assert();
467 : return ret;
468 : }
469 :
470 : _gnutls_hash(&td, text1, i + 1);
471 : _gnutls_hash(&td, secret, secret_len);
472 : _gnutls_hash(&td, rnd, rnd_len);
473 :
474 : _gnutls_hash_deinit(&td, digest);
475 : return 0;
476 : }
477 :
478 : #define SHA1_DIGEST_OUTPUT 20
479 : #define MD5_DIGEST_OUTPUT 16
480 :
481 : static int
482 : ssl3_md5(int i, uint8_t * secret, int secret_len,
483 : uint8_t * rnd, int rnd_len, void *digest)
484 : {
485 : uint8_t tmp[MAX_HASH_SIZE];
486 : digest_hd_st td;
487 : int ret;
488 :
489 : ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
490 : if (ret < 0) {
491 : gnutls_assert();
492 : return ret;
493 : }
494 :
495 : _gnutls_hash(&td, secret, secret_len);
496 :
497 : ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp);
498 : if (ret < 0) {
499 : gnutls_assert();
500 : _gnutls_hash_deinit(&td, digest);
501 : return ret;
502 : }
503 :
504 : _gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT);
505 :
506 : _gnutls_hash_deinit(&td, digest);
507 : return 0;
508 : }
509 :
510 : int
511 : _gnutls_ssl3_generate_random(void *secret, int secret_len,
512 : void *rnd, int rnd_len,
513 : int ret_bytes, uint8_t * ret)
514 : {
515 : int i = 0, copy, output_bytes;
516 : uint8_t digest[MAX_HASH_SIZE];
517 : int block = MD5_DIGEST_OUTPUT;
518 : int result, times;
519 :
520 : output_bytes = 0;
521 : do {
522 : output_bytes += block;
523 : }
524 : while (output_bytes < ret_bytes);
525 :
526 : times = output_bytes / block;
527 :
528 : for (i = 0; i < times; i++) {
529 :
530 : result =
531 : ssl3_md5(i, secret, secret_len, rnd, rnd_len, digest);
532 : if (result < 0) {
533 : gnutls_assert();
534 : return result;
535 : }
536 :
537 : if ((1 + i) * block < ret_bytes) {
538 : copy = block;
539 : } else {
540 : copy = ret_bytes - (i) * block;
541 : }
542 :
543 : memcpy(&ret[i * block], digest, copy);
544 : }
545 :
546 : return 0;
547 : }
548 :
549 : #endif
|