Coverage Report

Created: 2025-04-11 06:50

/src/cyclonedds/fuzz/fuzz_handshake/fuzz_handshake_harness.c
Line
Count
Source (jump to first uncovered line)
1
#include "fuzz_handshake_harness.h"
2
#include "fuzz_handshake_expose.h"
3
4
#include <string.h>
5
#include <dlfcn.h>
6
7
#include <dds/features.h>
8
#include <dds__types.h>
9
#include <dds__init.h>
10
#include <dds__domain.h>
11
#include <ddsi__addrset.h>
12
#include <ddsi__handshake.h>
13
#include <ddsi__thread.h>
14
#include <ddsi__plist.h>
15
#include <ddsi__proxy_participant.h>
16
#include <ddsi__vendor.h>
17
#include <ddsi__protocol.h>
18
#include <ddsi__security_util.h>
19
#include <ddsi__xevent.h>
20
#include <ddsi__gc.h>
21
#include <dds__qos.h>
22
#include <dds/ddsi/ddsi_iid.h>
23
#include <dds/ddsi/ddsi_init.h>
24
#include <dds/ddsi/ddsi_participant.h>
25
#include <dds/ddsi/ddsi_entity_index.h>
26
#include <dds/ddsi/ddsi_unused.h>
27
#include <ddsi__security_omg.h>
28
#include <dds/security/core/dds_security_fsm.h>
29
#include <dds/security/core/dds_security_utils.h>
30
#include <dds/security/core/dds_security_serialize.h>
31
#include <common/test_identity.h>
32
33
#include <openssl/pem.h>
34
35
const char *sec_config =
36
    "<Domain id=\"any\">"
37
    "  <Discovery>"
38
    "    <Tag>${CYCLONEDDS_PID}</Tag>"
39
    "  </Discovery>"
40
    "  <Tracing><Verbosity>finest</></>"
41
    "  <Security>"
42
    "    <Authentication>"
43
    "      <Library initFunction=\"init_authentication\" finalizeFunction=\"finalize_authentication\" path=\"dds_security_auth\"/>"
44
    "      <IdentityCertificate>data:," TEST_IDENTITY1_CERTIFICATE "</IdentityCertificate>"
45
    "      <PrivateKey>data:," TEST_IDENTITY1_PRIVATE_KEY "</PrivateKey>"
46
    "      <IdentityCA>data:," TEST_IDENTITY_CA1_CERTIFICATE "</IdentityCA>"
47
    "    </Authentication>"
48
    "    <Cryptographic>"
49
    "      <Library initFunction=\"init_crypto\" finalizeFunction=\"finalize_crypto\" path=\"dds_security_crypto\"/>"
50
    "    </Cryptographic>"
51
    "    <AccessControl>"
52
    "      <Library initFunction=\"init_access_control\" finalizeFunction=\"finalize_access_control\" path=\"dds_security_ac\"/>"
53
    "      <Governance></Governance>"
54
    "      <PermissionsCA></PermissionsCA>"
55
    "      <Permissions></Permissions>"
56
    "    </AccessControl>"
57
    "  </Security>"
58
    "</Domain>";
59
struct ddsi_cfgst *g_cfgst;
60
struct ddsi_guid g_ppguid;
61
struct ddsi_guid g_proxy_ppguid;
62
static struct ddsi_thread_state *thrst;
63
static struct ddsi_domaingv gv;
64
EVP_PKEY *g_private_key;
65
66
2.74M
#define FUZZ_HANDSHAKE_EVENT_HANDLED (-4)
67
ddsrt_atomic_uint32_t g_fsm_done;
68
ddsrt_atomic_uint32_t g_fuzz_events;
69
70
static ddsrt_dynlib_t auth_plugin_handle;
71
72
typedef DDS_Security_ValidationResult_t (*dhpkey2oct_t)(EVP_PKEY *, int, unsigned char **, uint32_t *, DDS_Security_SecurityException *);
73
static dhpkey2oct_t dh_public_key_to_oct_ptr = NULL;
74
75
typedef DDS_Security_ValidationResult_t (*gendhkeys_t)(EVP_PKEY **, int, DDS_Security_SecurityException *);
76
static gendhkeys_t generate_dh_keys_ptr = NULL;
77
78
typedef DDS_Security_ValidationResult_t (*cvas_t)(bool, EVP_PKEY *, const unsigned char *, const size_t, unsigned char **, size_t *, DDS_Security_SecurityException *);
79
static cvas_t create_validate_asymmetrical_signature_ptr = NULL;
80
81
struct {
82
    struct ddsi_participant *pp;
83
    struct ddsi_proxy_participant *proxy_pp;
84
    struct ddsi_handshake *hs;
85
} harness;
86
87
bool fuzz_handshake_init()
88
1
{
89
    // Load private key for remote identity
90
1
    BIO *bio;
91
1
    bio = BIO_new_mem_buf(TEST_IDENTITY3_PRIVATE_KEY, -1);
92
1
    if (!bio) abort();
93
1
    g_private_key = PEM_read_bio_PrivateKey(bio, NULL, NULL, "");
94
1
    if (!g_private_key) abort();
95
1
    BIO_free(bio);
96
97
    //ddsi_iid_init();
98
1
    ddsi_thread_states_init();
99
    // register the main thread, then claim it as spawned by Cyclone because the
100
    // internal processing has various asserts that it isn't an application thread
101
    // doing the dirty work
102
1
    thrst = ddsi_lookup_thread_state ();
103
1
    assert (thrst->state == DDSI_THREAD_STATE_LAZILY_CREATED);
104
1
    thrst->state = DDSI_THREAD_STATE_ALIVE;
105
1
    thrst->vtime.v = 0;
106
1
    ddsrt_atomic_stvoidp (&thrst->gv, &gv);
107
1
    memset(&gv, 0, sizeof(gv));
108
1
    ddsi_config_init_default(&gv.config);
109
1
    gv.config.transport_selector = DDSI_TRANS_NONE;
110
1
    ddsi_config_prep(&gv, NULL);
111
1
    ddsi_init(&gv, NULL);
112
1
    gv.handshake_include_optional = true;
113
1
    g_cfgst = ddsi_config_init(sec_config, &gv.config, 1);
114
115
    //FILE *fp = fopen("/dev/stdout", "w");
116
    //dds_log_cfg_init(&gv.logconfig, 1, DDS_LC_TRACE | DDS_LC_ERROR | DDS_LC_WARNING, NULL, fp);
117
118
    // Disable logging
119
1
    dds_log_cfg_init(&gv.logconfig, 1, 0, NULL, NULL);
120
121
    // We use a statically linked build, all functions we need to lookup need to be
122
    // exported from the plugin
123
    //
124
    // See src/security/builtin_plugins/authentication/CMakeLists.txt
125
1
    if (ddsrt_dlopen("dds_security_auth", true, &auth_plugin_handle) != DDS_RETCODE_OK)
126
0
      abort();
127
1
    if (ddsrt_dlsym(auth_plugin_handle, "generate_dh_keys", (void **)&generate_dh_keys_ptr) != DDS_RETCODE_OK)
128
0
      abort();
129
1
    if (ddsrt_dlsym(auth_plugin_handle, "dh_public_key_to_oct", (void **)&dh_public_key_to_oct_ptr) != DDS_RETCODE_OK)
130
0
      abort();
131
1
    if (ddsrt_dlsym(auth_plugin_handle, "create_validate_asymmetrical_signature", (void **)&create_validate_asymmetrical_signature_ptr) != DDS_RETCODE_OK)
132
0
      abort();
133
134
    // Create participant
135
1
    ddsi_thread_state_awake(ddsi_lookup_thread_state(), &gv);
136
1
    {
137
1
        ddsi_plist_t pplist;
138
1
        ddsi_plist_init_empty(&pplist);
139
1
        dds_qos_t *new_qos = dds_create_qos();
140
1
        ddsi_xqos_mergein_missing (new_qos, &gv.default_local_xqos_pp, ~(uint64_t)0);
141
1
        dds_apply_entity_naming(new_qos, NULL, &gv);
142
1
        ddsi_xqos_mergein_missing (&pplist.qos, new_qos, ~(uint64_t)0);
143
1
        dds_delete_qos(new_qos);
144
145
1
        ddsi_generate_participant_guid (&g_ppguid, &gv);
146
1
        dds_return_t ret = ddsi_new_participant(&g_ppguid, &gv, 0, &pplist);
147
1
        if(ret != DDS_RETCODE_OK) abort();
148
1
        harness.pp = ddsi_entidx_lookup_participant_guid(gv.entity_index, &g_ppguid);
149
1
        ddsi_plist_fini(&pplist);
150
1
    }
151
0
    ddsi_thread_state_asleep(ddsi_lookup_thread_state());
152
153
1
    return true;
154
1
}
155
156
static void hs_end_cb(UNUSED_ARG(struct ddsi_handshake *handshake),
157
                      UNUSED_ARG(struct ddsi_participant *pp),
158
                      UNUSED_ARG(struct ddsi_proxy_participant *proxy_pp),
159
                      UNUSED_ARG(enum ddsi_handshake_state state))
160
546
{
161
    //printf("HANDSHAKE END: %d\n", state); fflush(stdout);
162
546
}
163
164
static void fsm_debug_func(UNUSED_ARG(struct dds_security_fsm *fsm), DDS_SECURITY_FSM_DEBUG_ACT act, UNUSED_ARG(const dds_security_fsm_state *current), int event_id, UNUSED_ARG(void *arg))
165
4.19M
{
166
    // This event is never generated by the state machine.
167
    // The fuzzer throws it in at the end of its events to signal that it's done
168
    // and the handshake can be abandoned.
169
4.19M
    if (act == DDS_SECURITY_FSM_DEBUG_ACT_HANDLING && event_id == DDS_SECURITY_FSM_EVENT_DELETE) {
170
4.04k
        ddsrt_atomic_st32(&g_fsm_done, 1);
171
4.04k
    }
172
173
    // This event is used to serialize the fuzzer, as the state machine is driven by a
174
    // separate thread. The fuzzer generates events and waits for the state machine to
175
    // finish the resulting transition. This prevents triggering any race conditions which
176
    // may result from a bug in the fuzzing harness. Further, the handshake data structures
177
    // containing the messages from a remote participant are being reused, so overwriting them
178
    // before the state machine handled a message will lead nowhere. Lastly, the harness does
179
    // not need to concern itself with locking.
180
4.19M
    if (act == DDS_SECURITY_FSM_DEBUG_ACT_HANDLING && event_id == FUZZ_HANDSHAKE_EVENT_HANDLED) {
181
639k
        ddsrt_atomic_inc32(&g_fuzz_events);
182
639k
    }
183
4.19M
}
184
185
4.04k
void fuzz_handshake_reset(bool initiate_remote) {
186
4.04k
    ddsrt_atomic_st32(&g_fsm_done, 0);
187
4.04k
    ddsrt_atomic_st32(&g_fuzz_events, 0);
188
189
    // Create proxy participant
190
4.04k
    ddsi_plist_t pplist;
191
4.04k
    ddsi_plist_init_empty(&pplist);
192
4.04k
    pplist.present |= PP_IDENTITY_TOKEN;
193
4.04k
    ddsi_token_t identity_token = {
194
4.04k
        .class_id = strdup(DDS_SECURITY_AUTH_TOKEN_CLASS_ID),
195
4.04k
        .properties = {
196
4.04k
            .n = 0,
197
4.04k
            .props = NULL
198
4.04k
        },
199
4.04k
        .binary_properties = {
200
4.04k
            .n = 0,
201
4.04k
            .props = NULL
202
4.04k
        }
203
4.04k
    };
204
205
4.04k
    pplist.identity_token = identity_token;
206
4.04k
    union { uint64_t u64; uint32_t u32[2]; } u;
207
4.04k
    u.u32[0] = gv.ppguid_base.prefix.u[1];
208
4.04k
    u.u32[1] = gv.ppguid_base.prefix.u[2];
209
4.04k
    u.u64 += ddsi_iid_gen ();
210
4.04k
    g_proxy_ppguid.prefix.u[0] = gv.ppguid_base.prefix.u[0];
211
4.04k
    g_proxy_ppguid.prefix.u[1] = u.u32[0];
212
4.04k
    g_proxy_ppguid.prefix.u[2] = u.u32[1];
213
4.04k
    g_proxy_ppguid.entityid.u = DDSI_ENTITYID_PARTICIPANT;
214
4.04k
    if (!initiate_remote) {
215
3.72k
        g_proxy_ppguid.prefix.s[0] = 0xff;
216
3.72k
        g_proxy_ppguid.prefix.s[1] = 0xff;
217
3.72k
        g_proxy_ppguid.prefix.s[2] = 0xff;
218
3.72k
    } else {
219
324
        g_proxy_ppguid.prefix.s[0] = 0x00;
220
324
        g_proxy_ppguid.prefix.s[1] = 0x00;
221
324
        g_proxy_ppguid.prefix.s[2] = 0x00;
222
324
    }
223
224
4.04k
    ddsrt_wctime_t timestamp = { .v = dds_time() };
225
226
    // We avoid generating network traffic by using DDSI_TRANS_NONE
227
    // This is the only valid locator for that "network".
228
4.04k
    const ddsi_locator_t loc = {
229
4.04k
      .kind = 2147483647, .address = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, .port = 0
230
4.04k
    };
231
4.04k
    struct ddsi_addrset *as = ddsi_new_addrset();
232
4.04k
    ddsi_add_locator_to_addrset(&gv,as, &loc);
233
4.04k
    assert(!ddsi_addrset_empty_uc(as));
234
235
4.04k
    ddsi_thread_state_awake(ddsi_lookup_thread_state(), &gv);
236
4.04k
    if (!ddsi_new_proxy_participant(&harness.proxy_pp, &gv,
237
4.04k
            &g_proxy_ppguid,
238
4.04k
            DDSI_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER|
239
4.04k
            DDSI_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_ANNOUNCER|DDSI_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_DETECTOR,
240
4.04k
            NULL,
241
4.04k
            as,
242
4.04k
            ddsi_ref_addrset(as),
243
4.04k
            &pplist,
244
4.04k
            DDS_INFINITY,
245
4.04k
            DDSI_VENDORID_ECLIPSE,
246
4.04k
            DDSI_CF_PROXYPP_NO_SPDP,
247
4.04k
            timestamp,
248
4.04k
            0)) {
249
0
        abort();
250
0
    }
251
4.04k
    ddsi_thread_state_asleep(ddsi_lookup_thread_state());
252
4.04k
    ddsi_plist_fini(&pplist);
253
254
4.04k
    harness.hs = ddsi_handshake_find(harness.pp, harness.proxy_pp);
255
4.04k
    if (harness.hs == NULL) abort();
256
257
    // We abuse the debug function for the serialization of the fuzzer thread
258
    // and the handshake fsm thread.
259
4.04k
    dds_security_fsm_set_debug(harness.hs->fsm, fsm_debug_func);
260
4.04k
    harness.hs->end_cb = hs_end_cb;
261
4.04k
    ddsi_handshake_release(harness.hs);
262
4.04k
}
263
264
196k
void fuzz_handshake_handle_timeout(void) {
265
196k
    dds_security_fsm_dispatch(harness.hs->fsm, DDS_SECURITY_FSM_EVENT_TIMEOUT, false);
266
196k
}
267
268
5.86k
static DDS_Security_ValidationResult_t create_dh_key(int algo, unsigned char **data, uint32_t *len) {
269
5.86k
    EVP_PKEY *key;
270
5.86k
    DDS_Security_SecurityException ex = {0};
271
5.86k
    DDS_Security_ValidationResult_t result = generate_dh_keys_ptr(&key, algo, &ex);
272
5.86k
    if (result != DDS_SECURITY_VALIDATION_OK) goto out;
273
274
5.86k
    result = dh_public_key_to_oct_ptr(key, algo, data, len, &ex);
275
5.86k
out:
276
5.86k
    EVP_PKEY_free(key);
277
5.86k
    DDS_Security_Exception_reset(&ex);
278
5.86k
    return result;
279
5.86k
}
280
281
316k
void fuzz_handshake_handle_request(ddsi_dataholder_t *token) {
282
316k
    struct ddsi_participant_generic_message msg;
283
316k
    msg.message_class_id = DDS_SECURITY_AUTH_HANDSHAKE;
284
316k
    msg.message_data.n = 1;
285
316k
    msg.message_data.tags = token;
286
316k
    token->class_id = DDS_SECURITY_AUTH_HANDSHAKE_REQUEST_TOKEN_ID;
287
288
1.13M
    for (uint32_t i = 0; i < token->binary_properties.n; i++) {
289
822k
        dds_binaryproperty_t *binprop = &token->binary_properties.props[i];
290
        // To avoid fuzzing openssl, always use a valid certificate
291
822k
        if (strcmp(binprop->name, "c.id") == 0) {
292
265k
            free(binprop->value.value);
293
265k
            binprop->value.length = strlen(TEST_IDENTITY3_CERTIFICATE);
294
265k
            binprop->value.value = (unsigned char *) strdup(TEST_IDENTITY3_CERTIFICATE);
295
265k
        }
296
        // Provide a valid dh public key
297
822k
        if (strcmp(binprop->name, "dh1") == 0) {
298
5.82k
            unsigned char *data;
299
5.82k
            uint32_t len;
300
5.82k
            if (create_dh_key(1, &data, &len) == DDS_SECURITY_VALIDATION_OK) {
301
5.82k
                free(binprop->value.value);
302
5.82k
                binprop->value.length = len;
303
5.82k
                binprop->value.value = data;
304
5.82k
            }
305
5.82k
        }
306
822k
    }
307
316k
    ddsi_handshake_handle_message(harness.hs, harness.pp, harness.proxy_pp, &msg);
308
316k
}
309
310
static void create_signature(const DDS_Security_BinaryProperty_t **bprops, uint32_t n_bprops, unsigned char **signature, size_t *signatureLen)
311
576
{
312
576
    unsigned char *buffer;
313
576
    size_t size;
314
576
    DDS_Security_Serializer serializer = DDS_Security_Serializer_new(4096, 4096);
315
576
    DDS_Security_Serialize_BinaryPropertyArray(serializer, bprops, n_bprops);
316
576
    DDS_Security_Serializer_buffer(serializer, &buffer, &size);
317
576
    DDS_Security_SecurityException ex;
318
576
    (void) create_validate_asymmetrical_signature_ptr(true, g_private_key, buffer, size, signature, signatureLen, &ex);
319
576
    free(buffer);
320
576
    DDS_Security_Serializer_free(serializer);
321
576
}
322
323
static void create_hash(const DDS_Security_DataHolder *dh, DDS_Security_BinaryProperty_t *bprop, const char *name)
324
56.0k
{
325
56.0k
    unsigned char *buffer;
326
56.0k
    size_t size;
327
328
56.0k
    DDS_Security_BinaryProperty_t *tokens = DDS_Security_BinaryPropertySeq_allocbuf(5);
329
56.0k
    const DDS_Security_BinaryProperty_t *c_id = DDS_Security_DataHolder_find_binary_property(dh, "c.id");
330
56.0k
    uint32_t tokidx = 0;
331
56.0k
    if (c_id) DDS_Security_BinaryProperty_copy(&tokens[tokidx++], c_id);
332
56.0k
    const DDS_Security_BinaryProperty_t *c_perm = DDS_Security_DataHolder_find_binary_property(dh, "c.perm");
333
56.0k
    if (c_perm) DDS_Security_BinaryProperty_copy(&tokens[tokidx++], c_perm);
334
56.0k
    const DDS_Security_BinaryProperty_t *c_pdata = DDS_Security_DataHolder_find_binary_property(dh, "c.pdata");
335
56.0k
    if (c_pdata) DDS_Security_BinaryProperty_copy(&tokens[tokidx++], c_pdata);
336
56.0k
    const DDS_Security_BinaryProperty_t *c_dsign_algo = DDS_Security_DataHolder_find_binary_property(dh, "c.dsign_algo");
337
56.0k
    if (c_dsign_algo) DDS_Security_BinaryProperty_copy(&tokens[tokidx++], c_dsign_algo);
338
56.0k
    const DDS_Security_BinaryProperty_t *c_kagree_algo = DDS_Security_DataHolder_find_binary_property(dh, "c.kagree_algo");
339
56.0k
    if (c_kagree_algo) DDS_Security_BinaryProperty_copy(&tokens[tokidx++], c_kagree_algo);
340
56.0k
    DDS_Security_BinaryPropertySeq seq = { ._length = tokidx, ._buffer = tokens };
341
56.0k
    DDS_Security_Serializer serializer = DDS_Security_Serializer_new(4096, 4096);
342
56.0k
    DDS_Security_Serialize_BinaryPropertySeq(serializer, &seq);
343
56.0k
    DDS_Security_Serializer_buffer(serializer, &buffer, &size);
344
345
56.0k
    unsigned char *hash = malloc(SHA256_DIGEST_LENGTH);
346
56.0k
    SHA256(buffer, size, hash);
347
56.0k
    free(buffer);
348
56.0k
    DDS_Security_Serializer_free(serializer);
349
350
56.0k
    bprop->name = strdup(name);
351
56.0k
    bprop->value._length = SHA256_DIGEST_LENGTH;
352
56.0k
    bprop->value._maximum = SHA256_DIGEST_LENGTH;
353
56.0k
    bprop->value._buffer = hash;
354
56.0k
    DDS_Security_BinaryPropertySeq_deinit(&seq);
355
56.0k
}
356
357
56.0k
void fuzz_handshake_handle_reply(ddsi_dataholder_t *token) {
358
56.0k
    struct ddsi_participant_generic_message msg;
359
56.0k
    msg.message_class_id = DDS_SECURITY_AUTH_HANDSHAKE;
360
56.0k
    msg.message_data.n = 1;
361
56.0k
    msg.message_data.tags = token;
362
56.0k
    token->class_id = DDS_SECURITY_AUTH_HANDSHAKE_REPLY_TOKEN_ID;
363
56.0k
    const DDS_Security_BinaryProperty_t *c1 = NULL;
364
56.0k
    const DDS_Security_BinaryProperty_t *c2 = NULL;
365
56.0k
    const DDS_Security_BinaryProperty_t *dh1 = NULL;
366
56.0k
    const DDS_Security_BinaryProperty_t *dh2 = NULL;
367
56.0k
    const DDS_Security_BinaryProperty_t *hash_c1 = NULL;
368
56.0k
    const DDS_Security_BinaryProperty_t *kagree_algo = NULL;
369
370
56.0k
    if (harness.hs->handshake_message_out != NULL) {
371
        // Using gv.handshake_include_optional = true;
372
1.32k
        c1 = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "challenge1");
373
1.32k
        dh1 = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "dh1");
374
1.32k
        hash_c1 = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "hash_c1");
375
1.32k
        kagree_algo = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "c.kagree_algo");
376
1.32k
    }
377
378
    // First fix up the values necessary for the hash
379
86.6k
    for (uint32_t i = 0; i < token->binary_properties.n; i++) {
380
30.6k
        dds_binaryproperty_t *binprop = &token->binary_properties.props[i];
381
        // To avoid fuzzing openssl, always use a valid certificate
382
30.6k
        if (strcmp(binprop->name, "c.id") == 0) {
383
2.84k
            free(binprop->value.value);
384
2.84k
            binprop->value.length = strlen(TEST_IDENTITY3_CERTIFICATE);
385
2.84k
            binprop->value.value = (unsigned char *) strdup(TEST_IDENTITY3_CERTIFICATE);
386
2.84k
        }
387
30.6k
        if ((strcmp(binprop->name, "challenge1") == 0) && c1) {
388
23
            free(binprop->value.value);
389
23
            binprop->value.length = DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE;
390
23
            binprop->value.value = malloc(DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE);
391
23
            memcpy(binprop->value.value, c1->value._buffer, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE);
392
23
        }
393
        // Provide a valid dh public key
394
30.6k
        if ((strcmp(binprop->name, "dh2") == 0) && kagree_algo) {
395
40
            int algo = 1;
396
40
            if (strncmp((const char *)kagree_algo->value._buffer, "ECDH+prime256v1-CEUM", kagree_algo->value._length) == 0) algo = 2;
397
40
            unsigned char *data;
398
40
            uint32_t len;
399
40
            if (create_dh_key(algo, &data, &len) == DDS_SECURITY_VALIDATION_OK) {
400
40
                free(binprop->value.value);
401
40
                binprop->value.length = len;
402
40
                binprop->value.value = data;
403
40
            }
404
40
        }
405
30.6k
    }
406
407
    // Generate the hash to be signed
408
56.0k
    DDS_Security_DataHolder token_holder;
409
56.0k
    ddsi_omg_shallow_copyin_DataHolder(&token_holder, token);
410
56.0k
    c2 = DDS_Security_DataHolder_find_binary_property(&token_holder, "challenge2");
411
56.0k
    dh2 = DDS_Security_DataHolder_find_binary_property(&token_holder, "dh2");
412
56.0k
    DDS_Security_BinaryProperty_t hash_c2 = {0};
413
56.0k
    create_hash(&token_holder, &hash_c2, "hash_c2");
414
415
86.6k
    for (uint32_t i = 0; i < token->binary_properties.n; i++) {
416
30.6k
        dds_binaryproperty_t *binprop = &token->binary_properties.props[i];
417
        // Need to provide a valid signature for the handshake to succeed
418
30.6k
        if (strcmp(binprop->name, "signature") == 0 && hash_c1 && c1 && c2 && dh1 && c2 && dh2 && hash_c2.value._buffer) {
419
165
            unsigned char *signature;
420
165
            size_t signatureLen;
421
165
            const DDS_Security_BinaryProperty_t *bprops[] = { &hash_c2, c2, dh2, c1, dh1, hash_c1};
422
165
            create_signature(bprops, 6, &signature, &signatureLen);
423
165
            free(binprop->value.value);
424
165
            binprop->value.length = (uint32_t) signatureLen;
425
165
            binprop->value.value = signature;
426
165
        }
427
30.6k
    }
428
56.0k
    DDS_Security_BinaryProperty_deinit(&hash_c2);
429
56.0k
    ddsi_handshake_handle_message(harness.hs, harness.pp, harness.proxy_pp, &msg);
430
56.0k
    ddsi_omg_shallow_free_DataHolder(&token_holder);
431
56.0k
}
432
433
41.9k
void fuzz_handshake_handle_final(ddsi_dataholder_t *token) {
434
41.9k
    struct ddsi_participant_generic_message msg;
435
41.9k
    msg.message_class_id = DDS_SECURITY_AUTH_HANDSHAKE;
436
41.9k
    msg.message_data.n = 1;
437
41.9k
    msg.message_data.tags = token;
438
41.9k
    token->class_id = DDS_SECURITY_AUTH_HANDSHAKE_FINAL_TOKEN_ID;
439
440
41.9k
    const DDS_Security_BinaryProperty_t *c1 = NULL;
441
41.9k
    const DDS_Security_BinaryProperty_t *c2 = NULL;
442
41.9k
    const DDS_Security_BinaryProperty_t *dh1 = NULL;
443
41.9k
    const DDS_Security_BinaryProperty_t *dh2 = NULL;
444
41.9k
    const DDS_Security_BinaryProperty_t *hash_c1 = NULL;
445
41.9k
    const DDS_Security_BinaryProperty_t *hash_c2 = NULL;
446
447
41.9k
    if (harness.hs->handshake_message_out != NULL) {
448
        // Using gv.handshake_include_optional = true;
449
1.30k
        c1 = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "challenge1");
450
1.30k
        c2 = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "challenge2");
451
1.30k
        dh1 = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "dh1");
452
1.30k
        dh2 = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "dh2");
453
1.30k
        hash_c1 = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "hash_c1");
454
1.30k
        hash_c2 = DDS_Security_DataHolder_find_binary_property(harness.hs->handshake_message_out, "hash_c2");
455
1.30k
    }
456
457
57.3k
    for (uint32_t i = 0; i < token->binary_properties.n; i++) {
458
15.3k
        dds_binaryproperty_t *binprop = &token->binary_properties.props[i];
459
        // Need to copy the correct values for challenge2 from the relation for the handshake to succeed
460
15.3k
        if ((strcmp(binprop->name, "challenge1") == 0) && c1) {
461
271
            free(binprop->value.value);
462
271
            binprop->value.length = DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE;
463
271
            binprop->value.value = malloc(DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE);
464
271
            memcpy(binprop->value.value, c1->value._buffer, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE);
465
271
        }
466
15.3k
        if ((strcmp(binprop->name, "challenge2") == 0) && c2) {
467
270
            free(binprop->value.value);
468
270
            binprop->value.length = DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE;
469
270
            binprop->value.value = malloc(DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE);
470
270
            memcpy(binprop->value.value, c2->value._buffer, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE);
471
270
        }
472
        // Need to provide a valid signature for the handshake to succeed
473
15.3k
        if (strcmp(binprop->name, "signature") == 0 && hash_c1 && c1 && c2 && dh1 && c2 && dh2 && hash_c2) {
474
411
            unsigned char *signature;
475
411
            size_t signatureLen;
476
411
            const DDS_Security_BinaryProperty_t *bprops[] = { hash_c1, c1, dh1, c2, dh2, hash_c2 };
477
411
            create_signature(bprops, 6, &signature, &signatureLen);
478
411
            free(binprop->value.value);
479
411
            binprop->value.length = (uint32_t) signatureLen;
480
411
            binprop->value.value = signature;
481
411
        }
482
15.3k
    }
483
484
41.9k
    ddsi_handshake_handle_message(harness.hs, harness.pp, harness.proxy_pp, &msg);
485
41.9k
}
486
487
28.5k
void fuzz_handshake_handle_crypto_tokens(void) {
488
28.5k
    ddsi_thread_state_awake(ddsi_lookup_thread_state(), &gv);
489
28.5k
    ddsi_handshake_crypto_tokens_received(harness.hs);
490
28.5k
    ddsi_thread_state_asleep(ddsi_lookup_thread_state());
491
28.5k
}
492
493
639k
void fuzz_handshake_wait_for_event(uint32_t event) {
494
639k
    dds_security_fsm_dispatch(harness.hs->fsm, FUZZ_HANDSHAKE_EVENT_HANDLED, false);
495
82.2G
    while(ddsrt_atomic_ld32(&g_fuzz_events) != event) {}
496
639k
}
497
498
4.04k
void fuzz_handshake_wait_for_completion(void) {
499
4.04k
    dds_security_fsm_dispatch(harness.hs->fsm, DDS_SECURITY_FSM_EVENT_DELETE, false);
500
23.3M
    while(ddsrt_atomic_ld32(&g_fsm_done) == 0) {}
501
4.04k
    ddsrt_wctime_t timestamp = { .v = dds_time() };
502
4.04k
    ddsi_thread_state_awake(ddsi_lookup_thread_state(), &gv);
503
4.04k
    ddsi_delete_proxy_participant_by_guid(&gv, &g_proxy_ppguid, timestamp, 1);
504
4.04k
    ddsi_thread_state_asleep(ddsi_lookup_thread_state());
505
4.04k
    harness.proxy_pp = NULL;
506
4.04k
    harness.hs = NULL;
507
508
    // To actually delete all we created we need to step the what is normally
509
    // done by 4 different threads in the background (multi-stage cleanup via
510
    // the GC involves bubbles sent through the delivery queues; and then one
511
    // has to "send" the messages queued by the handshake code).
512
4.04k
    bool x;
513
4.04k
    do {
514
4.04k
      x = false;
515
4.04k
      if (ddsi_gcreq_queue_step (gv.gcreq_queue))
516
0
        x = true;
517
4.04k
      if (ddsi_dqueue_step_deaf (gv.builtins_dqueue))
518
0
        x = true;
519
4.04k
      if (ddsi_dqueue_step_deaf (gv.user_dqueue))
520
0
        x = true;
521
4.04k
      ddsi_xeventq_step (gv.xevents);
522
4.04k
    } while (x);
523
4.04k
}