utils_crypt.c \
utils_crypt.h \
utils_debug.c \
- backends.c \
libdevmapper.c \
volumekey.c \
random.c \
- gcrypt.c \
+ crypt_plain.c \
crypto_backend.h
include_HEADERS = libcryptsetup.h
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "libcryptsetup.h"
-#include "internal.h"
-
-extern struct hash_backend hash_gcrypt_backend;
-
-static struct hash_backend *hash_backends[] = {
- &hash_gcrypt_backend,
- NULL
-};
-
-struct hash_backend *get_hash_backend(const char *name)
-{
- struct hash_backend **backend;
-
- for(backend = hash_backends; *backend; backend++)
- if (!name || strcmp(name, (*backend)->name) == 0)
- break;
-
- return *backend;
-}
-
-void put_hash_backend(struct hash_backend *backend)
-{
-}
-
-int hash(const char *backend_name, const char *hash_name,
- char *result, size_t size,
- const char *passphrase, size_t sizep)
-{
- struct hash_backend *backend;
- struct hash_type *hashes = NULL, *hash;
- char hash_name_buf[256], *s;
- size_t pad = 0;
- int r = -ENOENT;
-
- if (strlen(hash_name) >= sizeof(hash_name_buf)) {
- set_error("hash name too long: %s", hash_name);
- return -ENAMETOOLONG;
- }
-
- if ((s = strchr(hash_name, ':'))) {
- size_t hlen;
- strcpy(hash_name_buf, hash_name);
- hash_name_buf[s-hash_name] = '\0';
- hash_name = hash_name_buf;
- hlen = atoi(++s);
- if (hlen > size) {
- set_error("requested hash length (%zd) > key length (%zd)", hlen, size);
- return -EINVAL;
- }
- pad = size-hlen;
- size = hlen;
- }
-
- backend = get_hash_backend(backend_name);
- if (!backend) {
- set_error("No hash backend found");
- return -ENOSYS;
- }
-
- hashes = backend->get_hashes();
- if (!hashes) {
- set_error("No hash functions available");
- goto out;
- }
-
- for(hash = hashes; hash->name; hash++)
- if (strcmp(hash->name, hash_name) == 0)
- break;
- if (!hash->name) {
- set_error("Unknown hash type %s", hash_name);
- goto out;
- }
-
- r = hash->fn(hash->private, size, result, sizep, passphrase);
- if (r < 0) {
- set_error("Error hashing passphrase");
- goto out;
- }
-
- if (pad) {
- memset(result+size, 0, pad);
- }
-
-out:
- if (hashes)
- backend->free_hashes(hashes);
- put_hash_backend(backend);
-
- return r;
-}
--- /dev/null
+/*
+ * cryptsetup plain device helper functions
+ *
+ * Copyright (C) 2004 Christophe Saout <christophe@saout.de>
+ * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "internal.h"
+#include "crypto_backend.h"
+
+static int hash(const char *hash_name, int size, char *key,
+ int sizep, const char *passphrase)
+{
+ struct crypt_hash *md = NULL;
+ size_t slen;
+ int len = crypt_hash_size(hash_name);
+ int round, i;
+
+ if (crypt_hash_init(&md, hash_name))
+ return -ENOENT;
+
+ for(round = 0; size; round++) {
+ /* hack from hashalot to avoid null bytes in key */
+ for(i = 0; i < round; i++)
+ crypt_hash_write(md, "A", 1);
+
+ crypt_hash_write(md, passphrase, sizep);
+
+ if (len > size)
+ len = size;
+ slen = len;
+ crypt_hash_final(md, key, slen);
+ // FIXME: if slen != len
+
+ key += len;
+ size -= len;
+ if (size)
+ crypt_hash_restart(md);
+ }
+
+ crypt_hash_destroy(md);
+ return 0;
+}
+
+int crypt_plain_hash(struct crypt_device *ctx, const char *hash_name,
+ char *result, size_t size,
+ const char *passphrase, size_t sizep)
+{
+ char hash_name_buf[256], *s;
+ size_t hlen, pad = 0;
+ int r;
+
+ if (strlen(hash_name) >= sizeof(hash_name_buf))
+ return -EINVAL;
+
+ if ((s = strchr(hash_name, ':'))) {
+ strcpy(hash_name_buf, hash_name);
+ hash_name_buf[s-hash_name] = '\0';
+ hash_name = hash_name_buf;
+ hlen = atoi(++s);
+ if (hlen > size) {
+ log_err(ctx, "Requested hash length (%zd) > key length (%zd)\n", hlen, size);
+ return -EINVAL;
+ }
+ pad = size-hlen;
+ size = hlen;
+ }
+
+ r = hash(hash_name, size, result, sizep, passphrase);
+ if (r < 0)
+ log_err(ctx, "Hash algorithm %s not supported.\n", hash_name);
+
+ if (r == 0 && pad)
+ memset(result+size, 0, pad);
+
+ return r;
+}
+++ /dev/null
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <gcrypt.h>
-
-#include "libcryptsetup.h"
-#include "internal.h"
-
-#define MAX_DIGESTS 64
-#define GCRYPT_REQ_VERSION "1.1.42"
-
-int init_crypto(struct crypt_device *ctx)
-{
- int r;
-
- r = crypt_random_init(ctx);
- if (r < 0)
- goto fail;
-
- if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
- if (!gcry_check_version (GCRYPT_REQ_VERSION)) {
- r = -ENOSYS;
- goto fail;
- }
-
-/* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
- * it drops all privileges during secure memory initialisation.
- * For now, the only workaround is to disable secure memory in gcrypt.
- * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
- * and it locks its memory space anyway.
- */
-#if 0
- log_dbg("Initializing crypto backend (secure memory disabled).");
- gcry_control (GCRYCTL_DISABLE_SECMEM);
-#else
- log_dbg("Initializing crypto backend (using secure memory).");
- gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
- gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
- gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
-#endif
- gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
- }
-
- return 0;
-fail:
- log_err(ctx, _("Cannot initialize crypto backend.\n"));
- return r;
-}
-
-static int gcrypt_hash(void *data, int size, char *key,
- int sizep, const char *passphrase)
-{
- gcry_md_hd_t md;
- int algo = *((int *)data);
- int len = gcry_md_get_algo_dlen(algo);
- int round, i;
-
- if (gcry_md_open(&md, algo, 0))
- return -1;
-
- for(round = 0; size; round++) {
- /* hack from hashalot to avoid null bytes in key */
- for(i = 0; i < round; i++)
- gcry_md_write(md, "A", 1);
-
- gcry_md_write(md, passphrase, sizep);
-
- if (len > size)
- len = size;
- memcpy(key, gcry_md_read(md, algo), len);
-
- key += len;
- size -= len;
- if (size)
- gcry_md_reset(md);
- }
-
- gcry_md_close(md);
- return 0;
-}
-
-static struct hash_type *gcrypt_get_hashes(void)
-{
- struct hash_type *hashes;
- int size = MAX_DIGESTS;
- int *list;
- int i;
- gcry_error_t r;
-
- if (!gcry_check_version(GCRYPT_REQ_VERSION))
- return NULL;
-
- list = (int *)malloc(sizeof(*list) * size);
- if (!list)
- return NULL;
-
- r = gcry_md_list(list, &size);
- if (r || !size) {
- free(list);
- return NULL;
- }
-
- hashes = malloc(sizeof(*hashes) * (size + 1));
- if (!hashes) {
- free(list);
- return NULL;
- }
-
- for(i = 0; i < size; i++) {
- hashes[i].name = NULL;
- hashes[i].private = NULL;
- }
-
- for(i = 0; i < size; i++) {
- char *p;
-
- hashes[i].name = strdup(gcry_md_algo_name(list[i]));
- if(!hashes[i].name)
- goto err;
- for(p = (char *)hashes[i].name; *p; p++)
- *p = tolower(*p);
- hashes[i].private = malloc(sizeof(int));
- if(!hashes[i].private)
- goto err;
- *((int *)hashes[i].private) = list[i];
- hashes[i].fn = gcrypt_hash;
- }
- hashes[i].name = NULL;
- hashes[i].private = NULL;
- hashes[i].fn = NULL;
-
- free(list);
-
- return hashes;
-
-err:
- free(list);
- for(i = 0; i < size; i++) {
- free(hashes[i].name);
- free(hashes[i].private);
- }
- free(hashes);
- return NULL;
-}
-
-static void gcrypt_free_hashes(struct hash_type *hashes)
-{
- struct hash_type *hash;
-
- for(hash = hashes; hash->name; hash++) {
- free(hash->name);
- free(hash->private);
- }
-
- free(hashes);
-}
-
-struct hash_backend hash_gcrypt_backend = {
- .name = "libgcrypt",
- .get_hashes = gcrypt_get_hashes,
- .free_hashes = gcrypt_free_hashes
-};
void set_error(const char *fmt, ...);
const char *get_error(void);
-int init_crypto(struct crypt_device *ctx);
-struct hash_backend *get_hash_backend(const char *name);
-void put_hash_backend(struct hash_backend *backend);
-int hash(const char *backend_name, const char *hash_name,
- char *result, size_t size,
- const char *passphrase, size_t sizep);
-
/* Device mapper backend */
const char *dm_get_dir(void);
int dm_init(struct crypt_device *context, int check_kernel);
void crypt_random_exit(void);
int crypt_random_default_key_rng(void);
+int crypt_plain_hash(struct crypt_device *ctx, const char *hash_name,
+ char *result, size_t size,
+ const char *passphrase, size_t sizep);
+
#endif /* INTERNAL_H */
noinst_LTLIBRARIES = libluks1.la
-libluks1_la_CFLAGS = -Wall @LIBGCRYPT_CFLAGS@
+libluks1_la_CFLAGS = -Wall @CRYPTO_CFLAGS@
libluks1_la_SOURCES = \
af.c \
INCLUDES = -D_GNU_SOURCE \
-D_LARGEFILE64_SOURCE \
-D_FILE_OFFSET_BITS=64 \
- -I$(top_srcdir)/lib
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/lib/crypto_backend
/*
* AFsplitter - Anti forensic information splitter
- * Copyright 2004, Clemens Fruhwirth <clemens@endorphin.org>
- * Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+ *
+ * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved.
*
* AFsplitter diffuses information over a large stripe of data,
* therefor supporting secure data destruction.
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
-#include <gcrypt.h>
+#include "crypto_backend.h"
#include "internal.h"
-static void XORblock(char const *src1, char const *src2, char *dst, size_t n)
+static void XORblock(const char *src1, const char *src2, char *dst, size_t n)
{
size_t j;
dst[j] = src1[j] ^ src2[j];
}
-static int hash_buf(char *src, char *dst, uint32_t iv, int len, int hash_id)
+static int hash_buf(const char *src, char *dst, uint32_t iv,
+ size_t len, const char *hash_name)
{
- gcry_md_hd_t hd;
- unsigned char *digest;
+ struct crypt_hash *hd = NULL;
+ char *iv_char = (char *)&iv;
iv = htonl(iv);
- if (gcry_md_open(&hd, hash_id, 0))
+ if (crypt_hash_init(&hd, hash_name))
return 1;
- gcry_md_write(hd, (unsigned char *)&iv, sizeof(iv));
- gcry_md_write(hd, src, len);
- digest = gcry_md_read(hd, hash_id);
- memcpy(dst, digest, len);
- gcry_md_close(hd);
+ crypt_hash_write(hd, iv_char, sizeof(uint32_t));
+ crypt_hash_write(hd, src, len);
+ crypt_hash_final(hd, dst, len);
+ crypt_hash_destroy(hd);
return 0;
}
* the help of hash function.
*/
-static int diffuse(char *src, char *dst, size_t size, int hash_id)
+static int diffuse(char *src, char *dst, size_t size, const char *hash_name)
{
- unsigned int digest_size = gcry_md_get_algo_dlen(hash_id);
+ unsigned int digest_size = crypt_hash_size(hash_name);
unsigned int i, blocks, padding;
blocks = size / digest_size;
for (i = 0; i < blocks; i++)
if(hash_buf(src + digest_size * i,
dst + digest_size * i,
- i, digest_size, hash_id))
+ i, (size_t)digest_size, hash_name))
return 1;
if(padding)
if(hash_buf(src + digest_size * i,
dst + digest_size * i,
- i, padding, hash_id))
+ i, (size_t)padding, hash_name))
return 1;
return 0;
* must be supplied to AF_merge to recover information.
*/
-int AF_split(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash)
+int AF_split(char *src, char *dst, size_t blocksize,
+ unsigned int blocknumbers, const char *hash)
{
unsigned int i;
char *bufblock;
int r = -EINVAL;
- int hash_id;
-
- if (!(hash_id = gcry_md_map_name(hash)))
- return -EINVAL;
if((bufblock = calloc(blocksize, 1)) == NULL) return -ENOMEM;
if(r < 0) goto out;
XORblock(dst+(blocksize*i),bufblock,bufblock,blocksize);
- if(diffuse(bufblock, bufblock, blocksize, hash_id))
+ if(diffuse(bufblock, bufblock, blocksize, hash))
goto out;
}
/* the last block is computed */
return r;
}
-int AF_merge(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash)
+int AF_merge(char *src, char *dst, size_t blocksize,
+ unsigned int blocknumbers, const char *hash)
{
unsigned int i;
char *bufblock;
int r = -EINVAL;
- int hash_id;
-
- if (!(hash_id = gcry_md_map_name(hash)))
- return -EINVAL;
if((bufblock = calloc(blocksize, 1)) == NULL)
return -ENOMEM;
memset(bufblock,0,blocksize);
for(i=0; i<blocknumbers-1; i++) {
XORblock(src+(blocksize*i),bufblock,bufblock,blocksize);
- if(diffuse(bufblock, bufblock, blocksize, hash_id))
+ if(diffuse(bufblock, bufblock, blocksize, hash))
goto out;
}
XORblock(src + blocksize * i, bufblock, dst, blocksize);
#include <errno.h>
#include <signal.h>
#include <alloca.h>
+#include <string.h>
#include <sys/time.h>
-#include <gcrypt.h>
+#include "crypto_backend.h"
static volatile uint64_t __PBKDF2_global_j = 0;
static volatile uint64_t __PBKDF2_performance = 0;
-int init_crypto(void);
-
/*
* 5.2 PBKDF2
*
unsigned int c, unsigned int dkLen,
char *DK, int perfcheck)
{
- gcry_md_hd_t prf;
+ struct crypt_hmac *hmac;
char U[MAX_PRF_BLOCK_LEN];
char T[MAX_PRF_BLOCK_LEN];
- int PRF, i, k, rc = -EINVAL;
+ int i, k, rc = -EINVAL;
unsigned int u, hLen, l, r;
- unsigned char *p;
- size_t tmplen = Slen + 4;
+ size_t tmplen = Slen + 4, fLen;
char *tmp;
tmp = alloca(tmplen);
if (tmp == NULL)
return -ENOMEM;
- if (init_crypto())
- return -ENOSYS;
-
- PRF = gcry_md_map_name(hash);
- if (PRF == 0)
- return -EINVAL;
-
- hLen = gcry_md_get_algo_dlen(PRF);
+ hLen = crypt_hmac_size(hash);
if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN)
return -EINVAL;
*
*/
- if(gcry_md_open(&prf, PRF, GCRY_MD_FLAG_HMAC))
+ if (crypt_hmac_init(&hmac, hash, P, Plen))
return -EINVAL;
- if (gcry_md_setkey(prf, P, Plen))
- goto out;
-
for (i = 1; (uint) i <= l; i++) {
memset(T, 0, hLen);
for (u = 1; u <= c ; u++) {
- gcry_md_reset(prf);
+ crypt_hmac_restart(hmac);
if (u == 1) {
memcpy(tmp, S, Slen);
tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
tmp[Slen + 3] = (i & 0x000000ff) >> 0;
- gcry_md_write(prf, tmp, tmplen);
+ crypt_hmac_write(hmac, tmp, tmplen);
} else {
- gcry_md_write(prf, U, hLen);
+ crypt_hmac_write(hmac, U, hLen);
}
- p = gcry_md_read(prf, PRF);
- if (p == NULL)
- goto out;
+ //p = gcry_md_read(prf, PRF);
+ //if (p == NULL)
+ // goto out;
- memcpy(U, p, hLen);
+ fLen = hLen;
+ crypt_hmac_final(hmac, U, fLen);
+ //memcpy(U, p, hLen);
for (k = 0; (uint) k < hLen; k++)
T[k] ^= U[k];
}
rc = 0;
out:
- gcry_md_close(prf);
+ crypt_hmac_destroy(hmac);
return rc;
}
int PBKDF2_HMAC_ready(const char *hash)
{
- int hash_id = gcry_md_map_name(hash);
-
- if (!hash_id)
- return -EINVAL;
-
- /* Used hash must have at least 160 bits */
- if (gcry_md_get_algo_dlen(hash_id) < 20)
+ if (crypt_hmac_size(hash) < 20)
return -EINVAL;
return 1;
/* This code benchmarks PBKDF2 and returns iterations/second using wth specified hash */
int PBKDF2_performance_check(const char *hash, uint64_t *iter)
{
- int r;
+ int timer_type, r;
char buf;
struct itimerval it;
if (!PBKDF2_HMAC_ready(hash))
return -EINVAL;
+ /* If crypto backend is not implemented in userspace,
+ * but uses some kernel part, we must measure also time
+ * spent in kernel. */
+ if (crypt_backend_flags() & CRYPT_BACKEND_KERNEL)
+ timer_type = ITIMER_PROF;
+ else
+ timer_type = ITIMER_VIRTUAL;
+
signal(SIGVTALRM,sigvtalarm);
+ signal(SIGPROF,sigvtalarm);
it.it_interval.tv_usec = 0;
it.it_interval.tv_sec = 0;
it.it_value.tv_usec = 0;
it.it_value.tv_sec = 1;
- if (setitimer (ITIMER_VIRTUAL, &it, NULL) < 0)
+ if (setitimer(timer_type, &it, NULL) < 0)
return -EINVAL;
r = pkcs5_pbkdf2(hash, "foo", 3, "bar", 3, ~(0U), 1, &buf, 1);
#include "libcryptsetup.h"
#include "luks.h"
#include "internal.h"
+#include "crypto_backend.h"
struct crypt_device {
char *type;
free(target);
}
+static int init_crypto(struct crypt_device *ctx)
+{
+ int r;
+
+ r = crypt_random_init(ctx);
+ if (r < 0) {
+ log_err(ctx, _("Cannot initialize crypto RNG backend.\n"));
+ return r;
+ }
+
+ r = crypt_backend_init();
+ if (r < 0)
+ log_err(ctx, _("Cannot initialize crypto backend.\n"));
+
+ return r;
+}
+
/*
* Password processing behaviour matrix of process_key
*
/* key is coming from tty, fd or binary stdin */
if (hash_name) {
- if (hash(NULL, hash_name, key, key_size, pass, passLen) < 0) {
+ if (crypt_plain_hash(cd, hash_name, key, key_size, pass, passLen) < 0) {
log_err(cd, _("Key processing error (using hash algorithm %s).\n"),
hash_name);
crypt_safe_free(key);