xref: /dflybsd-src/contrib/cryptsetup/lib/gcrypt.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino #include <stdlib.h>
286d7f5d3SJohn Marino #include <string.h>
386d7f5d3SJohn Marino #include <ctype.h>
486d7f5d3SJohn Marino #include <errno.h>
586d7f5d3SJohn Marino #include <gcrypt.h>
686d7f5d3SJohn Marino 
786d7f5d3SJohn Marino #include "libcryptsetup.h"
886d7f5d3SJohn Marino #include "internal.h"
986d7f5d3SJohn Marino 
1086d7f5d3SJohn Marino #define MAX_DIGESTS		64
1186d7f5d3SJohn Marino #define GCRYPT_REQ_VERSION	"1.1.42"
1286d7f5d3SJohn Marino 
init_crypto(void)1386d7f5d3SJohn Marino int init_crypto(void)
1486d7f5d3SJohn Marino {
1586d7f5d3SJohn Marino 	if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
1686d7f5d3SJohn Marino 		if (!gcry_check_version (GCRYPT_REQ_VERSION))
1786d7f5d3SJohn Marino 			return -ENOSYS;
1886d7f5d3SJohn Marino 
1986d7f5d3SJohn Marino /* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
2086d7f5d3SJohn Marino  * it drops all privileges during secure memory initialisation.
2186d7f5d3SJohn Marino  * For now, the only workaround is to disable secure memory in gcrypt.
2286d7f5d3SJohn Marino  * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
2386d7f5d3SJohn Marino  * and it locks its memory space anyway.
2486d7f5d3SJohn Marino  */
2586d7f5d3SJohn Marino #if 0
2686d7f5d3SJohn Marino 		log_dbg("Initializing crypto backend (secure memory disabled).");
2786d7f5d3SJohn Marino 		gcry_control (GCRYCTL_DISABLE_SECMEM);
2886d7f5d3SJohn Marino #else
2986d7f5d3SJohn Marino 		log_dbg("Initializing crypto backend (using secure memory).");
3086d7f5d3SJohn Marino 		gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
3186d7f5d3SJohn Marino 		gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
3286d7f5d3SJohn Marino 		gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
3386d7f5d3SJohn Marino #endif
3486d7f5d3SJohn Marino 		gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
3586d7f5d3SJohn Marino 	}
3686d7f5d3SJohn Marino 
3786d7f5d3SJohn Marino 	return 0;
3886d7f5d3SJohn Marino }
3986d7f5d3SJohn Marino 
gcrypt_hash(void * data,int size,char * key,int sizep,const char * passphrase)4086d7f5d3SJohn Marino static int gcrypt_hash(void *data, int size, char *key,
4186d7f5d3SJohn Marino                        int sizep, const char *passphrase)
4286d7f5d3SJohn Marino {
4386d7f5d3SJohn Marino 	gcry_md_hd_t md;
4486d7f5d3SJohn Marino 	int algo = *((int *)data);
4586d7f5d3SJohn Marino 	int len = gcry_md_get_algo_dlen(algo);
4686d7f5d3SJohn Marino 	int round, i;
4786d7f5d3SJohn Marino 
4886d7f5d3SJohn Marino 	if (gcry_md_open(&md, algo, 0))
4986d7f5d3SJohn Marino 		return -1;
5086d7f5d3SJohn Marino 
5186d7f5d3SJohn Marino 	for(round = 0; size; round++) {
5286d7f5d3SJohn Marino 		/* hack from hashalot to avoid null bytes in key */
5386d7f5d3SJohn Marino 		for(i = 0; i < round; i++)
5486d7f5d3SJohn Marino 			gcry_md_write(md, "A", 1);
5586d7f5d3SJohn Marino 
5686d7f5d3SJohn Marino 		gcry_md_write(md, passphrase, sizep);
5786d7f5d3SJohn Marino 
5886d7f5d3SJohn Marino 		if (len > size)
5986d7f5d3SJohn Marino 			len = size;
6086d7f5d3SJohn Marino 		memcpy(key, gcry_md_read(md, algo), len);
6186d7f5d3SJohn Marino 
6286d7f5d3SJohn Marino 		key += len;
6386d7f5d3SJohn Marino 		size -= len;
6486d7f5d3SJohn Marino 		if (size)
6586d7f5d3SJohn Marino 			gcry_md_reset(md);
6686d7f5d3SJohn Marino 	}
6786d7f5d3SJohn Marino 
6886d7f5d3SJohn Marino 	gcry_md_close(md);
6986d7f5d3SJohn Marino 	return 0;
7086d7f5d3SJohn Marino }
7186d7f5d3SJohn Marino 
gcrypt_get_hashes(void)7286d7f5d3SJohn Marino static struct hash_type *gcrypt_get_hashes(void)
7386d7f5d3SJohn Marino {
7486d7f5d3SJohn Marino 	struct hash_type *hashes;
7586d7f5d3SJohn Marino 	int size = MAX_DIGESTS;
7686d7f5d3SJohn Marino 	int *list;
7786d7f5d3SJohn Marino 	int i;
7886d7f5d3SJohn Marino 	gcry_error_t r;
7986d7f5d3SJohn Marino 
8086d7f5d3SJohn Marino 	if (!gcry_check_version(GCRYPT_REQ_VERSION))
8186d7f5d3SJohn Marino 		return NULL;
8286d7f5d3SJohn Marino 
8386d7f5d3SJohn Marino 	list = (int *)malloc(sizeof(*list) * size);
8486d7f5d3SJohn Marino 	if (!list)
8586d7f5d3SJohn Marino 		return NULL;
8686d7f5d3SJohn Marino 
8786d7f5d3SJohn Marino 	r = gcry_md_list(list, &size);
8886d7f5d3SJohn Marino 	if (r || !size) {
8986d7f5d3SJohn Marino 		free(list);
9086d7f5d3SJohn Marino 		return NULL;
9186d7f5d3SJohn Marino 	}
9286d7f5d3SJohn Marino 
9386d7f5d3SJohn Marino 	hashes = malloc(sizeof(*hashes) * (size + 1));
9486d7f5d3SJohn Marino 	if (!hashes) {
9586d7f5d3SJohn Marino 		free(list);
9686d7f5d3SJohn Marino 		return NULL;
9786d7f5d3SJohn Marino 	}
9886d7f5d3SJohn Marino 
9986d7f5d3SJohn Marino 	for(i = 0; i < size; i++) {
10086d7f5d3SJohn Marino 		hashes[i].name = NULL;
10186d7f5d3SJohn Marino 		hashes[i].private = NULL;
10286d7f5d3SJohn Marino 	}
10386d7f5d3SJohn Marino 
10486d7f5d3SJohn Marino 	for(i = 0; i < size; i++) {
10586d7f5d3SJohn Marino 		char *p;
10686d7f5d3SJohn Marino 
10786d7f5d3SJohn Marino 		hashes[i].name = strdup(gcry_md_algo_name(list[i]));
10886d7f5d3SJohn Marino 		if(!hashes[i].name)
10986d7f5d3SJohn Marino 			goto err;
11086d7f5d3SJohn Marino 		for(p = (char *)hashes[i].name; *p; p++)
11186d7f5d3SJohn Marino 			*p = tolower(*p);
11286d7f5d3SJohn Marino 		hashes[i].private = malloc(sizeof(int));
11386d7f5d3SJohn Marino 		if(!hashes[i].private)
11486d7f5d3SJohn Marino 			goto err;
11586d7f5d3SJohn Marino 		*((int *)hashes[i].private) = list[i];
11686d7f5d3SJohn Marino 		hashes[i].fn = gcrypt_hash;
11786d7f5d3SJohn Marino 	}
11886d7f5d3SJohn Marino 	hashes[i].name = NULL;
11986d7f5d3SJohn Marino 	hashes[i].private = NULL;
12086d7f5d3SJohn Marino 	hashes[i].fn = NULL;
12186d7f5d3SJohn Marino 
12286d7f5d3SJohn Marino 	free(list);
12386d7f5d3SJohn Marino 
12486d7f5d3SJohn Marino 	return hashes;
12586d7f5d3SJohn Marino 
12686d7f5d3SJohn Marino err:
12786d7f5d3SJohn Marino 	free(list);
12886d7f5d3SJohn Marino 	for(i = 0; i < size; i++) {
12986d7f5d3SJohn Marino 		free(hashes[i].name);
13086d7f5d3SJohn Marino 		free(hashes[i].private);
13186d7f5d3SJohn Marino 	}
13286d7f5d3SJohn Marino 	free(hashes);
13386d7f5d3SJohn Marino 	return NULL;
13486d7f5d3SJohn Marino }
13586d7f5d3SJohn Marino 
gcrypt_free_hashes(struct hash_type * hashes)13686d7f5d3SJohn Marino static void gcrypt_free_hashes(struct hash_type *hashes)
13786d7f5d3SJohn Marino {
13886d7f5d3SJohn Marino 	struct hash_type *hash;
13986d7f5d3SJohn Marino 
14086d7f5d3SJohn Marino 	for(hash = hashes; hash->name; hash++) {
14186d7f5d3SJohn Marino 		free(hash->name);
14286d7f5d3SJohn Marino 		free(hash->private);
14386d7f5d3SJohn Marino 	}
14486d7f5d3SJohn Marino 
14586d7f5d3SJohn Marino 	free(hashes);
14686d7f5d3SJohn Marino }
14786d7f5d3SJohn Marino 
14886d7f5d3SJohn Marino struct hash_backend hash_gcrypt_backend = {
14986d7f5d3SJohn Marino 	.name = "libgcrypt",
15086d7f5d3SJohn Marino 	.get_hashes = gcrypt_get_hashes,
15186d7f5d3SJohn Marino 	.free_hashes = gcrypt_free_hashes
15286d7f5d3SJohn Marino };
153