ddb682c1eddce34ca8f31d93bdad907675d4bea5
[openssl.git] / crypto / evp / pkey_kdf.c
1 /*
2  * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright (c) 2018, Oracle and/or its affiliates.  All rights reserved.
4  *
5  * Licensed under the Apache License 2.0 (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10
11 #include <string.h>
12 #include <openssl/evp.h>
13 #include <openssl/err.h>
14 #include <openssl/kdf.h>
15 #include "internal/evp_int.h"
16
17 static int pkey_kdf_init(EVP_PKEY_CTX *ctx)
18 {
19     EVP_KDF_CTX *kctx;
20
21     kctx = EVP_KDF_CTX_new_id(ctx->pmeth->pkey_id);
22     if (kctx == NULL)
23         return 0;
24
25     ctx->data = kctx;
26     return 1;
27 }
28
29 static void pkey_kdf_cleanup(EVP_PKEY_CTX *ctx)
30 {
31     EVP_KDF_CTX *kctx = ctx->data;
32
33     EVP_KDF_CTX_free(kctx);
34 }
35
36 static int pkey_kdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
37 {
38     EVP_KDF_CTX *kctx = ctx->data;
39     uint64_t u64_value;
40     int cmd;
41     int ret;
42
43     switch (type) {
44     case EVP_PKEY_CTRL_PASS:
45         cmd = EVP_KDF_CTRL_SET_PASS;
46         break;
47     case EVP_PKEY_CTRL_HKDF_SALT:
48     case EVP_PKEY_CTRL_SCRYPT_SALT:
49         cmd = EVP_KDF_CTRL_SET_SALT;
50         break;
51     case EVP_PKEY_CTRL_TLS_MD:
52     case EVP_PKEY_CTRL_HKDF_MD:
53         cmd = EVP_KDF_CTRL_SET_MD;
54         break;
55     case EVP_PKEY_CTRL_TLS_SECRET:
56         cmd = EVP_KDF_CTRL_SET_TLS_SECRET;
57         ret = EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_RESET_TLS_SEED);
58         if (ret < 1)
59             return ret;
60         break;
61     case EVP_PKEY_CTRL_TLS_SEED:
62         cmd = EVP_KDF_CTRL_ADD_TLS_SEED;
63         break;
64     case EVP_PKEY_CTRL_HKDF_KEY:
65         cmd = EVP_KDF_CTRL_SET_KEY;
66         break;
67     case EVP_PKEY_CTRL_HKDF_INFO:
68         cmd = EVP_KDF_CTRL_ADD_HKDF_INFO;
69         break;
70     case EVP_PKEY_CTRL_HKDF_MODE:
71         cmd = EVP_KDF_CTRL_SET_HKDF_MODE;
72         break;
73     case EVP_PKEY_CTRL_SCRYPT_N:
74         cmd = EVP_KDF_CTRL_SET_SCRYPT_N;
75         break;
76     case EVP_PKEY_CTRL_SCRYPT_R:
77         cmd = EVP_KDF_CTRL_SET_SCRYPT_R;
78         break;
79     case EVP_PKEY_CTRL_SCRYPT_P:
80         cmd = EVP_KDF_CTRL_SET_SCRYPT_P;
81         break;
82     case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
83         cmd = EVP_KDF_CTRL_SET_MAXMEM_BYTES;
84         break;
85     default:
86         return -2;
87     }
88
89     switch (cmd) {
90     case EVP_KDF_CTRL_SET_PASS:
91     case EVP_KDF_CTRL_SET_SALT:
92     case EVP_KDF_CTRL_SET_KEY:
93     case EVP_KDF_CTRL_SET_TLS_SECRET:
94     case EVP_KDF_CTRL_ADD_TLS_SEED:
95     case EVP_KDF_CTRL_ADD_HKDF_INFO:
96         return EVP_KDF_ctrl(kctx, cmd, (const unsigned char *)p2, (size_t)p1);
97
98     case EVP_KDF_CTRL_SET_MD:
99         return EVP_KDF_ctrl(kctx, cmd, (const EVP_MD *)p2);
100
101     case EVP_KDF_CTRL_SET_HKDF_MODE:
102         return EVP_KDF_ctrl(kctx, cmd, (int)p1);
103
104     case EVP_KDF_CTRL_SET_SCRYPT_R:
105     case EVP_KDF_CTRL_SET_SCRYPT_P:
106         u64_value = *(uint64_t *)p2;
107         if (u64_value > UINT32_MAX) {
108             EVPerr(EVP_F_PKEY_KDF_CTRL, EVP_R_PARAMETER_TOO_LARGE);
109             return 0;
110         }
111
112         return EVP_KDF_ctrl(kctx, cmd, (uint32_t)u64_value);
113
114     case EVP_KDF_CTRL_SET_SCRYPT_N:
115     case EVP_KDF_CTRL_SET_MAXMEM_BYTES:
116         return EVP_KDF_ctrl(kctx, cmd, *(uint64_t *)p2);
117
118     default:
119         return 0;
120     }
121 }
122
123 static int pkey_kdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
124                              const char *value)
125 {
126     EVP_KDF_CTX *kctx = ctx->data;
127
128     if (strcmp(type, "md") == 0)
129         return EVP_KDF_ctrl_str(kctx, "digest", value);
130     return EVP_KDF_ctrl_str(kctx, type, value);
131 }
132
133 static int pkey_kdf_derive_init(EVP_PKEY_CTX *ctx)
134 {
135     EVP_KDF_CTX *kctx = ctx->data;
136
137     EVP_KDF_reset(kctx);
138     return 1;
139 }
140
141 /*
142  * For fixed-output algorithms the keylen parameter is an "out" parameter
143  * otherwise it is an "in" parameter.
144  */
145 static int pkey_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
146                            size_t *keylen)
147 {
148     EVP_KDF_CTX *kctx = ctx->data;
149     size_t outlen = EVP_KDF_size(kctx);
150
151     if (outlen == 0 || outlen == SIZE_MAX) {
152         /* Variable-output algorithm */
153         if (key == NULL)
154             return 0;
155     } else {
156         /* Fixed-output algorithm */
157         *keylen = outlen;
158         if (key == NULL)
159             return 1;
160     }
161     return EVP_KDF_derive(kctx, key, *keylen);
162 }
163
164 #ifndef OPENSSL_NO_SCRYPT
165 const EVP_PKEY_METHOD scrypt_pkey_meth = {
166     EVP_PKEY_SCRYPT,
167     0,
168     pkey_kdf_init,
169     0,
170     pkey_kdf_cleanup,
171
172     0, 0,
173     0, 0,
174
175     0,
176     0,
177
178     0,
179     0,
180
181     0, 0,
182
183     0, 0, 0, 0,
184
185     0, 0,
186
187     0, 0,
188
189     pkey_kdf_derive_init,
190     pkey_kdf_derive,
191     pkey_kdf_ctrl,
192     pkey_kdf_ctrl_str
193 };
194 #endif
195
196 const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
197     EVP_PKEY_TLS1_PRF,
198     0,
199     pkey_kdf_init,
200     0,
201     pkey_kdf_cleanup,
202
203     0, 0,
204     0, 0,
205
206     0,
207     0,
208
209     0,
210     0,
211
212     0, 0,
213
214     0, 0, 0, 0,
215
216     0, 0,
217
218     0, 0,
219
220     pkey_kdf_derive_init,
221     pkey_kdf_derive,
222     pkey_kdf_ctrl,
223     pkey_kdf_ctrl_str
224 };
225
226 const EVP_PKEY_METHOD hkdf_pkey_meth = {
227     EVP_PKEY_HKDF,
228     0,
229     pkey_kdf_init,
230     0,
231     pkey_kdf_cleanup,
232
233     0, 0,
234     0, 0,
235
236     0,
237     0,
238
239     0,
240     0,
241
242     0, 0,
243
244     0, 0, 0, 0,
245
246     0, 0,
247
248     0, 0,
249
250     pkey_kdf_derive_init,
251     pkey_kdf_derive,
252     pkey_kdf_ctrl,
253     pkey_kdf_ctrl_str
254 };
255