Blame lib/crypt_plain.c

Packit 94f725
/*
Packit 94f725
 * cryptsetup plain device helper functions
Packit 94f725
 *
Packit 94f725
 * Copyright (C) 2004 Jana Saout <jana@saout.de>
Packit 94f725
 * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved.
Packit 94f725
 * Copyright (C) 2010-2020 Milan Broz
Packit 94f725
 *
Packit 94f725
 * This program is free software; you can redistribute it and/or
Packit 94f725
 * modify it under the terms of the GNU General Public License
Packit 94f725
 * as published by the Free Software Foundation; either version 2
Packit 94f725
 * of the License, or (at your option) any later version.
Packit 94f725
 *
Packit 94f725
 * This program is distributed in the hope that it will be useful,
Packit 94f725
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 94f725
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 94f725
 * GNU General Public License for more details.
Packit 94f725
 *
Packit 94f725
 * You should have received a copy of the GNU General Public License
Packit 94f725
 * along with this program; if not, write to the Free Software
Packit 94f725
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit 94f725
 */
Packit 94f725
Packit 94f725
#include <string.h>
Packit 94f725
#include <stdio.h>
Packit 94f725
#include <errno.h>
Packit 94f725
Packit 94f725
#include "libcryptsetup.h"
Packit 94f725
#include "internal.h"
Packit 94f725
Packit 94f725
static int hash(const char *hash_name, size_t key_size, char *key,
Packit 94f725
		size_t passphrase_size, const char *passphrase)
Packit 94f725
{
Packit 94f725
	struct crypt_hash *md = NULL;
Packit 94f725
	size_t len;
Packit 94f725
	int round, i, r = 0;
Packit 94f725
Packit 94f725
	if (crypt_hash_init(&md, hash_name))
Packit 94f725
		return -ENOENT;
Packit 94f725
Packit 94f725
	len = crypt_hash_size(hash_name);
Packit 94f725
Packit 94f725
	for(round = 0; key_size && !r; round++) {
Packit 94f725
		/* hack from hashalot to avoid null bytes in key */
Packit 94f725
		for(i = 0; i < round; i++)
Packit 94f725
			if (crypt_hash_write(md, "A", 1))
Packit 94f725
				r = 1;
Packit 94f725
Packit 94f725
		if (crypt_hash_write(md, passphrase, passphrase_size))
Packit 94f725
			r = 1;
Packit 94f725
Packit 94f725
		if (len > key_size)
Packit 94f725
			len = key_size;
Packit 94f725
Packit 94f725
		if (crypt_hash_final(md, key, len))
Packit 94f725
			r = 1;
Packit 94f725
Packit 94f725
		key += len;
Packit 94f725
		key_size -= len;
Packit 94f725
	}
Packit 94f725
Packit 94f725
	crypt_hash_destroy(md);
Packit 94f725
	return r;
Packit 94f725
}
Packit 94f725
Packit 94f725
#define PLAIN_HASH_LEN_MAX 256
Packit 94f725
Packit 94f725
int crypt_plain_hash(struct crypt_device *cd,
Packit 94f725
		     const char *hash_name,
Packit 94f725
		     char *key, size_t key_size,
Packit 94f725
		     const char *passphrase, size_t passphrase_size)
Packit 94f725
{
Packit 94f725
	char hash_name_buf[PLAIN_HASH_LEN_MAX], *s;
Packit 94f725
	size_t hash_size, pad_size;
Packit 94f725
	int r;
Packit 94f725
Packit 94f725
	log_dbg(cd, "Plain: hashing passphrase using %s.", hash_name);
Packit 94f725
Packit 94f725
	if (strlen(hash_name) >= PLAIN_HASH_LEN_MAX)
Packit 94f725
		return -EINVAL;
Packit 94f725
	strncpy(hash_name_buf, hash_name, PLAIN_HASH_LEN_MAX);
Packit 94f725
	hash_name_buf[PLAIN_HASH_LEN_MAX - 1] = '\0';
Packit 94f725
Packit 94f725
	/* hash[:hash_length] */
Packit 94f725
	if ((s = strchr(hash_name_buf, ':'))) {
Packit 94f725
		*s = '\0';
Packit 94f725
		s++;
Packit 94f725
		if (!*s || sscanf(s, "%zd", &hash_size) != 1) {
Packit 94f725
			log_dbg(cd, "Hash length is not a number");
Packit 94f725
			return -EINVAL;
Packit 94f725
		}
Packit 94f725
		if (hash_size > key_size) {
Packit 94f725
			log_dbg(cd, "Hash length %zd > key length %zd",
Packit 94f725
				hash_size, key_size);
Packit 94f725
			return -EINVAL;
Packit 94f725
		}
Packit 94f725
		pad_size = key_size - hash_size;
Packit 94f725
	} else {
Packit 94f725
		hash_size = key_size;
Packit 94f725
		pad_size = 0;
Packit 94f725
	}
Packit 94f725
Packit 94f725
	/* No hash, copy passphrase directly */
Packit 94f725
	if (!strcmp(hash_name_buf, "plain")) {
Packit 94f725
		if (passphrase_size < hash_size) {
Packit 94f725
			log_dbg(cd, "Too short plain passphrase.");
Packit 94f725
			return -EINVAL;
Packit 94f725
		}
Packit 94f725
		memcpy(key, passphrase, hash_size);
Packit 94f725
		r = 0;
Packit 94f725
	} else
Packit 94f725
		r = hash(hash_name_buf, hash_size, key, passphrase_size, passphrase);
Packit 94f725
Packit 94f725
	if (r == 0 && pad_size)
Packit 94f725
		memset(key + hash_size, 0, pad_size);
Packit 94f725
Packit 94f725
	return r;
Packit 94f725
}