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