Require device device-mapper to build and do not use backend wrapper for dm calls.
[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
11 #ifdef USE_PLUGINS
12 static void init_plugins(void)
13 {
14 }
15 #else /* USE_PLUGINS */
16 #       define init_plugins()   do { } while(0)
17 #endif /* USE_PLUGINS */
18
19 static struct hash_backend *hash_backends[] = {
20 #ifdef BUILTIN_GCRYPT
21         &hash_gcrypt_backend,
22 #endif
23         NULL
24 };
25
26 struct hash_backend *get_hash_backend(const char *name)
27 {
28         struct hash_backend **backend;
29
30         init_plugins();
31
32         for(backend = hash_backends; *backend; backend++)
33                 if (!name || strcmp(name, (*backend)->name) == 0)
34                         break;
35
36         return *backend;
37 }
38
39 void put_hash_backend(struct hash_backend *backend)
40 {
41 }
42
43 int hash(const char *backend_name, const char *hash_name,
44          char *result, size_t size,
45          const char *passphrase, size_t sizep)
46 {
47         struct hash_backend *backend;
48         struct hash_type *hashes = NULL, *hash;
49         char hash_name_buf[256], *s;
50         size_t pad = 0;
51         int r = -ENOENT;
52
53         if (strlen(hash_name) >= sizeof(hash_name_buf)) {
54                 set_error("hash name too long: %s", hash_name);
55                 return -ENAMETOOLONG;
56         }
57
58         if ((s = strchr(hash_name, ':'))) {
59                 size_t hlen;
60                 strcpy(hash_name_buf, hash_name);
61                 hash_name_buf[s-hash_name] = '\0';
62                 hash_name = hash_name_buf;
63                 hlen = atoi(++s);
64                 if (hlen > size) {
65                         set_error("requested hash length (%zd) > key length (%zd)", hlen, size);
66                         return -EINVAL;
67                 }
68                 pad = size-hlen;
69                 size = hlen;
70         }
71
72         backend = get_hash_backend(backend_name);
73         if (!backend) {
74                 set_error("No hash backend found");
75                 return -ENOSYS;
76         }
77
78         hashes = backend->get_hashes();
79         if (!hashes) {
80                 set_error("No hash functions available");
81                 goto out;
82         }
83
84         for(hash = hashes; hash->name; hash++)
85                 if (strcmp(hash->name, hash_name) == 0)
86                         break;
87         if (!hash->name) {
88                 set_error("Unknown hash type %s", hash_name);
89                 goto out;
90         }
91
92         r = hash->fn(hash->private, size, result, sizep, passphrase);
93         if (r < 0) {
94                 set_error("Error hashing passphrase");
95                 goto out;
96         }
97
98         if (pad) {
99                 memset(result+size, 0, pad);
100         }
101
102 out:
103         if (hashes)
104                 backend->free_hashes(hashes);
105         put_hash_backend(backend);
106
107         return r;
108 }