]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/kdf/tls1_prf.c
Added differentiation between missing secret and missing seed
[thirdparty/openssl.git] / crypto / kdf / tls1_prf.c
1 /*
2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
3 *
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
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
16 static 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
25 typedef 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
36 static 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
48 static 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
56 static 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
92 static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx,
93 const char *type, const char *value)
94 {
95 if (value == NULL) {
96 KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
97 return 0;
98 }
99 if (strcmp(type, "md") == 0) {
100 TLS1_PRF_PKEY_CTX *kctx = ctx->data;
101
102 const EVP_MD *md = EVP_get_digestbyname(value);
103 if (md == NULL) {
104 KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_INVALID_DIGEST);
105 return 0;
106 }
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);
118
119 KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
120 return -2;
121 }
122
123 static 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;
127 if (kctx->md == NULL) {
128 KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
129 return 0;
130 }
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) {
136 KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
137 return 0;
138 }
139 return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen,
140 kctx->seed, kctx->seedlen,
141 key, *keylen);
142 }
143
144 const 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,
171 pkey_tls1_prf_ctrl_str
172 };
173
174 static 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);
187 OPENSSL_assert(chunk >= 0);
188
189 ctx = EVP_MD_CTX_new();
190 ctx_tmp = EVP_MD_CTX_new();
191 ctx_init = EVP_MD_CTX_new();
192 if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL)
193 goto err;
194 EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
195 mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
196 if (mac_key == NULL)
197 goto err;
198 if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key))
199 goto err;
200 if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
201 goto err;
202 if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len))
203 goto err;
204 if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
205 goto err;
206
207 for (;;) {
208 /* Reinit mac contexts */
209 if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
210 goto err;
211 if (!EVP_DigestSignUpdate(ctx, A1, A1_len))
212 goto err;
213 if (olen > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx))
214 goto err;
215 if (seed && !EVP_DigestSignUpdate(ctx, seed, seed_len))
216 goto err;
217
218 if (olen > (size_t)chunk) {
219 size_t mac_len;
220 if (!EVP_DigestSignFinal(ctx, out, &mac_len))
221 goto err;
222 out += mac_len;
223 olen -= mac_len;
224 /* calc the next A1 value */
225 if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len))
226 goto err;
227 } else { /* last one */
228
229 if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
230 goto err;
231 memcpy(out, A1, olen);
232 break;
233 }
234 }
235 ret = 1;
236 err:
237 EVP_PKEY_free(mac_key);
238 EVP_MD_CTX_free(ctx);
239 EVP_MD_CTX_free(ctx_tmp);
240 EVP_MD_CTX_free(ctx_init);
241 OPENSSL_cleanse(A1, sizeof(A1));
242 return ret;
243 }
244
245 static int tls1_prf_alg(const EVP_MD *md,
246 const unsigned char *sec, size_t slen,
247 const unsigned char *seed, size_t seed_len,
248 unsigned char *out, size_t olen)
249 {
250
251 if (EVP_MD_type(md) == NID_md5_sha1) {
252 size_t i;
253 unsigned char *tmp;
254 if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1),
255 seed, seed_len, out, olen))
256 return 0;
257
258 tmp = OPENSSL_malloc(olen);
259 if (tmp == NULL)
260 return 0;
261 if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
262 seed, seed_len, tmp, olen)) {
263 OPENSSL_clear_free(tmp, olen);
264 return 0;
265 }
266 for (i = 0; i < olen; i++)
267 out[i] ^= tmp[i];
268 OPENSSL_clear_free(tmp, olen);
269 return 1;
270 }
271 if (!tls1_prf_P_hash(md, sec, slen, seed, seed_len, out, olen))
272 return 0;
273
274 return 1;
275 }