/src/gnutls/lib/nettle/int/tls1-prf.c
Line | Count | Source (jump to first uncovered line) |
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 | | /* The RFC2246 P_hash() function. The mac_ctx is expected to |
42 | | * be initialized and key set to be the secret key. |
43 | | */ |
44 | | static void |
45 | | P_hash(void *mac_ctx, |
46 | | nettle_hash_update_func * update, |
47 | | nettle_hash_digest_func * digest, |
48 | | size_t digest_size, |
49 | | size_t seed_size, const uint8_t * seed, |
50 | | size_t label_size, const char *label, size_t dst_length, uint8_t * dst) |
51 | 0 | { |
52 | 0 | uint8_t Atmp[MAX_HASH_SIZE]; |
53 | 0 | ssize_t left; |
54 | 0 | unsigned started = 0; |
55 | | |
56 | | /* round up */ |
57 | 0 | left = dst_length; |
58 | |
|
59 | 0 | while (left > 0) { |
60 | 0 | if (started == 0) { /* A(0) */ |
61 | 0 | update(mac_ctx, label_size, (const uint8_t *)label); /* hash label */ |
62 | 0 | update(mac_ctx, seed_size, seed); |
63 | 0 | started = 1; |
64 | 0 | } else { |
65 | 0 | update(mac_ctx, digest_size, Atmp); |
66 | 0 | } |
67 | 0 | digest(mac_ctx, digest_size, Atmp); /* store A(i) */ |
68 | |
|
69 | 0 | update(mac_ctx, digest_size, Atmp); /* hash A(i) */ |
70 | 0 | update(mac_ctx, label_size, (const uint8_t *)label); /* hash label */ |
71 | 0 | update(mac_ctx, seed_size, seed); /* hash seed */ |
72 | |
|
73 | 0 | if (left < (ssize_t) digest_size) |
74 | 0 | digest_size = left; |
75 | |
|
76 | 0 | digest(mac_ctx, digest_size, dst); |
77 | |
|
78 | 0 | left -= digest_size; |
79 | 0 | dst += digest_size; |
80 | 0 | } |
81 | |
|
82 | 0 | return; |
83 | 0 | } |
84 | | |
85 | | int |
86 | | tls10_prf(size_t secret_size, const uint8_t * secret, |
87 | | size_t label_size, const char *label, |
88 | | size_t seed_size, const uint8_t * seed, size_t length, uint8_t * dst) |
89 | 0 | { |
90 | 0 | int l_s; |
91 | 0 | const uint8_t *s1, *s2; |
92 | 0 | struct hmac_md5_ctx md5_ctx; |
93 | 0 | struct hmac_sha1_ctx sha1_ctx; |
94 | 0 | uint8_t o1[MAX_PRF_BYTES]; |
95 | |
|
96 | 0 | if (length > MAX_PRF_BYTES) |
97 | 0 | return 0; |
98 | | |
99 | 0 | l_s = secret_size / 2; |
100 | 0 | s1 = &secret[0]; |
101 | 0 | s2 = &secret[l_s]; |
102 | 0 | if (secret_size % 2 != 0) { |
103 | 0 | l_s++; |
104 | 0 | } |
105 | |
|
106 | 0 | hmac_md5_set_key(&md5_ctx, l_s, s1); |
107 | |
|
108 | 0 | P_hash(&md5_ctx, (nettle_hash_update_func *) hmac_md5_update, |
109 | 0 | (nettle_hash_digest_func *) hmac_md5_digest, |
110 | 0 | MD5_DIGEST_SIZE, seed_size, seed, label_size, label, length, o1); |
111 | |
|
112 | 0 | hmac_sha1_set_key(&sha1_ctx, l_s, s2); |
113 | |
|
114 | 0 | P_hash(&sha1_ctx, (nettle_hash_update_func *) hmac_sha1_update, |
115 | 0 | (nettle_hash_digest_func *) hmac_sha1_digest, |
116 | 0 | SHA1_DIGEST_SIZE, |
117 | 0 | seed_size, seed, label_size, label, length, dst); |
118 | |
|
119 | 0 | memxor(dst, o1, length); |
120 | |
|
121 | 0 | return 1; |
122 | 0 | } |
123 | | |
124 | | /*- |
125 | | * tls12_prf: |
126 | | * @mac_ctx: a MAC context initialized with key being the secret |
127 | | * @update: a MAC update function |
128 | | * @digest: a MAC digest function |
129 | | * @digest_size: the MAC output size |
130 | | * @label_size: the size of the label |
131 | | * @label: the label to apply |
132 | | * @seed_size: the seed size |
133 | | * @seed: the seed |
134 | | * @length: size of desired PRF output |
135 | | * @dst: the location to store output |
136 | | * |
137 | | * The TLS 1.2 Pseudo-Random-Function (PRF). |
138 | | * |
139 | | * Returns: zero on failure, non zero on success. |
140 | | -*/ |
141 | | int |
142 | | tls12_prf(void *mac_ctx, |
143 | | nettle_hash_update_func * update, |
144 | | nettle_hash_digest_func * digest, |
145 | | size_t digest_size, |
146 | | size_t label_size, const char *label, |
147 | | size_t seed_size, const uint8_t * seed, size_t length, uint8_t * dst) |
148 | 0 | { |
149 | 0 | P_hash(mac_ctx, update, digest, digest_size, |
150 | 0 | seed_size, seed, label_size, label, length, dst); |
151 | |
|
152 | 0 | return 1; |
153 | 0 | } |