Example #1
0
void cp_set_header_key(xts_key *hdr_key, u8 salt[PKCS5_SALT_SIZE], int cipher, dc_pass *password)
{
	u8 dkey[DISKKEY_SIZE];
	
	sha512_pkcs5_2(
		1000, password->pass, password->size, salt, PKCS5_SALT_SIZE, dkey, PKCS_DERIVE_MAX);

	xts_set_key(dkey, cipher, hdr_key);

	/* prevent leaks */
	burn(dkey, sizeof(dkey));
}
Example #2
0
static void dc_simple_encryption_test()
{
	PXTS_TEST_CONTEXT ctx;
	unsigned char     dk[256];
	unsigned long     e_crc, d_crc, i;

	// test PKDBF2
	for (i = 0; i < (sizeof(pkcs5_vectors) / sizeof(pkcs5_vectors[0])); i++)
	{
		sha512_pkcs5_2(pkcs5_vectors[i].i_count,
			           pkcs5_vectors[i].password, strlen(pkcs5_vectors[i].password),
					   pkcs5_vectors[i].salt, strlen(pkcs5_vectors[i].salt),
					   dk, pkcs5_vectors[i].dklen);

		if (memcmp(dk, pkcs5_vectors[i].key, pkcs5_vectors[i].dklen) != 0)
		{
			KeBugCheckEx(STATUS_ENCRYPTION_FAILED, 'DCRP', i, 0, 0);
		}
	}
	DbgMsg("PKDBF2 test passed\n");

	// test XTS engine if memory may be allocated
	if ( (KeGetCurrentIrql() <= DISPATCH_LEVEL) &&
		 (ctx = (PXTS_TEST_CONTEXT)mm_secure_alloc(sizeof(XTS_TEST_CONTEXT))) != NULL )
	{
		// fill key and test buffer
		for (i = 0; i < (sizeof(ctx->key) / sizeof(ctx->key[0])); i++) ctx->key[i] = (unsigned char)i;
		for (i = 0; i < (sizeof(ctx->test) / sizeof(ctx->test[0])); i++) ctx->test[i] = (unsigned short)i;

		// run test cases
		for (i = 0; i < (sizeof(xts_crc_vectors) / sizeof(xts_crc_vectors[0])); i++)
		{
			xts_set_key(ctx->key, xts_crc_vectors[i].alg, &ctx->xkey);

			xts_encrypt((const unsigned char*)ctx->test, (unsigned char*)ctx->buff, sizeof(ctx->test), 0x3FFFFFFFC00, &ctx->xkey);
			e_crc = crc32((const unsigned char*)ctx->buff, sizeof(ctx->buff));

			xts_decrypt((const unsigned char*)ctx->test, (unsigned char*)ctx->buff, sizeof(ctx->test), 0x3FFFFFFFC00, &ctx->xkey);
			d_crc = crc32((const unsigned char*)ctx->buff, sizeof(ctx->buff));

			if ( e_crc != xts_crc_vectors[i].e_crc || d_crc != xts_crc_vectors[i].d_crc )
			{
				KeBugCheckEx(STATUS_ENCRYPTION_FAILED, 'DCRP', 0xFF00 | i, e_crc, d_crc);
			}
		}

		DbgMsg("XTS test passed\n");
		mm_secure_free(ctx);
	}
}
Example #3
0
int dc_wipe_init(wipe_ctx *ctx, void *hook, int max_size, int method, int cipher)
{
	char key[32];
	int  resl;

	do
	{
		zeroauto(ctx, sizeof(wipe_ctx));
		
		if (method > sizeof(wipe_modes) / sizeof(wipe_mode)) {
			resl = ST_INV_WIPE_MODE; break;
		}
		ctx->mode = wipe_modes[method];
		resl      = ST_NOMEM;

		if (ctx->mode != NULL) 
		{
			if ( (ctx->buff = mm_alloc(max_size, MEM_SECURE)) == NULL ) {
				break;
			}
			if ( (ctx->key = mm_alloc(sizeof(xts_key), MEM_SECURE)) == NULL ) {
				break;
			}
			/* generate random key */
			rnd_get_bytes(key, sizeof(key));
			xts_set_key(key, cipher, ctx->key);
		}
		ctx->hook = hook;
		ctx->size = max_size;
		resl      = ST_OK;
	} while (0);

	/* prevent leaks */
	zeroauto(key, sizeof(key));

	if (resl != ST_OK) {
		if (ctx->buff != NULL) { mm_free(ctx->buff); }
		if (ctx->key != NULL)  { mm_free(ctx->key); }
	}
	return resl;
}
Example #4
0
int cp_decrypt_header(xts_key *hdr_key, dc_header *header, dc_pass *password)
{
	u8        dk[DISKKEY_SIZE];
	int       i, succs = 0;
	dc_header *hcopy;

	if ( (hcopy = mm_alloc(sizeof(dc_header), MEM_SECURE)) == NULL ) {
		return 0;
	}
	sha512_pkcs5_2(
		1000, password->pass, password->size, 
		header->salt, PKCS5_SALT_SIZE, dk, PKCS_DERIVE_MAX);

	for (i = 0; i < CF_CIPHERS_NUM; i++)
	{
		xts_set_key(dk, i, hdr_key);

		xts_decrypt(
			pv(header), pv(hcopy), sizeof(dc_header), 0, hdr_key);

		/* Magic 'DCRP' */
		if (hcopy->sign != DC_VOLM_SIGN) {
			continue;
		}
		/* Check CRC of header */
		if (hcopy->hdr_crc != crc32(pv(&hcopy->version), DC_CRC_AREA_SIZE)) {
			continue;
		}			
		/* copy decrypted part to output */
		memcpy(&header->sign, &hcopy->sign, DC_ENCRYPTEDDATASIZE);
		succs = 1; break;
	}
	/* prevent leaks */
	burn(dk, sizeof(dk));
	mm_free(hcopy);

	return succs;
}
Example #5
0
int dc_encrypt_cd(
	  wchar_t *src_path, wchar_t *dst_path, dc_pass *pass, 
	  int      cipher, cd_callback callback, void *param
	  )
{
	dc_conf_data conf;
	HANDLE       h_src = NULL;
	HANDLE       h_dst = NULL;
	xts_key     *v_key = NULL;
	xts_key     *h_key = NULL;
	dc_header    head;
	int          resl;
	u64          iso_sz;
	u32          bytes;
	u8           salt[PKCS5_SALT_SIZE];
	u8           dk[DISKKEY_SIZE];
	
	if (alg_ok == 0) 
	{
		if (dc_load_conf(&conf) == ST_OK) {
			xts_init(conf.conf_flags & CONF_HW_CRYPTO);
		} else {
			xts_init(0);
		}
		alg_ok = 1;
	}

	do
	{
		if ( (resl = dc_lock_memory(dk, sizeof(dk))) != ST_OK ) {
			break;
		}
		if ( (resl = dc_lock_memory(&head, sizeof(head))) != ST_OK ) {
			break;
		}

		h_src = CreateFile(
			src_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);

		if (h_src == INVALID_HANDLE_VALUE) {
			h_src = NULL; resl = ST_NO_OPEN_FILE; break;
		}

		h_dst = CreateFile(
			dst_path, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);

		if (h_dst == INVALID_HANDLE_VALUE) {
			h_dst = NULL; resl = ST_NO_CREATE_FILE; break;
		}

		if (GetFileSizeEx(h_src, pv(&iso_sz)) == 0) {
			resl = ST_IO_ERROR; break;
		}

		v_key = VirtualAlloc(NULL, sizeof(xts_key), MEM_COMMIT+MEM_RESERVE, PAGE_EXECUTE_READWRITE);
		h_key = VirtualAlloc(NULL, sizeof(xts_key), MEM_COMMIT+MEM_RESERVE, PAGE_EXECUTE_READWRITE);
		
		if ( (v_key == NULL) || (h_key == NULL) ) {
			resl = ST_NOMEM; break;
		}

		/* lock keys in memory */
		if ( (resl = dc_lock_memory(v_key, sizeof(xts_key))) != ST_OK ) {
			break;
		}
		if ( (resl = dc_lock_memory(h_key, sizeof(xts_key))) != ST_OK ) {
			break;
		}

		/* create volume header */
		zeroauto(&head, sizeof(dc_header));

		dc_get_random(pv(salt),          PKCS5_SALT_SIZE);
		dc_get_random(pv(&head.disk_id), sizeof(u32));
		dc_get_random(pv(head.key_1),    DISKKEY_SIZE);

		head.sign     = DC_VOLM_SIGN;
		head.version  = DC_HDR_VERSION;
		head.flags    = VF_NO_REDIR;
		head.alg_1    = cipher;
		head.use_size = iso_sz;
		head.data_off = sizeof(dc_header);
		head.hdr_crc  = crc32(pv(&head.version), DC_CRC_AREA_SIZE);

		/* initialize volume key */
		xts_set_key(head.key_1, cipher, v_key);

		/* initialize header key */
		sha512_pkcs5_2(
			1000, pass->pass, 
			pass->size, salt, PKCS5_SALT_SIZE, dk, PKCS_DERIVE_MAX);

		xts_set_key(dk, cipher, h_key);

		/* encrypt volume header */
		xts_encrypt(pv(&head), pv(&head), sizeof(dc_header), 0, h_key);

		/* save salt */
		autocpy(head.salt, salt, PKCS5_SALT_SIZE);

		/* write volume header to file */
		if (WriteFile(h_dst, &head, sizeof(head), &bytes, NULL) == 0) {
			resl = ST_IO_ERROR; break;
		}

		resl = do_cd_encrypt(h_src, h_dst, iso_sz, v_key, callback, param);
	} while (0);

	/* prevent leaks */
	zeroauto(dk, sizeof(dk));
	zeroauto(&head, sizeof(head));
	dc_unlock_memory(dk);
	dc_unlock_memory(&head);

	if (v_key != NULL) {
		zeroauto(v_key, sizeof(xts_key));
		dc_unlock_memory(v_key);
		VirtualFree(v_key, 0, MEM_RELEASE);
	}

	if (h_key != NULL) {
		zeroauto(h_key, sizeof(xts_key));
		dc_unlock_memory(h_key);
		VirtualFree(h_key, 0, MEM_RELEASE);
	}

	if (h_src != NULL) {
		CloseHandle(h_src);
	}

	if (h_dst != NULL) 
	{
		CloseHandle(h_dst);

		if (resl != ST_OK) {
			DeleteFile(dst_path);
		}	
	}

	return resl;
}
Example #6
0
int dc_mount_device(wchar_t *dev_name, dc_pass *password, u32 mnt_flags)
{
	dc_header *hcopy = NULL;
	dev_hook  *hook  = NULL;
	xts_key   *hdr_key = NULL;
	int        resl;
	
	DbgMsg("dc_mount_device %ws\n", dev_name);

	do 
	{
		if ( (hook = dc_find_hook(dev_name)) == NULL ) {
			resl = ST_NF_DEVICE; break;
		}

		wait_object_infinity(&hook->busy_lock);

		if (hook->flags & F_ENABLED) {
			resl = ST_ALR_MOUNT; break;
		}
		if (hook->flags & (F_UNSUPRT | F_DISABLE | F_FORMATTING)) {
			resl = ST_ERROR; break;
		}

		if ( !NT_SUCCESS(dc_fill_device_info(hook)) ) {
			resl = ST_IO_ERROR; break;
		}

		if ( ( (hook->flags & F_CDROM) && (hook->bps != CD_SECTOR_SIZE) ) ||
			 (!(hook->flags & F_CDROM) && IS_INVALID_SECTOR_SIZE(hook->bps) ) )
		{
			hook->flags |= F_UNSUPRT; resl = ST_ERROR; break;
		}
		if ( (resl = dc_probe_decrypt(hook, &hcopy, &hdr_key, password)) != ST_OK ) {
			break;
		}

		/* check volume header */		
		if ( (IS_INVALID_VOL_FLAGS(hcopy->flags) != 0) ||
			 ( (hcopy->flags & VF_STORAGE_FILE) && (hcopy->stor_off == 0) ) ||
			 (hcopy->alg_1 >= CF_CIPHERS_NUM) ||
			 (hcopy->alg_2 >= CF_CIPHERS_NUM) || 
			 (hcopy->tmp_wp_mode >= WP_NUM) ||
			 ( (hook->flags & F_CDROM) && (hcopy->flags & (VF_TMP_MODE | VF_STORAGE_FILE)) ) )
		{
			resl = ST_INV_VOLUME; break;
		}
		if (hcopy->version > DC_HDR_VERSION) {
			resl = ST_VOLUME_TOO_NEW; break;
		}
#if 0
		/* update volume header if needed */
		if ( (hcopy->version < DC_HDR_VERSION) && !(hook->flags & F_CDROM) )
		{
			hcopy->version = DC_HDR_VERSION;
			memset(hcopy->deprecated, 0, sizeof(hcopy->deprecated));
			
			io_write_header(hook, hcopy, hdr_key, NULL);
		}
#endif

		DbgMsg("hdr_key=%p, dsk_key=%p\n", hdr_key, hook->dsk_key);

		// initialize volume key
		if ( (hook->dsk_key = (xts_key*)mm_secure_alloc(sizeof(xts_key))) == NULL ) {
			resl = ST_NOMEM;
			break;
		}
		xts_set_key(hcopy->key_1, hcopy->alg_1, hook->dsk_key);

		DbgMsg("device mounted\n");

		if (hcopy->flags & VF_STORAGE_FILE) {
			hook->use_size = hook->dsk_size;
			hook->stor_off = hcopy->stor_off;
		} else {
			hook->use_size = hook->dsk_size - hook->head_len;
			hook->stor_off = hook->use_size;
		}		
		hook->crypt.cipher_id = d8(hcopy->alg_1);
		hook->disk_id    = hcopy->disk_id;
		hook->vf_version = hcopy->version;		
		hook->tmp_size   = 0;
		hook->mnt_flags  = mnt_flags;

		DbgMsg("hook->vf_version %d\n", hook->vf_version);
		DbgMsg("hook->bps %d\n", hook->bps);
		DbgMsg("hook->head_len %d\n", hook->head_len);		
		DbgMsg("flags %x\n", hcopy->flags);

		if (hcopy->flags & VF_STORAGE_FILE) {
			hook->flags |= F_PROTECT_DCSYS;
		}
		if (hcopy->flags & VF_NO_REDIR) {
			hook->flags   |= F_NO_REDIRECT;
			hook->stor_off = 0;			
		}

		if (hcopy->flags & VF_TMP_MODE)
		{
			hook->tmp_size      = hcopy->tmp_size;
			hook->hdr_key       = hdr_key;
			hook->crypt.wp_mode = hcopy->tmp_wp_mode;			

			if (hcopy->flags & VF_REENCRYPT) {
				hook->sync_init_type = S_CONTINUE_RE_ENC;
			} else {
				hook->sync_init_type = S_CONTINUE_ENC;
			}
				
			/* copy decrypted header to device data */
			memcpy(&hook->tmp_header, hcopy, sizeof(dc_header));
				
			if ( (resl = dc_enable_sync_mode(hook)) != ST_OK ) 
			{
				burn(&hook->tmp_header, sizeof(dc_header));
				hdr_key = hook->hdr_key;
			} else  {				
				hdr_key = NULL; /* prevent key wiping */
			}
		} else {			
			hook->flags |= F_ENABLED;
			resl = ST_OK;
		}
		if (resl == ST_OK) {
			/* increment mount changes counter */
			lock_inc(&hook->chg_mount);
		}
	} while (0);

	if (hdr_key != NULL) mm_secure_free(hdr_key);
	if (hcopy != NULL)   mm_secure_free(hcopy);

	if (hook != NULL)
	{
		if ((hook->flags & F_ENABLED) == 0 && hook->dsk_key != NULL) {
			mm_secure_free(hook->dsk_key);
			hook->dsk_key = NULL;
		}

		KeReleaseMutex(&hook->busy_lock, FALSE);
		dc_deref_hook(hook);
	}
	return resl;
}
Example #7
0
int dc_format_start(wchar_t *dev_name, dc_pass *password, crypt_info *crypt)
{
	IO_STATUS_BLOCK iosb;
	NTSTATUS        status;
	dc_header      *header  = NULL;
	dev_hook       *hook    = NULL;
	xts_key        *tmp_key = NULL;
	HANDLE          h_dev   = NULL;
	u8             *buff    = NULL;
	int             w_init  = 0;
	u8              key_buf[32];
	int             resl;

	DbgMsg("dc_format_start\n");

	do
	{
		if ( (hook = dc_find_hook(dev_name)) == NULL ) {
			resl = ST_NF_DEVICE; break;
		}

		wait_object_infinity(&hook->busy_lock);

		if (hook->flags & (F_ENABLED | F_UNSUPRT | F_DISABLE | F_CDROM)) {
			resl = ST_ERROR; break;
		}

		/* verify encryption info */
		if ( (crypt->cipher_id >= CF_CIPHERS_NUM) || (crypt->wp_mode >= WP_NUM) ) {
			resl = ST_ERROR; break;
		}

		/* get device params */
		if ( (resl = dc_fill_disk_info(hook)) != ST_OK ) {
			break;
		}

		if ( (header = mm_alloc(sizeof(dc_header), MEM_SECURE)) == NULL ) {
			resl = ST_NOMEM; break;
		}
		if ( (buff = mm_alloc(ENC_BLOCK_SIZE, 0)) == NULL ) {
			resl = ST_NOMEM; break;
		}
		if ( (tmp_key = mm_alloc(sizeof(xts_key), MEM_SECURE)) == NULL ) {
			resl = ST_NOMEM; break;
		}		

		/* temporary disable automounting */
		hook->flags |= F_NO_AUTO_MOUNT;

		/* open volume device */
		if ( (h_dev = io_open_device(hook->dev_name)) == NULL ) {
			resl = ST_LOCK_ERR; break; 
		}		
		/* lock volume */
		status = ZwFsControlFile(
			h_dev, NULL, NULL, NULL, &iosb, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0);

		if (NT_SUCCESS(status) == FALSE) {
			resl = ST_LOCK_ERR; break; 
		}

		/* enable automounting */
		hook->flags &= ~F_NO_AUTO_MOUNT;
		/* set encryption info */
		hook->crypt = *crypt;

		/* init data wiping */
		resl = dc_wipe_init(
			&hook->wp_ctx, hook, ENC_BLOCK_SIZE, crypt->wp_mode, crypt->cipher_id);

		if (resl == ST_OK) {
			w_init = 1;			
		} else break;

		/* wipe first sectors */
		dc_wipe_process(&hook->wp_ctx, 0, hook->head_len);

		/* create random temporary key */
		cp_rand_bytes(key_buf, sizeof(key_buf));

		xts_set_key(key_buf, crypt->cipher_id, tmp_key);

		/* create volume header */
		memset(header, 0, sizeof(dc_header));

		cp_rand_bytes(pv(header->salt),     PKCS5_SALT_SIZE);
		cp_rand_bytes(pv(&header->disk_id), sizeof(u32));
		cp_rand_bytes(pv(header->key_1),    DISKKEY_SIZE);

		header->sign    = DC_VOLM_SIGN;
		header->version = DC_HDR_VERSION;
		header->alg_1   = crypt->cipher_id;		

		/* write volume header */
		if ( (resl = io_write_header(hook, header, NULL, password)) != ST_OK ) {
			break;
		}
		/* mount device */
		if ( (resl = dc_mount_device(dev_name, password, 0)) != ST_OK ) {
			break;
		}		
		/* set hook fields */
		hook->flags    |= F_FORMATTING;
		hook->tmp_size  = hook->head_len;
		hook->tmp_buff  = buff;
		hook->tmp_key   = tmp_key;
	} while (0);

	if ( (resl != ST_OK) )
	{
		if (w_init != 0) {
			dc_wipe_free(&hook->wp_ctx);
		}
		if (buff != NULL)    { mm_free(buff); }
		if (tmp_key != NULL) { mm_free(tmp_key); }
	}
	if (header != NULL) {
		mm_free(header);
	}
	if (hook != NULL) { 
		KeReleaseMutex(&hook->busy_lock, FALSE);
		dc_deref_hook(hook);
	}
	/* prevent leaks */
	burn(key_buf, sizeof(key_buf));
	
	if (h_dev != NULL)
	{
		if (resl != ST_LOCK_ERR)
		{
			/* dismount volume */
			ZwFsControlFile(
				h_dev, NULL, NULL, NULL, &iosb, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);

			/* unlock volume */
			ZwFsControlFile(
				h_dev, NULL, NULL, NULL, &iosb, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
		}
		/* close device */
		ZwClose(h_dev);
	}		

	return resl;
}