1 /* 2 * Copyright 2024-2025 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) 27 static void debug_print(char *fmt, ...) 28 { 29 } 30 31 #else 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 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 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 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 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 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 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 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 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 if (outlen != NULL && secretlen != NULL) 147 debug_print("encaps outlens set to %zu and %zu\n", *outlen, *secretlen); 148 return 1; 149 } 150 151 /* check key and perform real KEM operation */ 152 153 debug_print("encaps OK\n"); 154 return 1; 155 } 156 157 static int template_decapsulate(void *vctx, unsigned char *out, size_t *outlen, 158 const unsigned char *in, size_t inlen) 159 { 160 debug_print("decaps %p to %p inlen at %zu\n", vctx, out, inlen); 161 162 /* add algorithm-specific length checks */ 163 164 if (outlen != NULL) 165 *outlen = 0; /* replace with shared secret length */ 166 167 if (out == NULL) { 168 if (outlen != NULL) 169 debug_print("decaps outlen set to %zu \n", *outlen); 170 return 1; 171 } 172 173 /* check key and perform real decaps operation */ 174 175 debug_print("decaps OK\n"); 176 return 1; 177 } 178 179 const OSSL_DISPATCH ossl_template_asym_kem_functions[] = { 180 { OSSL_FUNC_KEM_NEWCTX, (void (*)(void))template_newctx }, 181 { OSSL_FUNC_KEM_ENCAPSULATE_INIT, 182 (void (*)(void))template_encapsulate_init }, 183 { OSSL_FUNC_KEM_ENCAPSULATE, (void (*)(void))template_encapsulate }, 184 { OSSL_FUNC_KEM_DECAPSULATE_INIT, 185 (void (*)(void))template_decapsulate_init }, 186 { OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))template_decapsulate }, 187 { OSSL_FUNC_KEM_FREECTX, (void (*)(void))template_freectx }, 188 { OSSL_FUNC_KEM_SET_CTX_PARAMS, 189 (void (*)(void))template_set_ctx_params }, 190 { OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS, 191 (void (*)(void))template_settable_ctx_params }, 192 OSSL_DISPATCH_END 193 }; 194