tcplay - bring in
[dragonfly.git] / lib / libtcplay / tcplay_api.c
1 /*
2  * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
20  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <errno.h>
33
34 #include "tcplay.h"
35 #include "tcplay_api.h"
36
37 int
38 tc_api_init(int verbose)
39 {
40         int error;
41
42         tc_internal_verbose = verbose;
43
44         if ((error = tc_play_init()) != 0)
45                 return TC_ERR;
46         else
47                 return TC_OK;
48 }
49
50 int
51 tc_api_uninit(void)
52 {
53         check_and_purge_safe_mem();
54         return TC_OK;
55 }
56
57 const char *
58 tc_api_get_error_msg(void)
59 {
60         return tc_internal_log_buffer;
61 }
62
63 const char *
64 tc_api_get_summary(void)
65 {
66         if (summary_fn != NULL) {
67                 summary_fn();
68                 return tc_internal_log_buffer;
69         }
70
71         return NULL;
72 }
73
74 int
75 tc_api_create_volume(tc_api_opts *api_opts)
76 {
77         int nkeyfiles, n_hkeyfiles = 0;
78         int create_hidden;
79         int err;
80
81         if ((api_opts == NULL) ||
82             (api_opts->tc_device == NULL)) {
83                 errno = EFAULT;
84                 return TC_ERR;
85         }
86
87         if ((err = tc_api_check_cipher(api_opts)) != TC_OK)
88                 return TC_ERR;
89
90         if ((err = tc_api_check_prf_hash(api_opts)) != TC_OK)
91                 return TC_ERR;
92
93         for (nkeyfiles = 0; (nkeyfiles < MAX_KEYFILES) &&
94             (api_opts->tc_keyfiles != NULL) &&
95             (api_opts->tc_keyfiles[nkeyfiles] != NULL); nkeyfiles++)
96                 ;
97
98         create_hidden = 0;
99
100         if (api_opts->tc_size_hidden_in_blocks > 0) {
101                 create_hidden = 1;
102                 for (n_hkeyfiles = 0; (n_hkeyfiles < MAX_KEYFILES) &&
103                     (api_opts->tc_keyfiles_hidden != NULL) &&
104                     (api_opts->tc_keyfiles_hidden[n_hkeyfiles] != NULL);
105                     n_hkeyfiles++)
106                         ;
107         }
108
109         err = create_volume(api_opts->tc_device, create_hidden,
110             api_opts->tc_keyfiles, nkeyfiles,
111             api_opts->tc_keyfiles_hidden, n_hkeyfiles,
112             check_prf_algo(api_opts->tc_prf_hash, 1),
113             check_cipher_chain(api_opts->tc_cipher, 1),
114             check_prf_algo(api_opts->tc_prf_hash_hidden, 1),
115             check_cipher_chain(api_opts->tc_cipher_hidden, 1),
116             api_opts->tc_passphrase, api_opts->tc_passphrase_hidden,
117             api_opts->tc_size_hidden_in_blocks, 0 /* non-interactive */);
118
119         return (err) ? TC_ERR : TC_OK;
120 }
121
122 int
123 tc_api_map_volume(tc_api_opts *api_opts)
124 {
125         int nkeyfiles;
126         int err;
127
128         if ((api_opts == NULL) ||
129             (api_opts->tc_device == NULL)) {
130                 errno = EFAULT;
131                 return TC_ERR;
132         }
133
134         for (nkeyfiles = 0; (nkeyfiles < MAX_KEYFILES) &&
135             (api_opts->tc_keyfiles != NULL) &&
136             (api_opts->tc_keyfiles[nkeyfiles] != NULL); nkeyfiles++)
137                 ;
138
139         err = map_volume(api_opts->tc_map_name, api_opts->tc_device,
140             /* sflag */ 0, /* sys_dev */ NULL,
141             /* protect_hidden */ 0, api_opts->tc_keyfiles, nkeyfiles,
142             /* h_keyfiles[] */ NULL, /* n_hkeyfiles */ 0,
143             api_opts->tc_passphrase, /* passphrase_hidden */ NULL,
144             api_opts->tc_interactive_prompt, api_opts->tc_password_retries,
145             (time_t)api_opts->tc_prompt_timeout);
146
147         return (err) ? TC_ERR : TC_OK;
148 }
149
150 int
151 tc_api_unmap_volume(tc_api_opts *api_opts)
152 {
153         int err;
154
155         if ((api_opts == NULL) ||
156             (api_opts->tc_map_name == NULL)) {
157                 errno = EFAULT;
158                 return TC_ERR;
159         }
160
161         err = dm_teardown(api_opts->tc_map_name, api_opts->tc_device);
162         return (err) ? TC_ERR : TC_OK;
163 }
164
165 int
166 tc_api_check_cipher(tc_api_opts *api_opts)
167 {
168         struct tc_cipher_chain *chain;
169
170         if (api_opts == NULL || api_opts->tc_cipher == NULL) {
171                 errno = EFAULT;
172                 return TC_ERR;
173         }
174
175         if ((chain = check_cipher_chain(api_opts->tc_cipher, 1)) != NULL)
176                 return TC_OK;
177
178         errno = ENOENT;
179         return TC_ERR;
180 }
181
182 int
183 tc_api_check_prf_hash(tc_api_opts *api_opts)
184 {
185         struct pbkdf_prf_algo *prf_hash;
186
187         if (api_opts == NULL || api_opts->tc_prf_hash == NULL) {
188                 errno = EFAULT;
189                 return TC_ERR;
190         }
191
192         if ((prf_hash = check_prf_algo(api_opts->tc_prf_hash, 1)) != NULL)
193                 return TC_OK;
194
195         errno = ENOENT;
196         return TC_ERR;
197 }
198