1 1.1 christos /* 2 1.1.1.2 christos * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include <string.h> 11 1.1 christos #include <openssl/core_names.h> 12 1.1 christos #include <openssl/core_dispatch.h> 13 1.1 christos #include <openssl/rand.h> 14 1.1 christos #include <openssl/params.h> 15 1.1 christos /* For TLS1_3_VERSION */ 16 1.1 christos #include <openssl/ssl.h> 17 1.1 christos #include "internal/nelem.h" 18 1.1 christos 19 1.1 christos static OSSL_FUNC_keymgmt_import_fn xor_import; 20 1.1 christos static OSSL_FUNC_keymgmt_import_types_fn xor_import_types; 21 1.1 christos static OSSL_FUNC_keymgmt_export_fn xor_export; 22 1.1 christos static OSSL_FUNC_keymgmt_export_types_fn xor_export_types; 23 1.1 christos 24 1.1 christos int tls_provider_init(const OSSL_CORE_HANDLE *handle, 25 1.1 christos const OSSL_DISPATCH *in, 26 1.1 christos const OSSL_DISPATCH **out, 27 1.1 christos void **provctx); 28 1.1 christos 29 1.1 christos #define XOR_KEY_SIZE 32 30 1.1 christos 31 1.1 christos /* 32 1.1 christos * Top secret. This algorithm only works if no one knows what this number is. 33 1.1 christos * Please don't tell anyone what it is. 34 1.1 christos * 35 1.1 christos * This algorithm is for testing only - don't really use it! 36 1.1 christos */ 37 1.1 christos static const unsigned char private_constant[XOR_KEY_SIZE] = { 38 1.1 christos 0xd3, 0x6b, 0x54, 0xec, 0x5b, 0xac, 0x89, 0x96, 0x8c, 0x2c, 0x66, 0xa5, 39 1.1 christos 0x67, 0x0d, 0xe3, 0xdd, 0x43, 0x69, 0xbc, 0x83, 0x3d, 0x60, 0xc7, 0xb8, 40 1.1 christos 0x2b, 0x1c, 0x5a, 0xfd, 0xb5, 0xcd, 0xd0, 0xf8 41 1.1 christos }; 42 1.1 christos 43 1.1 christos typedef struct xorkey_st { 44 1.1 christos unsigned char privkey[XOR_KEY_SIZE]; 45 1.1 christos unsigned char pubkey[XOR_KEY_SIZE]; 46 1.1 christos int hasprivkey; 47 1.1 christos int haspubkey; 48 1.1 christos } XORKEY; 49 1.1 christos 50 1.1 christos 51 1.1 christos /* Key Management for the dummy XOR KEX and KEM algorithms */ 52 1.1 christos 53 1.1 christos static OSSL_FUNC_keymgmt_new_fn xor_newdata; 54 1.1 christos static OSSL_FUNC_keymgmt_free_fn xor_freedata; 55 1.1 christos static OSSL_FUNC_keymgmt_has_fn xor_has; 56 1.1 christos static OSSL_FUNC_keymgmt_dup_fn xor_dup; 57 1.1 christos static OSSL_FUNC_keymgmt_gen_init_fn xor_gen_init; 58 1.1 christos static OSSL_FUNC_keymgmt_gen_set_params_fn xor_gen_set_params; 59 1.1 christos static OSSL_FUNC_keymgmt_gen_settable_params_fn xor_gen_settable_params; 60 1.1 christos static OSSL_FUNC_keymgmt_gen_fn xor_gen; 61 1.1 christos static OSSL_FUNC_keymgmt_gen_cleanup_fn xor_gen_cleanup; 62 1.1 christos static OSSL_FUNC_keymgmt_get_params_fn xor_get_params; 63 1.1 christos static OSSL_FUNC_keymgmt_gettable_params_fn xor_gettable_params; 64 1.1 christos static OSSL_FUNC_keymgmt_set_params_fn xor_set_params; 65 1.1 christos static OSSL_FUNC_keymgmt_settable_params_fn xor_settable_params; 66 1.1 christos 67 1.1 christos /* 68 1.1 christos * Dummy "XOR" Key Exchange algorithm. We just xor the private and public keys 69 1.1 christos * together. Don't use this! 70 1.1 christos */ 71 1.1 christos 72 1.1 christos static OSSL_FUNC_keyexch_newctx_fn xor_newctx; 73 1.1 christos static OSSL_FUNC_keyexch_init_fn xor_init; 74 1.1 christos static OSSL_FUNC_keyexch_set_peer_fn xor_set_peer; 75 1.1 christos static OSSL_FUNC_keyexch_derive_fn xor_derive; 76 1.1 christos static OSSL_FUNC_keyexch_freectx_fn xor_freectx; 77 1.1 christos static OSSL_FUNC_keyexch_dupctx_fn xor_dupctx; 78 1.1 christos 79 1.1 christos /* 80 1.1 christos * Dummy "XOR" Key Encapsulation Method. We just build a KEM over the xor KEX. 81 1.1 christos * Don't use this! 82 1.1 christos */ 83 1.1 christos 84 1.1 christos static OSSL_FUNC_kem_newctx_fn xor_newctx; 85 1.1 christos static OSSL_FUNC_kem_freectx_fn xor_freectx; 86 1.1 christos static OSSL_FUNC_kem_dupctx_fn xor_dupctx; 87 1.1 christos static OSSL_FUNC_kem_encapsulate_init_fn xor_init; 88 1.1 christos static OSSL_FUNC_kem_encapsulate_fn xor_encapsulate; 89 1.1 christos static OSSL_FUNC_kem_decapsulate_init_fn xor_init; 90 1.1 christos static OSSL_FUNC_kem_decapsulate_fn xor_decapsulate; 91 1.1 christos 92 1.1 christos 93 1.1 christos /* 94 1.1 christos * We define 2 dummy TLS groups called "xorgroup" and "xorkemgroup" for test 95 1.1 christos * purposes 96 1.1 christos */ 97 1.1 christos struct tls_group_st { 98 1.1 christos unsigned int group_id; /* for "tls-group-id", see provider-base(7) */ 99 1.1 christos unsigned int secbits; 100 1.1 christos unsigned int mintls; 101 1.1 christos unsigned int maxtls; 102 1.1 christos unsigned int mindtls; 103 1.1 christos unsigned int maxdtls; 104 1.1 christos unsigned int is_kem; /* boolean */ 105 1.1 christos }; 106 1.1 christos 107 1.1 christos #define XORGROUP_NAME "xorgroup" 108 1.1 christos #define XORGROUP_NAME_INTERNAL "xorgroup-int" 109 1.1 christos static struct tls_group_st xor_group = { 110 1.1 christos 0, /* group_id, set by randomize_tls_group_id() */ 111 1.1 christos 128, /* secbits */ 112 1.1 christos TLS1_3_VERSION, /* mintls */ 113 1.1 christos 0, /* maxtls */ 114 1.1 christos -1, /* mindtls */ 115 1.1 christos -1, /* maxdtls */ 116 1.1 christos 0 /* is_kem */ 117 1.1 christos }; 118 1.1 christos 119 1.1 christos #define XORKEMGROUP_NAME "xorkemgroup" 120 1.1 christos #define XORKEMGROUP_NAME_INTERNAL "xorkemgroup-int" 121 1.1 christos static struct tls_group_st xor_kemgroup = { 122 1.1 christos 0, /* group_id, set by randomize_tls_group_id() */ 123 1.1 christos 128, /* secbits */ 124 1.1 christos TLS1_3_VERSION, /* mintls */ 125 1.1 christos 0, /* maxtls */ 126 1.1 christos -1, /* mindtls */ 127 1.1 christos -1, /* maxdtls */ 128 1.1 christos 1 /* is_kem */ 129 1.1 christos }; 130 1.1 christos 131 1.1 christos #define ALGORITHM "XOR" 132 1.1 christos 133 1.1 christos static const OSSL_PARAM xor_group_params[] = { 134 1.1 christos OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, 135 1.1 christos XORGROUP_NAME, sizeof(XORGROUP_NAME)), 136 1.1 christos OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, 137 1.1 christos XORGROUP_NAME_INTERNAL, 138 1.1 christos sizeof(XORGROUP_NAME_INTERNAL)), 139 1.1 christos OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, ALGORITHM, 140 1.1 christos sizeof(ALGORITHM)), 141 1.1 christos OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, &xor_group.group_id), 142 1.1 christos OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, 143 1.1 christos &xor_group.secbits), 144 1.1 christos OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, &xor_group.mintls), 145 1.1 christos OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, &xor_group.maxtls), 146 1.1 christos OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, &xor_group.mindtls), 147 1.1 christos OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, &xor_group.maxdtls), 148 1.1 christos OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_IS_KEM, &xor_group.is_kem), 149 1.1 christos OSSL_PARAM_END 150 1.1 christos }; 151 1.1 christos 152 1.1 christos static const OSSL_PARAM xor_kemgroup_params[] = { 153 1.1 christos OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, 154 1.1 christos XORKEMGROUP_NAME, sizeof(XORKEMGROUP_NAME)), 155 1.1 christos OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, 156 1.1 christos XORKEMGROUP_NAME_INTERNAL, 157 1.1 christos sizeof(XORKEMGROUP_NAME_INTERNAL)), 158 1.1 christos OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, ALGORITHM, 159 1.1 christos sizeof(ALGORITHM)), 160 1.1 christos OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, &xor_kemgroup.group_id), 161 1.1 christos OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, 162 1.1 christos &xor_kemgroup.secbits), 163 1.1 christos OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, &xor_kemgroup.mintls), 164 1.1 christos OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, &xor_kemgroup.maxtls), 165 1.1 christos OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, &xor_kemgroup.mindtls), 166 1.1 christos OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, &xor_kemgroup.maxdtls), 167 1.1 christos OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_IS_KEM, &xor_kemgroup.is_kem), 168 1.1 christos OSSL_PARAM_END 169 1.1 christos }; 170 1.1 christos 171 1.1 christos #define NUM_DUMMY_GROUPS 50 172 1.1 christos static char *dummy_group_names[NUM_DUMMY_GROUPS]; 173 1.1 christos 174 1.1 christos static int tls_prov_get_capabilities(void *provctx, const char *capability, 175 1.1 christos OSSL_CALLBACK *cb, void *arg) 176 1.1 christos { 177 1.1 christos int ret; 178 1.1 christos int i; 179 1.1 christos const char *dummy_base = "dummy"; 180 1.1 christos const size_t dummy_name_max_size = strlen(dummy_base) + 3; 181 1.1 christos 182 1.1 christos if (strcmp(capability, "TLS-GROUP") != 0) { 183 1.1 christos /* We don't support this capability */ 184 1.1 christos return 0; 185 1.1 christos } 186 1.1 christos 187 1.1 christos /* Register our 2 groups */ 188 1.1.1.2 christos OPENSSL_assert(xor_group.group_id >= 65024 189 1.1.1.2 christos && xor_group.group_id < 65279 - NUM_DUMMY_GROUPS); 190 1.1 christos ret = cb(xor_group_params, arg); 191 1.1 christos ret &= cb(xor_kemgroup_params, arg); 192 1.1 christos 193 1.1 christos /* 194 1.1 christos * Now register some dummy groups > GROUPLIST_INCREMENT (== 40) as defined 195 1.1 christos * in ssl/t1_lib.c, to make sure we exercise the code paths for registering 196 1.1 christos * large numbers of groups. 197 1.1 christos */ 198 1.1 christos 199 1.1 christos for (i = 0; i < NUM_DUMMY_GROUPS; i++) { 200 1.1 christos OSSL_PARAM dummygroup[OSSL_NELEM(xor_group_params)]; 201 1.1.1.2 christos unsigned int dummygroup_id; 202 1.1 christos 203 1.1 christos memcpy(dummygroup, xor_group_params, sizeof(xor_group_params)); 204 1.1 christos 205 1.1 christos /* Give the dummy group a unique name */ 206 1.1 christos if (dummy_group_names[i] == NULL) { 207 1.1 christos dummy_group_names[i] = OPENSSL_zalloc(dummy_name_max_size); 208 1.1 christos if (dummy_group_names[i] == NULL) 209 1.1 christos return 0; 210 1.1 christos BIO_snprintf(dummy_group_names[i], 211 1.1 christos dummy_name_max_size, 212 1.1 christos "%s%d", dummy_base, i); 213 1.1 christos } 214 1.1 christos dummygroup[0].data = dummy_group_names[i]; 215 1.1 christos dummygroup[0].data_size = strlen(dummy_group_names[i]) + 1; 216 1.1.1.2 christos /* assign unique group IDs also to dummy groups for registration */ 217 1.1.1.2 christos dummygroup_id = 65279 - NUM_DUMMY_GROUPS + i; 218 1.1.1.2 christos dummygroup[3].data = (unsigned char*)&dummygroup_id; 219 1.1 christos ret &= cb(dummygroup, arg); 220 1.1 christos } 221 1.1 christos 222 1.1 christos return ret; 223 1.1 christos } 224 1.1 christos 225 1.1 christos /* 226 1.1 christos * Dummy "XOR" Key Exchange algorithm. We just xor the private and public keys 227 1.1 christos * together. Don't use this! 228 1.1 christos */ 229 1.1 christos 230 1.1 christos typedef struct { 231 1.1 christos XORKEY *key; 232 1.1 christos XORKEY *peerkey; 233 1.1 christos void *provctx; 234 1.1 christos } PROV_XOR_CTX; 235 1.1 christos 236 1.1 christos static void *xor_newctx(void *provctx) 237 1.1 christos { 238 1.1 christos PROV_XOR_CTX *pxorctx = OPENSSL_zalloc(sizeof(PROV_XOR_CTX)); 239 1.1 christos 240 1.1 christos if (pxorctx == NULL) 241 1.1 christos return NULL; 242 1.1 christos 243 1.1 christos pxorctx->provctx = provctx; 244 1.1 christos 245 1.1 christos return pxorctx; 246 1.1 christos } 247 1.1 christos 248 1.1 christos static int xor_init(void *vpxorctx, void *vkey, 249 1.1 christos ossl_unused const OSSL_PARAM params[]) 250 1.1 christos { 251 1.1 christos PROV_XOR_CTX *pxorctx = (PROV_XOR_CTX *)vpxorctx; 252 1.1 christos 253 1.1 christos if (pxorctx == NULL || vkey == NULL) 254 1.1 christos return 0; 255 1.1 christos pxorctx->key = vkey; 256 1.1 christos return 1; 257 1.1 christos } 258 1.1 christos 259 1.1 christos static int xor_set_peer(void *vpxorctx, void *vpeerkey) 260 1.1 christos { 261 1.1 christos PROV_XOR_CTX *pxorctx = (PROV_XOR_CTX *)vpxorctx; 262 1.1 christos 263 1.1 christos if (pxorctx == NULL || vpeerkey == NULL) 264 1.1 christos return 0; 265 1.1 christos pxorctx->peerkey = vpeerkey; 266 1.1 christos return 1; 267 1.1 christos } 268 1.1 christos 269 1.1 christos static int xor_derive(void *vpxorctx, unsigned char *secret, size_t *secretlen, 270 1.1 christos size_t outlen) 271 1.1 christos { 272 1.1 christos PROV_XOR_CTX *pxorctx = (PROV_XOR_CTX *)vpxorctx; 273 1.1 christos int i; 274 1.1 christos 275 1.1 christos if (pxorctx->key == NULL || pxorctx->peerkey == NULL) 276 1.1 christos return 0; 277 1.1 christos 278 1.1 christos *secretlen = XOR_KEY_SIZE; 279 1.1 christos if (secret == NULL) 280 1.1 christos return 1; 281 1.1 christos 282 1.1 christos if (outlen < XOR_KEY_SIZE) 283 1.1 christos return 0; 284 1.1 christos 285 1.1 christos for (i = 0; i < XOR_KEY_SIZE; i++) 286 1.1 christos secret[i] = pxorctx->key->privkey[i] ^ pxorctx->peerkey->pubkey[i]; 287 1.1 christos 288 1.1 christos return 1; 289 1.1 christos } 290 1.1 christos 291 1.1 christos static void xor_freectx(void *pxorctx) 292 1.1 christos { 293 1.1 christos OPENSSL_free(pxorctx); 294 1.1 christos } 295 1.1 christos 296 1.1 christos static void *xor_dupctx(void *vpxorctx) 297 1.1 christos { 298 1.1 christos PROV_XOR_CTX *srcctx = (PROV_XOR_CTX *)vpxorctx; 299 1.1 christos PROV_XOR_CTX *dstctx; 300 1.1 christos 301 1.1 christos dstctx = OPENSSL_zalloc(sizeof(*srcctx)); 302 1.1 christos if (dstctx == NULL) 303 1.1 christos return NULL; 304 1.1 christos 305 1.1 christos *dstctx = *srcctx; 306 1.1 christos 307 1.1 christos return dstctx; 308 1.1 christos } 309 1.1 christos 310 1.1 christos static const OSSL_DISPATCH xor_keyexch_functions[] = { 311 1.1 christos { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))xor_newctx }, 312 1.1 christos { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))xor_init }, 313 1.1 christos { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))xor_derive }, 314 1.1 christos { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))xor_set_peer }, 315 1.1 christos { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))xor_freectx }, 316 1.1 christos { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))xor_dupctx }, 317 1.1 christos { 0, NULL } 318 1.1 christos }; 319 1.1 christos 320 1.1 christos static const OSSL_ALGORITHM tls_prov_keyexch[] = { 321 1.1 christos /* 322 1.1 christos * Obviously this is not FIPS approved, but in order to test in conjuction 323 1.1 christos * with the FIPS provider we pretend that it is. 324 1.1 christos */ 325 1.1 christos { "XOR", "provider=tls-provider,fips=yes", xor_keyexch_functions }, 326 1.1 christos { NULL, NULL, NULL } 327 1.1 christos }; 328 1.1 christos 329 1.1 christos /* 330 1.1 christos * Dummy "XOR" Key Encapsulation Method. We just build a KEM over the xor KEX. 331 1.1 christos * Don't use this! 332 1.1 christos */ 333 1.1 christos 334 1.1 christos static int xor_encapsulate(void *vpxorctx, 335 1.1 christos unsigned char *ct, size_t *ctlen, 336 1.1 christos unsigned char *ss, size_t *sslen) 337 1.1 christos { 338 1.1 christos /* 339 1.1 christos * We are building this around a KEX: 340 1.1 christos * 341 1.1 christos * 1. we generate ephemeral keypair 342 1.1 christos * 2. we encode our ephemeral pubkey as the outgoing ct 343 1.1 christos * 3. we derive using our ephemeral privkey in combination with the peer 344 1.1 christos * pubkey from the ctx; the result is our ss. 345 1.1 christos */ 346 1.1 christos int rv = 0; 347 1.1 christos void *genctx = NULL, *derivectx = NULL; 348 1.1 christos XORKEY *ourkey = NULL; 349 1.1 christos PROV_XOR_CTX *pxorctx = vpxorctx; 350 1.1 christos 351 1.1 christos if (ct == NULL || ss == NULL) { 352 1.1 christos /* Just return sizes */ 353 1.1 christos 354 1.1 christos if (ctlen == NULL && sslen == NULL) 355 1.1 christos return 0; 356 1.1 christos if (ctlen != NULL) 357 1.1 christos *ctlen = XOR_KEY_SIZE; 358 1.1 christos if (sslen != NULL) 359 1.1 christos *sslen = XOR_KEY_SIZE; 360 1.1 christos return 1; 361 1.1 christos } 362 1.1 christos 363 1.1 christos /* 1. Generate keypair */ 364 1.1 christos genctx = xor_gen_init(pxorctx->provctx, OSSL_KEYMGMT_SELECT_KEYPAIR, NULL); 365 1.1 christos if (genctx == NULL) 366 1.1 christos goto end; 367 1.1 christos ourkey = xor_gen(genctx, NULL, NULL); 368 1.1 christos if (ourkey == NULL) 369 1.1 christos goto end; 370 1.1 christos 371 1.1 christos /* 2. Encode ephemeral pubkey as ct */ 372 1.1 christos memcpy(ct, ourkey->pubkey, XOR_KEY_SIZE); 373 1.1 christos *ctlen = XOR_KEY_SIZE; 374 1.1 christos 375 1.1 christos /* 3. Derive ss via KEX */ 376 1.1 christos derivectx = xor_newctx(pxorctx->provctx); 377 1.1 christos if (derivectx == NULL 378 1.1 christos || !xor_init(derivectx, ourkey, NULL) 379 1.1 christos || !xor_set_peer(derivectx, pxorctx->key) 380 1.1 christos || !xor_derive(derivectx, ss, sslen, XOR_KEY_SIZE)) 381 1.1 christos goto end; 382 1.1 christos 383 1.1 christos rv = 1; 384 1.1 christos 385 1.1 christos end: 386 1.1 christos xor_gen_cleanup(genctx); 387 1.1 christos xor_freedata(ourkey); 388 1.1 christos xor_freectx(derivectx); 389 1.1 christos return rv; 390 1.1 christos } 391 1.1 christos 392 1.1 christos static int xor_decapsulate(void *vpxorctx, 393 1.1 christos unsigned char *ss, size_t *sslen, 394 1.1 christos const unsigned char *ct, size_t ctlen) 395 1.1 christos { 396 1.1 christos /* 397 1.1 christos * We are building this around a KEX: 398 1.1 christos * 399 1.1 christos * - ct is our peer's pubkey 400 1.1 christos * - decapsulate is just derive. 401 1.1 christos */ 402 1.1 christos int rv = 0; 403 1.1 christos void *derivectx = NULL; 404 1.1 christos XORKEY *peerkey = NULL; 405 1.1 christos PROV_XOR_CTX *pxorctx = vpxorctx; 406 1.1 christos 407 1.1 christos if (ss == NULL) { 408 1.1 christos /* Just return size */ 409 1.1 christos if (sslen == NULL) 410 1.1 christos return 0; 411 1.1 christos *sslen = XOR_KEY_SIZE; 412 1.1 christos return 1; 413 1.1 christos } 414 1.1 christos 415 1.1 christos if (ctlen != XOR_KEY_SIZE) 416 1.1 christos return 0; 417 1.1 christos peerkey = xor_newdata(pxorctx->provctx); 418 1.1 christos if (peerkey == NULL) 419 1.1 christos goto end; 420 1.1 christos memcpy(peerkey->pubkey, ct, XOR_KEY_SIZE); 421 1.1 christos 422 1.1 christos /* Derive ss via KEX */ 423 1.1 christos derivectx = xor_newctx(pxorctx->provctx); 424 1.1 christos if (derivectx == NULL 425 1.1 christos || !xor_init(derivectx, pxorctx->key, NULL) 426 1.1 christos || !xor_set_peer(derivectx, peerkey) 427 1.1 christos || !xor_derive(derivectx, ss, sslen, XOR_KEY_SIZE)) 428 1.1 christos goto end; 429 1.1 christos 430 1.1 christos rv = 1; 431 1.1 christos 432 1.1 christos end: 433 1.1 christos xor_freedata(peerkey); 434 1.1 christos xor_freectx(derivectx); 435 1.1 christos return rv; 436 1.1 christos } 437 1.1 christos 438 1.1 christos static const OSSL_DISPATCH xor_kem_functions[] = { 439 1.1 christos { OSSL_FUNC_KEM_NEWCTX, (void (*)(void))xor_newctx }, 440 1.1 christos { OSSL_FUNC_KEM_FREECTX, (void (*)(void))xor_freectx }, 441 1.1 christos { OSSL_FUNC_KEM_DUPCTX, (void (*)(void))xor_dupctx }, 442 1.1 christos { OSSL_FUNC_KEM_ENCAPSULATE_INIT, (void (*)(void))xor_init }, 443 1.1 christos { OSSL_FUNC_KEM_ENCAPSULATE, (void (*)(void))xor_encapsulate }, 444 1.1 christos { OSSL_FUNC_KEM_DECAPSULATE_INIT, (void (*)(void))xor_init }, 445 1.1 christos { OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))xor_decapsulate }, 446 1.1 christos { 0, NULL } 447 1.1 christos }; 448 1.1 christos 449 1.1 christos static const OSSL_ALGORITHM tls_prov_kem[] = { 450 1.1 christos /* 451 1.1 christos * Obviously this is not FIPS approved, but in order to test in conjuction 452 1.1 christos * with the FIPS provider we pretend that it is. 453 1.1 christos */ 454 1.1 christos { "XOR", "provider=tls-provider,fips=yes", xor_kem_functions }, 455 1.1 christos { NULL, NULL, NULL } 456 1.1 christos }; 457 1.1 christos 458 1.1 christos /* Key Management for the dummy XOR key exchange algorithm */ 459 1.1 christos 460 1.1 christos static void *xor_newdata(void *provctx) 461 1.1 christos { 462 1.1 christos return OPENSSL_zalloc(sizeof(XORKEY)); 463 1.1 christos } 464 1.1 christos 465 1.1 christos static void xor_freedata(void *keydata) 466 1.1 christos { 467 1.1 christos OPENSSL_free(keydata); 468 1.1 christos } 469 1.1 christos 470 1.1 christos static int xor_has(const void *vkey, int selection) 471 1.1 christos { 472 1.1 christos const XORKEY *key = vkey; 473 1.1 christos int ok = 0; 474 1.1 christos 475 1.1 christos if (key != NULL) { 476 1.1 christos ok = 1; 477 1.1 christos 478 1.1 christos if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) 479 1.1 christos ok = ok && key->haspubkey; 480 1.1 christos if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) 481 1.1 christos ok = ok && key->hasprivkey; 482 1.1 christos } 483 1.1 christos return ok; 484 1.1 christos } 485 1.1 christos 486 1.1 christos static void *xor_dup(const void *vfromkey, int selection) 487 1.1 christos { 488 1.1 christos XORKEY *tokey = xor_newdata(NULL); 489 1.1 christos const XORKEY *fromkey = vfromkey; 490 1.1 christos int ok = 0; 491 1.1 christos 492 1.1 christos if (tokey != NULL && fromkey != NULL) { 493 1.1 christos ok = 1; 494 1.1 christos 495 1.1 christos if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { 496 1.1 christos if (fromkey->haspubkey) { 497 1.1 christos memcpy(tokey->pubkey, fromkey->pubkey, XOR_KEY_SIZE); 498 1.1 christos tokey->haspubkey = 1; 499 1.1 christos } else { 500 1.1 christos tokey->haspubkey = 0; 501 1.1 christos } 502 1.1 christos } 503 1.1 christos if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { 504 1.1 christos if (fromkey->hasprivkey) { 505 1.1 christos memcpy(tokey->privkey, fromkey->privkey, XOR_KEY_SIZE); 506 1.1 christos tokey->hasprivkey = 1; 507 1.1 christos } else { 508 1.1 christos tokey->hasprivkey = 0; 509 1.1 christos } 510 1.1 christos } 511 1.1 christos } 512 1.1 christos if (!ok) { 513 1.1 christos xor_freedata(tokey); 514 1.1 christos tokey = NULL; 515 1.1 christos } 516 1.1 christos return tokey; 517 1.1 christos } 518 1.1 christos 519 1.1 christos static ossl_inline int xor_get_params(void *vkey, OSSL_PARAM params[]) 520 1.1 christos { 521 1.1 christos XORKEY *key = vkey; 522 1.1 christos OSSL_PARAM *p; 523 1.1 christos 524 1.1 christos if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL 525 1.1 christos && !OSSL_PARAM_set_int(p, XOR_KEY_SIZE)) 526 1.1 christos return 0; 527 1.1 christos 528 1.1 christos if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL 529 1.1 christos && !OSSL_PARAM_set_int(p, xor_group.secbits)) 530 1.1 christos return 0; 531 1.1 christos 532 1.1 christos if ((p = OSSL_PARAM_locate(params, 533 1.1 christos OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) { 534 1.1 christos if (p->data_type != OSSL_PARAM_OCTET_STRING) 535 1.1 christos return 0; 536 1.1 christos p->return_size = XOR_KEY_SIZE; 537 1.1 christos if (p->data != NULL && p->data_size >= XOR_KEY_SIZE) 538 1.1 christos memcpy(p->data, key->pubkey, XOR_KEY_SIZE); 539 1.1 christos } 540 1.1 christos 541 1.1 christos return 1; 542 1.1 christos } 543 1.1 christos 544 1.1 christos static const OSSL_PARAM xor_params[] = { 545 1.1 christos OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), 546 1.1 christos OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), 547 1.1 christos OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), 548 1.1 christos OSSL_PARAM_END 549 1.1 christos }; 550 1.1 christos 551 1.1 christos static const OSSL_PARAM *xor_gettable_params(void *provctx) 552 1.1 christos { 553 1.1 christos return xor_params; 554 1.1 christos } 555 1.1 christos 556 1.1 christos static int xor_set_params(void *vkey, const OSSL_PARAM params[]) 557 1.1 christos { 558 1.1 christos XORKEY *key = vkey; 559 1.1 christos const OSSL_PARAM *p; 560 1.1 christos 561 1.1 christos p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); 562 1.1 christos if (p != NULL) { 563 1.1 christos if (p->data_type != OSSL_PARAM_OCTET_STRING 564 1.1 christos || p->data_size != XOR_KEY_SIZE) 565 1.1 christos return 0; 566 1.1 christos memcpy(key->pubkey, p->data, XOR_KEY_SIZE); 567 1.1 christos key->haspubkey = 1; 568 1.1 christos } 569 1.1 christos 570 1.1 christos return 1; 571 1.1 christos } 572 1.1 christos 573 1.1 christos static const OSSL_PARAM xor_known_settable_params[] = { 574 1.1 christos OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), 575 1.1 christos OSSL_PARAM_END 576 1.1 christos }; 577 1.1 christos 578 1.1 christos static const OSSL_PARAM *xor_settable_params(void *provctx) 579 1.1 christos { 580 1.1 christos return xor_known_settable_params; 581 1.1 christos } 582 1.1 christos 583 1.1 christos struct xor_gen_ctx { 584 1.1 christos int selection; 585 1.1 christos OSSL_LIB_CTX *libctx; 586 1.1 christos }; 587 1.1 christos 588 1.1 christos static void *xor_gen_init(void *provctx, int selection, 589 1.1 christos const OSSL_PARAM params[]) 590 1.1 christos { 591 1.1 christos struct xor_gen_ctx *gctx = NULL; 592 1.1 christos 593 1.1 christos if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR 594 1.1 christos | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0) 595 1.1 christos return NULL; 596 1.1 christos 597 1.1 christos if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) 598 1.1 christos gctx->selection = selection; 599 1.1 christos 600 1.1 christos /* Our provctx is really just an OSSL_LIB_CTX */ 601 1.1 christos gctx->libctx = (OSSL_LIB_CTX *)provctx; 602 1.1 christos 603 1.1 christos if (!xor_gen_set_params(gctx, params)) { 604 1.1 christos OPENSSL_free(gctx); 605 1.1 christos return NULL; 606 1.1 christos } 607 1.1 christos return gctx; 608 1.1 christos } 609 1.1 christos 610 1.1 christos static int xor_gen_set_params(void *genctx, const OSSL_PARAM params[]) 611 1.1 christos { 612 1.1 christos struct xor_gen_ctx *gctx = genctx; 613 1.1 christos const OSSL_PARAM *p; 614 1.1 christos 615 1.1 christos if (gctx == NULL) 616 1.1 christos return 0; 617 1.1 christos 618 1.1 christos p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME); 619 1.1 christos if (p != NULL) { 620 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING 621 1.1 christos || (strcmp(p->data, XORGROUP_NAME_INTERNAL) != 0 622 1.1 christos && strcmp(p->data, XORKEMGROUP_NAME_INTERNAL) != 0)) 623 1.1 christos return 0; 624 1.1 christos } 625 1.1 christos 626 1.1 christos return 1; 627 1.1 christos } 628 1.1 christos 629 1.1 christos static const OSSL_PARAM *xor_gen_settable_params(ossl_unused void *genctx, 630 1.1 christos ossl_unused void *provctx) 631 1.1 christos { 632 1.1 christos static OSSL_PARAM settable[] = { 633 1.1 christos OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), 634 1.1 christos OSSL_PARAM_END 635 1.1 christos }; 636 1.1 christos return settable; 637 1.1 christos } 638 1.1 christos 639 1.1 christos static void *xor_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) 640 1.1 christos { 641 1.1 christos struct xor_gen_ctx *gctx = genctx; 642 1.1 christos XORKEY *key = OPENSSL_zalloc(sizeof(*key)); 643 1.1 christos size_t i; 644 1.1 christos 645 1.1 christos if (key == NULL) 646 1.1 christos return NULL; 647 1.1 christos 648 1.1 christos if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { 649 1.1 christos if (RAND_bytes_ex(gctx->libctx, key->privkey, XOR_KEY_SIZE, 0) <= 0) { 650 1.1 christos OPENSSL_free(key); 651 1.1 christos return NULL; 652 1.1 christos } 653 1.1 christos for (i = 0; i < XOR_KEY_SIZE; i++) 654 1.1 christos key->pubkey[i] = key->privkey[i] ^ private_constant[i]; 655 1.1 christos key->hasprivkey = 1; 656 1.1 christos key->haspubkey = 1; 657 1.1 christos } 658 1.1 christos 659 1.1 christos return key; 660 1.1 christos } 661 1.1 christos 662 1.1 christos /* IMPORT + EXPORT */ 663 1.1 christos 664 1.1 christos static int xor_import(void *vkey, int select, const OSSL_PARAM params[]) 665 1.1 christos { 666 1.1 christos XORKEY *key = vkey; 667 1.1 christos const OSSL_PARAM *param_priv_key, *param_pub_key; 668 1.1 christos unsigned char privkey[XOR_KEY_SIZE]; 669 1.1 christos unsigned char pubkey[XOR_KEY_SIZE]; 670 1.1 christos void *pprivkey = privkey, *ppubkey = pubkey; 671 1.1 christos size_t priv_len = 0, pub_len = 0; 672 1.1 christos int res = 0; 673 1.1 christos 674 1.1 christos if (key == NULL || (select & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) 675 1.1 christos return 0; 676 1.1 christos 677 1.1 christos memset(privkey, 0, sizeof(privkey)); 678 1.1 christos memset(pubkey, 0, sizeof(pubkey)); 679 1.1 christos param_priv_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); 680 1.1 christos param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); 681 1.1 christos 682 1.1 christos if ((param_priv_key != NULL 683 1.1 christos && !OSSL_PARAM_get_octet_string(param_priv_key, &pprivkey, 684 1.1 christos sizeof(privkey), &priv_len)) 685 1.1 christos || (param_pub_key != NULL 686 1.1 christos && !OSSL_PARAM_get_octet_string(param_pub_key, &ppubkey, 687 1.1 christos sizeof(pubkey), &pub_len))) 688 1.1 christos goto err; 689 1.1 christos 690 1.1 christos if (priv_len > 0) { 691 1.1 christos memcpy(key->privkey, privkey, priv_len); 692 1.1 christos key->hasprivkey = 1; 693 1.1 christos } 694 1.1 christos if (pub_len > 0) { 695 1.1 christos memcpy(key->pubkey, pubkey, pub_len); 696 1.1 christos key->haspubkey = 1; 697 1.1 christos } 698 1.1 christos res = 1; 699 1.1 christos err: 700 1.1 christos return res; 701 1.1 christos } 702 1.1 christos 703 1.1 christos static int xor_export(void *vkey, int select, OSSL_CALLBACK *param_cb, 704 1.1 christos void *cbarg) 705 1.1 christos { 706 1.1 christos XORKEY *key = vkey; 707 1.1 christos OSSL_PARAM params[3], *p = params; 708 1.1 christos 709 1.1 christos if (key == NULL || (select & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) 710 1.1 christos return 0; 711 1.1 christos 712 1.1 christos *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, 713 1.1 christos key->privkey, 714 1.1 christos sizeof(key->privkey)); 715 1.1 christos *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, 716 1.1 christos key->pubkey, sizeof(key->pubkey)); 717 1.1 christos *p++ = OSSL_PARAM_construct_end(); 718 1.1 christos 719 1.1 christos return param_cb(params, cbarg); 720 1.1 christos } 721 1.1 christos 722 1.1 christos static const OSSL_PARAM xor_key_types[] = { 723 1.1 christos OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), 724 1.1 christos OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), 725 1.1 christos OSSL_PARAM_END 726 1.1 christos }; 727 1.1 christos 728 1.1 christos static const OSSL_PARAM *xor_import_types(int select) 729 1.1 christos { 730 1.1 christos return (select & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 ? xor_key_types : NULL; 731 1.1 christos } 732 1.1 christos 733 1.1 christos static const OSSL_PARAM *xor_export_types(int select) 734 1.1 christos { 735 1.1 christos return (select & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 ? xor_key_types : NULL; 736 1.1 christos } 737 1.1 christos 738 1.1 christos static void xor_gen_cleanup(void *genctx) 739 1.1 christos { 740 1.1 christos OPENSSL_free(genctx); 741 1.1 christos } 742 1.1 christos 743 1.1 christos static const OSSL_DISPATCH xor_keymgmt_functions[] = { 744 1.1 christos { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))xor_newdata }, 745 1.1 christos { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))xor_gen_init }, 746 1.1 christos { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))xor_gen_set_params }, 747 1.1 christos { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, 748 1.1 christos (void (*)(void))xor_gen_settable_params }, 749 1.1 christos { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))xor_gen }, 750 1.1 christos { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))xor_gen_cleanup }, 751 1.1 christos { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))xor_get_params }, 752 1.1 christos { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))xor_gettable_params }, 753 1.1 christos { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))xor_set_params }, 754 1.1 christos { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))xor_settable_params }, 755 1.1 christos { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))xor_has }, 756 1.1 christos { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))xor_dup }, 757 1.1 christos { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))xor_freedata }, 758 1.1 christos { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))xor_import }, 759 1.1 christos { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))xor_import_types }, 760 1.1 christos { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))xor_export }, 761 1.1 christos { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))xor_export_types }, 762 1.1 christos { 0, NULL } 763 1.1 christos }; 764 1.1 christos 765 1.1 christos static const OSSL_ALGORITHM tls_prov_keymgmt[] = { 766 1.1 christos /* 767 1.1 christos * Obviously this is not FIPS approved, but in order to test in conjuction 768 1.1 christos * with the FIPS provider we pretend that it is. 769 1.1 christos */ 770 1.1 christos { "XOR", "provider=tls-provider,fips=yes", xor_keymgmt_functions }, 771 1.1 christos { NULL, NULL, NULL } 772 1.1 christos }; 773 1.1 christos 774 1.1 christos static const OSSL_ALGORITHM *tls_prov_query(void *provctx, int operation_id, 775 1.1 christos int *no_cache) 776 1.1 christos { 777 1.1 christos *no_cache = 0; 778 1.1 christos switch (operation_id) { 779 1.1 christos case OSSL_OP_KEYMGMT: 780 1.1 christos return tls_prov_keymgmt; 781 1.1 christos case OSSL_OP_KEYEXCH: 782 1.1 christos return tls_prov_keyexch; 783 1.1 christos case OSSL_OP_KEM: 784 1.1 christos return tls_prov_kem; 785 1.1 christos } 786 1.1 christos return NULL; 787 1.1 christos } 788 1.1 christos 789 1.1 christos static void tls_prov_teardown(void *provctx) 790 1.1 christos { 791 1.1 christos int i; 792 1.1 christos 793 1.1 christos OSSL_LIB_CTX_free(provctx); 794 1.1 christos 795 1.1 christos for (i = 0; i < NUM_DUMMY_GROUPS; i++) { 796 1.1 christos OPENSSL_free(dummy_group_names[i]); 797 1.1 christos dummy_group_names[i] = NULL; 798 1.1 christos } 799 1.1 christos } 800 1.1 christos 801 1.1 christos /* Functions we provide to the core */ 802 1.1 christos static const OSSL_DISPATCH tls_prov_dispatch_table[] = { 803 1.1 christos { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))tls_prov_teardown }, 804 1.1 christos { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))tls_prov_query }, 805 1.1 christos { OSSL_FUNC_PROVIDER_GET_CAPABILITIES, (void (*)(void))tls_prov_get_capabilities }, 806 1.1 christos { 0, NULL } 807 1.1 christos }; 808 1.1 christos 809 1.1 christos static 810 1.1 christos unsigned int randomize_tls_group_id(OSSL_LIB_CTX *libctx) 811 1.1 christos { 812 1.1 christos /* 813 1.1 christos * Randomise the group_id we're going to use to ensure we don't interoperate 814 1.1 christos * with anything but ourselves. 815 1.1 christos */ 816 1.1 christos unsigned int group_id; 817 1.1 christos static unsigned int mem[10] = { 0 }; 818 1.1 christos static int in_mem = 0; 819 1.1 christos int i; 820 1.1 christos 821 1.1 christos retry: 822 1.1 christos if (RAND_bytes_ex(libctx, (unsigned char *)&group_id, sizeof(group_id), 0) <= 0) 823 1.1 christos return 0; 824 1.1 christos /* 825 1.1 christos * Ensure group_id is within the IANA Reserved for private use range 826 1.1.1.2 christos * (65024-65279). 827 1.1.1.2 christos * Carve out NUM_DUMMY_GROUPS ids for properly registering those. 828 1.1 christos */ 829 1.1.1.2 christos group_id %= 65279 - NUM_DUMMY_GROUPS - 65024; 830 1.1 christos group_id += 65024; 831 1.1 christos 832 1.1 christos /* Ensure we did not already issue this group_id */ 833 1.1 christos for (i = 0; i < in_mem; i++) 834 1.1 christos if (mem[i] == group_id) 835 1.1 christos goto retry; 836 1.1 christos 837 1.1 christos /* Add this group_id to the list of ids issued by this function */ 838 1.1 christos mem[in_mem++] = group_id; 839 1.1 christos 840 1.1 christos return group_id; 841 1.1 christos } 842 1.1 christos 843 1.1 christos int tls_provider_init(const OSSL_CORE_HANDLE *handle, 844 1.1 christos const OSSL_DISPATCH *in, 845 1.1 christos const OSSL_DISPATCH **out, 846 1.1 christos void **provctx) 847 1.1 christos { 848 1.1 christos OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); 849 1.1 christos 850 1.1 christos if (libctx == NULL) 851 1.1 christos return 0; 852 1.1 christos 853 1.1 christos *provctx = libctx; 854 1.1 christos 855 1.1 christos /* 856 1.1 christos * Randomise the group_id we're going to use to ensure we don't interoperate 857 1.1 christos * with anything but ourselves. 858 1.1 christos */ 859 1.1 christos xor_group.group_id = randomize_tls_group_id(libctx); 860 1.1 christos xor_kemgroup.group_id = randomize_tls_group_id(libctx); 861 1.1 christos 862 1.1 christos *out = tls_prov_dispatch_table; 863 1.1 christos return 1; 864 1.1 christos } 865