Initial checking of what was revision 56 on http://luks.endorphin.org/svn/cryptsetup
[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 static int gcrypt_hash(void *data, int size, char *key,
13                        int sizep, const char *passphrase)
14 {
15         gcry_md_hd_t md;
16         int algo = *((int *)data);
17         int len = gcry_md_get_algo_dlen(algo);
18         int round, i;
19
20         if (gcry_md_open(&md, algo, 0))
21                 return -1;
22
23         for(round = 0; size; round++) {
24                 /* hack from hashalot to avoid null bytes in key */
25                 for(i = 0; i < round; i++)
26                         gcry_md_write(md, "A", 1);
27
28                 gcry_md_write(md, passphrase, sizep);
29
30                 if (len > size)
31                         len = size;
32                 memcpy(key, gcry_md_read(md, algo), len);
33
34                 key += len;
35                 size -= len;
36                 if (size)
37                         gcry_md_reset(md);
38         }
39
40         gcry_md_close(md);
41         return 0;
42 }
43
44 static struct hash_type *gcrypt_get_hashes(void)
45 {
46         struct hash_type *hashes;
47         int size = MAX_DIGESTS;
48         int *list;
49         int i;
50         gcry_error_t r;
51
52         if (!gcry_check_version(GCRYPT_REQ_VERSION))
53                 return NULL;
54
55         list = (int *)malloc(sizeof(*list) * size);
56         if (!list)
57                 return NULL;
58
59         r = gcry_md_list(list, &size);
60         if (r || !size) {
61                 free(list);
62                 return NULL;
63         }
64
65         hashes = malloc(sizeof(*hashes) * (size + 1));
66         if (!hashes) {
67                 free(list);
68                 return NULL;
69         }
70
71         for(i = 0; i < size; i++) {
72                 hashes[i].name = NULL;
73                 hashes[i].private = NULL;
74         }
75
76         for(i = 0; i < size; i++) {
77                 char *p;
78
79                 hashes[i].name = strdup(gcry_md_algo_name(list[i]));
80                 if(!hashes[i].name)
81                         goto err;
82                 for(p = (char *)hashes[i].name; *p; p++)
83                         *p = tolower(*p);
84                 hashes[i].private = malloc(sizeof(int));
85                 if(!hashes[i].private)
86                         goto err;
87                 *((int *)hashes[i].private) = list[i];
88                 hashes[i].fn = gcrypt_hash;
89         }
90         hashes[i].name = NULL;
91         hashes[i].private = NULL;
92         hashes[i].fn = NULL;
93
94         free(list);
95
96         return hashes;
97
98 err:
99         free(list);
100         for(i = 0; i < size; i++) {
101                 free(hashes[i].name);
102                 free(hashes[i].private);
103         }
104         free(hashes);
105         return NULL;
106 }
107
108 static void gcrypt_free_hashes(struct hash_type *hashes)
109 {
110         struct hash_type *hash;
111
112         for(hash = hashes; hash->name; hash++) {
113                 free(hash->name);
114                 free(hash->private);
115         }
116
117         free(hashes);
118 }
119
120 struct hash_backend hash_gcrypt_backend = {
121         .name = "libgcrypt",
122         .get_hashes = gcrypt_get_hashes,
123         .free_hashes = gcrypt_free_hashes
124 };