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 <string.h>
11 #include <openssl/crypto.h>
12 #include <openssl/evp.h>
13 #include <openssl/core_dispatch.h>
14 #include <openssl/core_names.h>
15 #include <openssl/params.h>
16 #include <openssl/err.h>
17 #include <openssl/proverr.h>
18 #include "prov/provider_ctx.h"
19 #include "prov/implementations.h"
20 #include "prov/securitycheck.h"
21 #include "prov/providercommon.h"
22 
23 extern const OSSL_DISPATCH ossl_template_asym_kem_functions[];
24 
25 #define BUFSIZE 1000
26 #if defined(NDEBUG) || defined(OPENSSL_NO_STDIO)
debug_print(char * fmt,...)27 static void debug_print(char *fmt, ...)
28 {
29 }
30 
31 #else
debug_print(char * fmt,...)32 static void debug_print(char *fmt, ...)
33 {
34     char out[BUFSIZE];
35     va_list argptr;
36 
37     va_start(argptr, fmt);
38     vsnprintf(out, BUFSIZE, fmt, argptr);
39     va_end(argptr);
40     if (getenv("TEMPLATEKEM"))
41         fprintf(stderr, "TEMPLATE_KEM: %s", out);
42 }
43 #endif
44 
45 typedef struct {
46     OSSL_LIB_CTX *libctx;
47     /* some algorithm-specific key struct */
48     int op;
49 } PROV_TEMPLATE_CTX;
50 
51 static OSSL_FUNC_kem_newctx_fn template_newctx;
52 static OSSL_FUNC_kem_encapsulate_init_fn template_encapsulate_init;
53 static OSSL_FUNC_kem_encapsulate_fn template_encapsulate;
54 static OSSL_FUNC_kem_decapsulate_init_fn template_decapsulate_init;
55 static OSSL_FUNC_kem_decapsulate_fn template_decapsulate;
56 static OSSL_FUNC_kem_freectx_fn template_freectx;
57 static OSSL_FUNC_kem_set_ctx_params_fn template_set_ctx_params;
58 static OSSL_FUNC_kem_settable_ctx_params_fn template_settable_ctx_params;
59 
template_newctx(void * provctx)60 static void *template_newctx(void *provctx)
61 {
62     PROV_TEMPLATE_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
63 
64     debug_print("newctx called\n");
65     if (ctx == NULL)
66         return NULL;
67     ctx->libctx = PROV_LIBCTX_OF(provctx);
68 
69     debug_print("newctx returns %p\n", ctx);
70     return ctx;
71 }
72 
template_freectx(void * vctx)73 static void template_freectx(void *vctx)
74 {
75     PROV_TEMPLATE_CTX *ctx = (PROV_TEMPLATE_CTX *)vctx;
76 
77     debug_print("freectx %p\n", ctx);
78     OPENSSL_free(ctx);
79 }
80 
template_init(void * vctx,int operation,void * vkey,void * vauth,ossl_unused const OSSL_PARAM params[])81 static int template_init(void *vctx, int operation, void *vkey, void *vauth,
82                          ossl_unused const OSSL_PARAM params[])
83 {
84     PROV_TEMPLATE_CTX *ctx = (PROV_TEMPLATE_CTX *)vctx;
85 
86     debug_print("init %p / %p\n", ctx, vkey);
87     if (!ossl_prov_is_running())
88         return 0;
89 
90     /* check and fill in reference to key */
91     ctx->op = operation;
92     debug_print("init OK\n");
93     return 1;
94 }
95 
template_encapsulate_init(void * vctx,void * vkey,const OSSL_PARAM params[])96 static int template_encapsulate_init(void *vctx, void *vkey,
97                                      const OSSL_PARAM params[])
98 {
99     return template_init(vctx, EVP_PKEY_OP_ENCAPSULATE, vkey, NULL, params);
100 }
101 
template_decapsulate_init(void * vctx,void * vkey,const OSSL_PARAM params[])102 static int template_decapsulate_init(void *vctx, void *vkey,
103                                      const OSSL_PARAM params[])
104 {
105     return template_init(vctx, EVP_PKEY_OP_DECAPSULATE, vkey, NULL, params);
106 }
107 
template_set_ctx_params(void * vctx,const OSSL_PARAM params[])108 static int template_set_ctx_params(void *vctx, const OSSL_PARAM params[])
109 {
110     PROV_TEMPLATE_CTX *ctx = (PROV_TEMPLATE_CTX *)vctx;
111 
112     debug_print("set ctx params %p\n", ctx);
113     if (ctx == NULL)
114         return 0;
115     if (ossl_param_is_empty(params))
116         return 1;
117 
118     debug_print("set ctx params OK\n");
119     return 1;
120 }
121 
122 static const OSSL_PARAM known_settable_template_ctx_params[] = {
123     /* possibly more params */
124     OSSL_PARAM_END
125 };
126 
template_settable_ctx_params(ossl_unused void * vctx,ossl_unused void * provctx)127 static const OSSL_PARAM *template_settable_ctx_params(ossl_unused void *vctx,
128                                                       ossl_unused void *provctx)
129 {
130     return known_settable_template_ctx_params;
131 }
132 
template_encapsulate(void * vctx,unsigned char * out,size_t * outlen,unsigned char * secret,size_t * secretlen)133 static int template_encapsulate(void *vctx, unsigned char *out, size_t *outlen,
134                                 unsigned char *secret, size_t *secretlen)
135 {
136     debug_print("encaps %p to %p\n", vctx, out);
137 
138     /* add algorithm-specific length checks */
139 
140     if (outlen != NULL)
141         *outlen = 0; /* replace with real encapsulated data length */
142     if (secretlen != NULL)
143         *secretlen = 0; /* replace with real shared secret length */
144 
145     if (out == NULL) {
146         debug_print("encaps outlens set to %d and %d\n", *outlen, *secretlen);
147         return 1;
148     }
149 
150     /* check key and perform real KEM operation */
151 
152     debug_print("encaps OK\n");
153     return 1;
154 }
155 
template_decapsulate(void * vctx,unsigned char * out,size_t * outlen,const unsigned char * in,size_t inlen)156 static int template_decapsulate(void *vctx, unsigned char *out, size_t *outlen,
157                                 const unsigned char *in, size_t inlen)
158 {
159     debug_print("decaps %p to %p inlen at %d\n", vctx, out, inlen);
160 
161     /* add algorithm-specific length checks */
162 
163     if (outlen != NULL)
164         *outlen = 0; /* replace with shared secret length */
165 
166     if (out == NULL) {
167         debug_print("decaps outlen set to %d \n", *outlen);
168         return 1;
169     }
170 
171     /* check key and perform real decaps operation */
172 
173     debug_print("decaps OK\n");
174     return 1;
175 }
176 
177 const OSSL_DISPATCH ossl_template_asym_kem_functions[] = {
178     { OSSL_FUNC_KEM_NEWCTX, (void (*)(void))template_newctx },
179     { OSSL_FUNC_KEM_ENCAPSULATE_INIT,
180       (void (*)(void))template_encapsulate_init },
181     { OSSL_FUNC_KEM_ENCAPSULATE, (void (*)(void))template_encapsulate },
182     { OSSL_FUNC_KEM_DECAPSULATE_INIT,
183       (void (*)(void))template_decapsulate_init },
184     { OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))template_decapsulate },
185     { OSSL_FUNC_KEM_FREECTX, (void (*)(void))template_freectx },
186     { OSSL_FUNC_KEM_SET_CTX_PARAMS,
187       (void (*)(void))template_set_ctx_params },
188     { OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS,
189       (void (*)(void))template_settable_ctx_params },
190     OSSL_DISPATCH_END
191 };
192