int main(void) { if (sodium_init() == -1) { return -1; } return_status status = return_status_init(); //create buffers buffer_t *master_key = buffer_create_on_heap(50, 50); buffer_t *subkey1 = buffer_create_on_heap(60, 60); buffer_t *subkey2 = buffer_create_on_heap(60, 60); buffer_t *subkey1_copy = buffer_create_on_heap(60, 60); int status_int = 0; status_int = buffer_fill_random(master_key, master_key->buffer_length); if (status_int != 0) { throw(KEYDERIVATION_FAILED, "Failed to generate master key."); } printf("Master key:\n"); print_hex(master_key); putchar('\n'); status = derive_key(subkey1, subkey1->buffer_length, master_key, 0); throw_on_error(KEYDERIVATION_FAILED, "Failed to derive first subkey."); printf("First subkey:\n"); print_hex(subkey1); putchar('\n'); status = derive_key(subkey2, subkey2->buffer_length, master_key, 1); throw_on_error(KEYDERIVATION_FAILED, "Failed to derive the second subkey."); printf("Second subkey:\n"); print_hex(subkey2); putchar('\n'); if (buffer_compare(subkey1, subkey2) == 0) { throw(KEYGENERATION_FAILED, "Both subkeys are the same."); } status = derive_key(subkey1_copy, subkey1_copy->buffer_length, master_key, 0); throw_on_error(KEYDERIVATION_FAILED, "Failed to derive copy of the first subkey."); if (buffer_compare(subkey1, subkey1_copy) != 0) { throw(INCORRECT_DATA, "Failed to reproduce subkey."); } cleanup: buffer_destroy_from_heap_and_null_if_valid(master_key); buffer_destroy_from_heap_and_null_if_valid(subkey1); buffer_destroy_from_heap_and_null_if_valid(subkey2); buffer_destroy_from_heap_and_null_if_valid(subkey1_copy); on_error { print_errors(&status); } return_status_destroy_errors(&status); return status.status; }
int main(void) { sodium_init(); int status; //create random chain key buffer_t *chain_key = buffer_create(crypto_auth_BYTES, crypto_auth_BYTES); status = buffer_fill_random(chain_key, chain_key->buffer_length); if (status != 0) { fprintf(stderr, "ERROR: Failed to create chain key. (%i)\n", status); buffer_clear(chain_key); return status; } //print first chain key printf("Chain key (%zi Bytes):\n", chain_key->content_length); print_hex(chain_key); putchar('\n'); //derive message key from chain key buffer_t *message_key = buffer_create(crypto_auth_BYTES, crypto_auth_BYTES); status = derive_message_key(message_key, chain_key); buffer_clear(chain_key); if (status != 0) { fprintf(stderr, "ERROR: Failed to derive message key. (%i)\n", status); buffer_clear(message_key); return status; } //print message key printf("Message key (%zi Bytes):\n", message_key->content_length); print_hex(message_key); putchar('\n'); buffer_clear(message_key); return EXIT_SUCCESS; }
int main(void) { return_status status = return_status_init(); //generate keys buffer_t *header_key = buffer_create_on_heap(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); buffer_t *message_key = buffer_create_on_heap(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *public_identity_key = buffer_create_on_heap(PUBLIC_KEY_SIZE, PUBLIC_KEY_SIZE); buffer_t *public_ephemeral_key = buffer_create_on_heap(PUBLIC_KEY_SIZE, PUBLIC_KEY_SIZE); buffer_t *public_prekey = buffer_create_on_heap(PUBLIC_KEY_SIZE, PUBLIC_KEY_SIZE); buffer_t *header = buffer_create_on_heap(4, 4); buffer_create_from_string(message, "Hello world!\n"); buffer_t *packet = NULL; buffer_t *decrypted_header = NULL; if(sodium_init() == -1) { throw(INIT_ERROR, "Failed to initialize libsodium."); } //generate message header->content[0] = 0x01; header->content[1] = 0x02; header->content[2] = 0x03; header->content[3] = 0x04; molch_message_type packet_type = 1; printf("Packet type: %02x\n", packet_type); putchar('\n'); //NORMAL MESSAGE printf("NORMAL MESSAGE\n"); int status_int = 0; status = create_and_print_message( &packet, header_key, message_key, packet_type, header, message, NULL, NULL, NULL); throw_on_error(GENERIC_ERROR, "Failed to create and print message."); //now decrypt the header status = packet_decrypt_header( &decrypted_header, packet, header_key); throw_on_error(DECRYPT_ERROR, "Failed to decrypt the header."); if (decrypted_header->content_length != header->content_length) { throw(INVALID_VALUE, "Decrypted header isn't of the same length."); } printf("Decrypted header has the same length.\n\n"); //compare headers if (buffer_compare(header, decrypted_header) != 0) { throw(INVALID_VALUE, "Decrypted header doesn't match."); } printf("Decrypted header matches.\n\n"); //check if it decrypts manipulated packets (manipulated metadata) printf("Manipulating header length.\n"); packet->content[2]++; status = packet_decrypt_header( &decrypted_header, packet, header_key); if (status.status == SUCCESS) { throw(GENERIC_ERROR, "Manipulated packet was accepted."); } else { return_status_destroy_errors(&status); } printf("Header manipulation detected.\n\n"); //repair manipulation packet->content[2]--; //check if it decrypts manipulated packets (manipulated header) printf("Manipulate header.\n"); packet->content[3 + crypto_aead_chacha20poly1305_NPUBBYTES + 1] ^= 0x12; status = packet_decrypt_header( &decrypted_header, packet, header_key); if (status.status == SUCCESS) { throw(GENERIC_ERROR, "Manipulated packet was accepted."); } else { return_status_destroy_errors(&status); } printf("Header manipulation detected!\n\n"); //undo header manipulation packet->content[3 + crypto_aead_chacha20poly1305_NPUBBYTES + 1] ^= 0x12; //PREKEY MESSAGE printf("PREKEY_MESSAGE\n"); //create the public keys status_int = buffer_fill_random(public_identity_key, PUBLIC_KEY_SIZE); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate public identity key."); } status_int = buffer_fill_random(public_ephemeral_key, PUBLIC_KEY_SIZE); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate public ephemeral key."); } status_int = buffer_fill_random(public_prekey, PUBLIC_KEY_SIZE); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate public prekey."); } buffer_destroy_from_heap_and_null_if_valid(packet); packet_type = PREKEY_MESSAGE; status = create_and_print_message( &packet, header_key, message_key, packet_type, header, message, public_identity_key, public_ephemeral_key, public_prekey); throw_on_error(GENERIC_ERROR, "Failed to crate and print message."); //now decrypt the header status = packet_decrypt_header( &decrypted_header, packet, header_key); throw_on_error(DECRYPT_ERROR, "Failed to decrypt the header."); if (decrypted_header->content_length != header->content_length) { throw(INVALID_VALUE, "Decrypted header isn't of the same length."); } printf("Decrypted header has the same length.\n\n"); //compare headers if (buffer_compare(header, decrypted_header) != 0) { throw(INVALID_VALUE, "Decrypted header doesn't match."); } printf("Decrypted header matches.\n"); cleanup: buffer_destroy_from_heap_and_null_if_valid(header_key); buffer_destroy_from_heap_and_null_if_valid(message_key); buffer_destroy_from_heap_and_null_if_valid(header); buffer_destroy_from_heap_and_null_if_valid(public_identity_key); buffer_destroy_from_heap_and_null_if_valid(public_ephemeral_key); buffer_destroy_from_heap_and_null_if_valid(public_prekey); buffer_destroy_from_heap_and_null_if_valid(packet); buffer_destroy_from_heap_and_null_if_valid(decrypted_header); on_error { print_errors(&status); } return_status_destroy_errors(&status); return status.status; }
/* * Create message and header keys, encrypt header and message * and print them. */ int create_and_print_message( buffer_t * const packet, //needs to be 3 + crypto_aead_chacha20poly1305_NPUBBYTES + crypto_aead_chacha20poly1305_ABYTES + crypto_secretbox_NONCEBYTES + message_length + header_length + crypto_secretbox_MACBYTES + 255 const unsigned char packet_type, const unsigned char current_protocol_version, const unsigned char highest_supported_protocol_version, const buffer_t * const message, buffer_t * const message_key, //output, crypto_secretbox_KEYBYTES const buffer_t * const header, buffer_t * const header_key) { //output, crypto_aead_chacha20poly1305_KEYBYTES int status; //create header key status = buffer_fill_random(header_key, crypto_aead_chacha20poly1305_KEYBYTES); if (status != 0) { buffer_clear(header_key); return status; } printf("Header key (%zi Bytes):\n", header_key->content_length); print_hex(header_key); putchar('\n'); //create message key status = buffer_fill_random(message_key, crypto_secretbox_KEYBYTES); if (status != 0) { buffer_clear(header_key); buffer_clear(message_key); return status; } printf("Message key (%zi Bytes):\n", message_key->content_length); print_hex(message_key); putchar('\n'); //print the header (as hex): printf("Header (%zi Bytes):\n", header->content_length); print_hex(header); putchar('\n'); //print the message (as string): printf("Message (%zi Bytes):\n%.*s\n\n", message->content_length, (int)message->content_length, message->content); //now encrypt the message status = packet_encrypt( packet, packet_type, current_protocol_version, highest_supported_protocol_version, header, header_key, message, message_key); if (status != 0) { fprintf(stderr, "ERROR: Failed to encrypt message and header. (%i)\n", status); return status; } //print header nonce buffer_t *header_nonce = buffer_create_with_existing_array(packet->content + 3, crypto_aead_chacha20poly1305_NPUBBYTES); printf("Header Nonce (%zi Bytes):\n", header_nonce->content_length); print_hex(header_nonce); putchar('\n'); //print encrypted packet printf("Encrypted Packet (%zi Bytes):\n", packet->content_length); print_hex(packet); putchar('\n'); return 0; }
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; }
int main(void) { if (sodium_init() == -1) { return -1; } return_status status = return_status_init(); //create key buffers buffer_t *alice_public_ephemeral = buffer_create_on_heap(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t *alice_private_ephemeral = buffer_create_on_heap(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *bob_public_ephemeral = buffer_create_on_heap(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t *bob_private_ephemeral = buffer_create_on_heap(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *previous_root_key = buffer_create_on_heap(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *alice_root_key = buffer_create_on_heap(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *alice_chain_key = buffer_create_on_heap(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *alice_header_key = buffer_create_on_heap(HEADER_KEY_SIZE, HEADER_KEY_SIZE); buffer_t *bob_root_key = buffer_create_on_heap(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *bob_chain_key = buffer_create_on_heap(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *bob_header_key = buffer_create_on_heap(HEADER_KEY_SIZE, HEADER_KEY_SIZE); //create Alice's keypair buffer_create_from_string(alice_string, "Alice"); buffer_create_from_string(ephemeral_string, "ephemeral"); status = generate_and_print_keypair( alice_public_ephemeral, alice_private_ephemeral, alice_string, ephemeral_string); throw_on_error(KEYGENERATION_FAILED, "Failed to generate and print Alice's ephemeral keypair."); //create Bob's keypair buffer_create_from_string(bob_string, "Bob"); status = generate_and_print_keypair( bob_public_ephemeral, bob_private_ephemeral, bob_string, ephemeral_string); throw_on_error(KEYGENERATION_FAILED, "Failed to generate and print Bob's ephemeral keypair."); //create previous root key if (buffer_fill_random(previous_root_key, crypto_secretbox_KEYBYTES) != 0) { throw(KEYGENERATION_FAILED, "Failed to generate previous root key."); } //print previous root key printf("Previous root key (%zu Bytes):\n", previous_root_key->content_length); print_hex(previous_root_key); putchar('\n'); //derive root and chain key for Alice status = derive_root_next_header_and_chain_keys( alice_root_key, alice_header_key, alice_chain_key, alice_private_ephemeral, alice_public_ephemeral, bob_public_ephemeral, previous_root_key, true); throw_on_error(KEYDERIVATION_FAILED, "Failed to derive root, next header and chain key for Alice."); //print Alice's root and chain key printf("Alice's root key (%zu Bytes):\n", alice_root_key->content_length); print_hex(alice_root_key); printf("Alice's chain key (%zu Bytes):\n", alice_chain_key->content_length); print_hex(alice_chain_key); printf("Alice's header key (%zu Bytes):\n", alice_header_key->content_length); print_hex(alice_header_key); putchar('\n'); //derive root and chain key for Bob status = derive_root_next_header_and_chain_keys( bob_root_key, bob_header_key, bob_chain_key, bob_private_ephemeral, bob_public_ephemeral, alice_public_ephemeral, previous_root_key, false); throw_on_error(KEYDERIVATION_FAILED, "Failed to derive root, next header and chain key for Bob."); //print Bob's root and chain key printf("Bob's root key (%zu Bytes):\n", bob_root_key->content_length); print_hex(bob_root_key); printf("Bob's chain key (%zu Bytes):\n", bob_chain_key->content_length); print_hex(bob_chain_key); printf("Bob's header key (%zu Bytes):\n", bob_header_key->content_length); print_hex(bob_header_key); putchar('\n'); //compare Alice's and Bob's root keys if (buffer_compare(alice_root_key, bob_root_key) == 0) { printf("Alice's and Bob's root keys match.\n"); } else { throw(INCORRECT_DATA, "Alice's and Bob's root keys don't match."); } buffer_clear(alice_root_key); buffer_clear(bob_root_key); //compare Alice's and Bob's chain keys if (buffer_compare(alice_chain_key, bob_chain_key) == 0) { printf("Alice's and Bob's chain keys match.\n"); } else { throw(INCORRECT_DATA, "Alice's and Bob's chain keys don't match."); } //compare Alice's and Bob's header keys if (buffer_compare(alice_header_key, bob_header_key) == 0) { printf("Alice's and Bob's header keys match.\n"); } else { throw(INCORRECT_DATA, "Alice's and Bob's header keys don't match."); } cleanup: buffer_destroy_from_heap_and_null_if_valid(alice_public_ephemeral); buffer_destroy_from_heap_and_null_if_valid(alice_private_ephemeral); buffer_destroy_from_heap_and_null_if_valid(bob_public_ephemeral); buffer_destroy_from_heap_and_null_if_valid(bob_private_ephemeral); buffer_destroy_from_heap_and_null_if_valid(previous_root_key); buffer_destroy_from_heap_and_null_if_valid(alice_root_key); buffer_destroy_from_heap_and_null_if_valid(alice_chain_key); buffer_destroy_from_heap_and_null_if_valid(alice_header_key); buffer_destroy_from_heap_and_null_if_valid(bob_root_key); buffer_destroy_from_heap_and_null_if_valid(bob_chain_key); buffer_destroy_from_heap_and_null_if_valid(bob_header_key); on_error { print_errors(&status); } return_status_destroy_errors(&status); return status.status; }