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;
}
Пример #3
0
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;
}
Пример #6
0
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;
}
Пример #7
0
/*
 * 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;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #11
0
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;
}