int main(void) { sodium_init(); //create a user_store user_store *store = user_store_create(); //check the content buffer_t *list = user_store_list(store); if (list->content_length != 0) { fprintf(stderr, "ERROR: List of users is not empty.\n"); user_store_destroy(store); buffer_destroy_from_heap(list); return EXIT_FAILURE; } buffer_destroy_from_heap(list); int status; //create three users with prekeys and identity keys //first alice //alice identity key buffer_t *alice_private_identity = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *alice_public_identity = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); status = generate_and_print_keypair( alice_public_identity, alice_private_identity, buffer_create_from_string("Alice"), buffer_create_from_string("identity")); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Alice's identity keypair.\n"); buffer_clear(alice_private_identity); return status; } //alice prekeys buffer_t *alice_private_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES, PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES); buffer_t *alice_public_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES, PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES); status = generate_prekeys(alice_private_prekeys, alice_public_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Alice's prekeys.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); return status; } //then bob //bob's identity key buffer_t *bob_private_identity = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *bob_public_identity = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); status = generate_and_print_keypair( bob_public_identity, bob_private_identity, buffer_create_from_string("Bob"), buffer_create_from_string("identity")); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Bob's identity keypair.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); return status; } //bob's prekeys buffer_t *bob_private_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES, PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES); buffer_t *bob_public_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES, PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES); status = generate_prekeys(bob_private_prekeys, bob_public_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Bob's prekeys.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); return status; } //then charlie //charlie's identity key buffer_t *charlie_private_identity = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *charlie_public_identity = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); status = generate_and_print_keypair( charlie_public_identity, charlie_private_identity, buffer_create_from_string("Charlie"), buffer_create_from_string("identity")); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Charlie's identity keypair.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); return status; } //charlie's prekeys buffer_t *charlie_private_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES, PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES); buffer_t *charlie_public_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES, PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES); status = generate_prekeys(charlie_private_prekeys, charlie_public_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Charlie's prekeys.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); return status; } //add alice to the user store status = user_store_add( store, alice_public_identity, alice_private_identity, alice_public_prekeys, alice_private_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to add Alice to the user store.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return status; } printf("Successfully added Alice to the user store.\n"); //check length of the user store sodium_mprotect_readonly(store); if (store->length != 1) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //list user store list = user_store_list(store); if (buffer_compare(list, alice_public_identity) != 0) { fprintf(stderr, "ERROR: Failed to list users.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); buffer_destroy_from_heap(list); user_store_destroy(store); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully listed users.\n"); //add bob to the user store status = user_store_add( store, bob_public_identity, bob_private_identity, bob_public_prekeys, bob_private_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to add Bob to the user store.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return status; } printf("Successfully added Bob to the user store.\n"); //check length of the user store sodium_mprotect_readonly(store); if (store->length != 2) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //list user store list = user_store_list(store); if ((buffer_compare_partial(list, 0, alice_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, crypto_box_PUBLICKEYBYTES, bob_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0)) { fprintf(stderr, "ERROR: Failed to list users.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); buffer_destroy_from_heap(list); user_store_destroy(store); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully listed users.\n"); //add charlie to the user store status = user_store_add( store, charlie_public_identity, charlie_private_identity, charlie_public_prekeys, charlie_private_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to add Charlie to the user store.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return status; } printf("Successfully added Charlie to the user store.\n"); //check length of the user store sodium_mprotect_readonly(store); if (store->length != 3) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //list user store list = user_store_list(store); if ((buffer_compare_partial(list, 0, alice_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, crypto_box_PUBLICKEYBYTES, bob_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, 2 * crypto_box_PUBLICKEYBYTES, charlie_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0)) { fprintf(stderr, "ERROR: Failed to list users.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); buffer_destroy_from_heap(list); user_store_destroy(store); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully listed users.\n"); //find node user_store_node *bob_node = user_store_find_node(store, bob_public_identity); if (bob_node == NULL) { fprintf(stderr, "ERROR: Failed to find Bob's node.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } printf("Node found.\n"); sodium_mprotect_readonly(bob_node); if ((buffer_compare(&(bob_node->public_identity_key), bob_public_identity) != 0) || (buffer_compare(&(bob_node->private_identity_key), bob_private_identity) != 0) || (buffer_compare(&(bob_node->public_prekeys), bob_public_prekeys) != 0) || (buffer_compare(&(bob_node->private_prekeys), bob_private_prekeys) != 0)) { fprintf(stderr, "ERROR: Bob's data from the user store doesn't match.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(bob_node); printf("Data from the node matches.\n"); //remove a user identified by it's key user_store_remove_by_key(store, bob_public_identity); //check the length sodium_mprotect_readonly(store); if (store->length != 2) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //check the user list list = user_store_list(store); if ((buffer_compare_partial(list, 0, alice_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, crypto_box_PUBLICKEYBYTES, charlie_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0)) { fprintf(stderr, "ERROR: Removing user failed.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); buffer_destroy_from_heap(list); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully removed user.\n"); //readd bob status = user_store_add( store, bob_public_identity, bob_private_identity, bob_public_prekeys, bob_private_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to readd Bob to the user store.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return status; } printf("Successfully readded Bob to the user store.\n"); //now find bob again bob_node = user_store_find_node(store, bob_public_identity); if (bob_node == NULL) { fprintf(stderr, "ERROR: Failed to find Bob's node.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } printf("Bob's node found again.\n"); //remove bob by it's node user_store_remove(store, bob_node); //check the length sodium_mprotect_readonly(store); if (store->length != 2) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //check the user list list = user_store_list(store); if ((buffer_compare_partial(list, 0, alice_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, crypto_box_PUBLICKEYBYTES, charlie_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0)) { fprintf(stderr, "ERROR: Removing user failed.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); buffer_destroy_from_heap(list); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully removed user.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); //clear the user store user_store_clear(store); //check the length sodium_mprotect_readonly(store); if (store->length != 0) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); user_store_destroy(store); return EXIT_FAILURE; } printf("Successfully cleared user store.\n"); sodium_mprotect_noaccess(store); user_store_destroy(store); return EXIT_SUCCESS; }
int main(void) { if (sodium_init() == -1) { return -1; } return_status status = return_status_init(); buffer_t *public_prekey = buffer_create_on_heap(PUBLIC_KEY_SIZE, PUBLIC_KEY_SIZE); buffer_t *private_prekey1 = buffer_create_on_heap(PRIVATE_KEY_SIZE, PRIVATE_KEY_SIZE); buffer_t *private_prekey2 = buffer_create_on_heap(PRIVATE_KEY_SIZE, PRIVATE_KEY_SIZE); buffer_t *prekey_list = buffer_create_on_heap(PREKEY_AMOUNT * PUBLIC_KEY_SIZE, PREKEY_AMOUNT * PUBLIC_KEY_SIZE); Prekey **protobuf_export_prekeys = NULL; buffer_t **protobuf_export_prekeys_buffers = NULL; size_t protobuf_export_prekeys_size = 0; Prekey **protobuf_export_deprecated_prekeys = NULL; buffer_t **protobuf_export_deprecated_prekeys_buffers = NULL; size_t protobuf_export_deprecated_prekeys_size = 0; Prekey **protobuf_second_export_prekeys = NULL; buffer_t **protobuf_second_export_prekeys_buffers = NULL; size_t protobuf_second_export_prekeys_size = 0; Prekey **protobuf_second_export_deprecated_prekeys = NULL; buffer_t **protobuf_second_export_deprecated_prekeys_buffers = NULL; size_t protobuf_second_export_deprecated_prekeys_size = 0; prekey_store *store = NULL; status = prekey_store_create(&store); throw_on_error(CREATION_ERROR, "Failed to create a prekey store."); status = prekey_store_list(store, prekey_list); throw_on_error(DATA_FETCH_ERROR, "Failed to list prekeys."); printf("Prekey list:\n"); print_hex(prekey_list); putchar('\n'); //compare the public keys with the ones in the prekey store for (size_t i = 0; i < PREKEY_AMOUNT; i++) { if (buffer_compare_partial(prekey_list, PUBLIC_KEY_SIZE * i, store->prekeys[i].public_key, 0, PUBLIC_KEY_SIZE) != 0) { throw(INCORRECT_DATA, "Key list doesn't match the prekey store."); } } printf("Prekey list matches the prekey store!\n"); //get a private key const size_t prekey_index = 10; if (buffer_clone(public_prekey, store->prekeys[prekey_index].public_key) != 0) { throw(BUFFER_ERROR, "Failed to clone public key."); } status = prekey_store_get_prekey(store, public_prekey, private_prekey1); throw_on_error(DATA_FETCH_ERROR, "Failed to get prekey.") printf("Get a Prekey:\n"); printf("Public key:\n"); print_hex(public_prekey); printf("Private key:\n"); print_hex(private_prekey1); putchar('\n'); if (store->deprecated_prekeys == NULL) { throw(GENERIC_ERROR, "Failed to deprecate requested key."); } if ((buffer_compare(public_prekey, store->deprecated_prekeys->public_key) != 0) || (buffer_compare(private_prekey1, store->deprecated_prekeys->private_key) != 0)) { throw(INCORRECT_DATA, "Deprecated key is incorrect."); } if (buffer_compare(store->prekeys[prekey_index].public_key, public_prekey) == 0) { throw(KEYGENERATION_FAILED, "Failed to generate new key for deprecated one."); } printf("Successfully deprecated requested key!\n"); //check if the prekey can be obtained from the deprecated keys status = prekey_store_get_prekey(store, public_prekey, private_prekey2); throw_on_error(DATA_FETCH_ERROR, "Failed to get key from the deprecated area."); if (buffer_compare(private_prekey1, private_prekey2) != 0) { throw(INCORRECT_DATA, "Prekey from the deprecated area didn't match."); } printf("Successfully got prekey from the deprecated area!\n"); //try to get a nonexistent key if (buffer_fill_random(public_prekey, PUBLIC_KEY_SIZE) != 0) { throw(KEYGENERATION_FAILED, "Failed to generate invalid public prekey."); } status = prekey_store_get_prekey(store, public_prekey, private_prekey1); if (status.status == SUCCESS) { throw(GENERIC_ERROR, "Didn't complain about invalid public key."); } printf("Detected invalid public prekey!\n"); //reset return status return_status_destroy_errors(&status); status.status = SUCCESS; //Protobuf-C export printf("Protobuf-C export\n"); status = protobuf_export( store, &protobuf_export_prekeys, &protobuf_export_prekeys_size, &protobuf_export_prekeys_buffers, &protobuf_export_deprecated_prekeys, &protobuf_export_deprecated_prekeys_size, &protobuf_export_deprecated_prekeys_buffers); throw_on_error(EXPORT_ERROR, "Failed to export prekey store to protobuf."); printf("Prekeys:\n"); puts("[\n"); for (size_t i = 0; i < protobuf_export_prekeys_size; i++) { print_hex(protobuf_export_prekeys_buffers[i]); puts(",\n"); } puts("]\n\n"); printf("Deprecated Prekeys:\n"); puts("[\n"); for (size_t i = 0; i < protobuf_export_deprecated_prekeys_size; i++) { print_hex(protobuf_export_deprecated_prekeys_buffers[i]); puts(",\n"); } puts("]\n\n"); prekey_store_destroy(store); store = NULL; printf("Import from Protobuf-C\n"); status = protobuf_import( &store, protobuf_export_prekeys_buffers, protobuf_export_prekeys_size, protobuf_export_deprecated_prekeys_buffers, protobuf_export_deprecated_prekeys_size); throw_on_error(IMPORT_ERROR, "Failed to import from protobuf."); printf("Protobuf-C export again\n"); status = protobuf_export( store, &protobuf_second_export_prekeys, &protobuf_second_export_prekeys_size, &protobuf_second_export_prekeys_buffers, &protobuf_second_export_deprecated_prekeys, &protobuf_second_export_deprecated_prekeys_size, &protobuf_second_export_deprecated_prekeys_buffers); throw_on_error(EXPORT_ERROR, "Failed to export prekey store to protobuf."); //compare both prekey lists printf("Compare normal prekeys\n"); if (protobuf_export_prekeys_size != protobuf_second_export_prekeys_size) { throw(INCORRECT_DATA, "Both prekey exports contain different amounts of keys."); } for (size_t i = 0; i < protobuf_export_prekeys_size; i++) { if (buffer_compare(protobuf_export_prekeys_buffers[i], protobuf_second_export_prekeys_buffers[i]) != 0) { throw(INCORRECT_DATA, "First and second prekey export are not identical."); } } //compare both deprecated prekey lists printf("Compare deprecated prekeys\n"); if (protobuf_export_deprecated_prekeys_size != protobuf_second_export_deprecated_prekeys_size) { throw(INCORRECT_DATA, "Both depcated prekey exports contain different amounts of keys."); } for (size_t i = 0; i < protobuf_export_deprecated_prekeys_size; i++) { if (buffer_compare(protobuf_export_deprecated_prekeys_buffers[i], protobuf_second_export_deprecated_prekeys_buffers[i]) != 0) { throw(INCORRECT_DATA, "First and second deprecated prekey export are not identical."); } } //test the automatic deprecation of old keys if (buffer_clone(public_prekey, store->prekeys[PREKEY_AMOUNT-1].public_key) != 0) { throw(BUFFER_ERROR, "Failed to clone public key."); } store->prekeys[PREKEY_AMOUNT-1].expiration_date -= 365 * 24 * 3600; //one year store->oldest_expiration_date = store->prekeys[PREKEY_AMOUNT - 1].expiration_date; status = prekey_store_rotate(store); throw_on_error(GENERIC_ERROR, "Failed to rotate the prekeys."); if (buffer_compare(store->deprecated_prekeys->public_key, public_prekey) != 0) { throw(GENERIC_ERROR, "Failed to deprecate outdated key."); } printf("Successfully deprecated outdated key!\n"); //test the automatic removal of old deprecated keys! if (buffer_clone(public_prekey, store->deprecated_prekeys->next->public_key) != 0) { throw(BUFFER_ERROR, "Failed to clone public key."); } store->deprecated_prekeys->next->expiration_date -= 24 * 3600; store->oldest_deprecated_expiration_date = store->deprecated_prekeys->next->expiration_date; status = prekey_store_rotate(store); throw_on_error(GENERIC_ERROR, "Failed to rotate the prekeys."); if (store->deprecated_prekeys->next != NULL) { throw(GENERIC_ERROR, "Failed to remove outdated key."); } printf("Successfully removed outdated deprecated key!\n"); status = protobuf_no_deprecated_keys(); throw_on_error(GENERIC_ERROR, "Failed to im-/export a prekey store without deprecated prekeys."); cleanup: buffer_destroy_from_heap_and_null_if_valid(public_prekey); buffer_destroy_from_heap_and_null_if_valid(private_prekey1); buffer_destroy_from_heap_and_null_if_valid(private_prekey2); buffer_destroy_from_heap_and_null_if_valid(prekey_list); prekey_store_destroy(store); if (protobuf_export_prekeys != NULL) { for (size_t i = 0; i < protobuf_export_prekeys_size; i++) { if (protobuf_export_prekeys[i] != NULL) { prekey__free_unpacked(protobuf_export_prekeys[i], &protobuf_c_allocators); protobuf_export_prekeys[i] = NULL; } } zeroed_free_and_null_if_valid(protobuf_export_prekeys); } if (protobuf_export_deprecated_prekeys != NULL) { for (size_t i = 0; i < protobuf_export_deprecated_prekeys_size; i++) { if (protobuf_export_deprecated_prekeys[i] != NULL) { prekey__free_unpacked(protobuf_export_deprecated_prekeys[i], &protobuf_c_allocators); protobuf_export_deprecated_prekeys[i] = NULL; } } zeroed_free_and_null_if_valid(protobuf_export_deprecated_prekeys); } if (protobuf_export_prekeys_buffers != NULL) { for (size_t i = 0; i < protobuf_export_prekeys_size; i++) { buffer_destroy_from_heap_and_null_if_valid(protobuf_export_prekeys_buffers[i]); } zeroed_free_and_null_if_valid(protobuf_export_prekeys_buffers); } if (protobuf_export_deprecated_prekeys_buffers != NULL) { for (size_t i = 0; i < protobuf_export_deprecated_prekeys_size; i++) { buffer_destroy_from_heap_and_null_if_valid(protobuf_export_deprecated_prekeys_buffers[i]); } zeroed_free_and_null_if_valid(protobuf_export_deprecated_prekeys_buffers); } if (protobuf_second_export_prekeys != NULL) { for (size_t i = 0; i < protobuf_second_export_prekeys_size; i++) { if (protobuf_second_export_prekeys[i] != NULL) { prekey__free_unpacked(protobuf_second_export_prekeys[i], &protobuf_c_allocators); protobuf_second_export_prekeys[i] = NULL; } } zeroed_free_and_null_if_valid(protobuf_second_export_prekeys); } if (protobuf_second_export_deprecated_prekeys != NULL) { for (size_t i = 0; i < protobuf_second_export_deprecated_prekeys_size; i++) { if (protobuf_second_export_deprecated_prekeys[i] != NULL) { prekey__free_unpacked(protobuf_second_export_deprecated_prekeys[i], &protobuf_c_allocators); protobuf_second_export_deprecated_prekeys[i] = NULL; } } zeroed_free_and_null_if_valid(protobuf_second_export_deprecated_prekeys); } if (protobuf_second_export_prekeys_buffers != NULL) { for (size_t i = 0; i < protobuf_second_export_prekeys_size; i++) { buffer_destroy_from_heap_and_null_if_valid(protobuf_second_export_prekeys_buffers[i]); } zeroed_free_and_null_if_valid(protobuf_second_export_prekeys_buffers); } if (protobuf_second_export_deprecated_prekeys_buffers != NULL) { for (size_t i = 0; i < protobuf_second_export_deprecated_prekeys_size; i++) { buffer_destroy_from_heap_and_null_if_valid(protobuf_second_export_deprecated_prekeys_buffers[i]); } zeroed_free_and_null_if_valid(protobuf_second_export_deprecated_prekeys_buffers); } on_error { print_errors(&status); } return_status_destroy_errors(&status); return status.status; }