]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/kdf/tls1_prf.c
Added EVP_KDF (similiar to the EVP_MAC)
[thirdparty/openssl.git] / crypto / kdf / tls1_prf.c
1 /*
2 * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include "internal/cryptlib.h"
14 #include <openssl/evp.h>
15 #include <openssl/kdf.h>
16 #include "internal/evp_int.h"
17 #include "kdf_local.h"
18
19 static void kdf_tls1_prf_reset(EVP_KDF_IMPL *impl);
20 static int tls1_prf_alg(const EVP_MD *md,
21 const unsigned char *sec, size_t slen,
22 const unsigned char *seed, size_t seed_len,
23 unsigned char *out, size_t olen);
24
25 #define TLS1_PRF_MAXBUF 1024
26
27 /* TLS KDF kdf context structure */
28
29 struct evp_kdf_impl_st {
30 /* Digest to use for PRF */
31 const EVP_MD *md;
32 /* Secret value to use for PRF */
33 unsigned char *sec;
34 size_t seclen;
35 /* Buffer of concatenated seed data */
36 unsigned char seed[TLS1_PRF_MAXBUF];
37 size_t seedlen;
38 };
39
40 static EVP_KDF_IMPL *kdf_tls1_prf_new(void)
41 {
42 EVP_KDF_IMPL *impl;
43
44 if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL)
45 KDFerr(KDF_F_KDF_TLS1_PRF_NEW, ERR_R_MALLOC_FAILURE);
46 return impl;
47 }
48
49 static void kdf_tls1_prf_free(EVP_KDF_IMPL *impl)
50 {
51 kdf_tls1_prf_reset(impl);
52 OPENSSL_free(impl);
53 }
54
55 static void kdf_tls1_prf_reset(EVP_KDF_IMPL *impl)
56 {
57 OPENSSL_clear_free(impl->sec, impl->seclen);
58 OPENSSL_cleanse(impl->seed, impl->seedlen);
59 memset(impl, 0, sizeof(*impl));
60 }
61
62 static int kdf_tls1_prf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
63 {
64 const unsigned char *p;
65 size_t len;
66 const EVP_MD *md;
67
68 switch (cmd) {
69 case EVP_KDF_CTRL_SET_MD:
70 md = va_arg(args, const EVP_MD *);
71 if (md == NULL)
72 return 0;
73
74 impl->md = md;
75 return 1;
76
77 case EVP_KDF_CTRL_SET_TLS_SECRET:
78 p = va_arg(args, const unsigned char *);
79 len = va_arg(args, size_t);
80 OPENSSL_clear_free(impl->sec, impl->seclen);
81 impl->sec = OPENSSL_memdup(p, len);
82 if (impl->sec == NULL)
83 return 0;
84
85 impl->seclen = len;
86 return 1;
87
88 case EVP_KDF_CTRL_RESET_TLS_SEED:
89 OPENSSL_cleanse(impl->seed, impl->seedlen);
90 impl->seedlen = 0;
91 return 1;
92
93 case EVP_KDF_CTRL_ADD_TLS_SEED:
94 p = va_arg(args, const unsigned char *);
95 len = va_arg(args, size_t);
96 if (len == 0 || p == NULL)
97 return 1;
98
99 if (len > (TLS1_PRF_MAXBUF - impl->seedlen))
100 return 0;
101
102 memcpy(impl->seed + impl->seedlen, p, len);
103 impl->seedlen += len;
104 return 1;
105
106 default:
107 return -2;
108 }
109 }
110
111 static int kdf_tls1_prf_ctrl_str(EVP_KDF_IMPL *impl,
112 const char *type, const char *value)
113 {
114 if (value == NULL) {
115 KDFerr(KDF_F_KDF_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
116 return 0;
117 }
118 if (strcmp(type, "digest") == 0)
119 return kdf_md2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_SET_MD, value);
120
121 if (strcmp(type, "secret") == 0)
122 return kdf_str2ctrl(impl, kdf_tls1_prf_ctrl,
123 EVP_KDF_CTRL_SET_TLS_SECRET, value);
124
125 if (strcmp(type, "hexsecret") == 0)
126 return kdf_hex2ctrl(impl, kdf_tls1_prf_ctrl,
127 EVP_KDF_CTRL_SET_TLS_SECRET, value);
128
129 if (strcmp(type, "seed") == 0)
130 return kdf_str2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_ADD_TLS_SEED,
131 value);
132
133 if (strcmp(type, "hexseed") == 0)
134 return kdf_hex2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_ADD_TLS_SEED,
135 value);
136
137 return -2;
138 }
139
140 static int kdf_tls1_prf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
141 size_t keylen)
142 {
143 if (impl->md == NULL) {
144 KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
145 return 0;
146 }
147 if (impl->sec == NULL) {
148 KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET);
149 return 0;
150 }
151 if (impl->seedlen == 0) {
152 KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
153 return 0;
154 }
155 return tls1_prf_alg(impl->md, impl->sec, impl->seclen,
156 impl->seed, impl->seedlen,
157 key, keylen);
158 }
159
160 const EVP_KDF tls1_prf_kdf_meth = {
161 EVP_KDF_TLS1_PRF,
162 kdf_tls1_prf_new,
163 kdf_tls1_prf_free,
164 kdf_tls1_prf_reset,
165 kdf_tls1_prf_ctrl,
166 kdf_tls1_prf_ctrl_str,
167 NULL,
168 kdf_tls1_prf_derive
169 };
170
171 static int tls1_prf_P_hash(const EVP_MD *md,
172 const unsigned char *sec, size_t sec_len,
173 const unsigned char *seed, size_t seed_len,
174 unsigned char *out, size_t olen)
175 {
176 int chunk;
177 EVP_MAC_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL;
178 unsigned char A1[EVP_MAX_MD_SIZE];
179 size_t A1_len;
180 int ret = 0;
181
182 chunk = EVP_MD_size(md);
183 if (!ossl_assert(chunk > 0))
184 goto err;
185
186 ctx = EVP_MAC_CTX_new_id(EVP_MAC_HMAC);
187 ctx_tmp = EVP_MAC_CTX_new_id(EVP_MAC_HMAC);
188 ctx_init = EVP_MAC_CTX_new_id(EVP_MAC_HMAC);
189 if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL)
190 goto err;
191 if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_FLAGS, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW) != 1)
192 goto err;
193 if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_MD, md) != 1)
194 goto err;
195 if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_KEY, sec, sec_len) != 1)
196 goto err;
197 if (!EVP_MAC_init(ctx_init))
198 goto err;
199 if (!EVP_MAC_CTX_copy(ctx, ctx_init))
200 goto err;
201 if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len))
202 goto err;
203 if (!EVP_MAC_final(ctx, A1, &A1_len))
204 goto err;
205
206 for (;;) {
207 /* Reinit mac contexts */
208 if (!EVP_MAC_CTX_copy(ctx, ctx_init))
209 goto err;
210 if (!EVP_MAC_update(ctx, A1, A1_len))
211 goto err;
212 if (olen > (size_t)chunk && !EVP_MAC_CTX_copy(ctx_tmp, ctx))
213 goto err;
214 if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len))
215 goto err;
216
217 if (olen > (size_t)chunk) {
218 size_t mac_len;
219 if (!EVP_MAC_final(ctx, out, &mac_len))
220 goto err;
221 out += mac_len;
222 olen -= mac_len;
223 /* calc the next A1 value */
224 if (!EVP_MAC_final(ctx_tmp, A1, &A1_len))
225 goto err;
226 } else { /* last one */
227
228 if (!EVP_MAC_final(ctx, A1, &A1_len))
229 goto err;
230 memcpy(out, A1, olen);
231 break;
232 }
233 }
234 ret = 1;
235 err:
236 EVP_MAC_CTX_free(ctx);
237 EVP_MAC_CTX_free(ctx_tmp);
238 EVP_MAC_CTX_free(ctx_init);
239 OPENSSL_cleanse(A1, sizeof(A1));
240 return ret;
241 }
242
243 static int tls1_prf_alg(const EVP_MD *md,
244 const unsigned char *sec, size_t slen,
245 const unsigned char *seed, size_t seed_len,
246 unsigned char *out, size_t olen)
247 {
248 if (EVP_MD_type(md) == NID_md5_sha1) {
249 size_t i;
250 unsigned char *tmp;
251 if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1),
252 seed, seed_len, out, olen))
253 return 0;
254
255 if ((tmp = OPENSSL_malloc(olen)) == NULL) {
256 KDFerr(KDF_F_TLS1_PRF_ALG, ERR_R_MALLOC_FAILURE);
257 return 0;
258 }
259 if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
260 seed, seed_len, tmp, olen)) {
261 OPENSSL_clear_free(tmp, olen);
262 return 0;
263 }
264 for (i = 0; i < olen; i++)
265 out[i] ^= tmp[i];
266 OPENSSL_clear_free(tmp, olen);
267 return 1;
268 }
269 if (!tls1_prf_P_hash(md, sec, slen, seed, seed_len, out, olen))
270 return 0;
271
272 return 1;
273 }