fix check
[openssl.git] / crypto / kdf / hkdf.c
1 /* ====================================================================
2  * Copyright (c) 2016 The OpenSSL Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the OpenSSL Project
19  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    openssl-core@openssl.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  *    nor may "OpenSSL" appear in their names without prior written
28  *    permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the OpenSSL Project
33  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  */
48
49 #include <stdlib.h>
50 #include <string.h>
51 #include <openssl/hmac.h>
52 #include <openssl/kdf.h>
53 #include <openssl/evp.h>
54 #include "internal/cryptlib.h"
55 #include "internal/evp_int.h"
56
57 #define HKDF_MAXBUF 1024
58
59 static unsigned char *HKDF(const EVP_MD *evp_md,
60                            const unsigned char *salt, size_t salt_len,
61                            const unsigned char *key, size_t key_len,
62                            const unsigned char *info, size_t info_len,
63                            unsigned char *okm, size_t okm_len);
64
65 static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
66                                    const unsigned char *salt, size_t salt_len,
67                                    const unsigned char *key, size_t key_len,
68                                    unsigned char *prk, size_t *prk_len);
69
70 static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
71                                   const unsigned char *prk, size_t prk_len,
72                                   const unsigned char *info, size_t info_len,
73                                   unsigned char *okm, size_t okm_len);
74
75 typedef struct {
76     const EVP_MD *md;
77     unsigned char *salt;
78     size_t salt_len;
79     unsigned char *key;
80     size_t key_len;
81     unsigned char info[HKDF_MAXBUF];
82     size_t info_len;
83 } HKDF_PKEY_CTX;
84
85 static int pkey_hkdf_init(EVP_PKEY_CTX *ctx)
86 {
87     HKDF_PKEY_CTX *kctx;
88
89     kctx = OPENSSL_zalloc(sizeof(*kctx));
90     if (kctx == NULL)
91         return 0;
92
93     ctx->data = kctx;
94
95     return 1;
96 }
97
98 static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx)
99 {
100     HKDF_PKEY_CTX *kctx = ctx->data;
101     OPENSSL_clear_free(kctx->salt, kctx->salt_len);
102     OPENSSL_clear_free(kctx->key, kctx->key_len);
103     OPENSSL_cleanse(kctx->info, kctx->info_len);
104     OPENSSL_free(kctx);
105 }
106
107 static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
108 {
109     HKDF_PKEY_CTX *kctx = ctx->data;
110
111     switch (type) {
112     case EVP_PKEY_CTRL_HKDF_MD:
113         if (p2 == NULL)
114             return 0;
115
116         kctx->md = p2;
117         return 1;
118
119     case EVP_PKEY_CTRL_HKDF_SALT:
120         if (p1 == 0 || p2 == NULL)
121             return 1;
122
123         if (p1 < 0)
124             return 0;
125
126         if (kctx->salt != NULL)
127             OPENSSL_clear_free(kctx->salt, kctx->salt_len);
128
129         kctx->salt = OPENSSL_memdup(p2, p1);
130         if (kctx->salt == NULL)
131             return 0;
132
133         kctx->salt_len = p1;
134         return 1;
135
136     case EVP_PKEY_CTRL_HKDF_KEY:
137         if (p1 < 0)
138             return 0;
139
140         if (kctx->key != NULL)
141             OPENSSL_clear_free(kctx->key, kctx->key_len);
142
143         kctx->key = OPENSSL_memdup(p2, p1);
144         if (kctx->key == NULL)
145             return 0;
146
147         kctx->key_len  = p1;
148         return 1;
149
150     case EVP_PKEY_CTRL_HKDF_INFO:
151         if (p1 == 0 || p2 == NULL)
152             return 1;
153
154         if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
155             return 0;
156
157         memcpy(kctx->info + kctx->info_len, p2, p1);
158         kctx->info_len += p1;
159         return 1;
160
161     default:
162         return -2;
163
164     }
165 }
166
167 static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
168                               const char *value)
169 {
170     if (strcmp(type, "md") == 0)
171         return EVP_PKEY_CTX_set_hkdf_md(ctx, EVP_get_digestbyname(value));
172
173     if (strcmp(type, "salt") == 0)
174         return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
175
176     if (strcmp(type, "hexsalt") == 0)
177         return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
178
179     if (strcmp(type, "key") == 0)
180         return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
181
182     if (strcmp(type, "hexkey") == 0)
183         return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
184
185     if (strcmp(type, "info") == 0)
186         return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
187
188     if (strcmp(type, "hexinfo") == 0)
189         return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
190
191     return -2;
192 }
193
194 static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
195                             size_t *keylen)
196 {
197     HKDF_PKEY_CTX *kctx = ctx->data;
198
199     if (kctx->md == NULL || kctx->key == NULL)
200         return 0;
201
202     if (HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key, kctx->key_len,
203              kctx->info, kctx->info_len, key, *keylen) == NULL)
204     {
205         return 0;
206     }
207
208     return 1;
209 }
210
211 const EVP_PKEY_METHOD hkdf_pkey_meth = {
212     EVP_PKEY_HKDF,
213     0,
214     pkey_hkdf_init,
215     0,
216     pkey_hkdf_cleanup,
217
218     0, 0,
219     0, 0,
220
221     0,
222     0,
223
224     0,
225     0,
226
227     0, 0,
228
229     0, 0, 0, 0,
230
231     0, 0,
232
233     0, 0,
234
235     0,
236     pkey_hkdf_derive,
237     pkey_hkdf_ctrl,
238     pkey_hkdf_ctrl_str
239 };
240
241 static unsigned char *HKDF(const EVP_MD *evp_md,
242                            const unsigned char *salt, size_t salt_len,
243                            const unsigned char *key, size_t key_len,
244                            const unsigned char *info, size_t info_len,
245                            unsigned char *okm, size_t okm_len)
246 {
247     unsigned char prk[EVP_MAX_MD_SIZE];
248     size_t prk_len;
249
250     if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
251         return NULL;
252
253     return HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
254 }
255
256 static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
257                                    const unsigned char *salt, size_t salt_len,
258                                    const unsigned char *key, size_t key_len,
259                                    unsigned char *prk, size_t *prk_len)
260 {
261     unsigned int tmp_len;
262
263     if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
264         return NULL;
265
266     *prk_len = tmp_len;
267     return prk;
268 }
269
270 static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
271                                   const unsigned char *prk, size_t prk_len,
272                                   const unsigned char *info, size_t info_len,
273                                   unsigned char *okm, size_t okm_len)
274 {
275     HMAC_CTX *hmac;
276
277     unsigned int i;
278
279     unsigned char prev[EVP_MAX_MD_SIZE];
280
281     size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
282
283     size_t n = okm_len / dig_len;
284     if (okm_len % dig_len)
285         n++;
286
287     if (n > 255)
288         return NULL;
289
290     if ((hmac = HMAC_CTX_new()) == NULL)
291         return NULL;
292
293     if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
294         goto err;
295
296     for (i = 1; i <= n; i++) {
297         size_t copy_len;
298         const unsigned char ctr = i;
299
300         if (i > 1) {
301             if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
302                 goto err;
303
304             if (!HMAC_Update(hmac, prev, dig_len))
305                 goto err;
306         }
307
308         if (!HMAC_Update(hmac, info, info_len))
309             goto err;
310
311         if (!HMAC_Update(hmac, &ctr, 1))
312             goto err;
313
314         if (!HMAC_Final(hmac, prev, NULL))
315             goto err;
316
317         copy_len = (done_len + dig_len > okm_len) ?
318                        okm_len - done_len :
319                        dig_len;
320
321         memcpy(okm + done_len, prev, copy_len);
322
323         done_len += copy_len;
324     }
325
326     HMAC_CTX_free(hmac);
327     return okm;
328
329  err:
330     HMAC_CTX_free(hmac);
331     return NULL;
332 }