xref: /dflybsd-src/contrib/cryptsetup/lib/gcrypt.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino #include <stdlib.h>
2*86d7f5d3SJohn Marino #include <string.h>
3*86d7f5d3SJohn Marino #include <ctype.h>
4*86d7f5d3SJohn Marino #include <errno.h>
5*86d7f5d3SJohn Marino #include <gcrypt.h>
6*86d7f5d3SJohn Marino 
7*86d7f5d3SJohn Marino #include "libcryptsetup.h"
8*86d7f5d3SJohn Marino #include "internal.h"
9*86d7f5d3SJohn Marino 
10*86d7f5d3SJohn Marino #define MAX_DIGESTS		64
11*86d7f5d3SJohn Marino #define GCRYPT_REQ_VERSION	"1.1.42"
12*86d7f5d3SJohn Marino 
init_crypto(void)13*86d7f5d3SJohn Marino int init_crypto(void)
14*86d7f5d3SJohn Marino {
15*86d7f5d3SJohn Marino 	if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
16*86d7f5d3SJohn Marino 		if (!gcry_check_version (GCRYPT_REQ_VERSION))
17*86d7f5d3SJohn Marino 			return -ENOSYS;
18*86d7f5d3SJohn Marino 
19*86d7f5d3SJohn Marino /* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
20*86d7f5d3SJohn Marino  * it drops all privileges during secure memory initialisation.
21*86d7f5d3SJohn Marino  * For now, the only workaround is to disable secure memory in gcrypt.
22*86d7f5d3SJohn Marino  * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
23*86d7f5d3SJohn Marino  * and it locks its memory space anyway.
24*86d7f5d3SJohn Marino  */
25*86d7f5d3SJohn Marino #if 0
26*86d7f5d3SJohn Marino 		log_dbg("Initializing crypto backend (secure memory disabled).");
27*86d7f5d3SJohn Marino 		gcry_control (GCRYCTL_DISABLE_SECMEM);
28*86d7f5d3SJohn Marino #else
29*86d7f5d3SJohn Marino 		log_dbg("Initializing crypto backend (using secure memory).");
30*86d7f5d3SJohn Marino 		gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
31*86d7f5d3SJohn Marino 		gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
32*86d7f5d3SJohn Marino 		gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
33*86d7f5d3SJohn Marino #endif
34*86d7f5d3SJohn Marino 		gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
35*86d7f5d3SJohn Marino 	}
36*86d7f5d3SJohn Marino 
37*86d7f5d3SJohn Marino 	return 0;
38*86d7f5d3SJohn Marino }
39*86d7f5d3SJohn Marino 
gcrypt_hash(void * data,int size,char * key,int sizep,const char * passphrase)40*86d7f5d3SJohn Marino static int gcrypt_hash(void *data, int size, char *key,
41*86d7f5d3SJohn Marino                        int sizep, const char *passphrase)
42*86d7f5d3SJohn Marino {
43*86d7f5d3SJohn Marino 	gcry_md_hd_t md;
44*86d7f5d3SJohn Marino 	int algo = *((int *)data);
45*86d7f5d3SJohn Marino 	int len = gcry_md_get_algo_dlen(algo);
46*86d7f5d3SJohn Marino 	int round, i;
47*86d7f5d3SJohn Marino 
48*86d7f5d3SJohn Marino 	if (gcry_md_open(&md, algo, 0))
49*86d7f5d3SJohn Marino 		return -1;
50*86d7f5d3SJohn Marino 
51*86d7f5d3SJohn Marino 	for(round = 0; size; round++) {
52*86d7f5d3SJohn Marino 		/* hack from hashalot to avoid null bytes in key */
53*86d7f5d3SJohn Marino 		for(i = 0; i < round; i++)
54*86d7f5d3SJohn Marino 			gcry_md_write(md, "A", 1);
55*86d7f5d3SJohn Marino 
56*86d7f5d3SJohn Marino 		gcry_md_write(md, passphrase, sizep);
57*86d7f5d3SJohn Marino 
58*86d7f5d3SJohn Marino 		if (len > size)
59*86d7f5d3SJohn Marino 			len = size;
60*86d7f5d3SJohn Marino 		memcpy(key, gcry_md_read(md, algo), len);
61*86d7f5d3SJohn Marino 
62*86d7f5d3SJohn Marino 		key += len;
63*86d7f5d3SJohn Marino 		size -= len;
64*86d7f5d3SJohn Marino 		if (size)
65*86d7f5d3SJohn Marino 			gcry_md_reset(md);
66*86d7f5d3SJohn Marino 	}
67*86d7f5d3SJohn Marino 
68*86d7f5d3SJohn Marino 	gcry_md_close(md);
69*86d7f5d3SJohn Marino 	return 0;
70*86d7f5d3SJohn Marino }
71*86d7f5d3SJohn Marino 
gcrypt_get_hashes(void)72*86d7f5d3SJohn Marino static struct hash_type *gcrypt_get_hashes(void)
73*86d7f5d3SJohn Marino {
74*86d7f5d3SJohn Marino 	struct hash_type *hashes;
75*86d7f5d3SJohn Marino 	int size = MAX_DIGESTS;
76*86d7f5d3SJohn Marino 	int *list;
77*86d7f5d3SJohn Marino 	int i;
78*86d7f5d3SJohn Marino 	gcry_error_t r;
79*86d7f5d3SJohn Marino 
80*86d7f5d3SJohn Marino 	if (!gcry_check_version(GCRYPT_REQ_VERSION))
81*86d7f5d3SJohn Marino 		return NULL;
82*86d7f5d3SJohn Marino 
83*86d7f5d3SJohn Marino 	list = (int *)malloc(sizeof(*list) * size);
84*86d7f5d3SJohn Marino 	if (!list)
85*86d7f5d3SJohn Marino 		return NULL;
86*86d7f5d3SJohn Marino 
87*86d7f5d3SJohn Marino 	r = gcry_md_list(list, &size);
88*86d7f5d3SJohn Marino 	if (r || !size) {
89*86d7f5d3SJohn Marino 		free(list);
90*86d7f5d3SJohn Marino 		return NULL;
91*86d7f5d3SJohn Marino 	}
92*86d7f5d3SJohn Marino 
93*86d7f5d3SJohn Marino 	hashes = malloc(sizeof(*hashes) * (size + 1));
94*86d7f5d3SJohn Marino 	if (!hashes) {
95*86d7f5d3SJohn Marino 		free(list);
96*86d7f5d3SJohn Marino 		return NULL;
97*86d7f5d3SJohn Marino 	}
98*86d7f5d3SJohn Marino 
99*86d7f5d3SJohn Marino 	for(i = 0; i < size; i++) {
100*86d7f5d3SJohn Marino 		hashes[i].name = NULL;
101*86d7f5d3SJohn Marino 		hashes[i].private = NULL;
102*86d7f5d3SJohn Marino 	}
103*86d7f5d3SJohn Marino 
104*86d7f5d3SJohn Marino 	for(i = 0; i < size; i++) {
105*86d7f5d3SJohn Marino 		char *p;
106*86d7f5d3SJohn Marino 
107*86d7f5d3SJohn Marino 		hashes[i].name = strdup(gcry_md_algo_name(list[i]));
108*86d7f5d3SJohn Marino 		if(!hashes[i].name)
109*86d7f5d3SJohn Marino 			goto err;
110*86d7f5d3SJohn Marino 		for(p = (char *)hashes[i].name; *p; p++)
111*86d7f5d3SJohn Marino 			*p = tolower(*p);
112*86d7f5d3SJohn Marino 		hashes[i].private = malloc(sizeof(int));
113*86d7f5d3SJohn Marino 		if(!hashes[i].private)
114*86d7f5d3SJohn Marino 			goto err;
115*86d7f5d3SJohn Marino 		*((int *)hashes[i].private) = list[i];
116*86d7f5d3SJohn Marino 		hashes[i].fn = gcrypt_hash;
117*86d7f5d3SJohn Marino 	}
118*86d7f5d3SJohn Marino 	hashes[i].name = NULL;
119*86d7f5d3SJohn Marino 	hashes[i].private = NULL;
120*86d7f5d3SJohn Marino 	hashes[i].fn = NULL;
121*86d7f5d3SJohn Marino 
122*86d7f5d3SJohn Marino 	free(list);
123*86d7f5d3SJohn Marino 
124*86d7f5d3SJohn Marino 	return hashes;
125*86d7f5d3SJohn Marino 
126*86d7f5d3SJohn Marino err:
127*86d7f5d3SJohn Marino 	free(list);
128*86d7f5d3SJohn Marino 	for(i = 0; i < size; i++) {
129*86d7f5d3SJohn Marino 		free(hashes[i].name);
130*86d7f5d3SJohn Marino 		free(hashes[i].private);
131*86d7f5d3SJohn Marino 	}
132*86d7f5d3SJohn Marino 	free(hashes);
133*86d7f5d3SJohn Marino 	return NULL;
134*86d7f5d3SJohn Marino }
135*86d7f5d3SJohn Marino 
gcrypt_free_hashes(struct hash_type * hashes)136*86d7f5d3SJohn Marino static void gcrypt_free_hashes(struct hash_type *hashes)
137*86d7f5d3SJohn Marino {
138*86d7f5d3SJohn Marino 	struct hash_type *hash;
139*86d7f5d3SJohn Marino 
140*86d7f5d3SJohn Marino 	for(hash = hashes; hash->name; hash++) {
141*86d7f5d3SJohn Marino 		free(hash->name);
142*86d7f5d3SJohn Marino 		free(hash->private);
143*86d7f5d3SJohn Marino 	}
144*86d7f5d3SJohn Marino 
145*86d7f5d3SJohn Marino 	free(hashes);
146*86d7f5d3SJohn Marino }
147*86d7f5d3SJohn Marino 
148*86d7f5d3SJohn Marino struct hash_backend hash_gcrypt_backend = {
149*86d7f5d3SJohn Marino 	.name = "libgcrypt",
150*86d7f5d3SJohn Marino 	.get_hashes = gcrypt_get_hashes,
151*86d7f5d3SJohn Marino 	.free_hashes = gcrypt_free_hashes
152*86d7f5d3SJohn Marino };
153