Home | History | Annotate | Line # | Download | only in test
      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