fix check
[openssl.git] / crypto / kdf / tls1_prf.c
1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3  * 2016.
4  */
5 /* ====================================================================
6  * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <stdio.h>
60 #include "internal/cryptlib.h"
61 #include <openssl/kdf.h>
62 #include <openssl/evp.h>
63 #include "internal/evp_int.h"
64
65 static int tls1_prf_alg(const EVP_MD *md,
66                         const unsigned char *sec, size_t slen,
67                         const unsigned char *seed, size_t seed_len,
68                         unsigned char *out, size_t olen);
69
70 #define TLS1_PRF_MAXBUF 1024
71
72 /* TLS KDF pkey context structure */
73
74 typedef struct {
75     /* Digest to use for PRF */
76     const EVP_MD *md;
77     /* Secret value to use for PRF */
78     unsigned char *sec;
79     size_t seclen;
80     /* Buffer of concatenated seed data */
81     unsigned char seed[TLS1_PRF_MAXBUF];
82     size_t seedlen;
83 } TLS1_PRF_PKEY_CTX;
84
85 static int pkey_tls1_prf_init(EVP_PKEY_CTX *ctx)
86 {
87     TLS1_PRF_PKEY_CTX *kctx;
88
89     kctx = OPENSSL_zalloc(sizeof(*kctx));
90     if (kctx == NULL)
91         return 0;
92     ctx->data = kctx;
93
94     return 1;
95 }
96
97 static void pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx)
98 {
99     TLS1_PRF_PKEY_CTX *kctx = ctx->data;
100     OPENSSL_clear_free(kctx->sec, kctx->seclen);
101     OPENSSL_cleanse(kctx->seed, kctx->seedlen);
102     OPENSSL_free(kctx);
103 }
104
105 static int pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
106 {
107     TLS1_PRF_PKEY_CTX *kctx = ctx->data;
108     switch (type) {
109     case EVP_PKEY_CTRL_TLS_MD:
110         kctx->md = p2;
111         return 1;
112
113     case EVP_PKEY_CTRL_TLS_SECRET:
114         if (p1 < 0)
115             return 0;
116         if (kctx->sec != NULL)
117             OPENSSL_clear_free(kctx->sec, kctx->seclen);
118         OPENSSL_cleanse(kctx->seed, kctx->seedlen);
119         kctx->seedlen = 0;
120         kctx->sec = OPENSSL_memdup(p2, p1);
121         if (kctx->sec == NULL)
122             return 0;
123         kctx->seclen  = p1;
124         return 1;
125
126     case EVP_PKEY_CTRL_TLS_SEED:
127         if (p1 == 0 || p2 == NULL)
128             return 1;
129         if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen))
130             return 0;
131         memcpy(kctx->seed + kctx->seedlen, p2, p1);
132         kctx->seedlen += p1;
133         return 1;
134
135     default:
136         return -2;
137
138     }
139 }
140
141 static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx,
142                                   const char *type, const char *value)
143 {
144     if (value == NULL) {
145         KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
146         return 0;
147     }
148     if (strcmp(type, "md") == 0) {
149         TLS1_PRF_PKEY_CTX *kctx = ctx->data;
150
151         const EVP_MD *md = EVP_get_digestbyname(value);
152         if (md == NULL) {
153             KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_INVALID_DIGEST);
154             return 0;
155         }
156         kctx->md = md;
157         return 1;
158     }
159     if (strcmp(type, "secret") == 0)
160         return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
161     if (strcmp(type, "hexsecret") == 0)
162         return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
163     if (strcmp(type, "seed") == 0)
164         return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
165     if (strcmp(type, "hexseed") == 0)
166         return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
167     return -2;
168 }
169
170 static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
171                                 size_t *keylen)
172 {
173     TLS1_PRF_PKEY_CTX *kctx = ctx->data;
174     if (kctx->md == NULL || kctx->sec == NULL || kctx->seedlen == 0) {
175         KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_PARAMETER);
176         return 0;
177     }
178     return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen,
179                         kctx->seed, kctx->seedlen,
180                         key, *keylen);
181 }
182
183 const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
184     EVP_PKEY_TLS1_PRF,
185     0,
186     pkey_tls1_prf_init,
187     0,
188     pkey_tls1_prf_cleanup,
189
190     0, 0,
191     0, 0,
192
193     0,
194     0,
195
196     0,
197     0,
198
199     0, 0,
200
201     0, 0, 0, 0,
202
203     0, 0,
204
205     0, 0,
206
207     0,
208     pkey_tls1_prf_derive,
209     pkey_tls1_prf_ctrl,
210     pkey_tls1_prf_ctrl_str
211 };
212
213 static int tls1_prf_P_hash(const EVP_MD *md,
214                            const unsigned char *sec, size_t sec_len,
215                            const unsigned char *seed, size_t seed_len,
216                            unsigned char *out, size_t olen)
217 {
218     int chunk;
219     EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL;
220     EVP_PKEY *mac_key = NULL;
221     unsigned char A1[EVP_MAX_MD_SIZE];
222     size_t A1_len;
223     int ret = 0;
224
225     chunk = EVP_MD_size(md);
226     OPENSSL_assert(chunk >= 0);
227
228     ctx = EVP_MD_CTX_new();
229     ctx_tmp = EVP_MD_CTX_new();
230     ctx_init = EVP_MD_CTX_new();
231     if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL)
232         goto err;
233     EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
234     mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
235     if (mac_key == NULL)
236         goto err;
237     if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key))
238         goto err;
239     if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
240         goto err;
241     if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len))
242         goto err;
243     if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
244         goto err;
245
246     for (;;) {
247         /* Reinit mac contexts */
248         if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
249             goto err;
250         if (!EVP_DigestSignUpdate(ctx, A1, A1_len))
251             goto err;
252         if (olen > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx))
253             goto err;
254         if (seed && !EVP_DigestSignUpdate(ctx, seed, seed_len))
255             goto err;
256
257         if (olen > (size_t)chunk) {
258             size_t mac_len;
259             if (!EVP_DigestSignFinal(ctx, out, &mac_len))
260                 goto err;
261             out += mac_len;
262             olen -= mac_len;
263             /* calc the next A1 value */
264             if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len))
265                 goto err;
266         } else {                /* last one */
267
268             if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
269                 goto err;
270             memcpy(out, A1, olen);
271             break;
272         }
273     }
274     ret = 1;
275  err:
276     EVP_PKEY_free(mac_key);
277     EVP_MD_CTX_free(ctx);
278     EVP_MD_CTX_free(ctx_tmp);
279     EVP_MD_CTX_free(ctx_init);
280     OPENSSL_cleanse(A1, sizeof(A1));
281     return ret;
282 }
283
284 static int tls1_prf_alg(const EVP_MD *md,
285                         const unsigned char *sec, size_t slen,
286                         const unsigned char *seed, size_t seed_len,
287                         unsigned char *out, size_t olen)
288 {
289
290     if (EVP_MD_type(md) == NID_md5_sha1) {
291         size_t i;
292         unsigned char *tmp;
293         if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1),
294                          seed, seed_len, out, olen))
295             return 0;
296
297         tmp = OPENSSL_malloc(olen);
298         if (tmp == NULL)
299             return 0;
300         if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
301                          seed, seed_len, tmp, olen)) {
302             OPENSSL_clear_free(tmp, olen);
303             return 0;
304         }
305         for (i = 0; i < olen; i++)
306             out[i] ^= tmp[i];
307         OPENSSL_clear_free(tmp, olen);
308         return 1;
309     }
310     if (!tls1_prf_P_hash(md, sec, slen, seed, seed_len, out, olen))
311         return 0;
312
313     return 1;
314 }