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