]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/kdf/tls1_prf.c
Don't auto-instantiate a DRBG when trying to use it and it's not
[thirdparty/openssl.git] / crypto / kdf / tls1_prf.c
CommitLineData
1eff3485 1/*
d2e9e320 2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
1eff3485 3 *
d2e9e320
RS
4 * Licensed under the OpenSSL license (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
1eff3485
DSH
8 */
9
10#include <stdio.h>
11#include "internal/cryptlib.h"
12#include <openssl/kdf.h>
13#include <openssl/evp.h>
14#include "internal/evp_int.h"
15
16static int tls1_prf_alg(const EVP_MD *md,
17 const unsigned char *sec, size_t slen,
18 const unsigned char *seed, size_t seed_len,
19 unsigned char *out, size_t olen);
20
21#define TLS1_PRF_MAXBUF 1024
22
23/* TLS KDF pkey context structure */
24
25typedef struct {
26 /* Digest to use for PRF */
27 const EVP_MD *md;
28 /* Secret value to use for PRF */
29 unsigned char *sec;
30 size_t seclen;
31 /* Buffer of concatenated seed data */
32 unsigned char seed[TLS1_PRF_MAXBUF];
33 size_t seedlen;
34} TLS1_PRF_PKEY_CTX;
35
36static int pkey_tls1_prf_init(EVP_PKEY_CTX *ctx)
37{
38 TLS1_PRF_PKEY_CTX *kctx;
39
40 kctx = OPENSSL_zalloc(sizeof(*kctx));
41 if (kctx == NULL)
42 return 0;
43 ctx->data = kctx;
44
45 return 1;
46}
47
48static void pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx)
49{
50 TLS1_PRF_PKEY_CTX *kctx = ctx->data;
51 OPENSSL_clear_free(kctx->sec, kctx->seclen);
52 OPENSSL_cleanse(kctx->seed, kctx->seedlen);
53 OPENSSL_free(kctx);
54}
55
56static int pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
57{
58 TLS1_PRF_PKEY_CTX *kctx = ctx->data;
59 switch (type) {
60 case EVP_PKEY_CTRL_TLS_MD:
61 kctx->md = p2;
62 return 1;
63
64 case EVP_PKEY_CTRL_TLS_SECRET:
65 if (p1 < 0)
66 return 0;
67 if (kctx->sec != NULL)
68 OPENSSL_clear_free(kctx->sec, kctx->seclen);
69 OPENSSL_cleanse(kctx->seed, kctx->seedlen);
70 kctx->seedlen = 0;
71 kctx->sec = OPENSSL_memdup(p2, p1);
72 if (kctx->sec == NULL)
73 return 0;
74 kctx->seclen = p1;
75 return 1;
76
77 case EVP_PKEY_CTRL_TLS_SEED:
78 if (p1 == 0 || p2 == NULL)
79 return 1;
80 if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen))
81 return 0;
82 memcpy(kctx->seed + kctx->seedlen, p2, p1);
83 kctx->seedlen += p1;
84 return 1;
85
86 default:
87 return -2;
88
89 }
90}
91
4e8cb45c
DSH
92static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx,
93 const char *type, const char *value)
94{
3e30fa0a
DSH
95 if (value == NULL) {
96 KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
4e8cb45c 97 return 0;
3e30fa0a 98 }
4e8cb45c
DSH
99 if (strcmp(type, "md") == 0) {
100 TLS1_PRF_PKEY_CTX *kctx = ctx->data;
101
102 const EVP_MD *md = EVP_get_digestbyname(value);
3e30fa0a
DSH
103 if (md == NULL) {
104 KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_INVALID_DIGEST);
4e8cb45c 105 return 0;
3e30fa0a 106 }
4e8cb45c
DSH
107 kctx->md = md;
108 return 1;
109 }
110 if (strcmp(type, "secret") == 0)
111 return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
112 if (strcmp(type, "hexsecret") == 0)
113 return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
114 if (strcmp(type, "seed") == 0)
115 return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
116 if (strcmp(type, "hexseed") == 0)
117 return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
a24a5b8c
JB
118
119 KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
4e8cb45c
DSH
120 return -2;
121}
122
1eff3485
DSH
123static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
124 size_t *keylen)
125{
126 TLS1_PRF_PKEY_CTX *kctx = ctx->data;
f55129c7
JB
127 if (kctx->md == NULL) {
128 KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
129 return 0;
130 }
5b277519
JB
131 if (kctx->sec == NULL) {
132 KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET);
133 return 0;
134 }
135 if (kctx->seedlen == 0) {
f55129c7 136 KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
1eff3485 137 return 0;
3e30fa0a 138 }
1eff3485
DSH
139 return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen,
140 kctx->seed, kctx->seedlen,
141 key, *keylen);
142}
143
144const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
145 EVP_PKEY_TLS1_PRF,
146 0,
147 pkey_tls1_prf_init,
148 0,
149 pkey_tls1_prf_cleanup,
150
151 0, 0,
152 0, 0,
153
154 0,
155 0,
156
157 0,
158 0,
159
160 0, 0,
161
162 0, 0, 0, 0,
163
164 0, 0,
165
166 0, 0,
167
168 0,
169 pkey_tls1_prf_derive,
170 pkey_tls1_prf_ctrl,
4e8cb45c 171 pkey_tls1_prf_ctrl_str
1eff3485
DSH
172};
173
174static int tls1_prf_P_hash(const EVP_MD *md,
175 const unsigned char *sec, size_t sec_len,
176 const unsigned char *seed, size_t seed_len,
177 unsigned char *out, size_t olen)
178{
179 int chunk;
180 EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL;
181 EVP_PKEY *mac_key = NULL;
182 unsigned char A1[EVP_MAX_MD_SIZE];
183 size_t A1_len;
184 int ret = 0;
185
186 chunk = EVP_MD_size(md);
88809830 187 if (!ossl_assert(chunk > 0))
7d248ee0 188 goto err;
1eff3485
DSH
189
190 ctx = EVP_MD_CTX_new();
191 ctx_tmp = EVP_MD_CTX_new();
192 ctx_init = EVP_MD_CTX_new();
193 if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL)
194 goto err;
195 EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
196 mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
197 if (mac_key == NULL)
198 goto err;
199 if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key))
200 goto err;
201 if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
202 goto err;
203 if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len))
204 goto err;
205 if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
206 goto err;
207
208 for (;;) {
209 /* Reinit mac contexts */
210 if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
211 goto err;
212 if (!EVP_DigestSignUpdate(ctx, A1, A1_len))
213 goto err;
214 if (olen > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx))
215 goto err;
216 if (seed && !EVP_DigestSignUpdate(ctx, seed, seed_len))
217 goto err;
218
219 if (olen > (size_t)chunk) {
220 size_t mac_len;
221 if (!EVP_DigestSignFinal(ctx, out, &mac_len))
222 goto err;
223 out += mac_len;
224 olen -= mac_len;
225 /* calc the next A1 value */
226 if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len))
227 goto err;
228 } else { /* last one */
229
230 if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
231 goto err;
232 memcpy(out, A1, olen);
233 break;
234 }
235 }
236 ret = 1;
237 err:
238 EVP_PKEY_free(mac_key);
239 EVP_MD_CTX_free(ctx);
240 EVP_MD_CTX_free(ctx_tmp);
241 EVP_MD_CTX_free(ctx_init);
242 OPENSSL_cleanse(A1, sizeof(A1));
243 return ret;
244}
245
246static int tls1_prf_alg(const EVP_MD *md,
247 const unsigned char *sec, size_t slen,
248 const unsigned char *seed, size_t seed_len,
249 unsigned char *out, size_t olen)
250{
251
252 if (EVP_MD_type(md) == NID_md5_sha1) {
253 size_t i;
254 unsigned char *tmp;
255 if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1),
256 seed, seed_len, out, olen))
257 return 0;
258
259 tmp = OPENSSL_malloc(olen);
260 if (tmp == NULL)
261 return 0;
262 if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
263 seed, seed_len, tmp, olen)) {
264 OPENSSL_clear_free(tmp, olen);
265 return 0;
266 }
267 for (i = 0; i < olen; i++)
268 out[i] ^= tmp[i];
269 OPENSSL_clear_free(tmp, olen);
270 return 1;
271 }
272 if (!tls1_prf_P_hash(md, sec, slen, seed, seed_len, out, olen))
273 return 0;
274
275 return 1;
276}