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_bytes > 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_bytes, 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 199