Example #1
0
/**
 *  Create a new buffer with the replaced environment values.
 * 
 *  \param buf  Buffer with values to be replaced.
 *  \param len  Length of original buffer and output of final.
 *  \return The allocated buffer that should be freed with free.
 */
static char *tc_cmd_env_subs(const char *buf, uint32_t *len)
{
	uint8_t state = 0;
	uint32_t l = 0;
	uint32_t alloc = 0;
	char *result = NULL;
	uint32_t i = 0;
	bool finished = false;
	while (true) {
		if (l == alloc) {
			alloc = alloc ? (alloc << 1) : 16;
			result = (char *)realloc(result, alloc);
		}
		if (i == *len) {
			finished = true;
			break;
		}
		if (buf[i] == '$') {
			i++;
			if (i == *len)  {
				tc_log(TC_LOG_ERR, "Syntax error: $ at end of command");
				break;
			}
			if (buf[i] != '$') {
				uint32_t endi;
				for (endi = i; endi < *len; endi++)
					if (!tc_cmd_env_ischar(buf[endi]))
						break;
				if (endi == i) { 
					tc_log(TC_LOG_ERR, "Syntax error: $ not followed by variable name");
					break;
				}
				tc_cmd_env_t *env = tc_cmd_env_find(buf + i, endi - i);
				if (!env) {
					tc_log(TC_LOG_ERR, "Syntax error: Variable \"%s\" not found",
					       strndupa(buf + i, endi - i));
					break;
				}
				uint32_t newl = l + strlen(env->value);
				while (alloc < newl) {
					alloc = alloc << 1;
					result = (char *)realloc(result, alloc);
				}
				memcpy(result + l, env->value, strlen(env->value));
				l = newl;
				i = endi;
				continue;
			}
		}
		result[l++] = buf[i++];
	}
	*len = l;
	if (!finished) {
		if (result) {
			free(result);
			result = NULL;
		}
	}
	return result;
}
Example #2
0
int tc_server_init(void)
{
	/* Open the socket */
	tc_server_fd = socket(PF_INET, SOCK_DGRAM, 0);
	if (tc_server_fd == -1) {
		tc_log(TC_LOG_ERR, "Error creating server socket");
		return -1;
	}

	/* Bind for the address */
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(1423);
	addr.sin_addr.s_addr = INADDR_ANY;
	int r = bind(tc_server_fd, (struct sockaddr *)&addr, sizeof(addr));
	if (r) {
		tc_log(TC_LOG_ERR, "Error binding server socket");
		tc_server_release();
		return -1;
	}

	/* Create the event pipe */
	if (tc_msg_queue_create(&tc_server_queue)) {
		tc_server_release();
		return -1;
	}

	/* Return success */
	return 0;
}
Example #3
0
int tc_cmd_env_set(const char *name,  uint32_t namelen,
                   const char *value, uint32_t valuelen)
{
	/* Validate the name */
	uint32_t i = 0;
	for (i = 0; i < namelen; i++) {
		if (!tc_cmd_env_ischar(name[i]))
			break;
	}
	if (i < namelen || namelen == 0) {
		tc_log(TC_LOG_ERR, "Invalid name for variable \"%s\"",
		       strndupa(name, namelen));
		return -1;
	}

	/* Replace an existing value if found */
	tc_cmd_env_t *e = tc_cmd_env_find(name, namelen);
	if (e) {
		free((void *)e->value);
		e->value = strndup(value, valuelen);
		tc_log(TC_LOG_INFO, "Variable %s = \"%s\" (replaced value)",
		       strndupa(name, namelen), strndupa(value, valuelen));
		return 0;
	}

	/* Add the new value if not found */
	e = (tc_cmd_env_t *)malloc(sizeof(tc_cmd_env_t));
	e->name = strndup(name, namelen);
	e->value = strndup(value, valuelen);
	e->next = tc_cmd_env;
	tc_cmd_env = e;
	tc_log(TC_LOG_INFO, "Variable %s = \"%s\" (new value)",
	       strndupa(name, namelen), strndupa(value, valuelen));
	return 0;
}
Example #4
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;
}
Example #5
0
static
struct tcplay_info *
new_info(const char *dev, int flags, struct tc_cipher_chain *cipher_chain,
    struct pbkdf_prf_algo *prf, struct tchdr_dec *hdr, off_t start)
{
	struct tc_cipher_chain *chain_start;
	struct tcplay_info *info;
	int i;
	int error;

	chain_start = cipher_chain;

	if ((info = (struct tcplay_info *)alloc_safe_mem(sizeof(*info))) == NULL) {
		tc_log(1, "could not allocate safe info memory\n");
		return NULL;
	}

	strncpy(info->dev, dev, sizeof(info->dev));
	info->cipher_chain = cipher_chain;
	info->pbkdf_prf = prf;
	info->start = start;
	info->hdr = hdr;
	info->blk_sz = hdr->sec_sz;
	info->size = hdr->sz_mk_scope / hdr->sec_sz;	/* volume size */
	info->skip = hdr->off_mk_scope / hdr->sec_sz;	/* iv skip */

	info->volflags = hdr->flags;
	info->flags = flags;

	if (TC_FLAG_SET(flags, SYS))
		info->offset = 0; /* offset is 0 for system volumes */
	else
		info->offset = hdr->off_mk_scope / hdr->sec_sz;	/* block offset */

	/* Associate a key out of the key pool with each cipher in the chain */
	error = tc_cipher_chain_populate_keys(cipher_chain, hdr->keys);
	if (error) {
		tc_log(1, "could not populate keys in cipher chain\n");
		return NULL;
	}

	for (; cipher_chain != NULL; cipher_chain = cipher_chain->next) {
		for (i = 0; i < cipher_chain->cipher->klen; i++)
			sprintf(&cipher_chain->dm_key[i*2], "%02x",
			    cipher_chain->key[i]);
	}

	tc_cipher_chain_free_keys(chain_start);

	return info;
}
Example #6
0
/* Update router table */
void
router_update(tc_ip_header_t *ip_header, int len)
{
    void                   *fd;
    uint32_t                size_ip;
    uint64_t                key;
    msg_server_t            msg;
    struct tcphdr          *tcp_header;

    size_ip    = ip_header->ihl << 2;
    tcp_header = (struct tcphdr*)((char *)ip_header + size_ip);

    memcpy(&msg, ip_header, len);

    key = get_key(ip_header->daddr, tcp_header->dest);

    pthread_mutex_lock(&mutex);

    fd  = hash_find(table, key);
    if ( NULL == fd ) {
        tc_log((LOG_DEBUG), 0, "fd is null");
        delay_table_add(key, &msg);

        pthread_mutex_unlock(&mutex);

        return ;
    }

    pthread_mutex_unlock(&mutex);

    tc_socket_send((int) (long) fd, (char *) &msg, MSG_SERVER_SIZE);
}
Example #7
0
int
get_disk_info(const char *dev, disksz_t *blocks, size_t *bsize)
{
	uint64_t nbytes;
	int blocksz;
	int fd;

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

	if ((ioctl(fd, BLKSSZGET, &blocksz)) < 0) {
		close(fd);
		return -1;
	}

	if ((ioctl(fd, BLKGETSIZE64, &nbytes)) < 0) {
		close(fd);
		return -1;
	}

	*blocks = (disksz_t)(nbytes / blocksz);
	*bsize = (size_t)(blocksz);

	close(fd);
	return 0;
}
Example #8
0
const char *tc_cmd_env_csv(void)
{
	/* Debug */
	#ifdef TC_CMD_DEBUG
	tc_log(TC_LOG_DEBUG, "tc_cmd: env_csv");
	#endif /* TC_CMD_DEBUG */

	/* Calculate tht length */
	uint32_t len = 1;
	tc_cmd_env_t *e = tc_cmd_env;
	while (e) {
		len += tc_cmd_env_csv_scape_len(e->name);
		len++;
		len += tc_cmd_env_csv_scape_len(e->value);
		len++;
		e = e->next;
	}

	/* Allocate the output */
	#ifdef TC_CMD_DEBUG
	tc_log(TC_LOG_DEBUG, "tc_cmd: env_csv: alloc:%u", (unsigned)len);
	#endif /* TC_CMD_DEBUG */
	char *output = (char *)malloc(len);

	/* Write each entry of the output */
	char *o = output;
	e = tc_cmd_env;
	while (e) {
		o = tc_cmd_env_csv_scape(o, e->name);
		*o++ = ',';
		o = tc_cmd_env_csv_scape(o, e->value);
		*o++ = '\n';
		e = e->next;
	}

	/* Write the end of text */
	*o++ = 0;

	/* Debug */
	#ifdef TC_CMD_DEBUG
	tc_log(TC_LOG_DEBUG, "tc_cmd: env_csv: finished");
	#endif /* TC_CMD_DEBUG */

	/* Return the output */
	return output;
}
Example #9
0
static
void
get_random_summary(void)
{
	float pct_done = get_random_read_progress();

	tc_log(0, "Gathering true randomness, %.0f%% done.\n", pct_done);
}
Example #10
0
int tc_server_event(const char *buffer, uint8_t len)
{
	if (tc_msg_send(&tc_server_queue, buffer, len)) {
		tc_log(TC_LOG_ERR, "Error enqueuing event");
		return -1;
	}
	return 0;
}
Example #11
0
/**
 *  Internal function to execute an scripting command.
 *
 *  \param cmd  Pointer to the command to execute.
 *  \param buf  Buffer with the command to execute.
 *  \param len  Length of the command to execute
 *  \retval 0 on success of normal command.
 *  \retval 1 on exit command.
 *  \retval -1 on error in command.
 */
static int tc_cmd_script_exec(tc_cmd_t *cmd, const char *buf, uint32_t len)
{
	tc_cmd_script_t *s = tc_containerof(cmd, tc_cmd_script_t, cmd);
	tc_cmd_script_entry_t *e = s->entry;
	while (e) {
		tc_log(TC_LOG_INFO, "Subcommand \"%s\"", e->cmd);
		int r = tc_cmd(e->cmd, strlen(e->cmd));
		if (r) {
			if (r < 0)
				tc_log(TC_LOG_ERR, "Error in subcommand \"%s\"",
				       e->cmd);
			return r;
		}
		e = e->next;
	}
	return 0;
}
Example #12
0
/**
 *  Add a new command to the list of available commands.
 *
 *  \param cmd  Command to be added.
 */
static void tc_cmd_add(tc_cmd_t *cmd)
{
	cmd->next = tc_cmd_first;
	tc_cmd_first = cmd;
	#ifdef TC_CMD_DEBUG
	tc_log(TC_LOG_DEBUG, "cmd: add: \"%s\"", cmd->name);
	#endif /* TC_CMD_DEBUG */
}
Example #13
0
void tc_server_exec(void)
{
	/* Wait for anything to be received */
	while (true) {
		/* Check if there is any reception event */
		struct pollfd fds[2];	
		fds[0].fd = tc_server_fd;
		fds[0].events = POLLIN;
		fds[1].fd = TC_MSG_QUEUE_POLLFD(&tc_server_queue);
		fds[1].events = POLLIN;
		int r = poll(fds, 2, -1);
		if (fds[0].revents & POLLIN) {
			/* We have received a message */
			struct sockaddr_in src;
			socklen_t src_len = sizeof(src);
			char buf[257];
			ssize_t r = recvfrom(tc_server_fd, buf, sizeof(buf)-1,
			                     0, (struct sockaddr *)&src, &src_len);
			if (r > 0) {
				buf[r] = 0;
				tc_log(TC_LOG_INFO, "Command: \"%s\"", buf);
				int ret = tc_cmd(buf, r);
				if (ret > 0)
					break;
				if (ret < 0)
					tc_log(TC_LOG_ERR, "Error in command: \"%s\"", buf);
			}
		}
		if (fds[1].revents & POLLIN) {
			/* We have received an event */
			tc_msg_t msg;
			if (tc_msg_recv(&tc_server_queue, &msg)) {
				tc_log(TC_LOG_ERR, "server: Error reading from event pipe");
				break;
			}
			/* Execute the event */
			tc_log(TC_LOG_INFO, "Event: \"%s\"", msg.buf);
			int ret = tc_cmd((const char *)msg.buf, msg.len);
			if (ret > 0)
				break;
			if (ret < 0)
				tc_log(TC_LOG_ERR, "Error in event: \"%s\"", msg.buf);
		}
	}
}
Example #14
0
/**
 *  Load a file to add new commands 
 *
 *  \param path   Path of the file with the new commands.
 *  \retval -1 on error (with a log entry).
 *  \retval 1 on file not possible to be read.
 *  \retval 0 on success.
 */
static int tc_cmd_load(const char *path)
{
	/* Try to open the file */
	FILE *f = fopen(path, "rt");
	if (!f) {
		tc_log(TC_LOG_WARN, "Script file \"%s\" not present",
		       path);
		return 1;
	}
	tc_log(TC_LOG_INFO, "Executing script file \"%s\"", path);

	/* Try to read a line until it finishes */
	int result = 0;
	while (true) {
		/* Get a new line without carry return */
		char buf[256];
		char *r = fgets(buf, sizeof(buf), f);
		if (!r)
			break;
		int buf_len = strlen(buf);
		if (!buf_len)
			continue;
		if (buf[buf_len-1] == '\n') {
			buf[--buf_len] = 0;
			if (!buf_len)
				continue;
		}

		/* Execute the commands */
		tc_log(TC_LOG_INFO, "Command \"%s\"", strndupa(buf, buf_len));
		int nr = tc_cmd(buf, buf_len);
		if (nr) {
			if (nr < 0)
				result = -1;
			break;
		}
	}

	/* Close the file */
	fclose(f);

	/* Return the result */
	return result;
}
Example #15
0
/**
 *  Execute an process command
 *
 *  \param cmd  Pointer to the command to execute.
 *  \param buf  Buffer with the command to execute.
 *  \param len  Length of the command to execute
 *  \retval 0 on success of normal command.
 *  \retval 1 on exit command.
 *  \retval -1 on error in command.
 */
static int tc_cmd_exec_exec(tc_cmd_t *cmd, const char *buf, uint32_t len)
{
	/* exec <process> <arguments> */
	char *command = (char *)malloc(len + 1);
	memcpy(command, buf, len);
	command[len] = 0;
	tc_log(TC_LOG_INFO, "Executing command: \"%s\"", command);
	int r = system(command);
	return r ? -1 : 0;
}
Example #16
0
File: io.c Project: GDXN/tc-play
int
write_to_file(const char *file, void *mem, size_t bytes)
{
	int fd;
	ssize_t w;

	if ((fd = open(file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
		tc_log(1, "Error opening file %s\n", file);
		return -1;
	}

	if ((w = write(fd, mem, bytes)) < 0) {
		tc_log(1, "Error writing to file %s\n", file);
		close(fd);
		return -1;
	}

	close(fd);
	return 0;
}
Example #17
0
int
verify_hdr(int veracrypt_mode, struct tchdr_dec *hdr)
{
    uint32_t crc;

    if (   (!veracrypt_mode && (memcmp(hdr->tc_str, TC_SIG, sizeof(hdr->tc_str)) != 0))
            || ( veracrypt_mode && (memcmp(hdr->tc_str, VC_SIG, sizeof(hdr->tc_str)) != 0))) {
#ifdef DEBUG
        fprintf(stderr, "Signature mismatch\n");
#endif
        return 0;
    }

    crc = crc32((void *)&hdr->keys, 256);
    if (crc != hdr->crc_keys) {
#ifdef DEBUG
        fprintf(stderr, "CRC32 mismatch (crc_keys)\n");
#endif
        return 0;
    }

    switch(hdr->tc_ver) {
    case 1:
    case 2:
        /* Unsupported header version */
        tc_log(1, "Header version %d unsupported\n", hdr->tc_ver);
        return 0;

    case 3:
    case 4:
        if (veracrypt_mode) {
            /* Unsupported header version in VeraCrypt mode*/
            tc_log(1, "Header version %d unsupported in VeraCrypt mode\n", hdr->tc_ver);
            return 0;
        }
        hdr->sec_sz = 512;
        break;
    }

    return 1;
}
Example #18
0
static
struct tc_cipher_chain *
tc_dup_cipher_chain(struct tc_cipher_chain *src)
{
	struct tc_cipher_chain *first = NULL, *prev = NULL, *elem;

	for (; src != NULL; src = src->next) {
		if ((elem = alloc_safe_mem(sizeof(*elem))) == NULL) {
			tc_log(1, "Error allocating memory for "
			    "duplicate cipher chain\n");
			return NULL;
		}

		memcpy(elem, src, sizeof(*elem));

		if (src->key != NULL) {
			if ((elem->key = alloc_safe_mem(src->cipher->klen)) == NULL) {
				tc_log(1, "Error allocating memory for "
				    "duplicate key in cipher chain\n");
				return NULL;
			}

			memcpy(elem->key, src->key, src->cipher->klen);
		}

		if (first == NULL)
			first = elem;

		elem->next = NULL;
		elem->prev = prev;

		if (prev != NULL)
			prev->next = elem;

		prev = elem;
	}

	return first;
}
Example #19
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;
}
Example #20
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;
}
Example #21
0
int tc_cmd(const char *buf, uint32_t len)
{
	char *newb = tc_cmd_env_subs(buf, &len);
	if (!newb)
		return -1;
	if (len == 0)
		return 0;
	buf = newb;
	if (buf[0] == '#') {
		free(newb);
		return 0;
	}
	bool extend = (buf[0] == '\t');
	if (!extend)
		tc_cmd_extend = NULL;
	if (extend) {
		if (!tc_cmd_extend || !tc_cmd_extend->extend) {
			tc_log(TC_LOG_ERR, "Error extending command not supported");
			free(newb);
			return -1;
		}
		int r = tc_cmd_extend->extend(tc_cmd_extend, buf+1, len-1);
		free(newb);
		return r;
	}
	tc_cmd_t *cmd = tc_cmd_first;
	while (cmd) {
		if (tc_cmd_starts(&buf, &len, cmd->name)) {
			int r = cmd->exec(cmd, buf, len);
			free(newb);
			return r;
		}
		cmd = cmd->next;
	}
	tc_log(TC_LOG_ERR, "Unknown command \"%s\"", strndupa(buf, len));
	free(newb);
	return -1;
}
Example #22
0
void
router_update(struct iphdr *ip_header)
{
    void                   *fd;
    uint32_t                size_ip;
    uint64_t                key;
    msg_server_t            msg;
    struct tcphdr          *tcp_header;
#if (TCPCOPY_MYSQL_ADVANCED)
    uint32_t                size_tcp, cont_len, tot_len;
    unsigned char          *payload;
#endif

    if (ip_header->protocol != IPPROTO_TCP) {
        tc_log_info(LOG_INFO, 0, "this is not a tcp packet");
        return;
    }

    size_ip = ip_header->ihl << 2;
    tcp_header = (struct tcphdr*)((char *)ip_header + size_ip);

    memset(&msg, 0, sizeof(struct msg_server_s));
    memcpy((void *) &(msg.ip_header),  ip_header,  sizeof(struct iphdr));
    memcpy((void *) &(msg.tcp_header), tcp_header, sizeof(struct tcphdr));

#if (TCPCOPY_MYSQL_ADVANCED)
    tot_len  = ntohs(ip_header->tot_len);
    size_tcp = tcp_header->doff << 2;
    cont_len = tot_len - size_ip - size_tcp;
    if (cont_len > 0) {
        payload = (unsigned char*)((char*)tcp_header + size_tcp);
        if (cont_len <= MAX_PAYLOAD_LEN) {
            /*
             * Only transfer payload if content length is less
             * than MAX_PAYLOAD_LEN
             */
            memcpy((void *) &(msg.payload), payload, cont_len);
        }
    }
#endif
    key = get_key(ip_header->daddr, tcp_header->dest);
    fd  = hash_find(table, key);
    if ( NULL == fd ) {
        tc_log((LOG_DEBUG), 0, "fd is null");
        delay_table_add(key, &msg);
        return ;
    }

    tc_socket_send((int) (long) fd, (char *) &msg, MSG_SERVER_SIZE);
}
Example #23
0
int
tc_cipher_chain_populate_keys(struct tc_cipher_chain *cipher_chain,
    unsigned char *key)
{
	int total_key_bytes, used_key_bytes;
	struct tc_cipher_chain *dummy_chain;

	/*
	 * We need to determine the total key bytes as the key locations
	 * depend on it.
	 */
	total_key_bytes = 0;
	for (dummy_chain = cipher_chain;
	    dummy_chain != NULL;
	    dummy_chain = dummy_chain->next) {
		total_key_bytes += dummy_chain->cipher->klen;
	}

	/*
	 * Now we need to get prepare the keys, as the keys are in
	 * forward order with respect to the cipher cascade, but
	 * the actual decryption is in reverse cipher cascade order.
	 */
	used_key_bytes = 0;
	for (dummy_chain = cipher_chain;
	    dummy_chain != NULL;
	    dummy_chain = dummy_chain->next) {
		dummy_chain->key = alloc_safe_mem(dummy_chain->cipher->klen);
		if (dummy_chain->key == NULL) {
			tc_log(1, "tc_decrypt: Could not allocate key "
			    "memory\n");
			return ENOMEM;
		}

		/* XXX: here we assume XTS operation! */
		memcpy(dummy_chain->key,
		    key + used_key_bytes/2,
		    dummy_chain->cipher->klen/2);
		memcpy(dummy_chain->key + dummy_chain->cipher->klen/2,
		    key + (total_key_bytes/2) + used_key_bytes/2,
		    dummy_chain->cipher->klen/2);

		/* Remember how many key bytes we've seen */
		used_key_bytes += dummy_chain->cipher->klen;
	}

	return 0;
}
Example #24
0
int
info_mapped_volume(struct tcplay_opts *opts)
{
	struct tcplay_info *info;

	info = dm_info_map(opts->map_name);
	if (info != NULL) {
		if (opts->interactive)
			print_info(info);

		free_info(info);

		return 0;
		/* NOT REACHED */
	} else if (opts->interactive) {
		tc_log(1, "Could not retrieve information about mapped "
		    "volume %s. Does it exist?\n", opts->map_name);
	}

	return -1;
}
Example #25
0
int
get_disk_info(const char *dev, size_t *blocks, size_t *bsize)
{
	struct partinfo pinfo;
	int fd;

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

	memset(&pinfo, 0, sizeof(struct partinfo));

	if (ioctl(fd, DIOCGPART, &pinfo) < 0) {
		close(fd);
		return -1;
	}

	*blocks = pinfo.media_blocks;
	*bsize = pinfo.media_blksize;

	close(fd);
	return 0;
}
Example #26
0
int
map_volume(struct tcplay_opts *opts)
{
	struct tcplay_info *info;
	int error;

	info = info_map_common(opts, NULL);

	if (info == NULL)
		return -1;

	if ((error = dm_setup(opts->map_name, info)) != 0) {
		tc_log(1, "Could not set up mapping %s\n", opts->map_name);
		free_info(info);
		return -1;
	}

	if (opts->interactive)
		printf("All ok!\n");

	free_info(info);

	return 0;
}
Example #27
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;
}
Example #28
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;
}
Example #29
0
int
main(int argc, char *argv[])
{
	const char *dev = NULL, *sys_dev = NULL, *map_name = NULL;
	const char *keyfiles[MAX_KEYFILES];
	const char *h_keyfiles[MAX_KEYFILES];
	int nkeyfiles;
	int n_hkeyfiles;
	int ch, error;
	int flags = 0;
	int info_vol = 0, map_vol = 0, protect_hidden = 0,
	    unmap_vol = 0, info_map = 0,
	    create_vol = 0, contain_hidden = 0, use_secure_erase = 1,
	    use_weak_keys = 0;
	struct pbkdf_prf_algo *prf = NULL;
	struct tc_cipher_chain *cipher_chain = NULL;
	struct pbkdf_prf_algo *h_prf = NULL;
	struct tc_cipher_chain *h_cipher_chain = NULL;

	if ((error = tc_play_init()) != 0) {
		fprintf(stderr, "Initialization failed, exiting.");
		exit(EXIT_FAILURE);
	}

	atexit(check_and_purge_safe_mem);
	signal(SIGUSR1, sig_handler);
	signal(SIGINFO, sig_handler);

	nkeyfiles = 0;
	n_hkeyfiles = 0;

	while ((ch = getopt_long(argc, argv, "a:b:cd:ef:ghij:k:m:s:u:vwx:y:z",
	    longopts, NULL)) != -1) {
		switch(ch) {
		case 'a':
			if (prf != NULL)
				usage();
			if ((prf = check_prf_algo(optarg, 0)) == NULL) {
				if (strcmp(optarg, "help") == 0)
					exit(EXIT_SUCCESS);
				else
					usage();
				/* NOT REACHED */
			}
			break;
		case 'b':
			if (cipher_chain != NULL)
				usage();
			if ((cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
				if (strcmp(optarg, "help") == 0)
					exit(EXIT_SUCCESS);
				else
					usage();
				/* NOT REACHED */
			}
			break;
		case 'c':
			create_vol = 1;
			break;
		case 'd':
			dev = optarg;
			break;
		case 'e':
			protect_hidden = 1;
			break;
		case 'f':
			h_keyfiles[n_hkeyfiles++] = optarg;
			break;
		case 'g':
			contain_hidden = 1;
			break;
		case 'i':
			info_vol = 1;
			break;
		case 'j':
			info_map = 1;
			map_name = optarg;
			break;
		case 'k':
			keyfiles[nkeyfiles++] = optarg;
			break;
		case 'm':
			map_vol = 1;
			map_name = optarg;
			break;
		case 's':
			flags |= TC_FLAG_SYS;
			sys_dev = optarg;
			break;
		case 'u':
			unmap_vol = 1;
			map_name = optarg;
			break;
		case 'v':
			printf("tcplay v%d.%d\n", MAJ_VER, MIN_VER);
			exit(EXIT_SUCCESS);
			/* NOT REACHED */
		case 'w':
			fprintf(stderr, "WARNING: Using urandom as source of "
			    "entropy for key material is a really bad idea.\n");
			use_weak_keys = 1;
			break;
		case 'x':
			if (h_prf != NULL)
				usage();
			if ((h_prf = check_prf_algo(optarg, 0)) == NULL) {
				if (strcmp(optarg, "help") == 0)
					exit(EXIT_SUCCESS);
				else
					usage();
				/* NOT REACHED */
			}
			break;
		case 'y':
			if (h_cipher_chain != NULL)
				usage();
			if ((h_cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
				if (strcmp(optarg, "help") == 0)
					exit(EXIT_SUCCESS);
				else
					usage();
				/* NOT REACHED */
			}
			break;
		case 'z':
			use_secure_erase = 0;
			break;
		case FLAG_LONG_FDE:
			flags |= TC_FLAG_FDE;
			break;
		case FLAG_LONG_USE_BACKUP:
			flags |= TC_FLAG_BACKUP;
			break;
		case 'h':
		case '?':
		default:
			usage();
			/* NOT REACHED */
		}
	}

	argc -= optind;
	argv += optind;

	/* Check arguments */
	if (!(((map_vol || info_vol || create_vol) && dev != NULL) ||
	    ((unmap_vol || info_map) && map_name != NULL)) ||
	    (TC_FLAG_SET(flags, SYS) && TC_FLAG_SET(flags, FDE)) ||
	    (map_vol && info_vol) ||
	    (map_vol && create_vol) ||
	    (unmap_vol && map_vol) ||
	    (unmap_vol && info_vol) ||
	    (unmap_vol && create_vol) ||
	    (create_vol && info_vol) ||
	    (contain_hidden && !create_vol) ||
	    (TC_FLAG_SET(flags, SYS) && (sys_dev == NULL)) ||
	    (map_vol && (map_name == NULL)) ||
	    (unmap_vol && (map_name == NULL)) ||
	    (!(protect_hidden || create_vol) && n_hkeyfiles > 0)) {
		usage();
		/* NOT REACHED */
	}

	/* Create a new volume */
	if (create_vol) {
		error = create_volume(dev, contain_hidden, keyfiles, nkeyfiles,
		    h_keyfiles, n_hkeyfiles, prf, cipher_chain, h_prf,
		    h_cipher_chain, NULL, NULL,
		    0, 1 /* interactive */,
		    use_secure_erase, use_weak_keys);
		if (error) {
			tc_log(1, "could not create new volume on %s\n", dev);
		}
	} else if (info_map) {
		error = info_mapped_volume(map_name, 1 /* interactive */);
	} else if (info_vol) {
		error = info_volume(dev, flags, sys_dev, protect_hidden,
		    keyfiles, nkeyfiles, h_keyfiles, n_hkeyfiles, NULL, NULL,
		    1 /* interactive */, DEFAULT_RETRIES, 0);
	} else if (map_vol) {
		error = map_volume(map_name,
		    dev, flags, sys_dev, protect_hidden,
		    keyfiles, nkeyfiles, h_keyfiles, n_hkeyfiles, NULL, NULL,
		    1 /* interactive */, DEFAULT_RETRIES, 0);
	} else if (unmap_vol) {
		error = dm_teardown(map_name, NULL);
	}

	return error;
}
Example #30
0
int
read_passphrase(const char *prompt, char *pass, size_t passlen, size_t bufsz, time_t timeout)
{
	struct termios termios_new;
	struct timeval to;
	fd_set fds;
	ssize_t n;
	int fd = STDIN_FILENO, r = 0, nready;
	struct sigaction act, old_act;
	int is_tty = isatty(fd);

	if (is_tty == 0)
		errno = 0;

	memset(pass, 0, bufsz);

	printf("%s", prompt);
	fflush(stdout);

	/* If input is being provided by something which is not a terminal, don't
	 * change the settings. */
	if (is_tty) {
		tcgetattr(fd, &termios_old);
		memcpy(&termios_new, &termios_old, sizeof(termios_new));
		termios_new.c_lflag &= ~ECHO;

		act.sa_handler = sigint_termios;
		act.sa_flags   = SA_RESETHAND;
		sigemptyset(&act.sa_mask);

		tty_fd = fd;
		sigaction(SIGINT, &act, &old_act);

		tcsetattr(fd, TCSAFLUSH, &termios_new);
	}

	if (timeout > 0) {
		memset(&to, 0, sizeof(to));
		to.tv_sec = timeout;

		FD_ZERO(&fds);
		FD_SET(fd, &fds);
		nready = select(fd + 1, &fds, NULL, NULL, &to);
		if (nready <= 0) {
			r = EINTR;
			goto out;
		}
	}

	n = read(fd, pass, bufsz-1);
	if (n > 0) {
		pass[n-1] = '\0'; /* Strip trailing \n */
	} else {
		r = EIO;
	}

	/* Warn about passphrase trimming */
	if (strlen(pass) > MAX_PASSSZ)
		tc_log(0, "WARNING: Passphrase is being trimmed to %zu "
		    "characters, discarding rest.\n", passlen);

	/* Cut off after passlen characters */
	pass[passlen] = '\0';

out:
	if (is_tty) {
		tcsetattr(fd, TCSAFLUSH, &termios_old);
		putchar('\n');

		sigaction(SIGINT, &old_act, NULL);
	}

	return r;
}