Initial checking of what was revision 56 on http://luks.endorphin.org/svn/cryptsetup
[platform/upstream/cryptsetup.git] / lib / backends.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <errno.h>
5
6 #include "libcryptsetup.h"
7 #include "internal.h"
8
9 extern struct hash_backend hash_gcrypt_backend;
10 extern struct setup_backend setup_libdevmapper_backend;
11
12 #ifdef USE_PLUGINS
13 static void init_plugins(void)
14 {
15 }
16 #else /* USE_PLUGINS */
17 #       define init_plugins()   do { } while(0)
18 #endif /* USE_PLUGINS */
19
20 static struct hash_backend *hash_backends[] = {
21 #ifdef BUILTIN_GCRYPT
22         &hash_gcrypt_backend,
23 #endif
24         NULL
25 };
26
27 static struct setup_backend *setup_backends[] = {
28 #ifdef BUILTIN_LIBDEVMAPPER
29         &setup_libdevmapper_backend,
30 #endif
31         NULL
32 };
33
34 struct hash_backend *get_hash_backend(const char *name)
35 {
36         struct hash_backend **backend;
37
38         init_plugins();
39
40         for(backend = hash_backends; *backend; backend++)
41                 if (!name || strcmp(name, (*backend)->name) == 0)
42                         break;
43
44         return *backend;
45 }
46
47 void put_hash_backend(struct hash_backend *backend)
48 {
49 }
50
51 int hash(const char *backend_name, const char *hash_name,
52          char *result, size_t size,
53          const char *passphrase, size_t sizep)
54 {
55         struct hash_backend *backend;
56         struct hash_type *hashes = NULL, *hash;
57         char hash_name_buf[256], *s;
58         size_t pad = 0;
59         int r = -ENOENT;
60
61         if (strlen(hash_name) >= sizeof(hash_name_buf)) {
62                 set_error("hash name too long: %s", hash_name);
63                 return -ENAMETOOLONG;
64         }
65
66         if ((s = strchr(hash_name, ':'))) {
67                 size_t hlen;
68                 strcpy(hash_name_buf, hash_name);
69                 hash_name_buf[s-hash_name] = '\0';
70                 hash_name = hash_name_buf;
71                 hlen = atoi(++s);
72                 if (hlen > size) {
73                         set_error("requested hash length (%zd) > key length (%zd)", hlen, size);
74                         return -EINVAL;
75                 }
76                 pad = size-hlen;
77                 size = hlen;
78         }
79
80         backend = get_hash_backend(backend_name);
81         if (!backend) {
82                 set_error("No hash backend found");
83                 return -ENOSYS;
84         }
85
86         hashes = backend->get_hashes();
87         if (!hashes) {
88                 set_error("No hash functions available");
89                 goto out;
90         }
91
92         for(hash = hashes; hash->name; hash++)
93                 if (strcmp(hash->name, hash_name) == 0)
94                         break;
95         if (!hash->name) {
96                 set_error("Unknown hash type %s", hash_name);
97                 goto out;
98         }
99
100         r = hash->fn(hash->private, size, result, sizep, passphrase);
101         if (r < 0) {
102                 set_error("Error hashing passphrase");
103                 goto out;
104         }
105
106         if (pad) {
107                 memset(result+size, 0, pad);
108         }
109
110 out:
111         if (hashes)
112                 backend->free_hashes(hashes);
113         put_hash_backend(backend);
114
115         return r;
116 }
117
118 struct setup_backend *get_setup_backend(const char *name)
119 {
120         struct setup_backend **backend;
121
122         init_plugins();
123
124         for(backend = setup_backends; *backend; backend++)
125                 if (!name || strcmp(name, (*backend)->name) == 0)
126                         break;
127
128         return *backend;
129 }
130
131 void put_setup_backend(struct setup_backend *backend)
132 {
133 #ifdef USE_PLUGINS
134 #endif
135 }