Line data Source code
1 : /*
2 : * Copyright (C) 2017 Red Hat, 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 : /* Functions for the TLS PRF handling.
24 : */
25 :
26 : #if HAVE_CONFIG_H
27 : # include <config.h>
28 : #endif
29 :
30 : #include <gnutls_int.h>
31 :
32 : #include <stdlib.h>
33 : #include <string.h>
34 :
35 : #include <nettle/hmac.h>
36 : #include <nettle/memxor.h>
37 : #include "int/tls1-prf.h"
38 : #include <nettle/sha1.h>
39 : #include <nettle/md5.h>
40 :
41 :
42 : /* The RFC2246 P_hash() function. The mac_ctx is expected to
43 : * be initialized and key set to be the secret key.
44 : */
45 : static void
46 44332 : P_hash( void *mac_ctx,
47 : nettle_hash_update_func *update,
48 : nettle_hash_digest_func *digest,
49 : size_t digest_size,
50 : size_t seed_size, const uint8_t *seed,
51 : size_t label_size, const char *label,
52 : size_t dst_length,
53 : uint8_t *dst)
54 : {
55 44332 : uint8_t Atmp[MAX_HASH_SIZE];
56 44332 : ssize_t left;
57 44332 : unsigned started = 0;
58 :
59 : /* round up */
60 44332 : left = dst_length;
61 :
62 137807 : while(left > 0) {
63 93475 : if (started == 0) { /* A(0) */
64 44332 : update(mac_ctx, label_size, (const uint8_t *)label); /* hash label */
65 44332 : update(mac_ctx, seed_size, seed);
66 44332 : started = 1;
67 : } else {
68 49143 : update(mac_ctx, digest_size, Atmp);
69 : }
70 93475 : digest(mac_ctx, digest_size, Atmp); /* store A(i) */
71 :
72 93475 : update(mac_ctx, digest_size, Atmp); /* hash A(i) */
73 93475 : update(mac_ctx, label_size, (const uint8_t *)label); /* hash label */
74 93475 : update(mac_ctx, seed_size, seed); /* hash seed */
75 :
76 93475 : if (left < (ssize_t)digest_size)
77 38758 : digest_size = left;
78 :
79 93475 : digest(mac_ctx, digest_size, dst);
80 :
81 93475 : left -= digest_size;
82 93475 : dst += digest_size;
83 : }
84 :
85 44332 : return;
86 : }
87 :
88 : int
89 8311 : tls10_prf(size_t secret_size, const uint8_t *secret,
90 : size_t label_size, const char *label,
91 : size_t seed_size, const uint8_t *seed,
92 : size_t length, uint8_t *dst)
93 : {
94 8311 : int l_s;
95 8311 : const uint8_t *s1, *s2;
96 8311 : struct hmac_md5_ctx md5_ctx;
97 8311 : struct hmac_sha1_ctx sha1_ctx;
98 8311 : uint8_t o1[MAX_PRF_BYTES];
99 :
100 8311 : if (length > MAX_PRF_BYTES)
101 : return 0;
102 :
103 8311 : l_s = secret_size / 2;
104 8311 : s1 = &secret[0];
105 8311 : s2 = &secret[l_s];
106 8311 : if (secret_size % 2 != 0) {
107 8 : l_s++;
108 : }
109 :
110 8311 : hmac_md5_set_key(&md5_ctx, l_s, s1);
111 :
112 8311 : P_hash(&md5_ctx, (nettle_hash_update_func*)hmac_md5_update,
113 : (nettle_hash_digest_func*)hmac_md5_digest,
114 : MD5_DIGEST_SIZE,
115 : seed_size, seed, label_size, label, length, o1);
116 :
117 8311 : hmac_sha1_set_key(&sha1_ctx, l_s, s2);
118 :
119 8311 : P_hash(&sha1_ctx, (nettle_hash_update_func*)hmac_sha1_update,
120 : (nettle_hash_digest_func*)hmac_sha1_digest,
121 : SHA1_DIGEST_SIZE,
122 : seed_size, seed, label_size, label, length, dst);
123 :
124 8311 : memxor(dst, o1, length);
125 :
126 8311 : return 1;
127 : }
128 :
129 : /*-
130 : * tls12_prf:
131 : * @mac_ctx: a MAC context initialized with key being the secret
132 : * @update: a MAC update function
133 : * @digest: a MAC digest function
134 : * @digest_size: the MAC output size
135 : * @label_size: the size of the label
136 : * @label: the label to apply
137 : * @seed_size: the seed size
138 : * @seed: the seed
139 : * @length: size of desired PRF output
140 : * @dst: the location to store output
141 : *
142 : * The TLS 1.2 Pseudo-Random-Function (PRF).
143 : *
144 : * Returns: zero on failure, non zero on success.
145 : -*/
146 : int
147 27710 : tls12_prf(void *mac_ctx,
148 : nettle_hash_update_func *update,
149 : nettle_hash_digest_func *digest,
150 : size_t digest_size,
151 : size_t label_size, const char *label,
152 : size_t seed_size, const uint8_t *seed,
153 : size_t length, uint8_t *dst)
154 : {
155 27710 : P_hash(mac_ctx, update, digest, digest_size,
156 : seed_size, seed, label_size, label, length, dst);
157 :
158 27710 : return 1;
159 : }
|