Extend the EVP_PKEY KDF to KDF provider bridge to also support Scrypt
[openssl.git] / providers / implementations / exchange / kdf_exch.c
1 /*
2  * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (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 <openssl/crypto.h>
11 #include <openssl/kdf.h>
12 #include <openssl/core_dispatch.h>
13 #include <openssl/core_names.h>
14 #include <openssl/params.h>
15 #include "prov/implementations.h"
16 #include "prov/provider_ctx.h"
17 #include "prov/kdfexchange.h"
18
19 static OSSL_FUNC_keyexch_newctx_fn kdf_tls1_prf_newctx;
20 static OSSL_FUNC_keyexch_newctx_fn kdf_hkdf_newctx;
21 static OSSL_FUNC_keyexch_newctx_fn kdf_scrypt_newctx;
22 static OSSL_FUNC_keyexch_init_fn kdf_init;
23 static OSSL_FUNC_keyexch_derive_fn kdf_derive;
24 static OSSL_FUNC_keyexch_freectx_fn kdf_freectx;
25 static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx;
26 static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params;
27 static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params;
28 static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
29 static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_scrypt_settable_ctx_params;
30
31 typedef struct {
32     void *provctx;
33     EVP_KDF_CTX *kdfctx;
34     KDF_DATA *kdfdata;
35 } PROV_KDF_CTX;
36
37 #define KDF_NEWCTX(funcname, kdfname) \
38     static void *kdf_##funcname##_newctx(void *provctx) \
39     { \
40         PROV_KDF_CTX *kdfctx = OPENSSL_zalloc(sizeof(PROV_KDF_CTX)); \
41         EVP_KDF *kdf = NULL; \
42         \
43         if (kdfctx == NULL) \
44             return NULL; \
45         \
46         kdfctx->provctx = provctx; \
47         \
48         kdf = EVP_KDF_fetch(PROV_LIBRARY_CONTEXT_OF(provctx), kdfname, NULL); \
49         if (kdf == NULL) \
50             goto err; \
51         kdfctx->kdfctx = EVP_KDF_CTX_new(kdf); \
52         EVP_KDF_free(kdf); \
53         \
54         if (kdfctx->kdfctx == NULL) \
55             goto err; \
56         \
57         return kdfctx; \
58     err: \
59         OPENSSL_free(kdfctx); \
60         return NULL; \
61     }
62
63 KDF_NEWCTX(tls1_prf, "TLS1-PRF")
64 KDF_NEWCTX(hkdf, "HKDF")
65 KDF_NEWCTX(scrypt, "SCRYPT")
66
67 static int kdf_init(void *vpkdfctx, void *vkdf)
68 {
69     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
70
71     if (pkdfctx == NULL || vkdf == NULL || !kdf_data_up_ref(vkdf))
72         return 0;
73     pkdfctx->kdfdata = vkdf;
74
75     return 1;
76 }
77
78 static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen,
79                       size_t outlen)
80 {
81     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
82
83     return EVP_KDF_derive(pkdfctx->kdfctx, secret, *secretlen);
84 }
85
86 static void kdf_freectx(void *vpkdfctx)
87 {
88     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
89
90     EVP_KDF_CTX_free(pkdfctx->kdfctx);
91     kdf_data_free(pkdfctx->kdfdata);
92
93     OPENSSL_free(pkdfctx);
94 }
95
96 static void *kdf_dupctx(void *vpkdfctx)
97 {
98     PROV_KDF_CTX *srcctx = (PROV_KDF_CTX *)vpkdfctx;
99     PROV_KDF_CTX *dstctx;
100
101     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
102     if (dstctx == NULL)
103         return NULL;
104
105     *dstctx = *srcctx;
106
107     dstctx->kdfctx = EVP_KDF_CTX_dup(srcctx->kdfctx);
108     if (dstctx->kdfctx == NULL) {
109         OPENSSL_free(dstctx);
110         return NULL;
111     }
112     if (!kdf_data_up_ref(dstctx->kdfdata)) {
113         EVP_KDF_CTX_free(dstctx->kdfctx);
114         OPENSSL_free(dstctx);
115         return NULL;
116     }
117
118     return dstctx;
119 }
120
121 static int kdf_set_ctx_params(void *vpkdfctx, const OSSL_PARAM params[])
122 {
123     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
124
125     return EVP_KDF_CTX_set_params(pkdfctx->kdfctx, params);
126 }
127
128 #define KDF_SETTABLE_CTX_PARAMS(funcname, kdfname) \
129     static const OSSL_PARAM *kdf_##funcname##_settable_ctx_params(void) \
130     { \
131         /* \
132         * TODO(3.0): FIXME FIXME!! These settable_ctx_params functions should \
133         * should have a provctx argument so we can get hold of the libctx. \
134         */ \
135         EVP_KDF *kdf = EVP_KDF_fetch(NULL, kdfname, NULL); \
136         const OSSL_PARAM *params; \
137         \
138         if (kdf == NULL) \
139             return NULL; \
140         \
141         params = EVP_KDF_settable_ctx_params(kdf); \
142         EVP_KDF_free(kdf); \
143         \
144         return params; \
145     }
146
147 KDF_SETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF")
148 KDF_SETTABLE_CTX_PARAMS(hkdf, "HKDF")
149 KDF_SETTABLE_CTX_PARAMS(scrypt, "SCRYPT")
150
151
152 #define KDF_KEYEXCH_FUNCTIONS(funcname) \
153     const OSSL_DISPATCH kdf_##funcname##_keyexch_functions[] = { \
154         { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))kdf_##funcname##_newctx }, \
155         { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))kdf_init }, \
156         { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))kdf_derive }, \
157         { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))kdf_freectx }, \
158         { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))kdf_dupctx }, \
159         { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))kdf_set_ctx_params }, \
160         { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, \
161         (void (*)(void))kdf_##funcname##_settable_ctx_params }, \
162         { 0, NULL } \
163     };
164
165 KDF_KEYEXCH_FUNCTIONS(tls1_prf)
166 KDF_KEYEXCH_FUNCTIONS(hkdf)
167 KDF_KEYEXCH_FUNCTIONS(scrypt)