ce8425d4d4fb7dcbde14fa4353dd813680144409
[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     if (!ossl_assert(chunk >= 0))
188         goto err;
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
246 static 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 }