Use proper NLS macros and detection (so the message translation works again).
[platform/upstream/cryptsetup.git] / lib / gcrypt.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <ctype.h>
4 #include <gcrypt.h>
5
6 #include "libcryptsetup.h"
7 #include "internal.h"
8
9 #define MAX_DIGESTS             64
10 #define GCRYPT_REQ_VERSION      "1.1.42"
11
12 int init_crypto(void)
13 {
14         if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
15                 //if (!gcry_check_version (GCRYPT_VERSION))
16                 //      return -ENOSYS;
17                 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
18                 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
19                 gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
20                 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
21         }
22
23         return 0;
24 }
25
26 static int gcrypt_hash(void *data, int size, char *key,
27                        int sizep, const char *passphrase)
28 {
29         gcry_md_hd_t md;
30         int algo = *((int *)data);
31         int len = gcry_md_get_algo_dlen(algo);
32         int round, i;
33
34         if (gcry_md_open(&md, algo, 0))
35                 return -1;
36
37         for(round = 0; size; round++) {
38                 /* hack from hashalot to avoid null bytes in key */
39                 for(i = 0; i < round; i++)
40                         gcry_md_write(md, "A", 1);
41
42                 gcry_md_write(md, passphrase, sizep);
43
44                 if (len > size)
45                         len = size;
46                 memcpy(key, gcry_md_read(md, algo), len);
47
48                 key += len;
49                 size -= len;
50                 if (size)
51                         gcry_md_reset(md);
52         }
53
54         gcry_md_close(md);
55         return 0;
56 }
57
58 static struct hash_type *gcrypt_get_hashes(void)
59 {
60         struct hash_type *hashes;
61         int size = MAX_DIGESTS;
62         int *list;
63         int i;
64         gcry_error_t r;
65
66         if (!gcry_check_version(GCRYPT_REQ_VERSION))
67                 return NULL;
68
69         list = (int *)malloc(sizeof(*list) * size);
70         if (!list)
71                 return NULL;
72
73         r = gcry_md_list(list, &size);
74         if (r || !size) {
75                 free(list);
76                 return NULL;
77         }
78
79         hashes = malloc(sizeof(*hashes) * (size + 1));
80         if (!hashes) {
81                 free(list);
82                 return NULL;
83         }
84
85         for(i = 0; i < size; i++) {
86                 hashes[i].name = NULL;
87                 hashes[i].private = NULL;
88         }
89
90         for(i = 0; i < size; i++) {
91                 char *p;
92
93                 hashes[i].name = strdup(gcry_md_algo_name(list[i]));
94                 if(!hashes[i].name)
95                         goto err;
96                 for(p = (char *)hashes[i].name; *p; p++)
97                         *p = tolower(*p);
98                 hashes[i].private = malloc(sizeof(int));
99                 if(!hashes[i].private)
100                         goto err;
101                 *((int *)hashes[i].private) = list[i];
102                 hashes[i].fn = gcrypt_hash;
103         }
104         hashes[i].name = NULL;
105         hashes[i].private = NULL;
106         hashes[i].fn = NULL;
107
108         free(list);
109
110         return hashes;
111
112 err:
113         free(list);
114         for(i = 0; i < size; i++) {
115                 free(hashes[i].name);
116                 free(hashes[i].private);
117         }
118         free(hashes);
119         return NULL;
120 }
121
122 static void gcrypt_free_hashes(struct hash_type *hashes)
123 {
124         struct hash_type *hash;
125
126         for(hash = hashes; hash->name; hash++) {
127                 free(hash->name);
128                 free(hash->private);
129         }
130
131         free(hashes);
132 }
133
134 struct hash_backend hash_gcrypt_backend = {
135         .name = "libgcrypt",
136         .get_hashes = gcrypt_get_hashes,
137         .free_hashes = gcrypt_free_hashes
138 };