Implement a EVP_PKEY KDF to KDF provider bridge
[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_newctx;
20 static OSSL_FUNC_keyexch_init_fn kdf_init;
21 static OSSL_FUNC_keyexch_derive_fn kdf_derive;
22 static OSSL_FUNC_keyexch_freectx_fn kdf_freectx;
23 static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx;
24 static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params;
25 static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_settable_ctx_params;
26
27 typedef struct {
28     void *provctx;
29     EVP_KDF_CTX *kdfctx;
30     KDF_DATA *kdfdata;
31 } PROV_KDF_CTX;
32
33 static void *kdf_newctx(void *provctx)
34 {
35     PROV_KDF_CTX *kdfctx = OPENSSL_zalloc(sizeof(PROV_KDF_CTX));
36     EVP_KDF *kdf = NULL;
37
38     if (kdfctx == NULL)
39         return NULL;
40
41     kdfctx->provctx = provctx;
42
43     kdf = EVP_KDF_fetch(PROV_LIBRARY_CONTEXT_OF(provctx), "TLS1-PRF", NULL);
44     if (kdf == NULL)
45         goto err;
46     kdfctx->kdfctx = EVP_KDF_new_ctx(kdf);
47     EVP_KDF_free(kdf);
48
49     if (kdfctx->kdfctx == NULL)
50         goto err;
51
52     return kdfctx;
53  err:
54     OPENSSL_free(kdfctx);
55     return NULL;
56 }
57
58 static int kdf_init(void *vpkdfctx, void *vkdf)
59 {
60     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
61
62     if (pkdfctx == NULL || vkdf == NULL || !kdf_data_up_ref(vkdf))
63         return 0;
64     pkdfctx->kdfdata = vkdf;
65
66     return 1;
67 }
68
69 static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen,
70                       size_t outlen)
71 {
72     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
73
74     return EVP_KDF_derive(pkdfctx->kdfctx, secret, *secretlen);
75 }
76
77 static void kdf_freectx(void *vpkdfctx)
78 {
79     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
80
81     EVP_KDF_CTX_free(pkdfctx->kdfctx);
82     kdf_data_free(pkdfctx->kdfdata);
83
84     OPENSSL_free(pkdfctx);
85 }
86
87 static void *kdf_dupctx(void *vpkdfctx)
88 {
89     PROV_KDF_CTX *srcctx = (PROV_KDF_CTX *)vpkdfctx;
90     PROV_KDF_CTX *dstctx;
91
92     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
93     if (dstctx == NULL)
94         return NULL;
95
96     *dstctx = *srcctx;
97
98     dstctx->kdfctx = EVP_KDF_dup_ctx(srcctx->kdfctx);
99     if (dstctx->kdfctx == NULL) {
100         OPENSSL_free(dstctx);
101         return NULL;
102     }
103     if (!kdf_data_up_ref(dstctx->kdfdata)) {
104         EVP_KDF_CTX_free(dstctx->kdfctx);
105         OPENSSL_free(dstctx);
106         return NULL;
107     }
108
109     return dstctx;
110 }
111
112 static int kdf_set_ctx_params(void *vpkdfctx, const OSSL_PARAM params[])
113 {
114     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
115
116     return EVP_KDF_set_ctx_params(pkdfctx->kdfctx, params);
117 }
118
119
120 static const OSSL_PARAM *kdf_settable_ctx_params(void)
121 {
122     /*
123      * TODO(3.0): FIXME FIXME!! These settable_ctx_params functions should
124      * should have a provctx argument so we can get hold of the libctx.
125      */
126     EVP_KDF *kdf = EVP_KDF_fetch(NULL, "TLS1-PRF", NULL);
127     const OSSL_PARAM *params;
128
129     if (kdf == NULL)
130         return NULL;
131
132     params = EVP_KDF_settable_ctx_params(kdf);
133     EVP_KDF_free(kdf);
134
135     return params;
136 }
137
138 const OSSL_DISPATCH kdf_keyexch_functions[] = {
139     { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))kdf_newctx },
140     { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))kdf_init },
141     { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))kdf_derive },
142     { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))kdf_freectx },
143     { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))kdf_dupctx },
144     { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))kdf_set_ctx_params },
145     { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
146       (void (*)(void))kdf_settable_ctx_params },
147     { 0, NULL }
148 };