コード例 #1
0
FileBase::FileBase(int data_fd, int meta_fd, const key_type& key_, const id_type& id_, bool check)
    : m_lock()
    , m_refcount(1)
    , m_header()
    , m_id(id_)
    , m_data_fd(data_fd)
    , m_meta_fd(meta_fd)
    , m_dirty(false)
    , m_check(check)
    , m_stream()
    , m_removed(false)
{
    auto data_stream = std::make_shared<POSIXFileStream>(data_fd);
    auto meta_stream = std::make_shared<POSIXFileStream>(meta_fd);

    key_type data_key, meta_key;
    byte generated_keys[KEY_LENGTH * 3];
    hkdf(key_.data(),
         key_.size(),
         nullptr,
         0,
         id_.data(),
         id_.size(),
         generated_keys,
         sizeof(generated_keys));
    memcpy(data_key.data(), generated_keys, KEY_LENGTH);
    memcpy(meta_key.data(), generated_keys + KEY_LENGTH, KEY_LENGTH);
    memcpy(m_key.data(), generated_keys + 2 * KEY_LENGTH, KEY_LENGTH);
    auto crypt = make_cryptstream_aes_gcm(
        std::move(data_stream), std::move(meta_stream), data_key, meta_key, id_, check);

    m_stream = crypt.first;
    m_header = crypt.second;
    read_header();
}
コード例 #2
0
ファイル: hkdf-test.c プロジェクト: gitter-badger/molch
int main(void) {
	sodium_init();

	printf("HKDF as described in RFC 5869 based on HMAC-SHA512256!\n\n");

	unsigned char output_key[200];
	size_t output_key_length = sizeof(output_key);

	//create random salt
	unsigned char salt[crypto_auth_KEYBYTES];
	randombytes_buf(salt, crypto_auth_KEYBYTES);
	printf("Salt (%i Bytes):\n", crypto_auth_KEYBYTES);
	print_hex(salt, crypto_auth_KEYBYTES, 30);
	putchar('\n');

	//create key to derive from
	unsigned char input_key[100];
	size_t input_key_length = sizeof(input_key);
	randombytes_buf(input_key, input_key_length);
	printf("Input key (%zu Bytes):\n", input_key_length);
	print_hex(input_key, input_key_length, 30);
	putchar('\n');

	//info
	unsigned char* info = (unsigned char*) "This is some info!";
	size_t info_length = sizeof(info);
	printf("Info (%zu Bytes):\n", info_length); //this could also be binary data
	printf("%s\n\n", info);

	int status;
	status = hkdf(output_key, output_key_length, salt, input_key, input_key_length, info, info_length);
	if (status != 0) {
		fprintf(stderr, "ERROR: Failed to derive key. %i\n", status);
		return EXIT_FAILURE;
	}

	printf("Derived key (%zu Bytes):\n", output_key_length);
	print_hex(output_key, output_key_length, 30);
	putchar('\n');
	return EXIT_SUCCESS;
}
コード例 #3
0
ファイル: key-derivation.c プロジェクト: tiagogehring/molch
/*
 * 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;
}
コード例 #4
0
ファイル: key-derivation.c プロジェクト: tiagogehring/molch
/*
 * 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;
}