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