int main(void) { sodium_init(); //generate keys and message buffer_t *header_key = buffer_create(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); buffer_t *message_key = buffer_create(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *message = buffer_create_from_string("Hello world!\n"); buffer_t *header = buffer_create(4, 4); header->content[0] = 0x01; header->content[1] = 0x02; header->content[2] = 0x03; header->content[3] = 0x04; buffer_t *packet = buffer_create(3 + crypto_aead_chacha20poly1305_NPUBBYTES + crypto_aead_chacha20poly1305_ABYTES + crypto_secretbox_NONCEBYTES + message->content_length + header->content_length + crypto_secretbox_MACBYTES + 255, 3 + crypto_aead_chacha20poly1305_NPUBBYTES + crypto_aead_chacha20poly1305_ABYTES + crypto_secretbox_NONCEBYTES + message->content_length + header->content_length + crypto_secretbox_MACBYTES + 255); const unsigned char packet_type = 1; printf("Packet type: %02x\n", packet_type); const unsigned char current_protocol_version = 2; printf("Current protocol version: %02x\n", current_protocol_version); const unsigned char highest_supported_protocol_version = 3; printf("Highest supported protocol version: %02x\n", highest_supported_protocol_version); putchar('\n'); int status = create_and_print_message( packet, packet_type, current_protocol_version, highest_supported_protocol_version, message, message_key, header, header_key); buffer_clear(message_key); buffer_clear(message); if (status != 0) { buffer_clear(header_key); buffer_clear(header); return status; } //now decrypt the header buffer_t *decrypted_header = buffer_create(255, 255); buffer_t *decrypted_message_nonce = buffer_create(crypto_secretbox_NONCEBYTES, crypto_secretbox_NONCEBYTES); status = packet_decrypt_header( packet, decrypted_header, decrypted_message_nonce, header_key); if (status != 0) { fprintf(stderr, "ERROR: Failed to decrypt the header. (%i)\n", status); buffer_clear(header); buffer_clear(decrypted_header); buffer_clear(decrypted_message_nonce); buffer_clear(header_key); return status; } if (decrypted_header->content_length != header->content_length) { fprintf(stderr, "ERROR: Decrypted header isn't of the same length!\n"); buffer_clear(header); buffer_clear(decrypted_header); buffer_clear(decrypted_message_nonce); buffer_clear(header_key); return EXIT_SUCCESS; } printf("Decrypted header has the same length.\n\n"); printf("Decrypted message nonce (%zi Bytes):\n", decrypted_message_nonce->content_length); print_hex(decrypted_message_nonce); putchar('\n'); buffer_clear(decrypted_message_nonce); //compare headers if (buffer_compare(header, decrypted_header) != 0) { fprintf(stderr, "ERROR: Decrypted header doesn't match!\n"); buffer_clear(header); buffer_clear(decrypted_header); buffer_clear(header_key); return EXIT_FAILURE; } 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( packet, decrypted_header, decrypted_message_nonce, header_key); buffer_clear(decrypted_message_nonce); buffer_clear(decrypted_header); if (status == 0) { //header was decrypted despite manipulation fprintf(stderr, "ERROR: Manipulated packet was accepted!\n"); buffer_clear(header); buffer_clear(header_key); return EXIT_FAILURE; } 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( packet, decrypted_header, decrypted_message_nonce, header_key); buffer_clear(decrypted_message_nonce); buffer_clear(decrypted_header); if (status == 0) { //header was decrypted desp fprintf(stderr, "ERROR: Manipulated packet was accepted!\n"); buffer_clear(header); buffer_clear(header_key); return EXIT_FAILURE; } printf("Header manipulation detected!\n"); //undo header manipulation packet->content[3 + crypto_aead_chacha20poly1305_NPUBBYTES + 1] ^= 0x12; buffer_clear(header); buffer_clear(header_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; }
int main(void) { if (sodium_init() == -1) { return -1; } return_status status = return_status_init(); //create buffers buffer_t *alice_public_key = buffer_create_on_heap(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t *alice_private_key = buffer_create_on_heap(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *alice_shared_secret = buffer_create_on_heap(crypto_generichash_BYTES, crypto_generichash_BYTES); buffer_t *bob_public_key = buffer_create_on_heap(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t *bob_private_key = buffer_create_on_heap(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *bob_shared_secret = buffer_create_on_heap(crypto_generichash_BYTES, crypto_generichash_BYTES); int status_int = 0; //create Alice's keypair buffer_create_from_string(alice_string, "Alice"); buffer_create_from_string(empty_string, ""); status = generate_and_print_keypair( alice_public_key, alice_private_key, alice_string, empty_string); throw_on_error(KEYGENERATION_FAILED, "Failed to generate and print Alice's keypair."); //create Bob's keypair buffer_create_from_string(bob_string, "Bob"); status = generate_and_print_keypair( bob_public_key, bob_private_key, bob_string, empty_string); throw_on_error(KEYGENERATION_FAILED, "Failed to generate and print Bob's keypair."); //Diffie Hellman on Alice's side status = diffie_hellman( alice_shared_secret, alice_private_key, alice_public_key, bob_public_key, true); buffer_clear(alice_private_key); throw_on_error(KEYGENERATION_FAILED, "Diffie Hellman with Alice's private key failed."); //print Alice's shared secret printf("Alice's shared secret ECDH(A_priv, B_pub) (%zu Bytes):\n", alice_shared_secret->content_length); print_hex(alice_shared_secret); putchar('\n'); //Diffie Hellman on Bob's side status = diffie_hellman( bob_shared_secret, bob_private_key, bob_public_key, alice_public_key, false); buffer_clear(bob_private_key); throw_on_error(KEYGENERATION_FAILED, "Diffie Hellman with Bob's private key failed."); //print Bob's shared secret printf("Bob's shared secret ECDH(B_priv, A_pub) (%zu Bytes):\n", bob_shared_secret->content_length); print_hex(bob_shared_secret); putchar('\n'); //compare both shared secrets status_int = buffer_compare(alice_shared_secret, bob_shared_secret); buffer_clear(alice_shared_secret); buffer_clear(bob_shared_secret); if (status_int != 0) { throw(INCORRECT_DATA, "Diffie Hellman didn't produce the same shared secret."); } printf("Both shared secrets match!\n"); cleanup: buffer_destroy_from_heap_and_null_if_valid(alice_public_key); buffer_destroy_from_heap_and_null_if_valid(alice_private_key); buffer_destroy_from_heap_and_null_if_valid(alice_shared_secret); buffer_destroy_from_heap_and_null_if_valid(bob_public_key); buffer_destroy_from_heap_and_null_if_valid(bob_private_key); buffer_destroy_from_heap_and_null_if_valid(bob_shared_secret); on_error { print_errors(&status); } return_status_destroy_errors(&status); return status.status; }
int main(void) { sodium_init(); int status; //create Alice's identity keypair buffer_t *alice_public_identity = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t *alice_private_identity = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); status = generate_and_print_keypair( alice_public_identity, alice_private_identity, buffer_create_from_string("Alice"), buffer_create_from_string("identity")); if (status != 0) { buffer_clear(alice_private_identity); return status; } //create Alice's ephemeral keypair buffer_t *alice_public_ephemeral = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t *alice_private_ephemeral = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); status = generate_and_print_keypair( alice_public_ephemeral, alice_private_ephemeral, buffer_create_from_string("Alice"), buffer_create_from_string("ephemeral")); if (status != 0) { buffer_clear(alice_private_identity); buffer_clear(alice_private_ephemeral); return status; } //create Bob's identity keypair buffer_t *bob_public_identity = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t *bob_private_identity = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); status = generate_and_print_keypair( bob_public_identity, bob_private_identity, buffer_create_from_string("Bob"), buffer_create_from_string("identity")); if (status != 0) { buffer_clear(alice_private_identity); buffer_clear(alice_private_ephemeral); buffer_clear(bob_private_identity); return status; } //create Bob's ephemeral keypair buffer_t *bob_public_ephemeral = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t *bob_private_ephemeral = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); status = generate_and_print_keypair( bob_public_ephemeral, bob_private_ephemeral, buffer_create_from_string("Bob"), buffer_create_from_string("ephemeral")); if (status != 0) { buffer_clear(alice_private_identity); buffer_clear(alice_private_ephemeral); buffer_clear(bob_private_identity); buffer_clear(bob_private_ephemeral); return status; } //derive Alice's initial root and chain key buffer_t *alice_root_key = buffer_create(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *alice_send_chain_key = buffer_create(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *alice_receive_chain_key = buffer_create(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *alice_send_header_key = buffer_create(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); buffer_t *alice_receive_header_key = buffer_create(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); buffer_t *alice_next_send_header_key = buffer_create(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); buffer_t *alice_next_receive_header_key = buffer_create(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); status = derive_initial_root_chain_and_header_keys( alice_root_key, alice_send_chain_key, alice_receive_chain_key, alice_send_header_key, alice_receive_header_key, alice_next_send_header_key, alice_next_receive_header_key, alice_private_identity, alice_public_identity, bob_public_identity, alice_private_ephemeral, alice_public_ephemeral, bob_public_ephemeral, true); buffer_clear(alice_private_identity); buffer_clear(alice_private_ephemeral); if (status != 0) { fprintf(stderr, "ERROR: Failed to derive Alice's initial root and chain key. (%i)\n", status); buffer_clear(alice_root_key); buffer_clear(alice_send_chain_key); buffer_clear(alice_receive_chain_key); buffer_clear(alice_send_header_key); buffer_clear(alice_receive_header_key); buffer_clear(alice_next_send_header_key); buffer_clear(alice_next_receive_header_key); buffer_clear(bob_private_identity); buffer_clear(bob_private_ephemeral); return status; } //print Alice's initial root and chain key printf("Alice's initial root key (%zi Bytes):\n", alice_root_key->content_length); print_hex(alice_root_key); putchar('\n'); printf("Alice's initial send chain key (%zi Bytes):\n", alice_send_chain_key->content_length); print_hex(alice_send_chain_key); putchar('\n'); printf("Alice's initial receive chain key (%zi Bytes):\n", alice_receive_chain_key->content_length); print_hex(alice_receive_chain_key); putchar('\n'); printf("Alice's initial send header key (%zi Bytes):\n", alice_send_header_key->content_length); print_hex(alice_send_header_key); putchar('\n'); printf("Alice's initial receive header key (%zi Bytes):\n", alice_receive_header_key->content_length); print_hex(alice_receive_header_key); printf("Alice's initial next send header key (%zi Bytes):\n", alice_next_send_header_key->content_length); print_hex(alice_next_send_header_key); putchar('\n'); printf("Alice's initial next receive header key (%zi Bytes):\n", alice_next_receive_header_key->content_length); print_hex(alice_next_receive_header_key); putchar('\n'); //derive Bob's initial root and chain key buffer_t *bob_root_key = buffer_create(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *bob_send_chain_key = buffer_create(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *bob_receive_chain_key = buffer_create(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); buffer_t *bob_send_header_key = buffer_create(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); buffer_t *bob_receive_header_key = buffer_create(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); buffer_t *bob_next_send_header_key = buffer_create(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); buffer_t *bob_next_receive_header_key = buffer_create(crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); status = derive_initial_root_chain_and_header_keys( bob_root_key, bob_send_chain_key, bob_receive_chain_key, bob_send_header_key, bob_receive_header_key, bob_next_send_header_key, bob_next_receive_header_key, bob_private_identity, bob_public_identity, alice_public_identity, bob_private_ephemeral, bob_public_ephemeral, alice_public_ephemeral, false); buffer_clear(bob_private_identity); buffer_clear(bob_private_ephemeral); if (status != 0) { fprintf(stderr, "ERROR: Failed to derive Bob's initial root and chain key. (%i)", status); buffer_clear(alice_root_key); buffer_clear(alice_send_chain_key); buffer_clear(alice_receive_chain_key); buffer_clear(alice_send_header_key); buffer_clear(alice_receive_header_key); buffer_clear(alice_next_send_header_key); buffer_clear(alice_next_receive_header_key); buffer_clear(bob_root_key); buffer_clear(bob_send_chain_key); buffer_clear(bob_receive_chain_key); buffer_clear(bob_send_header_key); buffer_clear(bob_receive_header_key); buffer_clear(bob_next_send_header_key); buffer_clear(bob_next_receive_header_key); return status; } //print Bob's initial root and chain key printf("Bob's initial root key (%zi Bytes):\n", bob_root_key->content_length); print_hex(bob_root_key); putchar('\n'); printf("Bob's initial send chain key (%zi Bytes):\n", bob_send_chain_key->content_length); print_hex(bob_send_chain_key); putchar('\n'); printf("Bob's initial receive chain key (%zi Bytes):\n", bob_receive_chain_key->content_length); print_hex(bob_receive_chain_key); putchar('\n'); printf("Bob's initial send header key (%zi Bytes):\n", bob_send_header_key->content_length); print_hex(bob_send_header_key); putchar('\n'); printf("Bob's initial receive header key (%zi Bytes):\n", bob_receive_header_key->content_length); print_hex(bob_receive_header_key); printf("Bob's initial next send header key (%zi Bytes):\n", bob_next_send_header_key->content_length); print_hex(bob_next_send_header_key); putchar('\n'); printf("Bob's initial next receive header key (%zi Bytes):\n", bob_next_receive_header_key->content_length); print_hex(bob_next_receive_header_key); putchar('\n'); //compare Alice's and Bob's initial root key if (buffer_compare(alice_root_key, bob_root_key) != 0) { fprintf(stderr, "ERROR: Alice's and Bob's initial root keys don't match.\n"); buffer_clear(alice_root_key); buffer_clear(alice_send_chain_key); buffer_clear(alice_receive_chain_key); buffer_clear(alice_send_header_key); buffer_clear(alice_receive_header_key); buffer_clear(alice_next_send_header_key); buffer_clear(alice_next_receive_header_key); buffer_clear(bob_root_key); buffer_clear(bob_send_chain_key); buffer_clear(bob_receive_chain_key); buffer_clear(bob_send_header_key); buffer_clear(bob_receive_header_key); buffer_clear(bob_next_send_header_key); buffer_clear(bob_next_receive_header_key); return -10; } printf("Alice's and Bob's initial root keys match.\n"); buffer_clear(alice_root_key); buffer_clear(bob_root_key); //compare Alice's and Bob's initial chain keys if (buffer_compare(alice_send_chain_key, bob_receive_chain_key) != 0) { fprintf(stderr, "ERROR: Alice's and Bob's initial chain keys don't match.\n"); buffer_clear(alice_send_chain_key); buffer_clear(alice_receive_chain_key); buffer_clear(alice_send_header_key); buffer_clear(alice_receive_header_key); buffer_clear(alice_next_send_header_key); buffer_clear(alice_next_receive_header_key); buffer_clear(bob_send_chain_key); buffer_clear(bob_receive_chain_key); buffer_clear(bob_send_header_key); buffer_clear(bob_receive_header_key); buffer_clear(bob_next_send_header_key); buffer_clear(bob_next_receive_header_key); return -10; } printf("Alice's and Bob's initial chain keys match.\n"); buffer_clear(alice_send_chain_key); buffer_clear(bob_receive_chain_key); if (buffer_compare(alice_receive_chain_key, bob_send_chain_key) != 0) { fprintf(stderr, "ERROR: Alice's and Bob's initial chain keys don't match.\n"); buffer_clear(alice_receive_chain_key); buffer_clear(alice_send_header_key); buffer_clear(alice_receive_header_key); buffer_clear(alice_next_send_header_key); buffer_clear(alice_next_receive_header_key); buffer_clear(bob_send_chain_key); buffer_clear(bob_send_header_key); buffer_clear(bob_receive_header_key); buffer_clear(bob_next_send_header_key); buffer_clear(bob_next_receive_header_key); return -10; } printf("Alice's and Bob's initial chain keys match.\n"); //compare Alice's and Bob's initial header keys 1/2 if (buffer_compare(alice_send_header_key, bob_receive_header_key) != 0) { fprintf(stderr, "ERROR: Alice's initial send and Bob's initial receive header keys don't match.\n"); buffer_clear(alice_send_header_key); buffer_clear(alice_receive_header_key); buffer_clear(alice_next_send_header_key); buffer_clear(alice_next_receive_header_key); buffer_clear(bob_send_header_key); buffer_clear(bob_receive_header_key); buffer_clear(bob_next_send_header_key); buffer_clear(bob_next_receive_header_key); return -10; } printf("Alice's initial send and Bob's initial receive header keys match.\n"); buffer_clear(alice_send_header_key); buffer_clear(bob_receive_header_key); //compare Alice's and Bob's initial header keys 2/2 if (buffer_compare(alice_receive_header_key, bob_send_header_key) != 0) { fprintf(stderr, "ERROR: Alice's initial receive and Bob's initial send header keys don't match.\n"); buffer_clear(alice_receive_header_key); buffer_clear(alice_next_receive_header_key); buffer_clear(alice_next_send_header_key); buffer_clear(bob_send_header_key); buffer_clear(bob_next_send_header_key); buffer_clear(bob_next_receive_header_key); return -10; } printf("Alice's initial receive and Bob's initial send header keys match.\n"); buffer_clear(alice_receive_header_key); buffer_clear(bob_send_header_key); //compare Alice's and Bob's initial next header keys 1/2 if (buffer_compare(alice_next_send_header_key, bob_next_receive_header_key) != 0) { fprintf(stderr, "ERROR: Alice's initial next send and Bob's initial next receive header keys don't match.\n"); buffer_clear(alice_next_receive_header_key); buffer_clear(alice_next_send_header_key); buffer_clear(bob_next_send_header_key); buffer_clear(bob_next_receive_header_key); return -10; } printf("Alice's initial next send and Bob's initial next receive header keys match.\n"); buffer_clear(alice_next_send_header_key); buffer_clear(bob_next_receive_header_key); //compare Alice's and Bob's initial next header keys 2/2 if (buffer_compare(alice_next_receive_header_key, bob_next_send_header_key) != 0) { fprintf(stderr, "ERROR: Alice's initial next receive and Bob's initial next send header keys don't match.\n"); buffer_clear(alice_next_receive_header_key); buffer_clear(bob_next_send_header_key); return -10; } printf("Alice's initial next receive and Bob's initial next send header keys match.\n"); buffer_clear(alice_next_receive_header_key); buffer_clear(bob_next_send_header_key); return EXIT_SUCCESS; }
int main(void) { if (sodium_init() == -1) { return -1; } return_status status = return_status_init(); //create buffers //alice keys buffer_t * const alice_public_identity = buffer_create_on_heap(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t * const alice_private_identity = buffer_create_on_heap(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t * const alice_public_ephemeral = buffer_create_on_heap(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t * const alice_private_ephemeral = buffer_create_on_heap(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t * const alice_shared_secret = buffer_create_on_heap(crypto_generichash_BYTES, crypto_generichash_BYTES); //bobs keys buffer_t * const bob_public_identity = buffer_create_on_heap(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t * const bob_private_identity = buffer_create_on_heap(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t * const bob_public_ephemeral = buffer_create_on_heap(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); buffer_t * const bob_private_ephemeral = buffer_create_on_heap(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t * const bob_shared_secret = buffer_create_on_heap(crypto_generichash_BYTES, crypto_generichash_BYTES); printf("Generate Alice's keys -------------------------------------------------------\n\n"); int status_int = 0; //create Alice's identity keypair buffer_create_from_string(alice_string, "Alice"); buffer_create_from_string(identity_string, "identity"); status = generate_and_print_keypair( alice_public_identity, alice_private_identity, alice_string, identity_string); throw_on_error(KEYGENERATION_FAILED, "Failed to generate and print Alice' identity keypair."); //create Alice's ephemeral keypair 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' ephemeral keypair."); printf("Generate Bob's keys ---------------------------------------------------------\n\n"); //create Bob's identity keypair buffer_create_from_string(bob_string, "Bob"); status = generate_and_print_keypair( bob_public_identity, bob_private_identity, bob_string, identity_string); throw_on_error(KEYGENERATION_FAILED, "Failed to generate and print Bob's identity keypair."); //create Bob's ephemeral keypair 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."); printf("Calculate shared secret via Triple Diffie Hellman ---------------------------\n\n"); //Triple Diffie Hellman on Alice's side status = triple_diffie_hellman( alice_shared_secret, alice_private_identity, alice_public_identity, alice_private_ephemeral, alice_public_ephemeral, bob_public_identity, bob_public_ephemeral, true); buffer_clear(alice_private_identity); buffer_clear(alice_private_ephemeral); throw_on_error(KEYGENERATION_FAILED, "Triple Diffie Hellman for Alice failed."); //print Alice's shared secret printf("Alice's shared secret H(DH(A_priv,B0_pub)||DH(A0_priv,B_pub)||DH(A0_priv,B0_pub)):\n"); print_hex(alice_shared_secret); putchar('\n'); //Triple Diffie Hellman on Bob's side status = triple_diffie_hellman( bob_shared_secret, bob_private_identity, bob_public_identity, bob_private_ephemeral, bob_public_ephemeral, alice_public_identity, alice_public_ephemeral, false); buffer_clear(bob_private_identity); buffer_clear(bob_private_ephemeral); throw_on_error(KEYGENERATION_FAILED, "Triple Diffie Hellnan for Bob failed."); //print Bob's shared secret printf("Bob's shared secret H(DH(B0_priv, A_pub)||DH(B_priv, A0_pub)||DH(B0_priv, A0_pub)):\n"); print_hex(bob_shared_secret); putchar('\n'); //compare both shared secrets status_int = buffer_compare(alice_shared_secret, bob_shared_secret); buffer_clear(alice_shared_secret); buffer_clear(bob_shared_secret); if (status_int != 0) { throw(INCORRECT_DATA, "Triple Diffie Hellman didn't produce the same shared secret."); } printf("Both shared secrets match!\n"); cleanup: //alice keys buffer_destroy_from_heap(alice_public_identity); buffer_destroy_from_heap(alice_private_identity); buffer_destroy_from_heap(alice_public_ephemeral); buffer_destroy_from_heap(alice_private_ephemeral); buffer_destroy_from_heap(alice_shared_secret); //bobs keys buffer_destroy_from_heap(bob_public_identity); buffer_destroy_from_heap(bob_private_identity); buffer_destroy_from_heap(bob_public_ephemeral); buffer_destroy_from_heap(bob_private_ephemeral); buffer_destroy_from_heap(bob_shared_secret); on_error { print_errors(&status); } return_status_destroy_errors(&status); return status.status; }
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; }
/* * Derive a root and initial chain key for a new ratchet. * * The chain and root key have to be crypto_secretbox_KEYBYTES long. * * RK, CK, HK = HKDF( RK, DH(DHRr, DHRs) ) */ int derive_root_chain_and_header_keys( buffer_t * const root_key, //crypto_secretbox_KEYBYTES buffer_t * const chain_key, //crypto_secretbox_KEYBYTES buffer_t * const header_key, //crypto_aead_chacha20poly1305_KEYBYTES const buffer_t * const our_private_ephemeral, const buffer_t * const our_public_ephemeral, const buffer_t * const their_public_ephemeral, const buffer_t * const previous_root_key, bool am_i_alice) { assert(crypto_secretbox_KEYBYTES == crypto_auth_KEYBYTES); //check size of the buffers if ((root_key->buffer_length < crypto_secretbox_KEYBYTES) || (chain_key->buffer_length < crypto_secretbox_KEYBYTES) || (header_key->buffer_length < crypto_aead_chacha20poly1305_KEYBYTES) || (our_private_ephemeral->content_length != crypto_box_SECRETKEYBYTES) || (our_public_ephemeral->content_length != crypto_box_PUBLICKEYBYTES) || (their_public_ephemeral->content_length != crypto_box_PUBLICKEYBYTES) || (previous_root_key->content_length != crypto_secretbox_KEYBYTES)) { return -6; } int status; //input key for HKDF (root key and chain key derivation) //input_key = DH(our_private_ephemeral, their_public_ephemeral) buffer_t *input_key = buffer_create(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); status = diffie_hellman( input_key, our_private_ephemeral, our_public_ephemeral, their_public_ephemeral, am_i_alice); if (status != 0) { buffer_clear(input_key); return status; } //now create root and chain key in temporary buffer //RK, CK = HKDF(previous_root_key, input_key) buffer_t *info = buffer_create_from_string(INFO); buffer_t *hkdf_buffer = buffer_create(2 * crypto_secretbox_KEYBYTES + crypto_aead_chacha20poly1305_KEYBYTES, 2 * crypto_secretbox_KEYBYTES + crypto_aead_chacha20poly1305_KEYBYTES); status = hkdf( hkdf_buffer, hkdf_buffer->content_length, previous_root_key, //salt input_key, info); buffer_clear(input_key); if (status != 0) { buffer_clear(hkdf_buffer); return status; } //copy keys from hkdf buffer status = buffer_copy(root_key, 0, hkdf_buffer, 0, crypto_secretbox_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); return status; } status = buffer_copy(chain_key, 0, hkdf_buffer, crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(chain_key); return status; } status = buffer_copy(header_key, 0, hkdf_buffer, 2 * crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(chain_key); buffer_clear(header_key); return status; } buffer_clear(hkdf_buffer); return 0; }
/* * Derive initial root, chain and header keys. * * RK, CKs/r, HKs/r, NHKs/r = HKDF(HASH(DH(A,B0) || DH(A0,B) || DH(A0,B0))) */ int derive_initial_root_chain_and_header_keys( buffer_t * const root_key, //crypto_secretbox_KEYBYTES buffer_t * const send_chain_key, //crypto_secretbox_KEYBYTES buffer_t * const receive_chain_key, //crypto_secretbox_KEYBYTES buffer_t * const send_header_key, //crypto_aead_chacha20poly1305_KEYBYTES buffer_t * const receive_header_key, //crypto_aead_chacha20poly1305_KEYBYTES buffer_t * const next_send_header_key, //crypto_aead_chacha20poly1305_KEYBYTES buffer_t * const next_receive_header_key, //crypto_aead_chacha20poly1305_KEYBYTES const buffer_t * const our_private_identity, const buffer_t * const our_public_identity, const buffer_t * const their_public_identity, const buffer_t * const our_private_ephemeral, const buffer_t * const our_public_ephemeral, const buffer_t * const their_public_ephemeral, bool am_i_alice) { //check buffer sizes if ((root_key->buffer_length < crypto_secretbox_KEYBYTES) || (send_chain_key->buffer_length < crypto_secretbox_KEYBYTES) || (receive_chain_key->buffer_length < crypto_secretbox_KEYBYTES) || (send_header_key->buffer_length < crypto_aead_chacha20poly1305_KEYBYTES) || (receive_header_key->buffer_length < crypto_aead_chacha20poly1305_KEYBYTES) || (next_send_header_key->buffer_length < crypto_aead_chacha20poly1305_KEYBYTES) || (next_receive_header_key->buffer_length < crypto_aead_chacha20poly1305_KEYBYTES) || (our_private_identity->content_length != crypto_box_SECRETKEYBYTES) || (our_public_identity->content_length != crypto_box_PUBLICKEYBYTES) || (their_public_identity->content_length != crypto_box_PUBLICKEYBYTES) || (our_private_ephemeral->content_length != crypto_box_SECRETKEYBYTES) || (our_public_ephemeral->content_length != crypto_box_PUBLICKEYBYTES) || (their_public_ephemeral->content_length != crypto_box_PUBLICKEYBYTES)) { return -6; } int status; //derive pre_root_key to later derive the initial root key, //header keys and chain keys from //pre_root_key = HASH( DH(A,B0) || DH(A0,B) || DH(A0,B0) ) assert(crypto_secretbox_KEYBYTES == crypto_auth_BYTES); buffer_t *pre_root_key = buffer_create(crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); status = triple_diffie_hellman( pre_root_key, our_private_identity, our_public_identity, our_private_ephemeral, our_public_ephemeral, their_public_identity, their_public_ephemeral, am_i_alice); if (status != 0) { buffer_clear(pre_root_key); return status; } //derive chain, root and header keys from pre_root_key via HKDF //RK, CK, HK, NHK1, NHK2 = HKDF(salt, pre_root_key) buffer_t *hkdf_buffer = buffer_create(2 * crypto_secretbox_KEYBYTES + 3 * crypto_aead_chacha20poly1305_KEYBYTES, 2 * crypto_secretbox_KEYBYTES + 3 * crypto_aead_chacha20poly1305_KEYBYTES); buffer_t *salt = buffer_create_from_string("molch--libsodium-crypto-library"); assert(salt->content_length == crypto_auth_KEYBYTES); buffer_t *info = buffer_create_from_string(INFO); status = hkdf( hkdf_buffer, hkdf_buffer->content_length, salt, pre_root_key, info); buffer_clear(pre_root_key); if (status != 0) { buffer_clear(hkdf_buffer); return status; } //now copy the keys //root key: status = buffer_copy(root_key, 0, hkdf_buffer, 0, crypto_secretbox_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); return status; } //chain keys and header keys if (am_i_alice) { //Alice: CKs=<none>, CKr=HKDF //TODO <none> will be an empty buffer in the future send_chain_key->content_length = crypto_secretbox_KEYBYTES; memset(send_chain_key->content, 0, send_chain_key->content_length); status = buffer_copy(receive_chain_key, 0, hkdf_buffer, crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(receive_chain_key); return status; } //HKs=<none>, HKr=HKDF //TODO <none> will be an empty buffer in the future send_header_key->content_length = crypto_aead_chacha20poly1305_KEYBYTES; memset(send_header_key->content, 0, send_header_key->content_length); status = buffer_copy(receive_header_key, 0, hkdf_buffer, 2 * crypto_secretbox_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(receive_chain_key); buffer_clear(receive_header_key); return status; } //NHKs, NHKr status = buffer_copy(next_send_header_key, 0, hkdf_buffer, 2 * crypto_secretbox_KEYBYTES + crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(receive_chain_key); buffer_clear(receive_header_key); buffer_clear(next_send_header_key); return status; } status = buffer_copy(next_receive_header_key, 0, hkdf_buffer, 2 * crypto_secretbox_KEYBYTES + 2 * crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(receive_chain_key); buffer_clear(receive_header_key); buffer_clear(next_send_header_key); buffer_clear(next_receive_header_key); return status; } } else { //Bob: CKs=HKDF, CKr=<none> receive_chain_key->content_length = crypto_secretbox_KEYBYTES; memset(receive_chain_key->content, 0, receive_chain_key->content_length); status = buffer_copy(send_chain_key, 0, hkdf_buffer, crypto_secretbox_KEYBYTES, crypto_secretbox_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(send_chain_key); return status; } //HKs=HKDF, HKr=<none> receive_header_key->content_length = crypto_aead_chacha20poly1305_KEYBYTES; memset(receive_header_key->content, 0, receive_header_key->content_length); status = buffer_copy(send_header_key, 0, hkdf_buffer, 2 * crypto_secretbox_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(send_chain_key); buffer_clear(send_header_key); return status; } //NHKr, NHKs status = buffer_copy(next_receive_header_key, 0, hkdf_buffer, 2 * crypto_secretbox_KEYBYTES + crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(send_chain_key); buffer_clear(send_header_key); buffer_clear(next_receive_header_key); return status; } status = buffer_copy(next_send_header_key, 0, hkdf_buffer, 2 * crypto_secretbox_KEYBYTES + 2 * crypto_aead_chacha20poly1305_KEYBYTES, crypto_aead_chacha20poly1305_KEYBYTES); if (status != 0) { buffer_clear(hkdf_buffer); buffer_clear(root_key); buffer_clear(send_chain_key); buffer_clear(send_header_key); buffer_clear(next_receive_header_key); buffer_clear(next_send_header_key); return status; } } buffer_clear(hkdf_buffer); return 0; }
/* Create a bunch of objects as demonstration. */ int create_objects(FILE *output_file) { /* declare a few. */ mcJSON *root; mcJSON *fmt; mcJSON *img; mcJSON *thm; mcJSON *fld; int i; /* Our "days of the week" array: */ buffer_create_from_string(sunday, "Sunday"); buffer_create_from_string(monday, "Monday"); buffer_create_from_string(tuesday, "Tuesday"); buffer_create_from_string(wednesday, "Wednesday"); buffer_create_from_string(thursday, "Thursday"); buffer_create_from_string(friday, "Friday"); buffer_create_from_string(saturday, "Saturday"); buffer_t *strings[7] = { sunday, monday, tuesday, wednesday, thursday, friday, saturday }; /* Our matrix: */ int numbers[3][3] = {{0, -1, 0}, {1, 0, 0}, {0, 0, 1}}; /* Our "gallery" item: */ int ids[4] = {116, 943, 234, 38793}; /* Our array of "records": */ buffer_create_from_string(zip_buffer, "zip"); buffer_create_from_string(empty_string_buffer, ""); buffer_create_from_string(san_francisco_buffer, "SAN FRANCISCO"); buffer_create_from_string(ca_buffer, "CA"); buffer_create_from_string(zip_number, "94107"); buffer_create_from_string(us_buffer, "US"); buffer_create_from_string(sunnyvale_buffer, "SUNNYVALE"); buffer_create_from_string(zip_number2, "94085"); struct record fields[2] = { { zip_buffer, 37.7668, -1.223959e+2, empty_string_buffer, san_francisco_buffer, ca_buffer, zip_number, us_buffer }, { zip_buffer, 37.371991, -1.22026e+2, empty_string_buffer, sunnyvale_buffer, ca_buffer, zip_number2, us_buffer } }; /* Here we construct some JSON standards, from the JSON site. */ /* Our "Video" datatype: */ root = mcJSON_CreateObject(NULL); buffer_create_from_string(jack_buffer, "Jack (\"Bee\") Nimble"); buffer_create_from_string(name_buffer, "name"); mcJSON_AddItemToObject(root, name_buffer, mcJSON_CreateString(jack_buffer, NULL), NULL); buffer_create_from_string(format_buffer, "format"); mcJSON_AddItemToObject(root, format_buffer, fmt=mcJSON_CreateObject(NULL), NULL); buffer_create_from_string(rect_buffer, "rect"); buffer_create_from_string(type_buffer, "type"); mcJSON_AddStringToObject(fmt, type_buffer, rect_buffer, NULL); buffer_create_from_string(width_buffer, "width"); mcJSON_AddNumberToObject(fmt, width_buffer, 1920, NULL); buffer_create_from_string(height_buffer, "height"); mcJSON_AddNumberToObject(fmt, height_buffer, 1080, NULL); buffer_create_from_string(interlace, "interlace"); mcJSON_AddFalseToObject (fmt, interlace, NULL); buffer_create_from_string(fps_buffer, "frame rate"); mcJSON_AddNumberToObject(fmt, fps_buffer, 24, NULL); buffer_t *output = NULL; /* Print to text, Delete the mcJSON, print it, release the string. */ output = mcJSON_Print(root); mcJSON_Delete(root); if (output == NULL) { return EXIT_FAILURE; } printf("%.*s\n", (int) output->content_length, (char*)output->content); if (output_file != NULL) { fprintf(output_file, "%.*s\n", (int)output->content_length, (char*)output->content); } buffer_destroy_from_heap(output); /* Our "days of the week" array: */ root = mcJSON_CreateStringArray((const buffer_t **)strings, 7, NULL); output = mcJSON_Print(root); mcJSON_Delete(root); if (output == NULL) { return EXIT_FAILURE; } printf("%.*s\n", (int)output->content_length, (char*)output->content); if (output_file != NULL) { fprintf(output_file, "%.*s\n", (int)output->content_length, (char*)output->content); } buffer_destroy_from_heap(output); /* Our matrix: */ root = mcJSON_CreateArray(NULL); for (i = 0; i < 3; i++) { mcJSON_AddItemToArray(root, mcJSON_CreateIntArray(numbers[i], 3, NULL), NULL); } /*mcJSON_ReplaceItemInArray(root,1,mcJSON_CreateString("Replacement")); */ output = mcJSON_Print(root); mcJSON_Delete(root); if (output == NULL) { return EXIT_FAILURE; } printf("%.*s\n", (int)output->content_length, (char*)output->content); if (output_file != NULL) { fprintf(output_file, "%.*s\n", (int)output->content_length, (char*)output->content); } buffer_destroy_from_heap(output); /* Our "gallery" item: */ root = mcJSON_CreateObject(NULL); buffer_create_from_string(image_buffer, "Image"); mcJSON_AddItemToObject(root, image_buffer, img = mcJSON_CreateObject(NULL), NULL); buffer_create_from_string(Width_buffer, "Width"); mcJSON_AddNumberToObject(img, Width_buffer, 800, NULL); buffer_create_from_string(Height_buffer, "Height"); mcJSON_AddNumberToObject(img, Height_buffer, 600, NULL); buffer_create_from_string(title_buffer, "Title"); buffer_create_from_string(view_buffer, "View from 15th Floor"); mcJSON_AddStringToObject(img, title_buffer, view_buffer, NULL); buffer_create_from_string(thumbnail_buffer, "Thumbnail"); mcJSON_AddItemToObject(img, thumbnail_buffer, thm = mcJSON_CreateObject(NULL), NULL); buffer_create_from_string(url_buffer, "Url"); buffer_create_from_string(url, "http:/*www.example.com/image/481989943"); mcJSON_AddStringToObject(thm, url_buffer, url, NULL); mcJSON_AddNumberToObject(thm, Height_buffer, 125, NULL); buffer_create_from_string(hundred_buffer, "100"); mcJSON_AddStringToObject(thm, Width_buffer, hundred_buffer, NULL); buffer_create_from_string(ids_buffer, "IDs"); mcJSON_AddItemToObject(img, ids_buffer, mcJSON_CreateIntArray(ids, 4, NULL), NULL); output = mcJSON_Print(root); mcJSON_Delete(root); if (output == NULL) { return EXIT_FAILURE; } printf("%.*s\n", (int)output->content_length, (char*)output->content); if (output_file != NULL) { fprintf(output_file, "%.*s\n", (int)output->content_length, (char*)output->content); } buffer_destroy_from_heap(output); /* Our array of "records": */ root = mcJSON_CreateArray(NULL); for (i = 0; i < 2; i++) { mcJSON_AddItemToArray(root, fld = mcJSON_CreateObject(NULL), NULL); buffer_create_from_string(precision_buffer, "precision"); mcJSON_AddStringToObject(fld, precision_buffer, fields[i].precision, NULL); buffer_create_from_string(latitude_buffer, "Latitude"); mcJSON_AddNumberToObject(fld, latitude_buffer, fields[i].lat, NULL); buffer_create_from_string(longitude_buffer, "Longitude"); mcJSON_AddNumberToObject(fld, longitude_buffer, fields[i].lon, NULL); buffer_create_from_string(address_buffer, "Address"); mcJSON_AddStringToObject(fld, address_buffer, fields[i].address, NULL); buffer_create_from_string(city_buffer, "City"); mcJSON_AddStringToObject(fld, city_buffer, fields[i].city, NULL); buffer_create_from_string(state_buffer, "State"); mcJSON_AddStringToObject(fld, state_buffer, fields[i].state, NULL); buffer_create_from_string(zip_buffer, "Zip"); mcJSON_AddStringToObject(fld, zip_buffer, fields[i].zip, NULL); buffer_create_from_string(country_buffer, "Country"); mcJSON_AddStringToObject(fld, country_buffer, fields[i].country, NULL); } /* mcJSON_ReplaceItemInObject(mcJSON_GetArrayItem(root,1),"City",mcJSON_CreateIntArray(ids,4,NULL)); */ output = mcJSON_Print(root); mcJSON_Delete(root); if (output == NULL) { return EXIT_FAILURE; } printf("%.*s\n", (int)output->content_length, (char*)output->content); if (output_file != NULL) { fprintf(output_file, "%.*s\n", (int)output->content_length, (char*)output->content); } buffer_destroy_from_heap(output); root = mcJSON_CreateObject(NULL); buffer_create_from_string(number_buffer, "number"); mcJSON_AddNumberToObject(root, number_buffer, INFINITY, NULL); output = mcJSON_Print(root); mcJSON_Delete(root); if (output == NULL) { return EXIT_FAILURE; } printf("%.*s\n", (int)output->content_length, (char*)output->content); if (output_file != NULL) { fprintf(output_file, "%.*s\n", (int)output->content_length, (char*)output->content); } buffer_destroy_from_heap(output); /* Check mcJSON_GetObjectItem and make sure it's case sensitive */ root = mcJSON_CreateObject(NULL); buffer_create_from_string(a_buffer, "a"); mcJSON_AddNumberToObject(root, a_buffer, 1, NULL); buffer_create_from_string(A_buffer, "A"); mcJSON_AddNumberToObject(root, A_buffer, 2, NULL); output = mcJSON_Print(root); if (output == NULL) { mcJSON_Delete(root); return EXIT_FAILURE; } printf("%.*s\n", (int)output->content_length, (char*)output->content); if (output_file != NULL) { fprintf(output_file, "%.*s\n", (int)output->content_length, (char*)output->content); } buffer_destroy_from_heap(output); mcJSON *one = mcJSON_GetObjectItem(root, a_buffer); mcJSON *two = mcJSON_GetObjectItem(root, A_buffer); if ((one == NULL) || (one->valueint != 1) || (two == NULL) || (two->valueint != 2)) { fprintf(stderr, "ERROR: Failed to get item from object.\n"); return EXIT_FAILURE; } mcJSON_Delete(root); /* test creation of hex strings */ buffer_create_from_string(newline_buffer, "\r\n"); root = mcJSON_CreateHexString(newline_buffer, NULL); if (root == NULL) { return EXIT_FAILURE; } output = mcJSON_Print(root); if (output == NULL) { mcJSON_Delete(root); return EXIT_FAILURE; } /* TODO: Make function that does this! */ printf("%.*s\n", (int)output->content_length, (char*)output->content); if (output_file != NULL) { fprintf(output_file, "%.*s\n", (int)output->content_length, (char*)output->content); } buffer_destroy_from_heap(output); mcJSON_Delete(root); return 0; }
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; }
int main(void) { return_status status = return_status_init(); char *error_stack = NULL; unsigned char *printed_status = NULL; //check if it was correctly initialized if ((status.status != SUCCESS) || (status.error != NULL)) { fprintf(stderr, "ERROR: Failed to initialize return statu!\n"); return EXIT_FAILURE; } printf("Initialized return status!\n"); // check the error stack status = first_level(); if (strcmp(status.error->message, "Error on the first level!") != 0) { fprintf(stderr, "ERROR: First error message is incorrect!\n"); status.status = GENERIC_ERROR; goto cleanup; } if (strcmp(status.error->next->message, "Error on the second level!") != 0) { fprintf(stderr, "ERROR: Second error message is incorrect!\n"); status.status = GENERIC_ERROR; goto cleanup; } printf("Successfully created error stack.\n"); size_t stack_print_length = 0; error_stack = return_status_print(&status, &stack_print_length); if (error_stack == NULL) { fprintf(stderr, "ERROR: Failed to print error stack.\n"); status.status = GENERIC_ERROR; goto cleanup; } printf("%s\n", error_stack); buffer_create_from_string(stack_trace, "ERROR\nerror stack trace:\n000: GENERIC_ERROR, Error on the first level!\n001: GENERIC_ERROR, Error on the second level!\n"); if (buffer_compare_to_raw(stack_trace, (unsigned char*)error_stack, stack_print_length) != 0) { throw(INCORRECT_DATA, "Stack trace looks differently than expected."); } status.status = SUCCESS; return_status_destroy_errors(&status); //more tests for return_status_print() return_status successful_status = return_status_init(); buffer_create_from_string(success_buffer, "SUCCESS"); size_t printed_status_length = 0; printed_status = (unsigned char*) return_status_print(&successful_status, &printed_status_length); if (buffer_compare_to_raw(success_buffer, printed_status, printed_status_length) != 0) { throw(INCORRECT_DATA, "molch_print_status produces incorrect output."); } cleanup: on_error { print_errors(&status); } free_and_null_if_valid(printed_status); return_status_destroy_errors(&status); free_and_null_if_valid(error_stack); return status.status; }