1 /*
2  * Copyright 2024 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/core_dispatch.h>
11 #include <openssl/core_names.h>
12 #include <openssl/params.h>
13 #include <openssl/err.h>
14 #include <openssl/proverr.h>
15 #include <openssl/evp.h>
16 #include <openssl/rand.h>
17 #include <openssl/self_test.h>
18 #include "internal/param_build_set.h"
19 #include <openssl/param_build.h>
20 #include "prov/implementations.h"
21 #include "prov/providercommon.h"
22 #include "prov/provider_ctx.h"
23 #include "prov/securitycheck.h"
24 
25 extern const OSSL_DISPATCH ossl_template_keymgmt_functions[];
26 
27 #define BUFSIZE 1000
28 #if defined(NDEBUG) || defined(OPENSSL_NO_STDIO)
debug_print(char * fmt,...)29 static void debug_print(char *fmt, ...)
30 {
31 }
32 #else
debug_print(char * fmt,...)33 static void debug_print(char *fmt, ...)
34 {
35     char out[BUFSIZE];
36     va_list argptr;
37 
38     va_start(argptr, fmt);
39     vsnprintf(out, BUFSIZE, fmt, argptr);
40     va_end(argptr);
41     if (getenv("TEMPLATEKM"))
42         fprintf(stderr, "TEMPLATE_KM: %s", out);
43 }
44 #endif
45 
46 static OSSL_FUNC_keymgmt_new_fn template_new;
47 static OSSL_FUNC_keymgmt_free_fn template_free;
48 static OSSL_FUNC_keymgmt_gen_init_fn template_gen_init;
49 static OSSL_FUNC_keymgmt_gen_fn template_gen;
50 static OSSL_FUNC_keymgmt_gen_cleanup_fn template_gen_cleanup;
51 static OSSL_FUNC_keymgmt_gen_set_params_fn template_gen_set_params;
52 static OSSL_FUNC_keymgmt_gen_settable_params_fn template_gen_settable_params;
53 static OSSL_FUNC_keymgmt_get_params_fn template_get_params;
54 static OSSL_FUNC_keymgmt_gettable_params_fn template_gettable_params;
55 static OSSL_FUNC_keymgmt_set_params_fn template_set_params;
56 static OSSL_FUNC_keymgmt_settable_params_fn template_settable_params;
57 static OSSL_FUNC_keymgmt_has_fn template_has;
58 static OSSL_FUNC_keymgmt_match_fn template_match;
59 static OSSL_FUNC_keymgmt_import_fn template_import;
60 static OSSL_FUNC_keymgmt_export_fn template_export;
61 static OSSL_FUNC_keymgmt_import_types_fn template_imexport_types;
62 static OSSL_FUNC_keymgmt_export_types_fn template_imexport_types;
63 
64 static OSSL_FUNC_keymgmt_dup_fn template_dup;
65 
66 struct template_gen_ctx {
67     void *provctx;
68     int selection;
69 };
70 
template_new(void * provctx)71 static void *template_new(void *provctx)
72 {
73     void *key = NULL;
74 
75     debug_print("new key req\n");
76     if (!ossl_prov_is_running())
77         return 0;
78 
79     /* add logic to create new key */
80 
81     debug_print("new key = %p\n", key);
82     return key;
83 }
84 
template_free(void * vkey)85 static void template_free(void *vkey)
86 {
87     debug_print("free key %p\n", vkey);
88     if (vkey == NULL)
89         return;
90 
91     /* add logic to free all key components */
92 
93     OPENSSL_free(vkey);
94 }
95 
template_has(const void * keydata,int selection)96 static int template_has(const void *keydata, int selection)
97 {
98     int ok = 0;
99 
100     debug_print("has %p\n", keydata);
101     if (ossl_prov_is_running() && keydata != NULL) {
102         /* add logic to check whether this key has the requested parameters */
103     }
104     debug_print("has result %d\n", ok);
105     return ok;
106 }
107 
template_match(const void * keydata1,const void * keydata2,int selection)108 static int template_match(const void *keydata1, const void *keydata2, int selection)
109 {
110     int ok = 1;
111 
112     debug_print("matching %p and %p\n", keydata1, keydata2);
113     if (!ossl_prov_is_running())
114         return 0;
115 
116     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
117         ok = ok && keydata1 != NULL && keydata2 != NULL;
118 
119     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
120         int key_checked = 0;
121 
122         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
123             /* validate whether the public keys match */
124         }
125         if (!key_checked
126             && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
127             /* validate whether the private keys match */
128         }
129         ok = ok && key_checked;
130     }
131     debug_print("match result %d\n", ok);
132     return ok;
133 }
134 
key_to_params(void * key,OSSL_PARAM_BLD * tmpl,OSSL_PARAM params[],int include_private)135 static int key_to_params(void *key, OSSL_PARAM_BLD *tmpl,
136                          OSSL_PARAM params[], int include_private)
137 {
138     if (key == NULL)
139         return 0;
140 
141     /* add public and/or private key parts to templ as possible */
142 
143     return 1;
144 }
145 
template_export(void * key,int selection,OSSL_CALLBACK * param_cb,void * cbarg)146 static int template_export(void *key, int selection, OSSL_CALLBACK *param_cb,
147                            void *cbarg)
148 {
149     OSSL_PARAM_BLD *tmpl;
150     OSSL_PARAM *params = NULL;
151     int ret = 0;
152 
153     debug_print("export %p\n", key);
154     if (!ossl_prov_is_running() || key == NULL)
155         return 0;
156 
157     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
158         return 0;
159 
160     tmpl = OSSL_PARAM_BLD_new();
161     if (tmpl == NULL)
162         return 0;
163 
164     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
165         int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
166 
167         if (!key_to_params(key, tmpl, NULL, include_private))
168             goto err;
169     }
170 
171     params = OSSL_PARAM_BLD_to_param(tmpl);
172     if (params == NULL)
173         goto err;
174 
175     ret = param_cb(params, cbarg);
176     OSSL_PARAM_free(params);
177 err:
178     OSSL_PARAM_BLD_free(tmpl);
179     debug_print("export result %d\n", ret);
180     return ret;
181 }
182 
ossl_template_key_fromdata(void * key,const OSSL_PARAM params[],int include_private)183 static int ossl_template_key_fromdata(void *key,
184                                       const OSSL_PARAM params[],
185                                       int include_private)
186 {
187     const OSSL_PARAM *param_priv_key = NULL, *param_pub_key;
188 
189     if (key == NULL)
190         return 0;
191     if (ossl_param_is_empty(params))
192         return 0;
193 
194     /* validate integrity of key (algorithm type specific) */
195 
196     param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
197     if (include_private)
198         param_priv_key =
199             OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
200 
201     if (param_pub_key == NULL && param_priv_key == NULL)
202         return 0;
203 
204     if (param_priv_key != NULL) {
205         /* retrieve private key and check integrity */
206     }
207 
208     if (param_pub_key != NULL) {
209         /* retrieve public key and check integrity */
210     }
211 
212     return 1;
213 }
214 
template_import(void * key,int selection,const OSSL_PARAM params[])215 static int template_import(void *key, int selection, const OSSL_PARAM params[])
216 {
217     int ok = 1;
218     int include_private;
219 
220     debug_print("import %p\n", key);
221     if (!ossl_prov_is_running() || key == NULL)
222         return 0;
223 
224     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
225         return 0;
226 
227     include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
228     ok = ok && ossl_template_key_fromdata(key, params, include_private);
229 
230     debug_print("import result %d\n", ok);
231     return ok;
232 }
233 
234 #define TEMPLATE_KEY_TYPES()                                     \
235     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),   \
236     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
237 
238 static const OSSL_PARAM template_key_types[] = {
239     TEMPLATE_KEY_TYPES(),
240     OSSL_PARAM_END
241 };
242 
template_imexport_types(int selection)243 static const OSSL_PARAM *template_imexport_types(int selection)
244 {
245     debug_print("getting imexport types\n");
246     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
247         return template_key_types;
248     return NULL;
249 }
250 
template_get_params(void * key,OSSL_PARAM params[])251 static int template_get_params(void *key, OSSL_PARAM params[])
252 {
253     OSSL_PARAM *p;
254 
255     debug_print("get params %p\n", key);
256 
257     if (ossl_param_is_empty(params))
258         return 0;
259 
260     /* return sensible values for at least these parameters */
261 
262     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
263         && !OSSL_PARAM_set_int(p, 0))
264         return 0;
265     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
266         && !OSSL_PARAM_set_int(p, 0))
267         return 0;
268     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
269         && !OSSL_PARAM_set_int(p, 0))
270         return 0;
271     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) {
272         if (!OSSL_PARAM_set_octet_string(p, NULL, 0))
273             return 0;
274     }
275 
276     debug_print("get params OK\n");
277     return 1;
278 }
279 
280 static const OSSL_PARAM template_gettable_params_arr[] = {
281     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
282     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
283     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
284     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
285     OSSL_PARAM_END
286 };
287 
template_gettable_params(void * provctx)288 static const OSSL_PARAM *template_gettable_params(void *provctx)
289 {
290     debug_print("gettable params called\n");
291     return template_gettable_params_arr;
292 }
293 
template_set_params(void * key,const OSSL_PARAM params[])294 static int template_set_params(void *key, const OSSL_PARAM params[])
295 {
296     const OSSL_PARAM *p;
297 
298     debug_print("set params called for %p\n", key);
299     if (ossl_param_is_empty(params))
300         return 1; /* OK not to set anything */
301 
302     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
303     if (p != NULL) {
304         /* load public key structure */
305     }
306 
307     debug_print("set params OK\n");
308     return 1;
309 }
310 
311 static const OSSL_PARAM template_settable_params_arr[] = {
312     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
313     OSSL_PARAM_END
314 };
315 
template_settable_params(void * provctx)316 static const OSSL_PARAM *template_settable_params(void *provctx)
317 {
318     debug_print("settable params called\n");
319     return template_settable_params_arr;
320 }
321 
template_gen_set_params(void * genctx,const OSSL_PARAM params[])322 static int template_gen_set_params(void *genctx, const OSSL_PARAM params[])
323 {
324     struct template_gen_ctx *gctx = genctx;
325 
326     if (gctx == NULL)
327         return 0;
328 
329     debug_print("empty gen_set params called for %p\n", gctx);
330     return 1;
331 }
332 
template_gen_init(void * provctx,int selection,const OSSL_PARAM params[])333 static void *template_gen_init(void *provctx, int selection,
334                                const OSSL_PARAM params[])
335 {
336     struct template_gen_ctx *gctx = NULL;
337 
338     debug_print("gen init called for %p\n", provctx);
339 
340     /* perform algorithm type specific sanity checks */
341 
342     if (!ossl_prov_is_running())
343         return NULL;
344 
345     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
346         gctx->provctx = provctx;
347         gctx->selection = selection;
348     }
349     if (!template_gen_set_params(gctx, params)) {
350         OPENSSL_free(gctx);
351         gctx = NULL;
352     }
353     debug_print("gen init returns %p\n", gctx);
354     return gctx;
355 }
356 
template_gen_settable_params(ossl_unused void * genctx,ossl_unused void * provctx)357 static const OSSL_PARAM *template_gen_settable_params(ossl_unused void *genctx,
358                                                       ossl_unused void *provctx)
359 {
360     static OSSL_PARAM settable[] = {
361         OSSL_PARAM_END
362     };
363     return settable;
364 }
365 
template_gen(void * vctx,OSSL_CALLBACK * osslcb,void * cbarg)366 static void *template_gen(void *vctx, OSSL_CALLBACK *osslcb, void *cbarg)
367 {
368     struct template_gen_ctx *gctx = (struct template_gen_ctx *)vctx;
369     void *key = NULL;
370 
371     debug_print("gen called for %p\n", gctx);
372 
373     if (gctx == NULL)
374         goto err;
375 
376     /* generate and return new key */
377 
378     debug_print("gen returns set %p\n", key);
379     return key;
380 err:
381     template_free(key);
382     debug_print("gen returns NULL\n");
383     return NULL;
384 }
385 
template_gen_cleanup(void * genctx)386 static void template_gen_cleanup(void *genctx)
387 {
388     struct template_gen_ctx *gctx = genctx;
389 
390     debug_print("gen cleanup for %p\n", gctx);
391     OPENSSL_free(gctx);
392 }
393 
template_dup(const void * vsrckey,int selection)394 static void *template_dup(const void *vsrckey, int selection)
395 {
396     void *dstkey = NULL;
397 
398     debug_print("dup called for %p\n", vsrckey);
399     if (!ossl_prov_is_running())
400         return NULL;
401 
402     dstkey = template_new(NULL);
403     if (dstkey == NULL)
404         goto err;
405 
406     /* populate dstkey from vsrckey material */
407 
408     debug_print("dup returns %p\n", dstkey);
409     return dstkey;
410  err:
411     template_free(dstkey);
412     debug_print("dup returns NULL\n");
413     return NULL;
414 }
415 
416 const OSSL_DISPATCH ossl_template_keymgmt_functions[] = {
417     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))template_new },
418     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))template_free },
419     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))template_get_params },
420     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))template_gettable_params },
421     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))template_set_params },
422     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))template_settable_params },
423     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))template_has },
424     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))template_match },
425     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))template_imexport_types },
426     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))template_imexport_types },
427     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))template_import },
428     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))template_export },
429     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))template_gen_init },
430     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))template_gen_set_params },
431     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
432       (void (*)(void))template_gen_settable_params },
433     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))template_gen },
434     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))template_gen_cleanup },
435     { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))template_dup },
436     OSSL_DISPATCH_END
437 };
438