Esempio n. 1
0
static
void test_load_v1_key(void)
{
	test_begin("test_load_v1_key");

	buffer_t *key_1 = buffer_create_dynamic(pool_datastack_create(), 128);

	struct dcrypt_private_key *pkey = NULL, *pkey2 = NULL;
	const char *error = NULL;

	test_assert(dcrypt_key_load_private(&pkey, DCRYPT_FORMAT_DOVECOT, "1\t716\t0\t048FD04FD3612B22D32790C592CF21CEF417EFD2EA34AE5F688FA5B51BED29E05A308B68DA78E16E90B47A11E133BD9A208A2894FD01B0BEE865CE339EA3FB17AC\td0cfaca5d335f9edc41c84bb47465184cb0e2ec3931bebfcea4dd433615e77a0", NULL, NULL, &error));
	if (pkey != NULL) {
		buffer_set_used_size(key_1, 0);
		/* check that key_id matches */
		struct dcrypt_public_key *pubkey = NULL;
		dcrypt_key_convert_private_to_public(pkey, &pubkey);
		test_assert(dcrypt_key_store_public(pubkey, DCRYPT_FORMAT_DOVECOT, key_1, NULL));
		buffer_set_used_size(key_1, 0);
		dcrypt_key_id_public(pubkey, "sha256", key_1, &error);
		test_assert(strcmp("792caad4d38c9eb2134a0cbc844eae386116de096a0ccafc98479825fc99b6a1", binary_to_hex(key_1->data, key_1->used)) == 0);

		dcrypt_key_free_public(&pubkey);
		pkey2 = NULL;

		test_assert(dcrypt_key_load_private(&pkey2, DCRYPT_FORMAT_DOVECOT, "1\t716\t1\t0567e6bf9579813ae967314423b0fceb14bda24749303923de9a9bb9370e0026f995901a57e63113eeb2baf0c940e978d00686cbb52bd5014bc318563375876255\t0300E46DA2125427BE968EB3B649910CDC4C405E5FFDE18D433A97CABFEE28CEEFAE9EE356C792004FFB80981D67E741B8CC036A34235A8D2E1F98D1658CFC963D07EB\td0cfaca5d335f9edc41c84bb47465184cb0e2ec3931bebfcea4dd433615e77a0\t7c9a1039ea2e4fed73e81dd3ffc3fa22ea4a28352939adde7bf8ea858b00fa4f", NULL, pkey, &error));
		if (pkey2 != NULL) {
			buffer_set_used_size(key_1, 0);
			/* check that key_id matches */
			struct dcrypt_public_key *pubkey = NULL;
			dcrypt_key_convert_private_to_public(pkey2, &pubkey);
			test_assert(dcrypt_key_store_public(pubkey, DCRYPT_FORMAT_DOVECOT, key_1, NULL));
			buffer_set_used_size(key_1, 0);
			test_assert(dcrypt_key_id_public_old(pubkey, key_1, &error));
			test_assert(strcmp("7c9a1039ea2e4fed73e81dd3ffc3fa22ea4a28352939adde7bf8ea858b00fa4f", binary_to_hex(key_1->data, key_1->used)) == 0);

			dcrypt_key_free_public(&pubkey);
			dcrypt_key_free_private(&pkey2);
		}
		dcrypt_key_free_private(&pkey);
	}

	test_end();
}
Esempio n. 2
0
static
int o_stream_encrypt_keydata_create_v1(struct encrypt_ostream *stream)
{
	buffer_t *encrypted_key, *ephemeral_key, *secret, *res, buf;
	const char *error = NULL;
	const struct hash_method *hash = &hash_method_sha256;

	/* various temporary buffers */
	unsigned char seed[IO_STREAM_ENCRYPT_SEED_SIZE];
	unsigned char pkhash[hash->digest_size];
	unsigned char ekhash[hash->digest_size];
	unsigned char hres[hash->digest_size];

	unsigned char hctx[hash->context_size];

	/* hash the public key first */
	buffer_create_from_data(&buf, pkhash, sizeof(pkhash));
	if (!dcrypt_key_id_public_old(stream->pub, &buf, &error)) {
		io_stream_set_error(&stream->ostream.iostream, "Key hash failed: %s", error);
		return -1;
	}

	/* hash the key base */
	hash->init(hctx);
	hash->loop(hctx, seed, sizeof(seed));
	hash->result(hctx, ekhash);

	ephemeral_key = buffer_create_dynamic(pool_datastack_create(), 256);
	encrypted_key = buffer_create_dynamic(pool_datastack_create(), 256);
	secret = buffer_create_dynamic(pool_datastack_create(), 256);

	if (!dcrypt_ecdh_derive_secret_peer(stream->pub, ephemeral_key, secret, &error)) {
		io_stream_set_error(&stream->ostream.iostream, "Cannot perform ECDH: %s", error);
		return -1;
	}

	/* hash the secret data */
	hash->init(hctx);
	hash->loop(hctx, secret->data, secret->used);
	hash->result(hctx, hres);
	safe_memset(buffer_get_modifiable_data(secret, 0), 0, secret->used);

	/* use it to encrypt the actual encryption key */
	struct dcrypt_context_symmetric *dctx;
	if (!dcrypt_ctx_sym_create("aes-256-ctr", DCRYPT_MODE_ENCRYPT, &dctx, &error)) {
		io_stream_set_error(&stream->ostream.iostream, "Key encryption error: %s", error);
		return -1;
	}

	random_fill(seed, sizeof(seed));
	hash->init(hctx);
	hash->loop(hctx, seed, sizeof(seed));
	hash->result(hctx, ekhash);

	int ec = 0;

	/* NB! The old code was broken and used this kind of IV - it is not correct, but
	   we need to stay compatible with old data */
	dcrypt_ctx_sym_set_iv(dctx, (const unsigned char*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
	dcrypt_ctx_sym_set_key(dctx, hres, sizeof(hres));

	if (!dcrypt_ctx_sym_init(dctx, &error) ||
	    !dcrypt_ctx_sym_update(dctx, seed, sizeof(seed), encrypted_key, &error) ||
	    !dcrypt_ctx_sym_final(dctx, encrypted_key, &error)) {
		ec = -1;
	}
	dcrypt_ctx_sym_destroy(&dctx);

	if (ec != 0) {
		safe_memset(seed, 0, sizeof(seed));
		io_stream_set_error(&stream->ostream.iostream, "Key encryption error: %s", error);
		return -1;
	}

	/* same as above */
	dcrypt_ctx_sym_set_iv(stream->ctx_sym, (const unsigned char*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
	dcrypt_ctx_sym_set_key(stream->ctx_sym, seed, sizeof(seed));
	safe_memset(seed, 0, sizeof(seed));

	if (!dcrypt_ctx_sym_init(stream->ctx_sym, &error)) {
		io_stream_set_error(&stream->ostream.iostream, "Encryption init error: %s", error);
		return -1;
	}

	res = buffer_create_dynamic(default_pool, 256);

	/* ephemeral key */
	unsigned short s;
	s = htons(ephemeral_key->used);
	buffer_append(res, &s, 2);
	buffer_append(res, ephemeral_key->data, ephemeral_key->used);
	/* public key hash */
	s = htons(sizeof(pkhash));
	buffer_append(res, &s, 2);
	buffer_append(res, pkhash, sizeof(pkhash));
	/* encrypted key hash */
	s = htons(sizeof(ekhash));
	buffer_append(res, &s, 2);
	buffer_append(res, ekhash, sizeof(ekhash));
	/* encrypted key */
	s = htons(encrypted_key->used);
	buffer_append(res, &s, 2);
	buffer_append(res, encrypted_key->data, encrypted_key->used);

	stream->key_data_len = res->used;
	stream->key_data = buffer_free_without_data(&res);

	return 0;
}