summaryrefslogtreecommitdiff
path: root/lib/nettle/prf.c
blob: 631ba3b8c092b433a229f37433709dc64358d795 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * Copyright (C) 2017 Red Hat, Inc.
 *
 * Author: Nikos Mavrogiannopoulos
 *
 * This file is part of GNUTLS.
 *
 * The GNUTLS library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
 *
 */

#include <gnutls_int.h>
#include "int/tls1-prf.h"
#include <nettle/hmac.h>
#if ENABLE_GOST
#include "gost/hmac-gost.h"
#endif

/*-
 * _gnutls_prf_raw:
 * @mac: the MAC algorithm to use, set to %GNUTLS_MAC_MD5_SHA1 for the TLS1.0 mac
 * @master_size: length of the @master variable.
 * @master: the master secret used in PRF computation
 * @label_size: length of the @label variable.
 * @label: label used in PRF computation, typically a short string.
 * @seed_size: length of the @seed variable.
 * @seed: optional extra data to seed the PRF with.
 * @outsize: size of pre-allocated output buffer to hold the output.
 * @out: pre-allocated buffer to hold the generated data.
 *
 * Apply the TLS Pseudo-Random-Function (PRF) on the master secret
 * and the provided data.
 *
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
 -*/
int
_gnutls_prf_raw(gnutls_mac_algorithm_t mac,
		size_t master_size, const void *master,
		size_t label_size, const char *label,
		size_t seed_size, const uint8_t *seed, size_t outsize, char *out)
{
	int ret;

	switch (mac) {
	case GNUTLS_MAC_MD5_SHA1:
		tls10_prf(master_size, (uint8_t*)master, label_size, label,
			  seed_size, seed, outsize, (uint8_t*)out);
		return 0;
	case GNUTLS_MAC_SHA256:{
		struct hmac_sha256_ctx ctx;
		hmac_sha256_set_key(&ctx, master_size, (uint8_t*)master);

		ret = tls12_prf(&ctx,
			  (nettle_hash_update_func *)
			  hmac_sha256_update,
			  (nettle_hash_digest_func *)
			  hmac_sha256_digest, SHA256_DIGEST_SIZE,
			  label_size, label, seed_size,
			  seed, outsize,
			  (uint8_t*)out);

		if (unlikely(ret != 1))
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
		break;
	}
	case GNUTLS_MAC_SHA384:{
		struct hmac_sha384_ctx ctx;
		hmac_sha384_set_key(&ctx, master_size, master);

		ret = tls12_prf(&ctx,
			  (nettle_hash_update_func *)
			  hmac_sha384_update,
			  (nettle_hash_digest_func *)
			  hmac_sha384_digest, SHA384_DIGEST_SIZE,
			  label_size, label, seed_size,
			  seed, outsize,
			  (uint8_t*)out);

		if (unlikely(ret != 1))
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
		break;
	}
#if ENABLE_GOST
	case GNUTLS_MAC_STREEBOG_256:{
		struct hmac_streebog256_ctx ctx;
		hmac_streebog256_set_key(&ctx, master_size, master);

		ret = tls12_prf(&ctx,
			  (nettle_hash_update_func *)
			  hmac_streebog256_update,
			  (nettle_hash_digest_func *)
			  hmac_streebog256_digest, STREEBOG256_DIGEST_SIZE,
			  label_size, label, seed_size,
			  seed, outsize,
			  (uint8_t*)out);

		if (unlikely(ret != 1))
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
		break;
	}
	case GNUTLS_MAC_STREEBOG_512:{
		struct hmac_streebog512_ctx ctx;
		hmac_streebog512_set_key(&ctx, master_size, master);

		ret = tls12_prf(&ctx,
			  (nettle_hash_update_func *)
			  hmac_streebog512_update,
			  (nettle_hash_digest_func *)
			  hmac_streebog512_digest, STREEBOG512_DIGEST_SIZE,
			  label_size, label, seed_size,
			  seed, outsize,
			  (uint8_t*)out);

		if (unlikely(ret != 1))
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
		break;
	}
#endif
	default:
		gnutls_assert();
		_gnutls_debug_log("unhandled PRF %s\n",
				  gnutls_mac_get_name(mac));
		return GNUTLS_E_INVALID_REQUEST;

	}

	return 0;
}