Esempio n. 1
0
int
free_info(struct tcplay_info *info)
{
	if (info->cipher_chain)
		tc_free_cipher_chain(info->cipher_chain);
	if (info->hdr)
		free_safe_mem(info->hdr);

	free_safe_mem(info);

	return 0;
}
Esempio n. 2
0
static
int
tc_free_cipher_chain(struct tc_cipher_chain *chain)
{
	struct tc_cipher_chain *next = chain;

	while ((chain = next) != NULL) {
		next = chain->next;

		if (chain->key != NULL)
			free_safe_mem(chain->key);
		free_safe_mem(chain);
	}

	return 0;
}
Esempio n. 3
0
int
write_to_disk(const char *dev, off_t offset, size_t blksz, void *mem,
    size_t bytes)
{
	unsigned char *mem_buf = NULL;
	ssize_t w;
	size_t sz;
	off_t internal_off;
	int fd;

	/* Align to block sizes */
	internal_off = offset % blksz;
#ifdef DEBUG
	printf("offset: %"PRIu64", internal offset: %"PRIu64"\n",
	    (uint64_t)offset, (uint64_t)internal_off);
#endif
	offset = (offset/blksz) * blksz;

	if ((internal_off + bytes) > blksz) {
		tc_log(1, "This should never happen: internal_off + bytes > "
		    "blksz (write_to_disk)\n");
		return -1;
	}

	if ((bytes < blksz) || (internal_off != 0)) {
		sz = blksz;
		if ((mem_buf = read_to_safe_mem(dev, offset, &sz)) == NULL) {
			tc_log(1, "Error buffering data on "
			    "write_to_disk(%s)\n", dev);
			return -1;
		}

		memcpy(mem_buf + internal_off, mem, bytes);
	}

	if ((fd = open(dev, O_WRONLY)) < 0) {
		tc_log(1, "Error opening device %s\n", dev);
		return -1;
	}

	if ((lseek(fd, offset, (offset >= 0) ? SEEK_SET : SEEK_END) < 0)) {
		tc_log(1, "Error seeking on device %s\n", dev);
		close(fd);
		return -1;
	}

	if ((w = write(fd, (mem_buf != NULL) ? mem_buf : mem, bytes)) <= 0) {
		tc_log(1, "Error writing to device %s\n", dev);
		close(fd);
		return -1;
	}

	close(fd);

	if (mem_buf != NULL)
		free_safe_mem(mem_buf);
	return 0;
}
Esempio n. 4
0
int
tc_api_task_uninit(tc_api_task task)
{
	if (task->last_info != NULL)
		free_info(task->last_info);
	opts_free(task->opts);
	free_safe_mem(task);

	return TC_OK;
}
Esempio n. 5
0
int
tc_cipher_chain_free_keys(struct tc_cipher_chain *cipher_chain)
{
	for (; cipher_chain != NULL; cipher_chain = cipher_chain->next) {
		if (cipher_chain->key != NULL) {
			free_safe_mem(cipher_chain->key);
			cipher_chain->key = NULL;
		}
	}

	return 0;
}
Esempio n. 6
0
int
tc_decrypt(struct tc_cipher_chain *cipher_chain, unsigned char *key,
    unsigned char *iv,
    unsigned char *in, int in_len, unsigned char *out)
{
	struct tc_cipher_chain *chain_start;
	int err;

	chain_start = cipher_chain;

	if ((err = tc_cipher_chain_populate_keys(cipher_chain, key)))
		return err;

#ifdef DEBUG
	printf("tc_decrypt: starting chain!\n");
#endif

	/*
	 * Now process the actual decryption, in reverse cascade order; so
	 * first find the last element in the chain.
	 */
	for (; cipher_chain->next != NULL; cipher_chain = cipher_chain->next)
		;
	for (;
	    cipher_chain != NULL;
	    cipher_chain = cipher_chain->prev) {
#ifdef DEBUG
		printf("tc_decrypt: Currently using cipher %s\n",
		    cipher_chain->cipher->name);
#endif

		err = syscrypt(cipher_chain->cipher, cipher_chain->key,
		    cipher_chain->cipher->klen, iv, in, out, in_len, 0);

		/* Deallocate this key, since we won't need it anymore */
		free_safe_mem(cipher_chain->key);
		cipher_chain->key = NULL;

		if (err != 0) {
			tc_cipher_chain_free_keys(chain_start);
			return err;
		}

		/* Set next input buffer as current output buffer */
		in = out;
	}

	tc_cipher_chain_free_keys(chain_start);

	return 0;
}
Esempio n. 7
0
tc_api_task
tc_api_task_init(const char *op)
{
	tc_api_task task = NULL;
	int fail = 1;

	if ((task = alloc_safe_mem(sizeof(*task))) == NULL) {
		errno = ENOMEM;
		goto out;
	}

	if ((task->opts = opts_init()) == NULL) {
		errno = ENOMEM;
		goto out;
	}

	if (_match(op, "create")) {
		task->op = TC_OP_CREATE;
	} else if (_match(op, "map")) {
		task->op = TC_OP_MAP;
	} else if (_match(op, "unmap")) {
		task->op = TC_OP_UNMAP;
	} else if (_match(op, "info")) {
		task->op = TC_OP_INFO;
	} else if (_match(op, "info_mapped")) {
		task->op = TC_OP_INFO_MAPPED;
	} else if (_match(op, "modify")) {
		task->op = TC_OP_MODIFY;
	} else if (_match(op, "restore")) {
		task->op = TC_OP_RESTORE;
	} else {
		errno = EINVAL;
		goto out;
	}

	tc_set_iteration_count(0);

	fail = 0;

out:
	if (fail && task != NULL) {
		if (task->opts != NULL)
			opts_free(task->opts);
		free_safe_mem(task);
	}

	return fail ? NULL : task;
}
Esempio n. 8
0
struct tchdr_dec *
decrypt_hdr(struct tchdr_enc *ehdr, struct tc_cipher_chain *cipher_chain,
            unsigned char *key)
{
    struct tchdr_dec *dhdr;
    unsigned char iv[128];
    int error;

    if ((dhdr = alloc_safe_mem(sizeof(struct tchdr_dec))) == NULL) {
        tc_log(1, "Error allocating safe tchdr_dec memory\n");
        return NULL;
    }

    memset(iv, 0, sizeof(iv));

    error = tc_decrypt(cipher_chain, key, iv, ehdr->enc,
                       sizeof(struct tchdr_dec), (unsigned char *)dhdr);
    if (error) {
        tc_log(1, "Header decryption failed\n");
        free_safe_mem(dhdr);
        return NULL;
    }

    BE_TO_HOST(16, dhdr->tc_ver);
    BE_TO_HOST(16, dhdr->tc_min_ver);
    BE_TO_HOST(32, dhdr->crc_keys);
    BE_TO_HOST(64, dhdr->vol_ctime);
    BE_TO_HOST(64, dhdr->hdr_ctime);
    BE_TO_HOST(64, dhdr->sz_hidvol);
    BE_TO_HOST(64, dhdr->sz_vol);
    BE_TO_HOST(64, dhdr->off_mk_scope);
    BE_TO_HOST(64, dhdr->sz_mk_scope);
    BE_TO_HOST(32, dhdr->flags);
    BE_TO_HOST(32, dhdr->sec_sz);
    BE_TO_HOST(32, dhdr->crc_dhdr);

    return dhdr;
}
Esempio n. 9
0
void *
read_to_safe_mem(const char *file, off_t offset, size_t *sz)
{
	void *mem = NULL;
	ssize_t r = 0;
	int fd;

	if ((fd = open(file, O_RDONLY)) < 0) {
		tc_log(1, "Error opening file %s\n", file);
		return NULL;
	}

	if ((mem = alloc_safe_mem(*sz)) == NULL) {
		tc_log(1, "Error allocating memory\n");
		goto out;
	}

	if ((lseek(fd, offset, (offset >= 0) ? SEEK_SET : SEEK_END) < 0)) {
		tc_log(1, "Error seeking on file %s\n", file);
		goto m_err;
	}

	if ((r = read(fd, mem, *sz)) <= 0) {
		tc_log(1, "Error reading from file %s\n", file);
		goto m_err;
	}

out:
	*sz = r;
	close(fd);
	return mem;
	/* NOT REACHED */

m_err:
	free_safe_mem(mem);
	close(fd);
	return NULL;
}
Esempio n. 10
0
struct tchdr_enc *copy_reencrypt_hdr(unsigned char *pass, int passlen,
                                     struct pbkdf_prf_algo *prf_algo, int weak, struct tcplay_info *info,
                                     struct tchdr_enc **backup_hdr)
{
    struct tchdr_enc *ehdr, *ehdr_backup;
    unsigned char *key, *key_backup;
    unsigned char iv[128];
    int error;

    key = key_backup = NULL;
    ehdr = ehdr_backup = NULL;

    /* By default stick to current PRF algo */
    if (prf_algo == NULL)
        prf_algo = info->pbkdf_prf;

    if ((ehdr = (struct tchdr_enc *)alloc_safe_mem(sizeof(*ehdr))) == NULL) {
        tc_log(1, "could not allocate safe ehdr memory\n");
        goto error;
    }

    if ((ehdr_backup = (struct tchdr_enc *)alloc_safe_mem
                       (sizeof(*ehdr_backup))) == NULL) {
        tc_log(1, "could not allocate safe ehdr_backup memory\n");
        goto error;
    }

    if ((key = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
        tc_log(1, "could not allocate safe key memory\n");
        goto error;
    }

    if ((key_backup = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
        tc_log(1, "could not allocate safe backup key memory\n");
        goto error;
    }

    if ((error = get_random(ehdr->salt, sizeof(ehdr->salt), weak)) != 0) {
        tc_log(1, "could not get salt\n");
        goto error;
    }

    if ((error = get_random(ehdr_backup->salt, sizeof(ehdr_backup->salt), weak))
            != 0) {
        tc_log(1, "could not get salt for backup header\n");
        goto error;
    }

    error = pbkdf2(prf_algo, (char *)pass, passlen,
                   ehdr->salt, sizeof(ehdr->salt),
                   MAX_KEYSZ, key);
    if (error) {
        tc_log(1, "could not derive key\n");
        goto error;
    }

    error = pbkdf2(prf_algo, (char *)pass, passlen,
                   ehdr_backup->salt, sizeof(ehdr_backup->salt),
                   MAX_KEYSZ, key_backup);
    if (error) {
        tc_log(1, "could not derive backup key\n");
        goto error;
    }

    HOST_TO_BE(16, info->hdr->tc_ver);
    HOST_TO_BE(16, info->hdr->tc_min_ver);
    HOST_TO_BE(32, info->hdr->crc_keys);
    HOST_TO_BE(64, info->hdr->vol_ctime);
    HOST_TO_BE(64, info->hdr->hdr_ctime);
    HOST_TO_BE(64, info->hdr->sz_vol);
    HOST_TO_BE(64, info->hdr->sz_hidvol);
    HOST_TO_BE(64, info->hdr->off_mk_scope);
    HOST_TO_BE(64, info->hdr->sz_mk_scope);
    HOST_TO_BE(32, info->hdr->sec_sz);
    HOST_TO_BE(32, info->hdr->flags);
    HOST_TO_BE(32, info->hdr->crc_dhdr);

    memset(iv, 0, sizeof(iv));
    error = tc_encrypt(info->cipher_chain, key, iv,
                       (unsigned char *)info->hdr, sizeof(struct tchdr_dec), ehdr->enc);
    if (error) {
        tc_log(1, "Header encryption failed\n");
        goto error;
    }

    memset(iv, 0, sizeof(iv));
    error = tc_encrypt(info->cipher_chain, key_backup, iv,
                       (unsigned char *)info->hdr,
                       sizeof(struct tchdr_dec), ehdr_backup->enc);
    if (error) {
        tc_log(1, "Backup header encryption failed\n");
        goto error;
    }

    free_safe_mem(key);
    free_safe_mem(key_backup);

    if (backup_hdr != NULL)
        *backup_hdr = ehdr_backup;
    else
        free_safe_mem(ehdr_backup);

    return ehdr;
    /* NOT REACHED */

error:
    if (key)
        free_safe_mem(key);
    if (key_backup)
        free_safe_mem(key_backup);
    if (ehdr)
        free_safe_mem(ehdr);
    if (ehdr_backup)
        free_safe_mem(ehdr_backup);

    return NULL;
}
Esempio n. 11
0
struct tchdr_enc *
create_hdr(unsigned char *pass, int passlen, struct pbkdf_prf_algo *prf_algo,
           struct tc_cipher_chain *cipher_chain, size_t sec_sz,
           disksz_t total_blocks __unused,
           off_t offset, disksz_t blocks, int veracrypt_mode, int hidden, int weak, struct tchdr_enc **backup_hdr)
{
    struct tchdr_enc *ehdr, *ehdr_backup;
    struct tchdr_dec *dhdr;
    unsigned char *key, *key_backup;
    unsigned char iv[128];
    int error;

    key = key_backup = NULL;
    dhdr = NULL;
    ehdr = ehdr_backup = NULL;

    if (backup_hdr != NULL)
        *backup_hdr = NULL;

    if ((dhdr = (struct tchdr_dec *)alloc_safe_mem(sizeof(*dhdr))) == NULL) {
        tc_log(1, "could not allocate safe dhdr memory\n");
        goto error;
    }

    if ((ehdr = (struct tchdr_enc *)alloc_safe_mem(sizeof(*ehdr))) == NULL) {
        tc_log(1, "could not allocate safe ehdr memory\n");
        goto error;
    }

    if ((ehdr_backup = (struct tchdr_enc *)alloc_safe_mem
                       (sizeof(*ehdr_backup))) == NULL) {
        tc_log(1, "could not allocate safe ehdr_backup memory\n");
        goto error;
    }

    if ((key = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
        tc_log(1, "could not allocate safe key memory\n");
        goto error;
    }

    if ((key_backup = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
        tc_log(1, "could not allocate safe backup key memory\n");
        goto error;
    }

    if ((error = get_random(ehdr->salt, sizeof(ehdr->salt), weak)) != 0) {
        tc_log(1, "could not get salt\n");
        goto error;
    }

    if ((error = get_random(ehdr_backup->salt, sizeof(ehdr_backup->salt), weak))
            != 0) {
        tc_log(1, "could not get salt for backup header\n");
        goto error;
    }

    error = pbkdf2(prf_algo, (char *)pass, passlen,
                   ehdr->salt, sizeof(ehdr->salt),
                   MAX_KEYSZ, key);
    if (error) {
        tc_log(1, "could not derive key\n");
        goto error;
    }

    error = pbkdf2(prf_algo, (char *)pass, passlen,
                   ehdr_backup->salt, sizeof(ehdr_backup->salt),
                   MAX_KEYSZ, key_backup);
    if (error) {
        tc_log(1, "could not derive backup key\n");
        goto error;
    }

    memset(dhdr, 0, sizeof(*dhdr));

    if ((error = get_random(dhdr->keys, sizeof(dhdr->keys), weak)) != 0) {
        tc_log(1, "could not get key random bits\n");
        goto error;
    }

    if (veracrypt_mode == 0) {
        memcpy(dhdr->tc_str, TC_SIG, 4);
        dhdr->tc_ver = 5;
        dhdr->tc_min_ver = 0x0700;
    }
    else {
        memcpy(dhdr->tc_str, VC_SIG, 4);
        dhdr->tc_ver = 5;
        dhdr->tc_min_ver = 0x010b;
    }
    dhdr->crc_keys = crc32((void *)&dhdr->keys, 256);
    dhdr->sz_vol = blocks * sec_sz;
    if (hidden)
        dhdr->sz_hidvol = dhdr->sz_vol;
    dhdr->off_mk_scope = offset * sec_sz;
    dhdr->sz_mk_scope = blocks * sec_sz;
    dhdr->sec_sz = sec_sz;
    dhdr->flags = 0;

    HOST_TO_BE(16, dhdr->tc_ver);
    HOST_TO_BE(16, dhdr->tc_min_ver);
    HOST_TO_BE(32, dhdr->crc_keys);
    HOST_TO_BE(64, dhdr->sz_vol);
    HOST_TO_BE(64, dhdr->sz_hidvol);
    HOST_TO_BE(64, dhdr->off_mk_scope);
    HOST_TO_BE(64, dhdr->sz_mk_scope);
    HOST_TO_BE(32, dhdr->sec_sz);
    HOST_TO_BE(32, dhdr->flags);

    dhdr->crc_dhdr = crc32((void *)dhdr, 188);
    HOST_TO_BE(32, dhdr->crc_dhdr);

    memset(iv, 0, sizeof(iv));
    error = tc_encrypt(cipher_chain, key, iv, (unsigned char *)dhdr,
                       sizeof(struct tchdr_dec), ehdr->enc);
    if (error) {
        tc_log(1, "Header encryption failed\n");
        goto error;
    }

    memset(iv, 0, sizeof(iv));
    error = tc_encrypt(cipher_chain, key_backup, iv,
                       (unsigned char *)dhdr,
                       sizeof(struct tchdr_dec), ehdr_backup->enc);
    if (error) {
        tc_log(1, "Backup header encryption failed\n");
        goto error;
    }

    free_safe_mem(key);
    free_safe_mem(key_backup);
    free_safe_mem(dhdr);

    if (backup_hdr != NULL)
        *backup_hdr = ehdr_backup;
    else
        free_safe_mem(ehdr_backup);

    return ehdr;
    /* NOT REACHED */

error:
    if (key)
        free_safe_mem(key);
    if (key_backup)
        free_safe_mem(key_backup);
    if (dhdr)
        free_safe_mem(dhdr);
    if (ehdr)
        free_safe_mem(ehdr);
    if (ehdr_backup)
        free_safe_mem(ehdr_backup);

    return NULL;
}
Esempio n. 12
0
int
apply_keyfiles(unsigned char *pass, size_t pass_memsz, const char *keyfiles[],
    int nkeyfiles)
{
	int pl, k;
	unsigned char *kpool;
	unsigned char *kdata;
	int kpool_idx;
	size_t i, kdata_sz;
	uint32_t crc;

	if (pass_memsz < MAX_PASSSZ) {
		tc_log(1, "Not enough memory for password manipluation\n");
		return ENOMEM;
	}

	pl = strlen((char *)pass);
	memset(pass+pl, 0, MAX_PASSSZ-pl);

	if ((kpool = alloc_safe_mem(KPOOL_SZ)) == NULL) {
		tc_log(1, "Error allocating memory for keyfile pool\n");
		return ENOMEM;
	}

	memset(kpool, 0, KPOOL_SZ);

	for (k = 0; k < nkeyfiles; k++) {
#ifdef DEBUG
		printf("Loading keyfile %s into kpool\n", keyfiles[k]);
#endif
		kpool_idx = 0;
		crc = ~0U;
		kdata_sz = MAX_KFILE_SZ;

		if ((kdata = read_to_safe_mem(keyfiles[k], 0, &kdata_sz)) == NULL) {
			tc_log(1, "Error reading keyfile %s content\n",
			    keyfiles[k]);
			free_safe_mem(kpool);
			return EIO;
		}

		for (i = 0; i < kdata_sz; i++) {
			crc = crc32_intermediate(crc, kdata[i]);

			kpool[kpool_idx++] += (unsigned char)(crc >> 24);
			kpool[kpool_idx++] += (unsigned char)(crc >> 16);
			kpool[kpool_idx++] += (unsigned char)(crc >> 8);
			kpool[kpool_idx++] += (unsigned char)(crc);

			/* Wrap around */
			if (kpool_idx == KPOOL_SZ)
				kpool_idx = 0;
		}

		free_safe_mem(kdata);
	}

#ifdef DEBUG
	printf("Applying kpool to passphrase\n");
#endif
	/* Apply keyfile pool to passphrase */
	for (i = 0; i < KPOOL_SZ; i++)
		pass[i] += kpool[i];

	free_safe_mem(kpool);

	return 0;
}
Esempio n. 13
0
struct tcplay_info *
info_map_common(struct tcplay_opts *opts, char *passphrase_out)
{
	struct tchdr_enc *ehdr, *hehdr = NULL;
	struct tcplay_info *info, *hinfo = NULL;
	char *pass;
	char *h_pass;
	int error, error2 = 0;
	size_t sz;
	size_t blksz;
	disksz_t blocks;
	int is_hidden = 0;
	int try_empty = 0;
	int retries;

	if ((error = get_disk_info(opts->dev, &blocks, &blksz)) != 0) {
		tc_log(1, "could not get disk information\n");
		return NULL;
	}

	if (opts->retries < 1)
		retries = 1;
	else
		retries = opts->retries;

	/*
	 * Add one retry so we can do a first try without asking for
	 * a password if keyfiles are passed in.
	 */
	if (opts->interactive && (opts->nkeyfiles > 0)) {
		try_empty = 1;
		++retries;
	}

	info = NULL;

	ehdr = NULL;
	pass = h_pass = NULL;

	while ((info == NULL) && retries-- > 0)
	{
		pass = h_pass = NULL;
		ehdr = hehdr = NULL;
		info = hinfo = NULL;

		if ((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
			tc_log(1, "could not allocate safe passphrase memory\n");
			goto out;
		}

		if (try_empty) {
			pass[0] = '\0';
		} else if (opts->interactive) {
		        if ((error = read_passphrase("Passphrase: ", pass,
			    MAX_PASSSZ, PASS_BUFSZ, opts->timeout))) {
				tc_log(1, "could not read passphrase\n");
				/* XXX: handle timeout differently? */
				goto out;
			}
			pass[MAX_PASSSZ] = '\0';
		} else {
			/* In batch mode, use provided passphrase */
			if (opts->passphrase != NULL) {
				strncpy(pass, opts->passphrase, MAX_PASSSZ);
				pass[MAX_PASSSZ] = '\0';
			}
		}

		if (passphrase_out != NULL) {
			strcpy(passphrase_out, pass);
		}

		if (opts->nkeyfiles > 0) {
			/* Apply keyfiles to 'pass' */
			if ((error = apply_keyfiles((unsigned char *)pass, PASS_BUFSZ,
			    opts->keyfiles, opts->nkeyfiles))) {
				tc_log(1, "could not apply keyfiles");
				goto out;
			}
		}

		if (opts->protect_hidden) {
			if ((h_pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
				tc_log(1, "could not allocate safe passphrase memory\n");
				goto out;
			}

			if (opts->interactive) {
			        if ((error = read_passphrase(
				    "Passphrase for hidden volume: ", h_pass,
				    MAX_PASSSZ, PASS_BUFSZ, opts->timeout))) {
					tc_log(1, "could not read passphrase\n");
					goto out;
				}
				h_pass[MAX_PASSSZ] = '\0';
			} else {
				/* In batch mode, use provided passphrase */
				if (opts->h_passphrase != NULL) {
					strncpy(h_pass, opts->h_passphrase, MAX_PASSSZ);
					h_pass[MAX_PASSSZ] = '\0';
				}
			}

			if (opts->n_hkeyfiles > 0) {
				/* Apply keyfiles to 'pass' */
				if ((error = apply_keyfiles((unsigned char *)h_pass, PASS_BUFSZ,
				    opts->h_keyfiles, opts->n_hkeyfiles))) {
					tc_log(1, "could not apply keyfiles");
					goto out;
				}
			}
		}

		/* Always read blksz-sized chunks */
		sz = blksz;

		if (TC_FLAG_SET(opts->flags, HDR_FROM_FILE)) {
			ehdr = (struct tchdr_enc *)read_to_safe_mem(
			    opts->hdr_file_in, 0, &sz);
			if (ehdr == NULL) {
				tc_log(1, "error read hdr_enc: %s", opts->hdr_file_in);
				goto out;
			}
		} else {
			ehdr = (struct tchdr_enc *)read_to_safe_mem(
			    (TC_FLAG_SET(opts->flags, SYS)) ? opts->sys_dev : opts->dev,
			    (TC_FLAG_SET(opts->flags, SYS) || TC_FLAG_SET(opts->flags, FDE)) ?
			    HDR_OFFSET_SYS :
			    (!TC_FLAG_SET(opts->flags, BACKUP)) ? 0 : -BACKUP_HDR_OFFSET_END,
			    &sz);
			if (ehdr == NULL) {
				tc_log(1, "error read hdr_enc: %s", opts->dev);
				goto out;
			}
		}

		if (!TC_FLAG_SET(opts->flags, SYS)) {
			/* Always read blksz-sized chunks */
			sz = blksz;

			if (TC_FLAG_SET(opts->flags, H_HDR_FROM_FILE)) {
				hehdr = (struct tchdr_enc *)read_to_safe_mem(
				    opts->h_hdr_file_in, 0, &sz);
				if (hehdr == NULL) {
					tc_log(1, "error read hdr_enc: %s", opts->h_hdr_file_in);
					goto out;
				}
			} else {
				hehdr = (struct tchdr_enc *)read_to_safe_mem(opts->dev,
				    (!TC_FLAG_SET(opts->flags, BACKUP)) ? HDR_OFFSET_HIDDEN :
				    -BACKUP_HDR_HIDDEN_OFFSET_END, &sz);
				if (hehdr == NULL) {
					tc_log(1, "error read hdr_enc: %s", opts->dev);
					goto out;
				}
			}
		} else {
			hehdr = NULL;
		}

		error = process_hdr(opts->dev, opts->flags, (unsigned char *)pass,
		    (opts->nkeyfiles > 0)?MAX_PASSSZ:strlen(pass),
		    ehdr, &info);

		/*
		 * Try to process hidden header if we have to protect the hidden
		 * volume, or the decryption/verification of the main header
		 * failed.
		 */
		if (hehdr && (error || opts->protect_hidden)) {
			if (error) {
				error2 = process_hdr(opts->dev, opts->flags, (unsigned char *)pass,
				    (opts->nkeyfiles > 0)?MAX_PASSSZ:strlen(pass), hehdr,
				    &info);
				is_hidden = !error2;
			} else if (opts->protect_hidden) {
				error2 = process_hdr(opts->dev, opts->flags, (unsigned char *)h_pass,
				    (opts->n_hkeyfiles > 0)?MAX_PASSSZ:strlen(h_pass), hehdr,
				    &hinfo);
			}
		}

		/* We need both to protect a hidden volume */
		if ((opts->protect_hidden && (error || error2)) ||
		    (error && error2)) {
			if (!try_empty)
				tc_log(1, "Incorrect password or not a TrueCrypt volume\n");

			if (info) {
				free_info(info);
				info = NULL;
			}
			if (hinfo) {
				free_info(hinfo);
				hinfo = NULL;
			}

			/* Try again (or finish) */
			free_safe_mem(pass);
			pass = NULL;

			if (h_pass) {
				free_safe_mem(h_pass);
				h_pass = NULL;
			}
			if (ehdr) {
				free_safe_mem(ehdr);
				ehdr = NULL;
			}
			if (hehdr) {
				free_safe_mem(hehdr);
				hehdr = NULL;
			}

			try_empty = 0;
			continue;
		}

		if (opts->protect_hidden) {
			if (adjust_info(info, hinfo) != 0) {
				tc_log(1, "Could not protect hidden volume\n");
				if (info)
					free_info(info);
				info = NULL;

				if (hinfo)
					free_info(hinfo);
				hinfo = NULL;

				goto out;
			}

			if (hinfo) {
				free_info(hinfo);
				hinfo = NULL;
			}
		}
		try_empty = 0;
        }

out:
	if (hinfo)
		free_info(hinfo);
	if (pass)
		free_safe_mem(pass);
	if (h_pass)
		free_safe_mem(h_pass);
	if (ehdr)
		free_safe_mem(ehdr);
	if (hehdr)
		free_safe_mem(hehdr);

	if (info != NULL)
		info->hidden = is_hidden;

	return info;
}
Esempio n. 14
0
int
create_volume(struct tcplay_opts *opts)
{
	char *pass, *pass_again;
	char *h_pass = NULL;
	char buf[1024];
	disksz_t blocks, hidden_blocks = 0;
	size_t blksz;
	struct tchdr_enc *ehdr, *hehdr;
	struct tchdr_enc *ehdr_backup, *hehdr_backup;
	uint64_t tmp;
	int error, r, ret;

	pass = h_pass = pass_again = NULL;
	ehdr = hehdr = NULL;
	ehdr_backup = hehdr_backup = NULL;
	ret = -1; /* Default to returning error */

	if (opts->cipher_chain == NULL)
		opts->cipher_chain = tc_cipher_chains[0];
	if (opts->prf_algo == NULL)
		opts->prf_algo = &pbkdf_prf_algos[0];
	if (opts->h_cipher_chain == NULL)
		opts->h_cipher_chain = opts->cipher_chain;
	if (opts->h_prf_algo == NULL)
		opts->h_prf_algo = opts->prf_algo;

	if ((error = get_disk_info(opts->dev, &blocks, &blksz)) != 0) {
		tc_log(1, "could not get disk info\n");
		return -1;
	}

	if ((blocks*blksz) <= MIN_VOL_BYTES) {
		tc_log(1, "Cannot create volumes on devices with less "
		    "than %d bytes\n", MIN_VOL_BYTES);
		return -1;
	}

	if (opts->interactive) {
		if (((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) ||
		   ((pass_again = alloc_safe_mem(PASS_BUFSZ)) == NULL)) {
			tc_log(1, "could not allocate safe passphrase memory\n");
			goto out;
		}

		if ((error = read_passphrase("Passphrase: ", pass, MAX_PASSSZ,
		    PASS_BUFSZ, 0) ||
		    (read_passphrase("Repeat passphrase: ", pass_again,
		    MAX_PASSSZ, PASS_BUFSZ, 0)))) {
			tc_log(1, "could not read passphrase\n");
			goto out;
		}

		if (strcmp(pass, pass_again) != 0) {
			tc_log(1, "Passphrases don't match\n");
			goto out;
		}

		free_safe_mem(pass_again);
		pass_again = NULL;
	} else {
		/* In batch mode, use provided passphrase */
		if ((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
			tc_log(1, "could not allocate safe "
			    "passphrase memory");
			goto out;
		}

		if (opts->passphrase != NULL) {
			strncpy(pass, opts->passphrase, MAX_PASSSZ);
			pass[MAX_PASSSZ] = '\0';
		}
	}

	if (opts->nkeyfiles > 0) {
		/* Apply keyfiles to 'pass' */
		if ((error = apply_keyfiles((unsigned char *)pass, PASS_BUFSZ,
		    opts->keyfiles, opts->nkeyfiles))) {
			tc_log(1, "could not apply keyfiles\n");
			goto out;
		}
	}

	if (opts->hidden) {
		if (opts->interactive) {
			if (((h_pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) ||
			   ((pass_again = alloc_safe_mem(PASS_BUFSZ)) == NULL)) {
				tc_log(1, "could not allocate safe "
				    "passphrase memory\n");
				goto out;
			}

			if ((error = read_passphrase("Passphrase for hidden volume: ",
			   h_pass, MAX_PASSSZ, PASS_BUFSZ, 0) ||
			   (read_passphrase("Repeat passphrase: ", pass_again,
			   MAX_PASSSZ, PASS_BUFSZ, 0)))) {
				tc_log(1, "could not read passphrase\n");
				goto out;
			}

			if (strcmp(h_pass, pass_again) != 0) {
				tc_log(1, "Passphrases for hidden volume don't "
				    "match\n");
				goto out;
			}

			free_safe_mem(pass_again);
			pass_again = NULL;
		} else {
			/* In batch mode, use provided passphrase */
			if ((h_pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
				tc_log(1, "could not allocate safe "
				    "passphrase memory");
				goto out;
			}

			if (opts->h_passphrase != NULL) {
				strncpy(h_pass, opts->h_passphrase, MAX_PASSSZ);
				h_pass[MAX_PASSSZ] = '\0';
			}
		}

		if (opts->n_hkeyfiles > 0) {
			/* Apply keyfiles to 'h_pass' */
			if ((error = apply_keyfiles((unsigned char *)h_pass,
			    PASS_BUFSZ, opts->h_keyfiles, opts->n_hkeyfiles))) {
				tc_log(1, "could not apply keyfiles\n");
				goto out;
			}
		}

		if (opts->interactive) {
			hidden_blocks = 0;
		} else {
			hidden_blocks = opts->hidden_size_bytes/blksz;
			if (hidden_blocks == 0) {
				tc_log(1, "hidden_blocks to create volume "
				    "cannot be zero!\n");
				goto out;
			}

			if (opts->hidden_size_bytes >=
			    (blocks*blksz) - MIN_VOL_BYTES) {
				tc_log(1, "Hidden volume needs to be "
				    "smaller than the outer volume\n");
				goto out;
			}
		}

		/* This only happens in interactive mode */
		while (hidden_blocks == 0) {
			if ((r = _humanize_number(buf, sizeof(buf),
			    (uint64_t)(blocks * blksz))) < 0) {
				sprintf(buf, "%"DISKSZ_FMT" bytes", (blocks * blksz));
			}

			printf("The total volume size of %s is %s (bytes)\n", opts->dev, buf);
			memset(buf, 0, sizeof(buf));
			printf("Size of hidden volume (e.g. 127M):  ");
			fflush(stdout);

			if ((fgets(buf, sizeof(buf), stdin)) == NULL) {
				tc_log(1, "Could not read from stdin\n");
				goto out;
			}

			/* get rid of trailing newline */
			buf[strlen(buf)-1] = '\0';
			if ((error = _dehumanize_number(buf,
			    &tmp)) != 0) {
				tc_log(1, "Could not interpret input: %s\n", buf);
				continue;
			}

			if (tmp >= (blocks*blksz) - MIN_VOL_BYTES) {
				tc_log(1, "Hidden volume needs to be "
				    "smaller than the outer volume\n");
				hidden_blocks = 0;
				continue;
			}

			hidden_blocks = (size_t)tmp;
			hidden_blocks /= blksz;
		}
	}

	if (opts->interactive) {
		/* Show summary and ask for confirmation */
		printf("Summary of actions:\n");
		if (opts->secure_erase)
			printf(" - Completely erase *EVERYTHING* on %s\n", opts->dev);
		printf(" - Create %svolume on %s\n", opts->hidden?("outer "):"", opts->dev);
		if (opts->hidden) {
			printf(" - Create hidden volume of %"DISKSZ_FMT" bytes at end of "
			    "outer volume\n",
			    hidden_blocks * blksz);
		}

		printf("\n Are you sure you want to proceed? (y/n) ");
		fflush(stdout);
		if ((fgets(buf, sizeof(buf), stdin)) == NULL) {
			tc_log(1, "Could not read from stdin\n");
			goto out;
		}

		if ((buf[0] != 'y') && (buf[0] != 'Y')) {
			tc_log(1, "User cancelled action(s)\n");
			goto out;
		}
	}

	/* erase volume */
	if (opts->secure_erase) {
		tc_log(0, "Securely erasing the volume...\nThis process may take "
		    "some time depending on the size of the volume\n");

		if (opts->state_change_fn)
			opts->state_change_fn(opts->api_ctx, "secure_erase", 1);

		if ((error = secure_erase(opts->dev, blocks * blksz, blksz)) != 0) {
			tc_log(1, "could not securely erase device %s\n", opts->dev);
			goto out;
		}

		if (opts->state_change_fn)
			opts->state_change_fn(opts->api_ctx, "secure_erase", 0);
	}

	tc_log(0, "Creating volume headers...\nDepending on your system, this "
	    "process may take a few minutes as it uses true random data which "
	    "might take a while to refill\n");

	if (opts->weak_keys_and_salt) {
		tc_log(0, "WARNING: Using a weak random generator to get "
		    "entropy for the key material. Odds are this is NOT "
		    "what you want.\n");
	}

	if (opts->state_change_fn)
		opts->state_change_fn(opts->api_ctx, "create_header", 1);

	/* create encrypted headers */
	ehdr = create_hdr((unsigned char *)pass,
	    (opts->nkeyfiles > 0)?MAX_PASSSZ:strlen(pass),
	    opts->prf_algo, opts->cipher_chain, blksz, blocks, VOL_RSVD_BYTES_START/blksz,
	    blocks - (MIN_VOL_BYTES/blksz), 0, opts->weak_keys_and_salt, &ehdr_backup);
	if (ehdr == NULL) {
		tc_log(1, "Could not create header\n");
		goto out;
	}

	if (opts->hidden) {
		hehdr = create_hdr((unsigned char *)h_pass,
		    (opts->n_hkeyfiles > 0)?MAX_PASSSZ:strlen(h_pass), opts->h_prf_algo,
		    opts->h_cipher_chain,
		    blksz, blocks,
		    blocks - (VOL_RSVD_BYTES_END/blksz) - hidden_blocks,
		    hidden_blocks, 1, opts->weak_keys_and_salt, &hehdr_backup);
		if (hehdr == NULL) {
			tc_log(1, "Could not create hidden volume header\n");
			goto out;
		}
	}

	if (opts->state_change_fn)
		opts->state_change_fn(opts->api_ctx, "create_header", 0);

	tc_log(0, "Writing volume headers to disk...\n");

	if ((error = write_to_disk(opts->dev, 0, blksz, ehdr, sizeof(*ehdr))) != 0) {
		tc_log(1, "Could not write volume header to device\n");
		goto out;
	}

	/* Write backup header; it's offset is relative to the end */
	if ((error = write_to_disk(opts->dev, (blocks*blksz - BACKUP_HDR_OFFSET_END),
	    blksz, ehdr_backup, sizeof(*ehdr_backup))) != 0) {
		tc_log(1, "Could not write backup volume header to device\n");
		goto out;
	}

	if (opts->hidden) {
		if ((error = write_to_disk(opts->dev, HDR_OFFSET_HIDDEN, blksz, hehdr,
		    sizeof(*hehdr))) != 0) {
			tc_log(1, "Could not write hidden volume header to "
			    "device\n");
			goto out;
		}

		/* Write backup hidden header; offset is relative to end */
		if ((error = write_to_disk(opts->dev,
		    (blocks*blksz - BACKUP_HDR_HIDDEN_OFFSET_END), blksz,
		    hehdr_backup, sizeof(*hehdr_backup))) != 0) {
			tc_log(1, "Could not write backup hidden volume "
			    "header to device\n");
			goto out;
		}
	}

	/* Everything went ok */
	tc_log(0, "All done!\n");

	ret = 0;

out:
	if (pass)
		free_safe_mem(pass);
	if (h_pass)
		free_safe_mem(h_pass);
	if (pass_again)
		free_safe_mem(pass_again);
	if (ehdr)
		free_safe_mem(ehdr);
	if (hehdr)
		free_safe_mem(hehdr);
	if (ehdr_backup)
		free_safe_mem(ehdr_backup);
	if (hehdr_backup)
		free_safe_mem(hehdr_backup);

	return ret;
}
Esempio n. 15
0
int
process_hdr(const char *dev, int flags, unsigned char *pass, int passlen,
    struct tchdr_enc *ehdr, struct tcplay_info **pinfo)
{
	struct tchdr_dec *dhdr;
	struct tcplay_info *info;
	struct tc_cipher_chain *cipher_chain = NULL;
	unsigned char *key;
	int i, j, found, error;

	*pinfo = NULL;

	if ((key = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
		tc_log(1, "could not allocate safe key memory\n");
		return ENOMEM;
	}

	/* Start search for correct algorithm combination */
	found = 0;
	for (i = 0; !found && pbkdf_prf_algos[i].name != NULL; i++) {
#ifdef DEBUG
		printf("\nTrying PRF algo %s (%d)\n", pbkdf_prf_algos[i].name,
		    pbkdf_prf_algos[i].iteration_count);
		printf("Salt: ");
		print_hex(ehdr->salt, 0, sizeof(ehdr->salt));
#endif
		error = pbkdf2(&pbkdf_prf_algos[i], (char *)pass, passlen,
		    ehdr->salt, sizeof(ehdr->salt),
		    MAX_KEYSZ, key);

		if (error) {
			tc_log(1, "pbkdf failed for algorithm %s\n",
			    pbkdf_prf_algos[i].name);
			free_safe_mem(key);
			return EINVAL;
		}

#if 0
		printf("Derived Key: ");
		print_hex(key, 0, MAX_KEYSZ);
#endif

		for (j = 0; !found && tc_cipher_chains[j] != NULL; j++) {
			cipher_chain = tc_dup_cipher_chain(tc_cipher_chains[j]);
#ifdef DEBUG
			printf("\nTrying cipher chain %d\n", j);
#endif

			dhdr = decrypt_hdr(ehdr, cipher_chain, key);
			if (dhdr == NULL) {
				tc_log(1, "hdr decryption failed for cipher "
				    "chain %d\n", j);
				free_safe_mem(key);
				return EINVAL;
			}

			if (verify_hdr(dhdr)) {
#ifdef DEBUG
				printf("tc_str: %.4s, tc_ver: %d, tc_min_ver: %d, "
				    "crc_keys: %d, sz_vol: %"PRIu64", "
				    "off_mk_scope: %"PRIu64", sz_mk_scope: %"PRIu64", "
				    "flags: %d, sec_sz: %d crc_dhdr: %d\n",
				    dhdr->tc_str, dhdr->tc_ver, dhdr->tc_min_ver,
				    dhdr->crc_keys, dhdr->sz_vol, dhdr->off_mk_scope,
				    dhdr->sz_mk_scope, dhdr->flags, dhdr->sec_sz,
				    dhdr->crc_dhdr);
#endif
				found = 1;
			} else {
				free_safe_mem(dhdr);
				tc_free_cipher_chain(cipher_chain);
			}
		}
	}

	free_safe_mem(key);

	if (!found)
		return EINVAL;

	if ((info = new_info(dev, flags, cipher_chain,
	    &pbkdf_prf_algos[i-1], dhdr, 0)) == NULL) {
		free_safe_mem(dhdr);
		return ENOMEM;
	}

	*pinfo = info;

	return 0;
}
Esempio n. 16
0
void
num_delete(num_t a)
{
	free_safe_mem(BUCKET_NUM, a);
}
Esempio n. 17
0
int
modify_volume(struct tcplay_opts *opts)
{
	struct tcplay_info *info;
	struct tchdr_enc *ehdr, *ehdr_backup;
	const char *new_passphrase = opts->new_passphrase;
	const char **new_keyfiles = opts->new_keyfiles;
	struct pbkdf_prf_algo *new_prf_algo = opts->new_prf_algo;
	int n_newkeyfiles = opts->n_newkeyfiles;
	char *pass, *pass_again;
	int ret = -1;
	off_t offset, offset_backup = 0;
	const char *dev;
	size_t blksz;
	disksz_t blocks;
	int error;

	ehdr = ehdr_backup = NULL;
	pass = pass_again = NULL;
	info = NULL;

	if (TC_FLAG_SET(opts->flags, ONLY_RESTORE)) {
		if (opts->interactive) {
			if ((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
				tc_log(1, "could not allocate safe "
				    "passphrase memory");
				goto out;
			}
		} else {
			new_passphrase = opts->passphrase;
		}
		new_keyfiles = opts->keyfiles;
		n_newkeyfiles = opts->nkeyfiles;
		new_prf_algo = NULL;
	}

	info = info_map_common(opts, pass);
	if (info == NULL)
		goto out;

	if (opts->interactive && !TC_FLAG_SET(opts->flags, ONLY_RESTORE)) {
		if (((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) ||
		   ((pass_again = alloc_safe_mem(PASS_BUFSZ)) == NULL)) {
			tc_log(1, "could not allocate safe passphrase memory\n");
			goto out;
		}

		if ((error = read_passphrase("New passphrase: ", pass, MAX_PASSSZ,
		    PASS_BUFSZ, 0) ||
		    (read_passphrase("Repeat passphrase: ", pass_again,
		    MAX_PASSSZ, PASS_BUFSZ, 0)))) {
			tc_log(1, "could not read passphrase\n");
			goto out;
		}

		if (strcmp(pass, pass_again) != 0) {
			tc_log(1, "Passphrases don't match\n");
			goto out;
		}

		free_safe_mem(pass_again);
		pass_again = NULL;
	} else if (!opts->interactive) {
		/* In batch mode, use provided passphrase */
		if ((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
			tc_log(1, "could not allocate safe "
			    "passphrase memory");
			goto out;
		}

		if (new_passphrase != NULL) {
			strncpy(pass, new_passphrase, MAX_PASSSZ);
			pass[MAX_PASSSZ] = '\0';
		}
	}

	if (n_newkeyfiles > 0) {
		/* Apply keyfiles to 'pass' */
		if ((error = apply_keyfiles((unsigned char *)pass, PASS_BUFSZ,
		    new_keyfiles, n_newkeyfiles))) {
			tc_log(1, "could not apply keyfiles\n");
			goto out;
		}
	}

	ehdr = copy_reencrypt_hdr((unsigned char *)pass,
	    (opts->n_newkeyfiles > 0)?MAX_PASSSZ:strlen(pass),
	    new_prf_algo, opts->weak_keys_and_salt, info, &ehdr_backup);
	if (ehdr == NULL) {
		tc_log(1, "Could not create header\n");
		goto out;
	}

	dev = (TC_FLAG_SET(opts->flags, SYS)) ? opts->sys_dev : opts->dev;
	if (TC_FLAG_SET(opts->flags, SYS) || TC_FLAG_SET(opts->flags, FDE)) {
		/* SYS and FDE don't have backup headers (as far as I understand) */
		if (info->hidden) {
			offset = HDR_OFFSET_HIDDEN;
		} else {
			offset = HDR_OFFSET_SYS;
		}
	} else {
		if (info->hidden) {
			offset = HDR_OFFSET_HIDDEN;
			offset_backup = -BACKUP_HDR_HIDDEN_OFFSET_END;
		} else {
			offset = 0;
			offset_backup = -BACKUP_HDR_OFFSET_END;
		}
	}

	if ((error = get_disk_info(dev, &blocks, &blksz)) != 0) {
		tc_log(1, "could not get disk information\n");
		goto out;
	}

	tc_log(0, "Writing new volume headers to disk/file...\n");

	if (TC_FLAG_SET(opts->flags, SAVE_TO_FILE)) {
		if ((error = write_to_file(opts->hdr_file_out, ehdr, sizeof(*ehdr))) != 0) {
			tc_log(1, "Could not write volume header to file\n");
			goto out;
		}
	} else {
		if ((error = write_to_disk(dev, offset, blksz, ehdr,
		    sizeof(*ehdr))) != 0) {
			tc_log(1, "Could not write volume header to device\n");
			goto out;
		}

		if (!TC_FLAG_SET(opts->flags, SYS) && !TC_FLAG_SET(opts->flags, FDE)) {
			if ((error = write_to_disk(dev, offset_backup, blksz,
			    ehdr_backup, sizeof(*ehdr_backup))) != 0) {
				tc_log(1, "Could not write backup volume header to device\n");
				goto out;
			}
		}
	}

	/* Everything went ok */
	tc_log(0, "All done!\n");

	ret = 0;

out:
	if (pass)
		free_safe_mem(pass);
	if (pass_again)
		free_safe_mem(pass_again);
	if (ehdr)
		free_safe_mem(ehdr);
	if (ehdr_backup)
		free_safe_mem(ehdr_backup);
	if (info)
		free_safe_mem(info);

	return ret;
}