xref: /dflybsd-src/contrib/cryptsetup/lib/setup.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino #include <string.h>
2*86d7f5d3SJohn Marino #include <stdio.h>
3*86d7f5d3SJohn Marino #include <stdlib.h>
4*86d7f5d3SJohn Marino #include <stdarg.h>
5*86d7f5d3SJohn Marino #include <fcntl.h>
6*86d7f5d3SJohn Marino #include <errno.h>
7*86d7f5d3SJohn Marino 
8*86d7f5d3SJohn Marino #include "libcryptsetup.h"
9*86d7f5d3SJohn Marino #include "luks.h"
10*86d7f5d3SJohn Marino #include "internal.h"
11*86d7f5d3SJohn Marino 
12*86d7f5d3SJohn Marino struct crypt_device {
13*86d7f5d3SJohn Marino 	char *type;
14*86d7f5d3SJohn Marino 
15*86d7f5d3SJohn Marino 	char *device;
16*86d7f5d3SJohn Marino 	struct luks_masterkey *volume_key;
17*86d7f5d3SJohn Marino 	uint64_t timeout;
18*86d7f5d3SJohn Marino 	uint64_t iteration_time;
19*86d7f5d3SJohn Marino 	int tries;
20*86d7f5d3SJohn Marino 	int password_verify;
21*86d7f5d3SJohn Marino 
22*86d7f5d3SJohn Marino 	/* used in CRYPT_LUKS1 */
23*86d7f5d3SJohn Marino 	struct luks_phdr hdr;
24*86d7f5d3SJohn Marino 	uint64_t PBKDF2_per_sec;
25*86d7f5d3SJohn Marino 
26*86d7f5d3SJohn Marino 	/* used in CRYPT_PLAIN */
27*86d7f5d3SJohn Marino 	struct crypt_params_plain plain_hdr;
28*86d7f5d3SJohn Marino 	char *plain_cipher;
29*86d7f5d3SJohn Marino 	char *plain_cipher_mode;
30*86d7f5d3SJohn Marino 	char *plain_uuid;
31*86d7f5d3SJohn Marino 
32*86d7f5d3SJohn Marino 	/* callbacks definitions */
33*86d7f5d3SJohn Marino 	void (*log)(int level, const char *msg, void *usrptr);
34*86d7f5d3SJohn Marino 	void *log_usrptr;
35*86d7f5d3SJohn Marino 	int (*confirm)(const char *msg, void *usrptr);
36*86d7f5d3SJohn Marino 	void *confirm_usrptr;
37*86d7f5d3SJohn Marino 	int (*password)(const char *msg, char *buf, size_t length, void *usrptr);
38*86d7f5d3SJohn Marino 	void *password_usrptr;
39*86d7f5d3SJohn Marino };
40*86d7f5d3SJohn Marino 
41*86d7f5d3SJohn Marino /* Log helper */
42*86d7f5d3SJohn Marino static void (*_default_log)(int level, const char *msg, void *usrptr) = NULL;
43*86d7f5d3SJohn Marino static int _debug_level = 0;
44*86d7f5d3SJohn Marino 
crypt_set_debug_level(int level)45*86d7f5d3SJohn Marino void crypt_set_debug_level(int level)
46*86d7f5d3SJohn Marino {
47*86d7f5d3SJohn Marino 	_debug_level = level;
48*86d7f5d3SJohn Marino }
49*86d7f5d3SJohn Marino 
crypt_get_debug_level()50*86d7f5d3SJohn Marino int crypt_get_debug_level()
51*86d7f5d3SJohn Marino {
52*86d7f5d3SJohn Marino 	return _debug_level;
53*86d7f5d3SJohn Marino }
54*86d7f5d3SJohn Marino 
crypt_log(struct crypt_device * cd,int level,const char * msg)55*86d7f5d3SJohn Marino void crypt_log(struct crypt_device *cd, int level, const char *msg)
56*86d7f5d3SJohn Marino {
57*86d7f5d3SJohn Marino 	if (cd && cd->log)
58*86d7f5d3SJohn Marino 		cd->log(level, msg, cd->log_usrptr);
59*86d7f5d3SJohn Marino 	else if (_default_log)
60*86d7f5d3SJohn Marino 		_default_log(level, msg, NULL);
61*86d7f5d3SJohn Marino }
62*86d7f5d3SJohn Marino 
logger(struct crypt_device * cd,int level,const char * file,int line,const char * format,...)63*86d7f5d3SJohn Marino void logger(struct crypt_device *cd, int level, const char *file,
64*86d7f5d3SJohn Marino 	    int line, const char *format, ...)
65*86d7f5d3SJohn Marino {
66*86d7f5d3SJohn Marino 	va_list argp;
67*86d7f5d3SJohn Marino 	char *target = NULL;
68*86d7f5d3SJohn Marino 
69*86d7f5d3SJohn Marino 	va_start(argp, format);
70*86d7f5d3SJohn Marino 
71*86d7f5d3SJohn Marino 	if (vasprintf(&target, format, argp) > 0) {
72*86d7f5d3SJohn Marino 		if (level >= 0) {
73*86d7f5d3SJohn Marino 			crypt_log(cd, level, target);
74*86d7f5d3SJohn Marino #ifdef CRYPT_DEBUG
75*86d7f5d3SJohn Marino 		} else if (_debug_level)
76*86d7f5d3SJohn Marino 			printf("# %s:%d %s\n", file ?: "?", line, target);
77*86d7f5d3SJohn Marino #else
78*86d7f5d3SJohn Marino 		} else if (_debug_level)
79*86d7f5d3SJohn Marino 			printf("# %s\n", target);
80*86d7f5d3SJohn Marino #endif
81*86d7f5d3SJohn Marino 	}
82*86d7f5d3SJohn Marino 
83*86d7f5d3SJohn Marino 	va_end(argp);
84*86d7f5d3SJohn Marino 	free(target);
85*86d7f5d3SJohn Marino }
86*86d7f5d3SJohn Marino 
87*86d7f5d3SJohn Marino /*
88*86d7f5d3SJohn Marino  * Password processing behaviour matrix of process_key
89*86d7f5d3SJohn Marino  *
90*86d7f5d3SJohn Marino  * from binary file: check if there is sufficently large key material
91*86d7f5d3SJohn Marino  * interactive & from fd: hash if requested, otherwise crop or pad with '0'
92*86d7f5d3SJohn Marino  */
process_key(struct crypt_device * cd,const char * hash_name,const char * key_file,size_t key_size,const char * pass,size_t passLen)93*86d7f5d3SJohn Marino static char *process_key(struct crypt_device *cd, const char *hash_name,
94*86d7f5d3SJohn Marino 			 const char *key_file, size_t key_size,
95*86d7f5d3SJohn Marino 			 const char *pass, size_t passLen)
96*86d7f5d3SJohn Marino {
97*86d7f5d3SJohn Marino 	char *key = safe_alloc(key_size);
98*86d7f5d3SJohn Marino 	memset(key, 0, key_size);
99*86d7f5d3SJohn Marino 
100*86d7f5d3SJohn Marino 	/* key is coming from binary file */
101*86d7f5d3SJohn Marino 	if (key_file && strcmp(key_file, "-")) {
102*86d7f5d3SJohn Marino 		if(passLen < key_size) {
103*86d7f5d3SJohn Marino 			log_err(cd, _("Cannot not read %d bytes from key file %s.\n"),
104*86d7f5d3SJohn Marino 				key_size, key_file);
105*86d7f5d3SJohn Marino 			safe_free(key);
106*86d7f5d3SJohn Marino 			return NULL;
107*86d7f5d3SJohn Marino 		}
108*86d7f5d3SJohn Marino 		memcpy(key, pass, key_size);
109*86d7f5d3SJohn Marino 		return key;
110*86d7f5d3SJohn Marino 	}
111*86d7f5d3SJohn Marino 
112*86d7f5d3SJohn Marino 	/* key is coming from tty, fd or binary stdin */
113*86d7f5d3SJohn Marino 	if (hash_name) {
114*86d7f5d3SJohn Marino 		if (hash(NULL, hash_name, key, key_size, pass, passLen) < 0) {
115*86d7f5d3SJohn Marino 			log_err(cd, _("Key processing error (using hash algorithm %s).\n"),
116*86d7f5d3SJohn Marino 				hash_name);
117*86d7f5d3SJohn Marino 			safe_free(key);
118*86d7f5d3SJohn Marino 			return NULL;
119*86d7f5d3SJohn Marino 		}
120*86d7f5d3SJohn Marino 	} else if (passLen > key_size) {
121*86d7f5d3SJohn Marino 		memcpy(key, pass, key_size);
122*86d7f5d3SJohn Marino 	} else {
123*86d7f5d3SJohn Marino 		memcpy(key, pass, passLen);
124*86d7f5d3SJohn Marino 	}
125*86d7f5d3SJohn Marino 
126*86d7f5d3SJohn Marino 	return key;
127*86d7f5d3SJohn Marino }
128*86d7f5d3SJohn Marino 
parse_into_name_and_mode(const char * nameAndMode,char * name,char * mode)129*86d7f5d3SJohn Marino int parse_into_name_and_mode(const char *nameAndMode, char *name, char *mode)
130*86d7f5d3SJohn Marino {
131*86d7f5d3SJohn Marino /* Token content stringification, see info cpp/stringification */
132*86d7f5d3SJohn Marino #define str(s) #s
133*86d7f5d3SJohn Marino #define xstr(s) str(s)
134*86d7f5d3SJohn Marino #define scanpattern1 "%" xstr(LUKS_CIPHERNAME_L) "[^-]-%" xstr(LUKS_CIPHERMODE_L)  "s"
135*86d7f5d3SJohn Marino #define scanpattern2 "%" xstr(LUKS_CIPHERNAME_L) "[^-]"
136*86d7f5d3SJohn Marino 
137*86d7f5d3SJohn Marino 	int r;
138*86d7f5d3SJohn Marino 
139*86d7f5d3SJohn Marino 	if(sscanf(nameAndMode,scanpattern1, name, mode) != 2) {
140*86d7f5d3SJohn Marino 		if((r = sscanf(nameAndMode,scanpattern2,name)) == 1)
141*86d7f5d3SJohn Marino 			strncpy(mode,"cbc-plain",10);
142*86d7f5d3SJohn Marino 		else
143*86d7f5d3SJohn Marino 			return -EINVAL;
144*86d7f5d3SJohn Marino 	}
145*86d7f5d3SJohn Marino 
146*86d7f5d3SJohn Marino 	return 0;
147*86d7f5d3SJohn Marino 
148*86d7f5d3SJohn Marino #undef scanpattern1
149*86d7f5d3SJohn Marino #undef scanpattern2
150*86d7f5d3SJohn Marino #undef str
151*86d7f5d3SJohn Marino #undef xstr
152*86d7f5d3SJohn Marino }
153*86d7f5d3SJohn Marino 
isPLAIN(const char * type)154*86d7f5d3SJohn Marino static int isPLAIN(const char *type)
155*86d7f5d3SJohn Marino {
156*86d7f5d3SJohn Marino 	return (type && !strcmp(CRYPT_PLAIN, type));
157*86d7f5d3SJohn Marino }
158*86d7f5d3SJohn Marino 
isLUKS(const char * type)159*86d7f5d3SJohn Marino static int isLUKS(const char *type)
160*86d7f5d3SJohn Marino {
161*86d7f5d3SJohn Marino 	return (type && !strcmp(CRYPT_LUKS1, type));
162*86d7f5d3SJohn Marino }
163*86d7f5d3SJohn Marino 
164*86d7f5d3SJohn Marino /* keyslot helpers */
keyslot_verify_or_find_empty(struct crypt_device * cd,int * keyslot)165*86d7f5d3SJohn Marino static int keyslot_verify_or_find_empty(struct crypt_device *cd, int *keyslot)
166*86d7f5d3SJohn Marino {
167*86d7f5d3SJohn Marino 	if (*keyslot == CRYPT_ANY_SLOT) {
168*86d7f5d3SJohn Marino 		*keyslot = LUKS_keyslot_find_empty(&cd->hdr);
169*86d7f5d3SJohn Marino 		if (*keyslot < 0) {
170*86d7f5d3SJohn Marino 			log_err(cd, _("All key slots full.\n"));
171*86d7f5d3SJohn Marino 			return -EINVAL;
172*86d7f5d3SJohn Marino 		}
173*86d7f5d3SJohn Marino 	}
174*86d7f5d3SJohn Marino 
175*86d7f5d3SJohn Marino 	switch (LUKS_keyslot_info(&cd->hdr, *keyslot)) {
176*86d7f5d3SJohn Marino 		case CRYPT_SLOT_INVALID:
177*86d7f5d3SJohn Marino 			log_err(cd, _("Key slot %d is invalid, please select between 0 and %d.\n"),
178*86d7f5d3SJohn Marino 				*keyslot, LUKS_NUMKEYS - 1);
179*86d7f5d3SJohn Marino 			return -EINVAL;
180*86d7f5d3SJohn Marino 		case CRYPT_SLOT_INACTIVE:
181*86d7f5d3SJohn Marino 			break;
182*86d7f5d3SJohn Marino 		default:
183*86d7f5d3SJohn Marino 			log_err(cd, _("Key slot %d is full, please select another one.\n"),
184*86d7f5d3SJohn Marino 				*keyslot);
185*86d7f5d3SJohn Marino 			return -EINVAL;
186*86d7f5d3SJohn Marino 	}
187*86d7f5d3SJohn Marino 
188*86d7f5d3SJohn Marino 	return 0;
189*86d7f5d3SJohn Marino }
190*86d7f5d3SJohn Marino 
verify_other_keyslot(struct crypt_device * cd,const char * key_file,unsigned int flags,int keyIndex)191*86d7f5d3SJohn Marino static int verify_other_keyslot(struct crypt_device *cd,
192*86d7f5d3SJohn Marino 				const char *key_file,
193*86d7f5d3SJohn Marino 				unsigned int flags,
194*86d7f5d3SJohn Marino 				int keyIndex)
195*86d7f5d3SJohn Marino {
196*86d7f5d3SJohn Marino 	struct luks_masterkey *mk;
197*86d7f5d3SJohn Marino 	crypt_keyslot_info ki;
198*86d7f5d3SJohn Marino 	int openedIndex;
199*86d7f5d3SJohn Marino 	char *password = NULL;
200*86d7f5d3SJohn Marino 	unsigned int passwordLen;
201*86d7f5d3SJohn Marino 
202*86d7f5d3SJohn Marino 	get_key(_("Enter any remaining LUKS passphrase: "), &password,
203*86d7f5d3SJohn Marino 		&passwordLen, 0, key_file, cd->timeout, flags, cd);
204*86d7f5d3SJohn Marino 	if(!password)
205*86d7f5d3SJohn Marino 		return -EINVAL;
206*86d7f5d3SJohn Marino 
207*86d7f5d3SJohn Marino 	ki = crypt_keyslot_status(cd, keyIndex);
208*86d7f5d3SJohn Marino 	if (ki == CRYPT_SLOT_ACTIVE) /* Not last slot */
209*86d7f5d3SJohn Marino 		LUKS_keyslot_set(&cd->hdr, keyIndex, 0);
210*86d7f5d3SJohn Marino 
211*86d7f5d3SJohn Marino 	openedIndex = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT,
212*86d7f5d3SJohn Marino 					     password, passwordLen,
213*86d7f5d3SJohn Marino 					     &cd->hdr, &mk, cd);
214*86d7f5d3SJohn Marino 
215*86d7f5d3SJohn Marino 	if (ki == CRYPT_SLOT_ACTIVE)
216*86d7f5d3SJohn Marino 		LUKS_keyslot_set(&cd->hdr, keyIndex, 1);
217*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
218*86d7f5d3SJohn Marino 	safe_free(password);
219*86d7f5d3SJohn Marino 
220*86d7f5d3SJohn Marino 	if (openedIndex < 0)
221*86d7f5d3SJohn Marino 		return -EPERM;
222*86d7f5d3SJohn Marino 
223*86d7f5d3SJohn Marino 	log_verbose(cd, _("Key slot %d verified.\n"), openedIndex);
224*86d7f5d3SJohn Marino 	return 0;
225*86d7f5d3SJohn Marino }
226*86d7f5d3SJohn Marino 
find_keyslot_by_passphrase(struct crypt_device * cd,const char * key_file,unsigned int flags,char * message)227*86d7f5d3SJohn Marino static int find_keyslot_by_passphrase(struct crypt_device *cd,
228*86d7f5d3SJohn Marino 				      const char *key_file,
229*86d7f5d3SJohn Marino 				      unsigned int flags,
230*86d7f5d3SJohn Marino 				      char *message)
231*86d7f5d3SJohn Marino {
232*86d7f5d3SJohn Marino 	struct luks_masterkey *mk;
233*86d7f5d3SJohn Marino 	char *password = NULL;
234*86d7f5d3SJohn Marino 	unsigned int passwordLen;
235*86d7f5d3SJohn Marino 	int keyIndex;
236*86d7f5d3SJohn Marino 
237*86d7f5d3SJohn Marino 	get_key(message,&password,&passwordLen, 0, key_file,
238*86d7f5d3SJohn Marino 		cd->timeout, flags, cd);
239*86d7f5d3SJohn Marino 	if(!password)
240*86d7f5d3SJohn Marino 		return -EINVAL;
241*86d7f5d3SJohn Marino 
242*86d7f5d3SJohn Marino 	keyIndex = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, password,
243*86d7f5d3SJohn Marino 					  passwordLen, &cd->hdr, &mk, cd);
244*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
245*86d7f5d3SJohn Marino 	safe_free(password);
246*86d7f5d3SJohn Marino 
247*86d7f5d3SJohn Marino 	return keyIndex;
248*86d7f5d3SJohn Marino }
249*86d7f5d3SJohn Marino 
device_check_and_adjust(struct crypt_device * cd,const char * device,uint64_t * size,uint64_t * offset,int * read_only)250*86d7f5d3SJohn Marino static int device_check_and_adjust(struct crypt_device *cd,
251*86d7f5d3SJohn Marino 				   const char *device,
252*86d7f5d3SJohn Marino 				   uint64_t *size, uint64_t *offset,
253*86d7f5d3SJohn Marino 				   int *read_only)
254*86d7f5d3SJohn Marino {
255*86d7f5d3SJohn Marino 	struct device_infos infos;
256*86d7f5d3SJohn Marino 
257*86d7f5d3SJohn Marino 	if (!device || get_device_infos(device, &infos, cd) < 0) {
258*86d7f5d3SJohn Marino 		log_err(cd, _("Cannot get info about device %s.\n"),
259*86d7f5d3SJohn Marino 			device ?: "[none]");
260*86d7f5d3SJohn Marino 		return -ENOTBLK;
261*86d7f5d3SJohn Marino 	}
262*86d7f5d3SJohn Marino 
263*86d7f5d3SJohn Marino 	if (!*size) {
264*86d7f5d3SJohn Marino 		*size = infos.size;
265*86d7f5d3SJohn Marino 		if (!*size) {
266*86d7f5d3SJohn Marino 			log_err(cd, _("Device %s has zero size.\n"), device);
267*86d7f5d3SJohn Marino 			return -ENOTBLK;
268*86d7f5d3SJohn Marino 		}
269*86d7f5d3SJohn Marino 		if (*size < *offset) {
270*86d7f5d3SJohn Marino 			log_err(cd, _("Device %s is too small.\n"), device);
271*86d7f5d3SJohn Marino 			return -EINVAL;
272*86d7f5d3SJohn Marino 		}
273*86d7f5d3SJohn Marino 		*size -= *offset;
274*86d7f5d3SJohn Marino 	}
275*86d7f5d3SJohn Marino 
276*86d7f5d3SJohn Marino 	if (infos.readonly)
277*86d7f5d3SJohn Marino 		*read_only = 1;
278*86d7f5d3SJohn Marino 
279*86d7f5d3SJohn Marino 	log_dbg("Calculated device size is %" PRIu64 " sectors (%s), offset %" PRIu64 ".",
280*86d7f5d3SJohn Marino 		*size, *read_only ? "RO" : "RW", *offset);
281*86d7f5d3SJohn Marino 	return 0;
282*86d7f5d3SJohn Marino }
283*86d7f5d3SJohn Marino 
luks_remove_helper(struct crypt_device * cd,int key_slot,const char * other_key_file,const char * key_file,int verify)284*86d7f5d3SJohn Marino static int luks_remove_helper(struct crypt_device *cd,
285*86d7f5d3SJohn Marino 			      int key_slot,
286*86d7f5d3SJohn Marino 			      const char *other_key_file,
287*86d7f5d3SJohn Marino 			      const char *key_file,
288*86d7f5d3SJohn Marino 			      int verify)
289*86d7f5d3SJohn Marino {
290*86d7f5d3SJohn Marino 	crypt_keyslot_info ki;
291*86d7f5d3SJohn Marino 	int r = -EINVAL;
292*86d7f5d3SJohn Marino 
293*86d7f5d3SJohn Marino 	if (key_slot == CRYPT_ANY_SLOT) {
294*86d7f5d3SJohn Marino 		key_slot = find_keyslot_by_passphrase(cd, key_file, 0,
295*86d7f5d3SJohn Marino 				_("Enter LUKS passphrase to be deleted: "));
296*86d7f5d3SJohn Marino 		if(key_slot < 0) {
297*86d7f5d3SJohn Marino 			r = -EPERM;
298*86d7f5d3SJohn Marino 			goto out;
299*86d7f5d3SJohn Marino 		}
300*86d7f5d3SJohn Marino 
301*86d7f5d3SJohn Marino 		log_std(cd, _("key slot %d selected for deletion.\n"), key_slot);
302*86d7f5d3SJohn Marino 	}
303*86d7f5d3SJohn Marino 
304*86d7f5d3SJohn Marino 	ki = crypt_keyslot_status(cd, key_slot);
305*86d7f5d3SJohn Marino 	if (ki == CRYPT_SLOT_INVALID) {
306*86d7f5d3SJohn Marino 		log_err(cd, _("Key slot %d is invalid, please select between 0 and %d.\n"),
307*86d7f5d3SJohn Marino 			key_slot, LUKS_NUMKEYS - 1);
308*86d7f5d3SJohn Marino 		r = -EINVAL;
309*86d7f5d3SJohn Marino 		goto out;
310*86d7f5d3SJohn Marino 	}
311*86d7f5d3SJohn Marino 	if (ki <= CRYPT_SLOT_INACTIVE) {
312*86d7f5d3SJohn Marino 		log_err(cd, _("Key %d not active. Can't wipe.\n"), key_slot);
313*86d7f5d3SJohn Marino 		r = -EINVAL;
314*86d7f5d3SJohn Marino 		goto out;
315*86d7f5d3SJohn Marino 	}
316*86d7f5d3SJohn Marino 
317*86d7f5d3SJohn Marino 	if (ki == CRYPT_SLOT_ACTIVE_LAST && cd->confirm &&
318*86d7f5d3SJohn Marino 	    !(cd->confirm(_("This is the last keyslot."
319*86d7f5d3SJohn Marino 			    " Device will become unusable after purging this key."),
320*86d7f5d3SJohn Marino 			 cd->confirm_usrptr))) {
321*86d7f5d3SJohn Marino 		r = -EINVAL;
322*86d7f5d3SJohn Marino 		goto out;
323*86d7f5d3SJohn Marino 	}
324*86d7f5d3SJohn Marino 
325*86d7f5d3SJohn Marino 	if(verify)
326*86d7f5d3SJohn Marino 		r = verify_other_keyslot(cd, other_key_file, 0, key_slot);
327*86d7f5d3SJohn Marino 	else
328*86d7f5d3SJohn Marino 		r = 0;
329*86d7f5d3SJohn Marino 
330*86d7f5d3SJohn Marino 	if (!r)
331*86d7f5d3SJohn Marino 		r = crypt_keyslot_destroy(cd, key_slot);
332*86d7f5d3SJohn Marino out:
333*86d7f5d3SJohn Marino 	return (r < 0) ? r : 0;
334*86d7f5d3SJohn Marino }
335*86d7f5d3SJohn Marino 
create_device_helper(struct crypt_device * cd,const char * name,const char * hash,const char * cipher,const char * cipher_mode,const char * key_file,const char * key,unsigned int keyLen,int key_size,uint64_t size,uint64_t skip,uint64_t offset,const char * uuid,int read_only,unsigned int flags,int reload)336*86d7f5d3SJohn Marino static int create_device_helper(struct crypt_device *cd,
337*86d7f5d3SJohn Marino 				const char *name,
338*86d7f5d3SJohn Marino 				const char *hash,
339*86d7f5d3SJohn Marino 				const char *cipher,
340*86d7f5d3SJohn Marino 				const char *cipher_mode,
341*86d7f5d3SJohn Marino 				const char *key_file,
342*86d7f5d3SJohn Marino 				const char *key,
343*86d7f5d3SJohn Marino 				unsigned int keyLen,
344*86d7f5d3SJohn Marino 				int key_size,
345*86d7f5d3SJohn Marino 				uint64_t size,
346*86d7f5d3SJohn Marino 				uint64_t skip,
347*86d7f5d3SJohn Marino 				uint64_t offset,
348*86d7f5d3SJohn Marino 				const char *uuid,
349*86d7f5d3SJohn Marino 				int read_only,
350*86d7f5d3SJohn Marino 				unsigned int flags,
351*86d7f5d3SJohn Marino 				int reload)
352*86d7f5d3SJohn Marino {
353*86d7f5d3SJohn Marino 	crypt_status_info ci;
354*86d7f5d3SJohn Marino 	char *dm_cipher = NULL;
355*86d7f5d3SJohn Marino 	char *processed_key = NULL;
356*86d7f5d3SJohn Marino 	int r;
357*86d7f5d3SJohn Marino 
358*86d7f5d3SJohn Marino 	ci = crypt_status(cd, name);
359*86d7f5d3SJohn Marino 	if (ci == CRYPT_INVALID)
360*86d7f5d3SJohn Marino 		return -EINVAL;
361*86d7f5d3SJohn Marino 
362*86d7f5d3SJohn Marino 	if (reload && ci < CRYPT_ACTIVE)
363*86d7f5d3SJohn Marino 		return -EINVAL;
364*86d7f5d3SJohn Marino 
365*86d7f5d3SJohn Marino 	if (!reload && ci >= CRYPT_ACTIVE) {
366*86d7f5d3SJohn Marino 		log_err(cd, _("Device %s already exists.\n"), name);
367*86d7f5d3SJohn Marino 		return -EEXIST;
368*86d7f5d3SJohn Marino 	}
369*86d7f5d3SJohn Marino 
370*86d7f5d3SJohn Marino 	if (key_size < 0 || key_size > 1024) {
371*86d7f5d3SJohn Marino 		log_err(cd, _("Invalid key size %d.\n"), key_size);
372*86d7f5d3SJohn Marino 		return -EINVAL;
373*86d7f5d3SJohn Marino 	}
374*86d7f5d3SJohn Marino 
375*86d7f5d3SJohn Marino 	r = device_check_and_adjust(cd, cd->device, &size, &offset, &read_only);
376*86d7f5d3SJohn Marino 	if (r)
377*86d7f5d3SJohn Marino 		return r;
378*86d7f5d3SJohn Marino 
379*86d7f5d3SJohn Marino 	if (cipher_mode && asprintf(&dm_cipher, "%s-%s", cipher, cipher_mode) < 0)
380*86d7f5d3SJohn Marino 		return -ENOMEM;
381*86d7f5d3SJohn Marino 
382*86d7f5d3SJohn Marino 	processed_key = process_key(cd, hash, key_file, key_size, key, keyLen);
383*86d7f5d3SJohn Marino 	if (!processed_key)
384*86d7f5d3SJohn Marino 		return -ENOENT;
385*86d7f5d3SJohn Marino 
386*86d7f5d3SJohn Marino 	r = dm_create_device(name, cd->device, dm_cipher ?: cipher, cd->type, uuid, size, skip, offset,
387*86d7f5d3SJohn Marino 			     key_size, processed_key, read_only, reload);
388*86d7f5d3SJohn Marino 
389*86d7f5d3SJohn Marino 	free(dm_cipher);
390*86d7f5d3SJohn Marino 	safe_free(processed_key);
391*86d7f5d3SJohn Marino 	return r;
392*86d7f5d3SJohn Marino }
393*86d7f5d3SJohn Marino 
open_from_hdr_and_mk(struct crypt_device * cd,struct luks_masterkey * mk,const char * name,uint32_t flags)394*86d7f5d3SJohn Marino static int open_from_hdr_and_mk(struct crypt_device *cd,
395*86d7f5d3SJohn Marino 				struct luks_masterkey *mk,
396*86d7f5d3SJohn Marino 				const char *name,
397*86d7f5d3SJohn Marino 				uint32_t flags)
398*86d7f5d3SJohn Marino {
399*86d7f5d3SJohn Marino 	uint64_t size, offset;
400*86d7f5d3SJohn Marino 	char *cipher;
401*86d7f5d3SJohn Marino 	int read_only, no_uuid, r;
402*86d7f5d3SJohn Marino 
403*86d7f5d3SJohn Marino 	size = 0;
404*86d7f5d3SJohn Marino 	offset = crypt_get_data_offset(cd);
405*86d7f5d3SJohn Marino 	read_only = flags & CRYPT_ACTIVATE_READONLY;
406*86d7f5d3SJohn Marino 	no_uuid = flags & CRYPT_ACTIVATE_NO_UUID;
407*86d7f5d3SJohn Marino 
408*86d7f5d3SJohn Marino 	r = device_check_and_adjust(cd, cd->device, &size, &offset, &read_only);
409*86d7f5d3SJohn Marino 	if (r)
410*86d7f5d3SJohn Marino 		return r;
411*86d7f5d3SJohn Marino 
412*86d7f5d3SJohn Marino 	if (asprintf(&cipher, "%s-%s", crypt_get_cipher(cd),
413*86d7f5d3SJohn Marino 		     crypt_get_cipher_mode(cd)) < 0)
414*86d7f5d3SJohn Marino 		r = -ENOMEM;
415*86d7f5d3SJohn Marino 	else
416*86d7f5d3SJohn Marino 		r = dm_create_device(name, cd->device, cipher, cd->type,
417*86d7f5d3SJohn Marino 				     no_uuid ? NULL : crypt_get_uuid(cd),
418*86d7f5d3SJohn Marino 				     size, 0, offset, mk->keyLength, mk->key,
419*86d7f5d3SJohn Marino 				     read_only, 0);
420*86d7f5d3SJohn Marino 	free(cipher);
421*86d7f5d3SJohn Marino 	return r;
422*86d7f5d3SJohn Marino }
423*86d7f5d3SJohn Marino 
log_wrapper(int level,const char * msg,void * usrptr)424*86d7f5d3SJohn Marino static void log_wrapper(int level, const char *msg, void *usrptr)
425*86d7f5d3SJohn Marino {
426*86d7f5d3SJohn Marino 	void (*xlog)(int level, char *msg) = usrptr;
427*86d7f5d3SJohn Marino 	xlog(level, (char *)msg);
428*86d7f5d3SJohn Marino }
429*86d7f5d3SJohn Marino 
yesDialog_wrapper(const char * msg,void * usrptr)430*86d7f5d3SJohn Marino static int yesDialog_wrapper(const char *msg, void *usrptr)
431*86d7f5d3SJohn Marino {
432*86d7f5d3SJohn Marino 	int (*xyesDialog)(char *msg) = usrptr;
433*86d7f5d3SJohn Marino 	return xyesDialog((char*)msg);
434*86d7f5d3SJohn Marino }
435*86d7f5d3SJohn Marino 
crypt_confirm(struct crypt_device * cd,const char * msg)436*86d7f5d3SJohn Marino int crypt_confirm(struct crypt_device *cd, const char *msg)
437*86d7f5d3SJohn Marino {
438*86d7f5d3SJohn Marino 	if (!cd || !cd->confirm)
439*86d7f5d3SJohn Marino 		return 1;
440*86d7f5d3SJohn Marino 	else
441*86d7f5d3SJohn Marino 		return cd->confirm(msg, cd->confirm_usrptr);
442*86d7f5d3SJohn Marino }
443*86d7f5d3SJohn Marino 
key_from_terminal(struct crypt_device * cd,char * msg,char ** key,unsigned int * key_len,int force_verify)444*86d7f5d3SJohn Marino static void key_from_terminal(struct crypt_device *cd, char *msg, char **key,
445*86d7f5d3SJohn Marino 			      unsigned int *key_len, int force_verify)
446*86d7f5d3SJohn Marino {
447*86d7f5d3SJohn Marino 	int r, flags = 0;
448*86d7f5d3SJohn Marino 
449*86d7f5d3SJohn Marino 	if (cd->password) {
450*86d7f5d3SJohn Marino 		*key = safe_alloc(MAX_TTY_PASSWORD_LEN);
451*86d7f5d3SJohn Marino 		if (*key)
452*86d7f5d3SJohn Marino 			return;
453*86d7f5d3SJohn Marino 		r = cd->password(msg, *key, (size_t)key_len, cd->password_usrptr);
454*86d7f5d3SJohn Marino 		if (r < 0) {
455*86d7f5d3SJohn Marino 			safe_free(*key);
456*86d7f5d3SJohn Marino 			*key = NULL;
457*86d7f5d3SJohn Marino 		} else
458*86d7f5d3SJohn Marino 			*key_len = r;
459*86d7f5d3SJohn Marino 	} else {
460*86d7f5d3SJohn Marino 		if (force_verify || cd->password_verify)
461*86d7f5d3SJohn Marino 			flags |= CRYPT_FLAG_VERIFY_IF_POSSIBLE;
462*86d7f5d3SJohn Marino 		get_key(msg, key, key_len, 0, NULL, cd->timeout, flags, cd);
463*86d7f5d3SJohn Marino 	}
464*86d7f5d3SJohn Marino }
465*86d7f5d3SJohn Marino 
volume_key_by_terminal_passphrase(struct crypt_device * cd,int keyslot,struct luks_masterkey ** mk)466*86d7f5d3SJohn Marino static int volume_key_by_terminal_passphrase(struct crypt_device *cd, int keyslot,
467*86d7f5d3SJohn Marino 					     struct luks_masterkey **mk)
468*86d7f5d3SJohn Marino {
469*86d7f5d3SJohn Marino 	char *prompt = NULL, *passphrase_read = NULL;
470*86d7f5d3SJohn Marino 	unsigned int passphrase_size_read;
471*86d7f5d3SJohn Marino 	int r = -EINVAL, tries = cd->tries;
472*86d7f5d3SJohn Marino 
473*86d7f5d3SJohn Marino 	if(asprintf(&prompt, _("Enter passphrase for %s: "), cd->device) < 0)
474*86d7f5d3SJohn Marino 		return -ENOMEM;
475*86d7f5d3SJohn Marino 
476*86d7f5d3SJohn Marino 	*mk = NULL;
477*86d7f5d3SJohn Marino 	do {
478*86d7f5d3SJohn Marino 		if (*mk)
479*86d7f5d3SJohn Marino 			LUKS_dealloc_masterkey(*mk);
480*86d7f5d3SJohn Marino 		*mk = NULL;
481*86d7f5d3SJohn Marino 
482*86d7f5d3SJohn Marino 		key_from_terminal(cd, prompt, &passphrase_read,
483*86d7f5d3SJohn Marino 				  &passphrase_size_read, 0);
484*86d7f5d3SJohn Marino 		if(!passphrase_read) {
485*86d7f5d3SJohn Marino 			r = -EINVAL;
486*86d7f5d3SJohn Marino 			break;
487*86d7f5d3SJohn Marino 		}
488*86d7f5d3SJohn Marino 
489*86d7f5d3SJohn Marino 		r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase_read,
490*86d7f5d3SJohn Marino 					   passphrase_size_read, &cd->hdr, mk, cd);
491*86d7f5d3SJohn Marino 		safe_free(passphrase_read);
492*86d7f5d3SJohn Marino 		passphrase_read = NULL;
493*86d7f5d3SJohn Marino 	} while (r == -EPERM && (--tries > 0));
494*86d7f5d3SJohn Marino 
495*86d7f5d3SJohn Marino 	if (r < 0 && *mk) {
496*86d7f5d3SJohn Marino 		LUKS_dealloc_masterkey(*mk);
497*86d7f5d3SJohn Marino 		*mk = NULL;
498*86d7f5d3SJohn Marino 	}
499*86d7f5d3SJohn Marino 	free(prompt);
500*86d7f5d3SJohn Marino 
501*86d7f5d3SJohn Marino 	return r;
502*86d7f5d3SJohn Marino 
503*86d7f5d3SJohn Marino }
504*86d7f5d3SJohn Marino 
key_from_file(struct crypt_device * cd,char * msg,char ** key,unsigned int * key_len,const char * key_file,size_t key_size)505*86d7f5d3SJohn Marino static void key_from_file(struct crypt_device *cd, char *msg,
506*86d7f5d3SJohn Marino 			  char **key, unsigned int *key_len,
507*86d7f5d3SJohn Marino 			  const char *key_file, size_t key_size)
508*86d7f5d3SJohn Marino {
509*86d7f5d3SJohn Marino 	get_key(msg, key, key_len, key_size, key_file, cd->timeout, 0, cd);
510*86d7f5d3SJohn Marino }
511*86d7f5d3SJohn Marino 
_crypt_init(struct crypt_device ** cd,const char * type,struct crypt_options * options,int load,int need_dm)512*86d7f5d3SJohn Marino static int _crypt_init(struct crypt_device **cd,
513*86d7f5d3SJohn Marino 		       const char *type,
514*86d7f5d3SJohn Marino 		       struct crypt_options *options,
515*86d7f5d3SJohn Marino 		       int load, int need_dm)
516*86d7f5d3SJohn Marino {
517*86d7f5d3SJohn Marino 	int init_by_name, r;
518*86d7f5d3SJohn Marino 
519*86d7f5d3SJohn Marino 	/* if it is plain device and mapping table is being reloaded
520*86d7f5d3SJohn Marino 	initialize it by name*/
521*86d7f5d3SJohn Marino 	init_by_name = (type && !strcmp(type, CRYPT_PLAIN) && load);
522*86d7f5d3SJohn Marino 
523*86d7f5d3SJohn Marino 	/* Some of old API calls do not require DM in kernel,
524*86d7f5d3SJohn Marino 	   fake initialisation by initialise it with kernel_check disabled */
525*86d7f5d3SJohn Marino 	if (!need_dm)
526*86d7f5d3SJohn Marino 		(void)dm_init(NULL, 0);
527*86d7f5d3SJohn Marino 	if (init_by_name)
528*86d7f5d3SJohn Marino 		r = crypt_init_by_name(cd, options->name);
529*86d7f5d3SJohn Marino 	else
530*86d7f5d3SJohn Marino 		r = crypt_init(cd, options->device);
531*86d7f5d3SJohn Marino 	if (!need_dm)
532*86d7f5d3SJohn Marino 		dm_exit();
533*86d7f5d3SJohn Marino 
534*86d7f5d3SJohn Marino 	if (r)
535*86d7f5d3SJohn Marino 		return -EINVAL;
536*86d7f5d3SJohn Marino 
537*86d7f5d3SJohn Marino 	crypt_set_log_callback(*cd, log_wrapper, options->icb->log);
538*86d7f5d3SJohn Marino 	crypt_set_confirm_callback(*cd, yesDialog_wrapper, options->icb->yesDialog);
539*86d7f5d3SJohn Marino 
540*86d7f5d3SJohn Marino 	crypt_set_timeout(*cd, options->timeout);
541*86d7f5d3SJohn Marino 	crypt_set_password_retry(*cd, options->tries);
542*86d7f5d3SJohn Marino 	crypt_set_iterarion_time(*cd, options->iteration_time ?: 1000);
543*86d7f5d3SJohn Marino 	crypt_set_password_verify(*cd, options->flags & CRYPT_FLAG_VERIFY);
544*86d7f5d3SJohn Marino 
545*86d7f5d3SJohn Marino 	if (load && !init_by_name)
546*86d7f5d3SJohn Marino 		r = crypt_load(*cd, type, NULL);
547*86d7f5d3SJohn Marino 
548*86d7f5d3SJohn Marino 	if (!r && type && !(*cd)->type) {
549*86d7f5d3SJohn Marino 		(*cd)->type = strdup(type);
550*86d7f5d3SJohn Marino 		if (!(*cd)->type)
551*86d7f5d3SJohn Marino 			r = -ENOMEM;
552*86d7f5d3SJohn Marino 	}
553*86d7f5d3SJohn Marino 
554*86d7f5d3SJohn Marino 	if (r)
555*86d7f5d3SJohn Marino 		crypt_free(*cd);
556*86d7f5d3SJohn Marino 
557*86d7f5d3SJohn Marino 	return r;
558*86d7f5d3SJohn Marino }
559*86d7f5d3SJohn Marino 
crypt_set_log_callback(struct crypt_device * cd,void (* log)(int level,const char * msg,void * usrptr),void * usrptr)560*86d7f5d3SJohn Marino void crypt_set_log_callback(struct crypt_device *cd,
561*86d7f5d3SJohn Marino 	void (*log)(int level, const char *msg, void *usrptr),
562*86d7f5d3SJohn Marino 	void *usrptr)
563*86d7f5d3SJohn Marino {
564*86d7f5d3SJohn Marino 	if (!cd)
565*86d7f5d3SJohn Marino 		_default_log = log;
566*86d7f5d3SJohn Marino 	else {
567*86d7f5d3SJohn Marino 		cd->log = log;
568*86d7f5d3SJohn Marino 		cd->log_usrptr = usrptr;
569*86d7f5d3SJohn Marino 	}
570*86d7f5d3SJohn Marino }
571*86d7f5d3SJohn Marino 
crypt_set_confirm_callback(struct crypt_device * cd,int (* confirm)(const char * msg,void * usrptr),void * usrptr)572*86d7f5d3SJohn Marino void crypt_set_confirm_callback(struct crypt_device *cd,
573*86d7f5d3SJohn Marino 	int (*confirm)(const char *msg, void *usrptr),
574*86d7f5d3SJohn Marino 	void *usrptr)
575*86d7f5d3SJohn Marino {
576*86d7f5d3SJohn Marino 	cd->confirm = confirm;
577*86d7f5d3SJohn Marino 	cd->confirm_usrptr = usrptr;
578*86d7f5d3SJohn Marino }
579*86d7f5d3SJohn Marino 
crypt_set_password_callback(struct crypt_device * cd,int (* password)(const char * msg,char * buf,size_t length,void * usrptr),void * usrptr)580*86d7f5d3SJohn Marino void crypt_set_password_callback(struct crypt_device *cd,
581*86d7f5d3SJohn Marino 	int (*password)(const char *msg, char *buf, size_t length, void *usrptr),
582*86d7f5d3SJohn Marino 	void *usrptr)
583*86d7f5d3SJohn Marino {
584*86d7f5d3SJohn Marino 	cd->password = password;
585*86d7f5d3SJohn Marino 	cd->password_usrptr = usrptr;
586*86d7f5d3SJohn Marino }
587*86d7f5d3SJohn Marino 
588*86d7f5d3SJohn Marino /* OPTIONS: name, cipher, device, hash, key_file, key_size, key_slot,
589*86d7f5d3SJohn Marino  *          offset, size, skip, timeout, tries, passphrase_fd (ignored),
590*86d7f5d3SJohn Marino  *          flags, icb */
crypt_create_and_update_device(struct crypt_options * options,int update)591*86d7f5d3SJohn Marino static int crypt_create_and_update_device(struct crypt_options *options, int update)
592*86d7f5d3SJohn Marino {
593*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
594*86d7f5d3SJohn Marino 	char *key = NULL;
595*86d7f5d3SJohn Marino 	unsigned int keyLen;
596*86d7f5d3SJohn Marino 	int r;
597*86d7f5d3SJohn Marino 
598*86d7f5d3SJohn Marino 	r = _crypt_init(&cd, CRYPT_PLAIN, options, 0, 1);
599*86d7f5d3SJohn Marino 	if (r)
600*86d7f5d3SJohn Marino 		return r;
601*86d7f5d3SJohn Marino 
602*86d7f5d3SJohn Marino 	get_key(_("Enter passphrase: "), &key, &keyLen, options->key_size,
603*86d7f5d3SJohn Marino 		options->key_file, cd->timeout, options->flags, cd);
604*86d7f5d3SJohn Marino 	if (!key)
605*86d7f5d3SJohn Marino 		r = -ENOENT;
606*86d7f5d3SJohn Marino 	else
607*86d7f5d3SJohn Marino 		r = create_device_helper(cd, options->name, options->hash,
608*86d7f5d3SJohn Marino 			options->cipher, NULL, options->key_file, key, keyLen,
609*86d7f5d3SJohn Marino 			options->key_size, options->size, options->skip,
610*86d7f5d3SJohn Marino 			options->offset, NULL, options->flags & CRYPT_FLAG_READONLY,
611*86d7f5d3SJohn Marino 			options->flags, update);
612*86d7f5d3SJohn Marino 
613*86d7f5d3SJohn Marino 	safe_free(key);
614*86d7f5d3SJohn Marino 	crypt_free(cd);
615*86d7f5d3SJohn Marino 	return r;
616*86d7f5d3SJohn Marino }
617*86d7f5d3SJohn Marino 
crypt_create_device(struct crypt_options * options)618*86d7f5d3SJohn Marino int crypt_create_device(struct crypt_options *options)
619*86d7f5d3SJohn Marino {
620*86d7f5d3SJohn Marino 	return crypt_create_and_update_device(options, 0);
621*86d7f5d3SJohn Marino }
622*86d7f5d3SJohn Marino 
crypt_update_device(struct crypt_options * options)623*86d7f5d3SJohn Marino int crypt_update_device(struct crypt_options *options)
624*86d7f5d3SJohn Marino {
625*86d7f5d3SJohn Marino 	return crypt_create_and_update_device(options, 1);
626*86d7f5d3SJohn Marino }
627*86d7f5d3SJohn Marino 
628*86d7f5d3SJohn Marino /* OPTIONS: name, size, icb */
crypt_resize_device(struct crypt_options * options)629*86d7f5d3SJohn Marino int crypt_resize_device(struct crypt_options *options)
630*86d7f5d3SJohn Marino {
631*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
632*86d7f5d3SJohn Marino 	char *device = NULL, *cipher = NULL, *uuid = NULL, *key = NULL;
633*86d7f5d3SJohn Marino 	char *type = NULL;
634*86d7f5d3SJohn Marino 	uint64_t size, skip, offset;
635*86d7f5d3SJohn Marino 	int key_size, read_only, r;
636*86d7f5d3SJohn Marino 
637*86d7f5d3SJohn Marino 	log_dbg("Resizing device %s to %" PRIu64 " sectors.", options->name, options->size);
638*86d7f5d3SJohn Marino 
639*86d7f5d3SJohn Marino 	if (dm_init(NULL, 1) < 0)
640*86d7f5d3SJohn Marino 		return -ENOSYS;
641*86d7f5d3SJohn Marino 
642*86d7f5d3SJohn Marino 	r = dm_query_device(options->name, &device, &size, &skip, &offset,
643*86d7f5d3SJohn Marino 			    &cipher, &key_size, &key, &read_only, NULL, &uuid);
644*86d7f5d3SJohn Marino 	if (r < 0) {
645*86d7f5d3SJohn Marino 		log_err(NULL, _("Device %s is not active.\n"), options->name);
646*86d7f5d3SJohn Marino 		goto out;
647*86d7f5d3SJohn Marino 	}
648*86d7f5d3SJohn Marino 
649*86d7f5d3SJohn Marino 	/* Try to determine type of device from UUID */
650*86d7f5d3SJohn Marino 	type = CRYPT_PLAIN;
651*86d7f5d3SJohn Marino 	if (uuid) {
652*86d7f5d3SJohn Marino 		if (!strncmp(uuid, CRYPT_PLAIN, strlen(CRYPT_PLAIN))) {
653*86d7f5d3SJohn Marino 			type = CRYPT_PLAIN;
654*86d7f5d3SJohn Marino 			free (uuid);
655*86d7f5d3SJohn Marino 			uuid = NULL;
656*86d7f5d3SJohn Marino 		} else if (!strncmp(uuid, CRYPT_LUKS1, strlen(CRYPT_LUKS1)))
657*86d7f5d3SJohn Marino 			type = CRYPT_LUKS1;
658*86d7f5d3SJohn Marino 	}
659*86d7f5d3SJohn Marino 
660*86d7f5d3SJohn Marino 	if (!options->device)
661*86d7f5d3SJohn Marino 		options->device = device;
662*86d7f5d3SJohn Marino 
663*86d7f5d3SJohn Marino 	r = _crypt_init(&cd, type, options, 1, 1);
664*86d7f5d3SJohn Marino 	if (r)
665*86d7f5d3SJohn Marino 		goto out;
666*86d7f5d3SJohn Marino 
667*86d7f5d3SJohn Marino 	size = options->size;
668*86d7f5d3SJohn Marino 	r = device_check_and_adjust(cd, device, &size, &offset, &read_only);
669*86d7f5d3SJohn Marino 	if (r)
670*86d7f5d3SJohn Marino 		goto out;
671*86d7f5d3SJohn Marino 
672*86d7f5d3SJohn Marino 	r = dm_create_device(options->name, device, cipher, type,
673*86d7f5d3SJohn Marino 			     crypt_get_uuid(cd), size, skip, offset,
674*86d7f5d3SJohn Marino 			     key_size, key, read_only, 1);
675*86d7f5d3SJohn Marino out:
676*86d7f5d3SJohn Marino 	safe_free(key);
677*86d7f5d3SJohn Marino 	free(cipher);
678*86d7f5d3SJohn Marino 	if (options->device == device)
679*86d7f5d3SJohn Marino 		options->device = NULL;
680*86d7f5d3SJohn Marino 	free(device);
681*86d7f5d3SJohn Marino 	free(uuid);
682*86d7f5d3SJohn Marino 	crypt_free(cd);
683*86d7f5d3SJohn Marino 	dm_exit();
684*86d7f5d3SJohn Marino 	return r;
685*86d7f5d3SJohn Marino }
686*86d7f5d3SJohn Marino 
687*86d7f5d3SJohn Marino /* OPTIONS: name, icb */
crypt_query_device(struct crypt_options * options)688*86d7f5d3SJohn Marino int crypt_query_device(struct crypt_options *options)
689*86d7f5d3SJohn Marino {
690*86d7f5d3SJohn Marino 	int read_only, r;
691*86d7f5d3SJohn Marino 
692*86d7f5d3SJohn Marino 	log_dbg("Query device %s.", options->name);
693*86d7f5d3SJohn Marino 
694*86d7f5d3SJohn Marino 	if (dm_init(NULL, 1) < 0)
695*86d7f5d3SJohn Marino 		return -ENOSYS;
696*86d7f5d3SJohn Marino 
697*86d7f5d3SJohn Marino 	r = dm_status_device(options->name);
698*86d7f5d3SJohn Marino 	if (r == -ENODEV) {
699*86d7f5d3SJohn Marino 		dm_exit();
700*86d7f5d3SJohn Marino 		return 0;
701*86d7f5d3SJohn Marino 	}
702*86d7f5d3SJohn Marino 
703*86d7f5d3SJohn Marino 	r = dm_query_device(options->name, (char **)&options->device, &options->size,
704*86d7f5d3SJohn Marino 			    &options->skip, &options->offset, (char **)&options->cipher,
705*86d7f5d3SJohn Marino 			    &options->key_size, NULL, &read_only, NULL, NULL);
706*86d7f5d3SJohn Marino 
707*86d7f5d3SJohn Marino 	dm_exit();
708*86d7f5d3SJohn Marino 	if (r < 0)
709*86d7f5d3SJohn Marino 		return r;
710*86d7f5d3SJohn Marino 
711*86d7f5d3SJohn Marino 	if (read_only)
712*86d7f5d3SJohn Marino 		options->flags |= CRYPT_FLAG_READONLY;
713*86d7f5d3SJohn Marino 
714*86d7f5d3SJohn Marino 	options->flags |= CRYPT_FLAG_FREE_DEVICE;
715*86d7f5d3SJohn Marino 	options->flags |= CRYPT_FLAG_FREE_CIPHER;
716*86d7f5d3SJohn Marino 
717*86d7f5d3SJohn Marino 	return 1;
718*86d7f5d3SJohn Marino }
719*86d7f5d3SJohn Marino 
720*86d7f5d3SJohn Marino /* OPTIONS: name, icb */
crypt_remove_device(struct crypt_options * options)721*86d7f5d3SJohn Marino int crypt_remove_device(struct crypt_options *options)
722*86d7f5d3SJohn Marino {
723*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
724*86d7f5d3SJohn Marino 	int r;
725*86d7f5d3SJohn Marino 
726*86d7f5d3SJohn Marino 	r = crypt_init_by_name(&cd, options->name);
727*86d7f5d3SJohn Marino 	if (r == 0)
728*86d7f5d3SJohn Marino 		r = crypt_deactivate(cd, options->name);
729*86d7f5d3SJohn Marino 
730*86d7f5d3SJohn Marino 	crypt_free(cd);
731*86d7f5d3SJohn Marino 	return r;
732*86d7f5d3SJohn Marino 
733*86d7f5d3SJohn Marino }
734*86d7f5d3SJohn Marino 
735*86d7f5d3SJohn Marino /* OPTIONS: device, cipher, hash, align_payload, key_size (master key), key_slot
736*86d7f5d3SJohn Marino  *          new_key_file, iteration_time, timeout, flags, icb */
crypt_luksFormat(struct crypt_options * options)737*86d7f5d3SJohn Marino int crypt_luksFormat(struct crypt_options *options)
738*86d7f5d3SJohn Marino {
739*86d7f5d3SJohn Marino 	char cipherName[LUKS_CIPHERNAME_L];
740*86d7f5d3SJohn Marino 	char cipherMode[LUKS_CIPHERMODE_L];
741*86d7f5d3SJohn Marino 	char *password=NULL;
742*86d7f5d3SJohn Marino 	unsigned int passwordLen;
743*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
744*86d7f5d3SJohn Marino 	struct crypt_params_luks1 cp = {
745*86d7f5d3SJohn Marino 		.hash = options->hash,
746*86d7f5d3SJohn Marino 		.data_alignment = options->align_payload
747*86d7f5d3SJohn Marino 	};
748*86d7f5d3SJohn Marino 	int r;
749*86d7f5d3SJohn Marino 
750*86d7f5d3SJohn Marino 	r = parse_into_name_and_mode(options->cipher, cipherName, cipherMode);
751*86d7f5d3SJohn Marino 	if(r < 0) {
752*86d7f5d3SJohn Marino 		log_err(cd, _("No known cipher specification pattern detected.\n"));
753*86d7f5d3SJohn Marino 		return r;
754*86d7f5d3SJohn Marino 	}
755*86d7f5d3SJohn Marino 
756*86d7f5d3SJohn Marino 	if ((r = _crypt_init(&cd, CRYPT_LUKS1, options, 0, 1)))
757*86d7f5d3SJohn Marino 		return r;
758*86d7f5d3SJohn Marino 
759*86d7f5d3SJohn Marino 	if (options->key_slot >= LUKS_NUMKEYS && options->key_slot != CRYPT_ANY_SLOT) {
760*86d7f5d3SJohn Marino 		log_err(cd, _("Key slot %d is invalid, please select between 0 and %d.\n"),
761*86d7f5d3SJohn Marino 			options->key_slot, LUKS_NUMKEYS - 1);
762*86d7f5d3SJohn Marino 		r = -EINVAL;
763*86d7f5d3SJohn Marino 		goto out;
764*86d7f5d3SJohn Marino 	}
765*86d7f5d3SJohn Marino 
766*86d7f5d3SJohn Marino 	get_key(_("Enter LUKS passphrase: "), &password, &passwordLen, 0,
767*86d7f5d3SJohn Marino 		options->new_key_file, options->timeout, options->flags, cd);
768*86d7f5d3SJohn Marino 
769*86d7f5d3SJohn Marino 	if(!password) {
770*86d7f5d3SJohn Marino 		r = -EINVAL;
771*86d7f5d3SJohn Marino 		goto out;
772*86d7f5d3SJohn Marino 	}
773*86d7f5d3SJohn Marino 
774*86d7f5d3SJohn Marino 	r = crypt_format(cd, CRYPT_LUKS1, cipherName, cipherMode,
775*86d7f5d3SJohn Marino 			 NULL, NULL, options->key_size, &cp);
776*86d7f5d3SJohn Marino 	if (r < 0)
777*86d7f5d3SJohn Marino 		goto out;
778*86d7f5d3SJohn Marino 
779*86d7f5d3SJohn Marino 	/* Add keyslot using internally stored volume key generated during format */
780*86d7f5d3SJohn Marino 	r = crypt_keyslot_add_by_volume_key(cd, options->key_slot, NULL, 0,
781*86d7f5d3SJohn Marino 					    password, passwordLen);
782*86d7f5d3SJohn Marino out:
783*86d7f5d3SJohn Marino 	crypt_free(cd);
784*86d7f5d3SJohn Marino 	safe_free(password);
785*86d7f5d3SJohn Marino 	return (r < 0) ? r : 0;
786*86d7f5d3SJohn Marino }
787*86d7f5d3SJohn Marino 
788*86d7f5d3SJohn Marino /* OPTIONS: name, device, key_size, key_file, timeout, tries, flags, icb */
crypt_luksOpen(struct crypt_options * options)789*86d7f5d3SJohn Marino int crypt_luksOpen(struct crypt_options *options)
790*86d7f5d3SJohn Marino {
791*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
792*86d7f5d3SJohn Marino 	uint32_t flags = 0;
793*86d7f5d3SJohn Marino 	int r;
794*86d7f5d3SJohn Marino 
795*86d7f5d3SJohn Marino 	if (!options->name)
796*86d7f5d3SJohn Marino 		return -EINVAL;
797*86d7f5d3SJohn Marino 
798*86d7f5d3SJohn Marino 	r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 1);
799*86d7f5d3SJohn Marino 	if (r)
800*86d7f5d3SJohn Marino 		return r;
801*86d7f5d3SJohn Marino 
802*86d7f5d3SJohn Marino 	if (options->flags & CRYPT_FLAG_READONLY)
803*86d7f5d3SJohn Marino 		flags |= CRYPT_ACTIVATE_READONLY;
804*86d7f5d3SJohn Marino 
805*86d7f5d3SJohn Marino 	if (options->flags & CRYPT_FLAG_NON_EXCLUSIVE_ACCESS)
806*86d7f5d3SJohn Marino 		flags |= CRYPT_ACTIVATE_NO_UUID;
807*86d7f5d3SJohn Marino 
808*86d7f5d3SJohn Marino 	if (options->key_file)
809*86d7f5d3SJohn Marino 		r = crypt_activate_by_keyfile(cd, options->name,
810*86d7f5d3SJohn Marino 			CRYPT_ANY_SLOT, options->key_file, options->key_size,
811*86d7f5d3SJohn Marino 			flags);
812*86d7f5d3SJohn Marino 	else
813*86d7f5d3SJohn Marino 		r = crypt_activate_by_passphrase(cd, options->name,
814*86d7f5d3SJohn Marino 			CRYPT_ANY_SLOT, options->passphrase,
815*86d7f5d3SJohn Marino 			options->passphrase ? strlen(options->passphrase) : 0,
816*86d7f5d3SJohn Marino 			flags);
817*86d7f5d3SJohn Marino 
818*86d7f5d3SJohn Marino 	crypt_free(cd);
819*86d7f5d3SJohn Marino 	return (r < 0) ? r : 0;
820*86d7f5d3SJohn Marino }
821*86d7f5d3SJohn Marino 
822*86d7f5d3SJohn Marino /* OPTIONS: device, keys_slot, key_file, timeout, flags, icb */
crypt_luksKillSlot(struct crypt_options * options)823*86d7f5d3SJohn Marino int crypt_luksKillSlot(struct crypt_options *options)
824*86d7f5d3SJohn Marino {
825*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
826*86d7f5d3SJohn Marino 	int r;
827*86d7f5d3SJohn Marino 
828*86d7f5d3SJohn Marino 	r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 1);
829*86d7f5d3SJohn Marino 	if (r)
830*86d7f5d3SJohn Marino 		return r;
831*86d7f5d3SJohn Marino 
832*86d7f5d3SJohn Marino 	r = luks_remove_helper(cd, options->key_slot, options->key_file, NULL,
833*86d7f5d3SJohn Marino 			       options->flags & CRYPT_FLAG_VERIFY_ON_DELKEY);
834*86d7f5d3SJohn Marino 
835*86d7f5d3SJohn Marino 	crypt_free(cd);
836*86d7f5d3SJohn Marino 	return (r < 0) ? r : 0;
837*86d7f5d3SJohn Marino }
838*86d7f5d3SJohn Marino 
839*86d7f5d3SJohn Marino /* OPTIONS: device, new_key_file, key_file, timeout, flags, icb */
crypt_luksRemoveKey(struct crypt_options * options)840*86d7f5d3SJohn Marino int crypt_luksRemoveKey(struct crypt_options *options)
841*86d7f5d3SJohn Marino {
842*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
843*86d7f5d3SJohn Marino 	int r;
844*86d7f5d3SJohn Marino 
845*86d7f5d3SJohn Marino 	r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 1);
846*86d7f5d3SJohn Marino 	if (r)
847*86d7f5d3SJohn Marino 		return r;
848*86d7f5d3SJohn Marino 
849*86d7f5d3SJohn Marino 	r = luks_remove_helper(cd, CRYPT_ANY_SLOT, options->key_file, options->new_key_file,
850*86d7f5d3SJohn Marino 			       options->flags & CRYPT_FLAG_VERIFY_ON_DELKEY);
851*86d7f5d3SJohn Marino 
852*86d7f5d3SJohn Marino 	crypt_free(cd);
853*86d7f5d3SJohn Marino 	return (r < 0) ? r : 0;
854*86d7f5d3SJohn Marino }
855*86d7f5d3SJohn Marino 
856*86d7f5d3SJohn Marino 
857*86d7f5d3SJohn Marino /* OPTIONS: device, new_key_file, key_file, key_slot, flags,
858*86d7f5d3SJohn Marino             iteration_time, timeout, icb */
crypt_luksAddKey(struct crypt_options * options)859*86d7f5d3SJohn Marino int crypt_luksAddKey(struct crypt_options *options)
860*86d7f5d3SJohn Marino {
861*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
862*86d7f5d3SJohn Marino 	int r = -EINVAL;
863*86d7f5d3SJohn Marino 
864*86d7f5d3SJohn Marino 	r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 1);
865*86d7f5d3SJohn Marino 	if (r)
866*86d7f5d3SJohn Marino 		return r;
867*86d7f5d3SJohn Marino 
868*86d7f5d3SJohn Marino 	if (options->key_file || options->new_key_file)
869*86d7f5d3SJohn Marino 		r = crypt_keyslot_add_by_keyfile(cd, options->key_slot,
870*86d7f5d3SJohn Marino 						 options->key_file, 0,
871*86d7f5d3SJohn Marino 						 options->new_key_file, 0);
872*86d7f5d3SJohn Marino 	else
873*86d7f5d3SJohn Marino 		r = crypt_keyslot_add_by_passphrase(cd, options->key_slot,
874*86d7f5d3SJohn Marino 						    NULL, 0, NULL, 0);
875*86d7f5d3SJohn Marino 
876*86d7f5d3SJohn Marino 	crypt_free(cd);
877*86d7f5d3SJohn Marino 	return (r < 0) ? r : 0;
878*86d7f5d3SJohn Marino }
879*86d7f5d3SJohn Marino 
880*86d7f5d3SJohn Marino /* OPTIONS: device, icb */
crypt_luksUUID(struct crypt_options * options)881*86d7f5d3SJohn Marino int crypt_luksUUID(struct crypt_options *options)
882*86d7f5d3SJohn Marino {
883*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
884*86d7f5d3SJohn Marino 	char *uuid;
885*86d7f5d3SJohn Marino 	int r;
886*86d7f5d3SJohn Marino 
887*86d7f5d3SJohn Marino 	r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 0);
888*86d7f5d3SJohn Marino 	if (r)
889*86d7f5d3SJohn Marino 		return r;
890*86d7f5d3SJohn Marino 
891*86d7f5d3SJohn Marino 	uuid = (char *)crypt_get_uuid(cd);
892*86d7f5d3SJohn Marino 	log_std(cd, uuid ?: "");
893*86d7f5d3SJohn Marino 	log_std(cd, "\n");
894*86d7f5d3SJohn Marino 	crypt_free(cd);
895*86d7f5d3SJohn Marino 	return 0;
896*86d7f5d3SJohn Marino }
897*86d7f5d3SJohn Marino 
898*86d7f5d3SJohn Marino /* OPTIONS: device, icb */
crypt_isLuks(struct crypt_options * options)899*86d7f5d3SJohn Marino int crypt_isLuks(struct crypt_options *options)
900*86d7f5d3SJohn Marino {
901*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
902*86d7f5d3SJohn Marino 	int r;
903*86d7f5d3SJohn Marino 
904*86d7f5d3SJohn Marino 	log_dbg("Check device %s for LUKS header.", options->device);
905*86d7f5d3SJohn Marino 
906*86d7f5d3SJohn Marino 	if (init_crypto()) {
907*86d7f5d3SJohn Marino 		log_err(cd, _("Cannot initialize crypto backend.\n"));
908*86d7f5d3SJohn Marino 		return -ENOSYS;
909*86d7f5d3SJohn Marino 	}
910*86d7f5d3SJohn Marino 
911*86d7f5d3SJohn Marino 	r = crypt_init(&cd, options->device);
912*86d7f5d3SJohn Marino 	if (r < 0)
913*86d7f5d3SJohn Marino 		return -EINVAL;
914*86d7f5d3SJohn Marino 
915*86d7f5d3SJohn Marino 	/* Do print fail here, no need to crypt_load() */
916*86d7f5d3SJohn Marino 	r = LUKS_read_phdr(cd->device, &cd->hdr, 0, cd) ? -EINVAL : 0;
917*86d7f5d3SJohn Marino 
918*86d7f5d3SJohn Marino 	crypt_free(cd);
919*86d7f5d3SJohn Marino 	return r;
920*86d7f5d3SJohn Marino }
921*86d7f5d3SJohn Marino 
922*86d7f5d3SJohn Marino /* OPTIONS: device, icb */
crypt_luksDump(struct crypt_options * options)923*86d7f5d3SJohn Marino int crypt_luksDump(struct crypt_options *options)
924*86d7f5d3SJohn Marino {
925*86d7f5d3SJohn Marino 	struct crypt_device *cd = NULL;
926*86d7f5d3SJohn Marino 	int r;
927*86d7f5d3SJohn Marino 
928*86d7f5d3SJohn Marino 	r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 0);
929*86d7f5d3SJohn Marino 	if(r < 0)
930*86d7f5d3SJohn Marino 		return r;
931*86d7f5d3SJohn Marino 
932*86d7f5d3SJohn Marino 	r = crypt_dump(cd);
933*86d7f5d3SJohn Marino 
934*86d7f5d3SJohn Marino 	crypt_free(cd);
935*86d7f5d3SJohn Marino 	return 0;
936*86d7f5d3SJohn Marino }
937*86d7f5d3SJohn Marino 
crypt_get_error(char * buf,size_t size)938*86d7f5d3SJohn Marino void crypt_get_error(char *buf, size_t size)
939*86d7f5d3SJohn Marino {
940*86d7f5d3SJohn Marino 	const char *error = get_error();
941*86d7f5d3SJohn Marino 
942*86d7f5d3SJohn Marino 	if (!buf || size < 1)
943*86d7f5d3SJohn Marino 		set_error(NULL);
944*86d7f5d3SJohn Marino 	else if (error) {
945*86d7f5d3SJohn Marino 		strncpy(buf, error, size - 1);
946*86d7f5d3SJohn Marino 		buf[size - 1] = '\0';
947*86d7f5d3SJohn Marino 		set_error(NULL);
948*86d7f5d3SJohn Marino 	} else
949*86d7f5d3SJohn Marino 		buf[0] = '\0';
950*86d7f5d3SJohn Marino }
951*86d7f5d3SJohn Marino 
crypt_put_options(struct crypt_options * options)952*86d7f5d3SJohn Marino void crypt_put_options(struct crypt_options *options)
953*86d7f5d3SJohn Marino {
954*86d7f5d3SJohn Marino 	if (options->flags & CRYPT_FLAG_FREE_DEVICE) {
955*86d7f5d3SJohn Marino 		free((char *)options->device);
956*86d7f5d3SJohn Marino 		options->device = NULL;
957*86d7f5d3SJohn Marino 		options->flags &= ~CRYPT_FLAG_FREE_DEVICE;
958*86d7f5d3SJohn Marino 	}
959*86d7f5d3SJohn Marino 	if (options->flags & CRYPT_FLAG_FREE_CIPHER) {
960*86d7f5d3SJohn Marino 		free((char *)options->cipher);
961*86d7f5d3SJohn Marino 		options->cipher = NULL;
962*86d7f5d3SJohn Marino 		options->flags &= ~CRYPT_FLAG_FREE_CIPHER;
963*86d7f5d3SJohn Marino 	}
964*86d7f5d3SJohn Marino }
965*86d7f5d3SJohn Marino 
crypt_get_dir(void)966*86d7f5d3SJohn Marino const char *crypt_get_dir(void)
967*86d7f5d3SJohn Marino {
968*86d7f5d3SJohn Marino 	return dm_get_dir();
969*86d7f5d3SJohn Marino }
970*86d7f5d3SJohn Marino 
971*86d7f5d3SJohn Marino /////////////////////////////////
972*86d7f5d3SJohn Marino //
973*86d7f5d3SJohn Marino // New API
974*86d7f5d3SJohn Marino //
975*86d7f5d3SJohn Marino 
crypt_init(struct crypt_device ** cd,const char * device)976*86d7f5d3SJohn Marino int crypt_init(struct crypt_device **cd, const char *device)
977*86d7f5d3SJohn Marino {
978*86d7f5d3SJohn Marino 	struct crypt_device *h = NULL;
979*86d7f5d3SJohn Marino 
980*86d7f5d3SJohn Marino 	if (!cd)
981*86d7f5d3SJohn Marino 		return -EINVAL;
982*86d7f5d3SJohn Marino 
983*86d7f5d3SJohn Marino 	log_dbg("Allocating crypt device %s context.", device);
984*86d7f5d3SJohn Marino 
985*86d7f5d3SJohn Marino 	if (device && !device_ready(NULL, device, O_RDONLY))
986*86d7f5d3SJohn Marino 		return -ENOTBLK;
987*86d7f5d3SJohn Marino 
988*86d7f5d3SJohn Marino 	if (!(h = malloc(sizeof(struct crypt_device))))
989*86d7f5d3SJohn Marino 		return -ENOMEM;
990*86d7f5d3SJohn Marino 
991*86d7f5d3SJohn Marino 	memset(h, 0, sizeof(*h));
992*86d7f5d3SJohn Marino 
993*86d7f5d3SJohn Marino 	if (device) {
994*86d7f5d3SJohn Marino 		h->device = strdup(device);
995*86d7f5d3SJohn Marino 		if (!h->device) {
996*86d7f5d3SJohn Marino 			free(h);
997*86d7f5d3SJohn Marino 			return -ENOMEM;
998*86d7f5d3SJohn Marino 		}
999*86d7f5d3SJohn Marino 	} else
1000*86d7f5d3SJohn Marino 		h->device = NULL;
1001*86d7f5d3SJohn Marino 
1002*86d7f5d3SJohn Marino 	if (dm_init(h, 1) < 0) {
1003*86d7f5d3SJohn Marino 		free(h);
1004*86d7f5d3SJohn Marino 		return -ENOSYS;
1005*86d7f5d3SJohn Marino 	}
1006*86d7f5d3SJohn Marino 
1007*86d7f5d3SJohn Marino 	h->iteration_time = 1000;
1008*86d7f5d3SJohn Marino 	h->password_verify = 0;
1009*86d7f5d3SJohn Marino 	h->tries = 3;
1010*86d7f5d3SJohn Marino 	*cd = h;
1011*86d7f5d3SJohn Marino 	return 0;
1012*86d7f5d3SJohn Marino }
1013*86d7f5d3SJohn Marino 
crypt_init_by_name(struct crypt_device ** cd,const char * name)1014*86d7f5d3SJohn Marino int crypt_init_by_name(struct crypt_device **cd, const char *name)
1015*86d7f5d3SJohn Marino {
1016*86d7f5d3SJohn Marino 	crypt_status_info ci;
1017*86d7f5d3SJohn Marino 	char *device = NULL;
1018*86d7f5d3SJohn Marino 	int r;
1019*86d7f5d3SJohn Marino 
1020*86d7f5d3SJohn Marino 	log_dbg("Allocating crypt device context by device %s.", name);
1021*86d7f5d3SJohn Marino 
1022*86d7f5d3SJohn Marino 	ci = crypt_status(NULL, name);
1023*86d7f5d3SJohn Marino 	if (ci == CRYPT_INVALID)
1024*86d7f5d3SJohn Marino 		return -ENODEV;
1025*86d7f5d3SJohn Marino 
1026*86d7f5d3SJohn Marino 	if (ci < CRYPT_ACTIVE) {
1027*86d7f5d3SJohn Marino 		log_err(NULL, _("Device %s is not active.\n"), name);
1028*86d7f5d3SJohn Marino 		return -ENODEV;
1029*86d7f5d3SJohn Marino 	}
1030*86d7f5d3SJohn Marino 
1031*86d7f5d3SJohn Marino 	r = dm_query_device(name, &device, NULL, NULL, NULL,
1032*86d7f5d3SJohn Marino 			    NULL, NULL, NULL, NULL, NULL, NULL);
1033*86d7f5d3SJohn Marino 
1034*86d7f5d3SJohn Marino 	/* Underlying device disappeared but mapping still active */
1035*86d7f5d3SJohn Marino 	if (r >= 0 && !device)
1036*86d7f5d3SJohn Marino 		log_verbose(NULL, _("Underlying device for crypt device %s disappeared.\n"),
1037*86d7f5d3SJohn Marino 			    name);
1038*86d7f5d3SJohn Marino 
1039*86d7f5d3SJohn Marino 	if (r >= 0)
1040*86d7f5d3SJohn Marino 		r = crypt_init(cd, device);
1041*86d7f5d3SJohn Marino 
1042*86d7f5d3SJohn Marino 	free(device);
1043*86d7f5d3SJohn Marino 	return r;
1044*86d7f5d3SJohn Marino }
1045*86d7f5d3SJohn Marino 
_crypt_format_plain(struct crypt_device * cd,const char * cipher,const char * cipher_mode,const char * uuid,struct crypt_params_plain * params)1046*86d7f5d3SJohn Marino static int _crypt_format_plain(struct crypt_device *cd,
1047*86d7f5d3SJohn Marino 			       const char *cipher,
1048*86d7f5d3SJohn Marino 			       const char *cipher_mode,
1049*86d7f5d3SJohn Marino 			       const char *uuid,
1050*86d7f5d3SJohn Marino 			       struct crypt_params_plain *params)
1051*86d7f5d3SJohn Marino {
1052*86d7f5d3SJohn Marino 	if (!cipher || !cipher_mode) {
1053*86d7f5d3SJohn Marino 		log_err(cd, _("Invalid plain crypt parameters.\n"));
1054*86d7f5d3SJohn Marino 		return -EINVAL;
1055*86d7f5d3SJohn Marino 	}
1056*86d7f5d3SJohn Marino 
1057*86d7f5d3SJohn Marino 	if (cd->volume_key->keyLength > 1024) {
1058*86d7f5d3SJohn Marino 		log_err(cd, _("Invalid key size.\n"));
1059*86d7f5d3SJohn Marino 		return -EINVAL;
1060*86d7f5d3SJohn Marino 	}
1061*86d7f5d3SJohn Marino 
1062*86d7f5d3SJohn Marino 	cd->plain_cipher = strdup(cipher);
1063*86d7f5d3SJohn Marino 	cd->plain_cipher_mode = strdup(cipher_mode);
1064*86d7f5d3SJohn Marino 
1065*86d7f5d3SJohn Marino 	if (uuid)
1066*86d7f5d3SJohn Marino 		cd->plain_uuid = strdup(uuid);
1067*86d7f5d3SJohn Marino 
1068*86d7f5d3SJohn Marino 	if (params && params->hash)
1069*86d7f5d3SJohn Marino 		cd->plain_hdr.hash = strdup(params->hash);
1070*86d7f5d3SJohn Marino 
1071*86d7f5d3SJohn Marino 	cd->plain_hdr.offset = params ? params->offset : 0;
1072*86d7f5d3SJohn Marino 	cd->plain_hdr.skip = params ? params->skip : 0;
1073*86d7f5d3SJohn Marino 
1074*86d7f5d3SJohn Marino 	if (!cd->plain_cipher || !cd->plain_cipher_mode)
1075*86d7f5d3SJohn Marino 		return -ENOMEM;
1076*86d7f5d3SJohn Marino 
1077*86d7f5d3SJohn Marino 	return 0;
1078*86d7f5d3SJohn Marino }
1079*86d7f5d3SJohn Marino 
_crypt_format_luks1(struct crypt_device * cd,const char * cipher,const char * cipher_mode,const char * uuid,struct crypt_params_luks1 * params)1080*86d7f5d3SJohn Marino static int _crypt_format_luks1(struct crypt_device *cd,
1081*86d7f5d3SJohn Marino 			       const char *cipher,
1082*86d7f5d3SJohn Marino 			       const char *cipher_mode,
1083*86d7f5d3SJohn Marino 			       const char *uuid,
1084*86d7f5d3SJohn Marino 			       struct crypt_params_luks1 *params)
1085*86d7f5d3SJohn Marino {
1086*86d7f5d3SJohn Marino 	int r;
1087*86d7f5d3SJohn Marino 	unsigned long required_alignment = DEFAULT_ALIGNMENT;
1088*86d7f5d3SJohn Marino 	unsigned long alignment_offset = 0;
1089*86d7f5d3SJohn Marino 
1090*86d7f5d3SJohn Marino 	if (!cd->device) {
1091*86d7f5d3SJohn Marino 		log_err(cd, _("Can't format LUKS without device.\n"));
1092*86d7f5d3SJohn Marino 		return -EINVAL;
1093*86d7f5d3SJohn Marino 	}
1094*86d7f5d3SJohn Marino 
1095*86d7f5d3SJohn Marino 	if (params && params->data_alignment)
1096*86d7f5d3SJohn Marino 		required_alignment = params->data_alignment * SECTOR_SIZE;
1097*86d7f5d3SJohn Marino 	else
1098*86d7f5d3SJohn Marino 		get_topology_alignment(cd->device, &required_alignment,
1099*86d7f5d3SJohn Marino 				       &alignment_offset, DEFAULT_ALIGNMENT);
1100*86d7f5d3SJohn Marino 
1101*86d7f5d3SJohn Marino 	r = LUKS_generate_phdr(&cd->hdr, cd->volume_key, cipher, cipher_mode,
1102*86d7f5d3SJohn Marino 			       (params && params->hash) ? params->hash : "sha1",
1103*86d7f5d3SJohn Marino 			       uuid, LUKS_STRIPES,
1104*86d7f5d3SJohn Marino 			       required_alignment / SECTOR_SIZE,
1105*86d7f5d3SJohn Marino 			       alignment_offset / SECTOR_SIZE,
1106*86d7f5d3SJohn Marino 			       cd->iteration_time, &cd->PBKDF2_per_sec, cd);
1107*86d7f5d3SJohn Marino 	if(r < 0)
1108*86d7f5d3SJohn Marino 		return r;
1109*86d7f5d3SJohn Marino 
1110*86d7f5d3SJohn Marino 	/* Wipe first 8 sectors - fs magic numbers etc. */
1111*86d7f5d3SJohn Marino 	r = wipe_device_header(cd->device, 8);
1112*86d7f5d3SJohn Marino 	if(r < 0) {
1113*86d7f5d3SJohn Marino 		log_err(cd, _("Can't wipe header on device %s.\n"), cd->device);
1114*86d7f5d3SJohn Marino 		return r;
1115*86d7f5d3SJohn Marino 	}
1116*86d7f5d3SJohn Marino 
1117*86d7f5d3SJohn Marino 	r = LUKS_write_phdr(cd->device, &cd->hdr, cd);
1118*86d7f5d3SJohn Marino 
1119*86d7f5d3SJohn Marino 	return r;
1120*86d7f5d3SJohn Marino }
1121*86d7f5d3SJohn Marino 
crypt_format(struct crypt_device * cd,const char * type,const char * cipher,const char * cipher_mode,const char * uuid,const char * volume_key,size_t volume_key_size,void * params)1122*86d7f5d3SJohn Marino int crypt_format(struct crypt_device *cd,
1123*86d7f5d3SJohn Marino 	const char *type,
1124*86d7f5d3SJohn Marino 	const char *cipher,
1125*86d7f5d3SJohn Marino 	const char *cipher_mode,
1126*86d7f5d3SJohn Marino 	const char *uuid,
1127*86d7f5d3SJohn Marino 	const char *volume_key,
1128*86d7f5d3SJohn Marino 	size_t volume_key_size,
1129*86d7f5d3SJohn Marino 	void *params)
1130*86d7f5d3SJohn Marino {
1131*86d7f5d3SJohn Marino 	int r;
1132*86d7f5d3SJohn Marino 
1133*86d7f5d3SJohn Marino 	log_dbg("Formatting device %s as type %s.", cd->device ?: "(none)", cd->type ?: "(none)");
1134*86d7f5d3SJohn Marino 
1135*86d7f5d3SJohn Marino 	if (!type)
1136*86d7f5d3SJohn Marino 		return -EINVAL;
1137*86d7f5d3SJohn Marino 
1138*86d7f5d3SJohn Marino 	/* Some hash functions need initialized gcrypt library */
1139*86d7f5d3SJohn Marino 	if (init_crypto()) {
1140*86d7f5d3SJohn Marino 		log_err(cd, _("Cannot initialize crypto backend.\n"));
1141*86d7f5d3SJohn Marino 		return -ENOSYS;
1142*86d7f5d3SJohn Marino 	}
1143*86d7f5d3SJohn Marino 
1144*86d7f5d3SJohn Marino 	if (volume_key)
1145*86d7f5d3SJohn Marino 		cd->volume_key = LUKS_alloc_masterkey(volume_key_size,
1146*86d7f5d3SJohn Marino 						      volume_key);
1147*86d7f5d3SJohn Marino 	else
1148*86d7f5d3SJohn Marino 		cd->volume_key = LUKS_generate_masterkey(volume_key_size);
1149*86d7f5d3SJohn Marino 
1150*86d7f5d3SJohn Marino 	if(!cd->volume_key)
1151*86d7f5d3SJohn Marino 		return -ENOMEM;
1152*86d7f5d3SJohn Marino 
1153*86d7f5d3SJohn Marino 	if (isPLAIN(type))
1154*86d7f5d3SJohn Marino 		r = _crypt_format_plain(cd, cipher, cipher_mode,
1155*86d7f5d3SJohn Marino 					uuid, params);
1156*86d7f5d3SJohn Marino 	else if (isLUKS(type))
1157*86d7f5d3SJohn Marino 		r = _crypt_format_luks1(cd, cipher, cipher_mode,
1158*86d7f5d3SJohn Marino 					uuid, params);
1159*86d7f5d3SJohn Marino 	else {
1160*86d7f5d3SJohn Marino 		/* FIXME: allow plugins here? */
1161*86d7f5d3SJohn Marino 		log_err(cd, _("Unknown crypt device type %s requested.\n"), type);
1162*86d7f5d3SJohn Marino 		r = -EINVAL;
1163*86d7f5d3SJohn Marino 	}
1164*86d7f5d3SJohn Marino 
1165*86d7f5d3SJohn Marino 	if (!r && !(cd->type = strdup(type)))
1166*86d7f5d3SJohn Marino 		r = -ENOMEM;
1167*86d7f5d3SJohn Marino 
1168*86d7f5d3SJohn Marino 	if (r < 0) {
1169*86d7f5d3SJohn Marino 		LUKS_dealloc_masterkey(cd->volume_key);
1170*86d7f5d3SJohn Marino 		cd->volume_key = NULL;
1171*86d7f5d3SJohn Marino 	}
1172*86d7f5d3SJohn Marino 
1173*86d7f5d3SJohn Marino 	return r;
1174*86d7f5d3SJohn Marino }
1175*86d7f5d3SJohn Marino 
crypt_load(struct crypt_device * cd,const char * requested_type,void * params)1176*86d7f5d3SJohn Marino int crypt_load(struct crypt_device *cd,
1177*86d7f5d3SJohn Marino 	       const char *requested_type,
1178*86d7f5d3SJohn Marino 	       void *params)
1179*86d7f5d3SJohn Marino {
1180*86d7f5d3SJohn Marino 	struct luks_phdr hdr;
1181*86d7f5d3SJohn Marino 	int r;
1182*86d7f5d3SJohn Marino 
1183*86d7f5d3SJohn Marino 	log_dbg("Trying to load %s crypt type from device %s.",
1184*86d7f5d3SJohn Marino 		requested_type ?: "any", cd->device ?: "(none)");
1185*86d7f5d3SJohn Marino 
1186*86d7f5d3SJohn Marino 	if (!cd->device)
1187*86d7f5d3SJohn Marino 		return -EINVAL;
1188*86d7f5d3SJohn Marino 
1189*86d7f5d3SJohn Marino 	if (requested_type && !isLUKS(requested_type))
1190*86d7f5d3SJohn Marino 		return -EINVAL;
1191*86d7f5d3SJohn Marino 
1192*86d7f5d3SJohn Marino 	/* Some hash functions need initialized gcrypt library */
1193*86d7f5d3SJohn Marino 	if (init_crypto()) {
1194*86d7f5d3SJohn Marino 		log_err(cd, _("Cannot initialize crypto backend.\n"));
1195*86d7f5d3SJohn Marino 		return -ENOSYS;
1196*86d7f5d3SJohn Marino 	}
1197*86d7f5d3SJohn Marino 
1198*86d7f5d3SJohn Marino 	r = LUKS_read_phdr(cd->device, &hdr, 1, cd);
1199*86d7f5d3SJohn Marino 
1200*86d7f5d3SJohn Marino 	if (!r) {
1201*86d7f5d3SJohn Marino 		memcpy(&cd->hdr, &hdr, sizeof(hdr));
1202*86d7f5d3SJohn Marino 		cd->type = strdup(requested_type);
1203*86d7f5d3SJohn Marino 		if (!cd->type)
1204*86d7f5d3SJohn Marino 			r = -ENOMEM;
1205*86d7f5d3SJohn Marino 	}
1206*86d7f5d3SJohn Marino 
1207*86d7f5d3SJohn Marino 	return r;
1208*86d7f5d3SJohn Marino }
1209*86d7f5d3SJohn Marino 
crypt_header_backup(struct crypt_device * cd,const char * requested_type,const char * backup_file)1210*86d7f5d3SJohn Marino int crypt_header_backup(struct crypt_device *cd,
1211*86d7f5d3SJohn Marino 			const char *requested_type,
1212*86d7f5d3SJohn Marino 			const char *backup_file)
1213*86d7f5d3SJohn Marino {
1214*86d7f5d3SJohn Marino 	if ((requested_type && !isLUKS(requested_type)) || !backup_file)
1215*86d7f5d3SJohn Marino 		return -EINVAL;
1216*86d7f5d3SJohn Marino 
1217*86d7f5d3SJohn Marino 	/* Some hash functions need initialized gcrypt library */
1218*86d7f5d3SJohn Marino 	if (init_crypto()) {
1219*86d7f5d3SJohn Marino 		log_err(cd, _("Cannot initialize crypto backend.\n"));
1220*86d7f5d3SJohn Marino 		return -ENOSYS;
1221*86d7f5d3SJohn Marino 	}
1222*86d7f5d3SJohn Marino 
1223*86d7f5d3SJohn Marino 	log_dbg("Requested header backup of device %s (%s) to "
1224*86d7f5d3SJohn Marino 		"file %s.", cd->device, requested_type, backup_file);
1225*86d7f5d3SJohn Marino 
1226*86d7f5d3SJohn Marino 	return LUKS_hdr_backup(backup_file, cd->device, &cd->hdr, cd);
1227*86d7f5d3SJohn Marino }
1228*86d7f5d3SJohn Marino 
crypt_header_restore(struct crypt_device * cd,const char * requested_type,const char * backup_file)1229*86d7f5d3SJohn Marino int crypt_header_restore(struct crypt_device *cd,
1230*86d7f5d3SJohn Marino 			 const char *requested_type,
1231*86d7f5d3SJohn Marino 			 const char *backup_file)
1232*86d7f5d3SJohn Marino {
1233*86d7f5d3SJohn Marino 	if (requested_type && !isLUKS(requested_type))
1234*86d7f5d3SJohn Marino 		return -EINVAL;
1235*86d7f5d3SJohn Marino 
1236*86d7f5d3SJohn Marino 	/* Some hash functions need initialized gcrypt library */
1237*86d7f5d3SJohn Marino 	if (init_crypto()) {
1238*86d7f5d3SJohn Marino 		log_err(cd, _("Cannot initialize crypto backend.\n"));
1239*86d7f5d3SJohn Marino 		return -ENOSYS;
1240*86d7f5d3SJohn Marino 	}
1241*86d7f5d3SJohn Marino 
1242*86d7f5d3SJohn Marino 	log_dbg("Requested header restore to device %s (%s) from "
1243*86d7f5d3SJohn Marino 		"file %s.", cd->device, requested_type, backup_file);
1244*86d7f5d3SJohn Marino 
1245*86d7f5d3SJohn Marino 	return LUKS_hdr_restore(backup_file, cd->device, &cd->hdr, cd);
1246*86d7f5d3SJohn Marino }
1247*86d7f5d3SJohn Marino 
crypt_free(struct crypt_device * cd)1248*86d7f5d3SJohn Marino void crypt_free(struct crypt_device *cd)
1249*86d7f5d3SJohn Marino {
1250*86d7f5d3SJohn Marino 	if (cd) {
1251*86d7f5d3SJohn Marino 		log_dbg("Releasing crypt device %s context.", cd->device);
1252*86d7f5d3SJohn Marino 
1253*86d7f5d3SJohn Marino 		dm_exit();
1254*86d7f5d3SJohn Marino 		if (cd->volume_key)
1255*86d7f5d3SJohn Marino 			LUKS_dealloc_masterkey(cd->volume_key);
1256*86d7f5d3SJohn Marino 
1257*86d7f5d3SJohn Marino 		free(cd->device);
1258*86d7f5d3SJohn Marino 		free(cd->type);
1259*86d7f5d3SJohn Marino 
1260*86d7f5d3SJohn Marino 		/* used in plain device only */
1261*86d7f5d3SJohn Marino 		free((char*)cd->plain_hdr.hash);
1262*86d7f5d3SJohn Marino 		free(cd->plain_cipher);
1263*86d7f5d3SJohn Marino 		free(cd->plain_cipher_mode);
1264*86d7f5d3SJohn Marino 		free(cd->plain_uuid);
1265*86d7f5d3SJohn Marino 
1266*86d7f5d3SJohn Marino 		free(cd);
1267*86d7f5d3SJohn Marino 	}
1268*86d7f5d3SJohn Marino }
1269*86d7f5d3SJohn Marino 
crypt_suspend(struct crypt_device * cd,const char * name)1270*86d7f5d3SJohn Marino int crypt_suspend(struct crypt_device *cd,
1271*86d7f5d3SJohn Marino 		  const char *name)
1272*86d7f5d3SJohn Marino {
1273*86d7f5d3SJohn Marino 	crypt_status_info ci;
1274*86d7f5d3SJohn Marino 	int r, suspended = 0;
1275*86d7f5d3SJohn Marino 
1276*86d7f5d3SJohn Marino 	log_dbg("Suspending volume %s.", name);
1277*86d7f5d3SJohn Marino 
1278*86d7f5d3SJohn Marino 	ci = crypt_status(NULL, name);
1279*86d7f5d3SJohn Marino 	if (ci < CRYPT_ACTIVE) {
1280*86d7f5d3SJohn Marino 		log_err(cd, _("Volume %s is not active.\n"), name);
1281*86d7f5d3SJohn Marino 		return -EINVAL;
1282*86d7f5d3SJohn Marino 	}
1283*86d7f5d3SJohn Marino 
1284*86d7f5d3SJohn Marino 	if (!cd && dm_init(NULL, 1) < 0)
1285*86d7f5d3SJohn Marino 		return -ENOSYS;
1286*86d7f5d3SJohn Marino 
1287*86d7f5d3SJohn Marino 	r = dm_query_device(name, NULL, NULL, NULL, NULL,
1288*86d7f5d3SJohn Marino 			    NULL, NULL, NULL, NULL, &suspended, NULL);
1289*86d7f5d3SJohn Marino 	if (r < 0)
1290*86d7f5d3SJohn Marino 		goto out;
1291*86d7f5d3SJohn Marino 
1292*86d7f5d3SJohn Marino 	if (suspended) {
1293*86d7f5d3SJohn Marino 		log_err(cd, _("Volume %s is already suspended.\n"), name);
1294*86d7f5d3SJohn Marino 		r = -EINVAL;
1295*86d7f5d3SJohn Marino 		goto out;
1296*86d7f5d3SJohn Marino 	}
1297*86d7f5d3SJohn Marino 
1298*86d7f5d3SJohn Marino 	r = dm_suspend_and_wipe_key(name);
1299*86d7f5d3SJohn Marino 	if (r == -ENOTSUP)
1300*86d7f5d3SJohn Marino 		log_err(cd, "Suspend is not supported for device %s.\n", name);
1301*86d7f5d3SJohn Marino 	else if (r)
1302*86d7f5d3SJohn Marino 		log_err(cd, "Error during suspending device %s.\n", name);
1303*86d7f5d3SJohn Marino out:
1304*86d7f5d3SJohn Marino 	if (!cd)
1305*86d7f5d3SJohn Marino 		dm_exit();
1306*86d7f5d3SJohn Marino 	return r;
1307*86d7f5d3SJohn Marino }
1308*86d7f5d3SJohn Marino 
crypt_resume_by_passphrase(struct crypt_device * cd,const char * name,int keyslot,const char * passphrase,size_t passphrase_size)1309*86d7f5d3SJohn Marino int crypt_resume_by_passphrase(struct crypt_device *cd,
1310*86d7f5d3SJohn Marino 			       const char *name,
1311*86d7f5d3SJohn Marino 			       int keyslot,
1312*86d7f5d3SJohn Marino 			       const char *passphrase,
1313*86d7f5d3SJohn Marino 			       size_t passphrase_size)
1314*86d7f5d3SJohn Marino {
1315*86d7f5d3SJohn Marino 	struct luks_masterkey *mk = NULL;
1316*86d7f5d3SJohn Marino 	int r, suspended = 0;
1317*86d7f5d3SJohn Marino 
1318*86d7f5d3SJohn Marino 	log_dbg("Resuming volume %s.", name);
1319*86d7f5d3SJohn Marino 
1320*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
1321*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1322*86d7f5d3SJohn Marino 		r = -EINVAL;
1323*86d7f5d3SJohn Marino 		goto out;
1324*86d7f5d3SJohn Marino 	}
1325*86d7f5d3SJohn Marino 
1326*86d7f5d3SJohn Marino 	r = dm_query_device(name, NULL, NULL, NULL, NULL,
1327*86d7f5d3SJohn Marino 			    NULL, NULL, NULL, NULL, &suspended, NULL);
1328*86d7f5d3SJohn Marino 	if (r < 0)
1329*86d7f5d3SJohn Marino 		return r;
1330*86d7f5d3SJohn Marino 
1331*86d7f5d3SJohn Marino 	if (!suspended) {
1332*86d7f5d3SJohn Marino 		log_err(cd, _("Volume %s is not suspended.\n"), name);
1333*86d7f5d3SJohn Marino 		return -EINVAL;
1334*86d7f5d3SJohn Marino 	}
1335*86d7f5d3SJohn Marino 
1336*86d7f5d3SJohn Marino 	if (passphrase) {
1337*86d7f5d3SJohn Marino 		r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
1338*86d7f5d3SJohn Marino 					   passphrase_size, &cd->hdr, &mk, cd);
1339*86d7f5d3SJohn Marino 	} else
1340*86d7f5d3SJohn Marino 		r = volume_key_by_terminal_passphrase(cd, keyslot, &mk);
1341*86d7f5d3SJohn Marino 
1342*86d7f5d3SJohn Marino 	if (r >= 0) {
1343*86d7f5d3SJohn Marino 		keyslot = r;
1344*86d7f5d3SJohn Marino 		r = dm_resume_and_reinstate_key(name, mk->keyLength, mk->key);
1345*86d7f5d3SJohn Marino 		if (r == -ENOTSUP)
1346*86d7f5d3SJohn Marino 			log_err(cd, "Resume is not supported for device %s.\n", name);
1347*86d7f5d3SJohn Marino 		else if (r)
1348*86d7f5d3SJohn Marino 			log_err(cd, "Error during resuming device %s.\n", name);
1349*86d7f5d3SJohn Marino 	} else
1350*86d7f5d3SJohn Marino 		r = keyslot;
1351*86d7f5d3SJohn Marino out:
1352*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
1353*86d7f5d3SJohn Marino 	return r < 0 ? r : keyslot;
1354*86d7f5d3SJohn Marino }
1355*86d7f5d3SJohn Marino 
crypt_resume_by_keyfile(struct crypt_device * cd,const char * name,int keyslot,const char * keyfile,size_t keyfile_size)1356*86d7f5d3SJohn Marino int crypt_resume_by_keyfile(struct crypt_device *cd,
1357*86d7f5d3SJohn Marino 			    const char *name,
1358*86d7f5d3SJohn Marino 			    int keyslot,
1359*86d7f5d3SJohn Marino 			    const char *keyfile,
1360*86d7f5d3SJohn Marino 			    size_t keyfile_size)
1361*86d7f5d3SJohn Marino {
1362*86d7f5d3SJohn Marino 	struct luks_masterkey *mk = NULL;
1363*86d7f5d3SJohn Marino 	char *passphrase_read = NULL;
1364*86d7f5d3SJohn Marino 	unsigned int passphrase_size_read;
1365*86d7f5d3SJohn Marino 	int r, suspended = 0;
1366*86d7f5d3SJohn Marino 
1367*86d7f5d3SJohn Marino 	log_dbg("Resuming volume %s.", name);
1368*86d7f5d3SJohn Marino 
1369*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
1370*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1371*86d7f5d3SJohn Marino 		r = -EINVAL;
1372*86d7f5d3SJohn Marino 		goto out;
1373*86d7f5d3SJohn Marino 	}
1374*86d7f5d3SJohn Marino 
1375*86d7f5d3SJohn Marino 	r = dm_query_device(name, NULL, NULL, NULL, NULL,
1376*86d7f5d3SJohn Marino 			    NULL, NULL, NULL, NULL, &suspended, NULL);
1377*86d7f5d3SJohn Marino 	if (r < 0)
1378*86d7f5d3SJohn Marino 		return r;
1379*86d7f5d3SJohn Marino 
1380*86d7f5d3SJohn Marino 	if (!suspended) {
1381*86d7f5d3SJohn Marino 		log_err(cd, _("Volume %s is not suspended.\n"), name);
1382*86d7f5d3SJohn Marino 		return -EINVAL;
1383*86d7f5d3SJohn Marino 	}
1384*86d7f5d3SJohn Marino 
1385*86d7f5d3SJohn Marino 	if (!keyfile)
1386*86d7f5d3SJohn Marino 		return -EINVAL;
1387*86d7f5d3SJohn Marino 
1388*86d7f5d3SJohn Marino 	key_from_file(cd, _("Enter passphrase: "), &passphrase_read,
1389*86d7f5d3SJohn Marino 		      &passphrase_size_read, keyfile, keyfile_size);
1390*86d7f5d3SJohn Marino 
1391*86d7f5d3SJohn Marino 	if(!passphrase_read)
1392*86d7f5d3SJohn Marino 		r = -EINVAL;
1393*86d7f5d3SJohn Marino 	else {
1394*86d7f5d3SJohn Marino 		r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase_read,
1395*86d7f5d3SJohn Marino 					   passphrase_size_read, &cd->hdr, &mk, cd);
1396*86d7f5d3SJohn Marino 		safe_free(passphrase_read);
1397*86d7f5d3SJohn Marino 	}
1398*86d7f5d3SJohn Marino 
1399*86d7f5d3SJohn Marino 	if (r >= 0) {
1400*86d7f5d3SJohn Marino 		keyslot = r;
1401*86d7f5d3SJohn Marino 		r = dm_resume_and_reinstate_key(name, mk->keyLength, mk->key);
1402*86d7f5d3SJohn Marino 		if (r)
1403*86d7f5d3SJohn Marino 			log_err(cd, "Error during resuming device %s.\n", name);
1404*86d7f5d3SJohn Marino 	} else
1405*86d7f5d3SJohn Marino 		r = keyslot;
1406*86d7f5d3SJohn Marino out:
1407*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
1408*86d7f5d3SJohn Marino 	return r < 0 ? r : keyslot;
1409*86d7f5d3SJohn Marino }
1410*86d7f5d3SJohn Marino 
1411*86d7f5d3SJohn Marino // slot manipulation
crypt_keyslot_add_by_passphrase(struct crypt_device * cd,int keyslot,const char * passphrase,size_t passphrase_size,const char * new_passphrase,size_t new_passphrase_size)1412*86d7f5d3SJohn Marino int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
1413*86d7f5d3SJohn Marino 	int keyslot, // -1 any
1414*86d7f5d3SJohn Marino 	const char *passphrase, // NULL -> terminal
1415*86d7f5d3SJohn Marino 	size_t passphrase_size,
1416*86d7f5d3SJohn Marino 	const char *new_passphrase, // NULL -> terminal
1417*86d7f5d3SJohn Marino 	size_t new_passphrase_size)
1418*86d7f5d3SJohn Marino {
1419*86d7f5d3SJohn Marino 	struct luks_masterkey *mk = NULL;
1420*86d7f5d3SJohn Marino 	char *password = NULL, *new_password = NULL;
1421*86d7f5d3SJohn Marino 	unsigned int passwordLen, new_passwordLen;
1422*86d7f5d3SJohn Marino 	int r;
1423*86d7f5d3SJohn Marino 
1424*86d7f5d3SJohn Marino 	log_dbg("Adding new keyslot, existing passphrase %sprovided,"
1425*86d7f5d3SJohn Marino 		"new passphrase %sprovided.",
1426*86d7f5d3SJohn Marino 		passphrase ? "" : "not ", new_passphrase  ? "" : "not ");
1427*86d7f5d3SJohn Marino 
1428*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
1429*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1430*86d7f5d3SJohn Marino 		return -EINVAL;
1431*86d7f5d3SJohn Marino 	}
1432*86d7f5d3SJohn Marino 
1433*86d7f5d3SJohn Marino 	r = keyslot_verify_or_find_empty(cd, &keyslot);
1434*86d7f5d3SJohn Marino 	if (r)
1435*86d7f5d3SJohn Marino 		return r;
1436*86d7f5d3SJohn Marino 
1437*86d7f5d3SJohn Marino 	if (!LUKS_keyslot_active_count(&cd->hdr)) {
1438*86d7f5d3SJohn Marino 		/* No slots used, try to use pre-generated key in header */
1439*86d7f5d3SJohn Marino 		if (cd->volume_key) {
1440*86d7f5d3SJohn Marino 			mk = LUKS_alloc_masterkey(cd->volume_key->keyLength, cd->volume_key->key);
1441*86d7f5d3SJohn Marino 			r = mk ? 0 : -ENOMEM;
1442*86d7f5d3SJohn Marino 		} else {
1443*86d7f5d3SJohn Marino 			log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided.\n"));
1444*86d7f5d3SJohn Marino 			return -EINVAL;
1445*86d7f5d3SJohn Marino 		}
1446*86d7f5d3SJohn Marino 	} else if (passphrase) {
1447*86d7f5d3SJohn Marino 		/* Passphrase provided, use it to unlock existing keyslot */
1448*86d7f5d3SJohn Marino 		r = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, passphrase,
1449*86d7f5d3SJohn Marino 					   passphrase_size, &cd->hdr, &mk, cd);
1450*86d7f5d3SJohn Marino 	} else {
1451*86d7f5d3SJohn Marino 		/* Passphrase not provided, ask first and use it to unlock existing keyslot */
1452*86d7f5d3SJohn Marino 		key_from_terminal(cd, _("Enter any passphrase: "),
1453*86d7f5d3SJohn Marino 				  &password, &passwordLen, 0);
1454*86d7f5d3SJohn Marino 		if (!password) {
1455*86d7f5d3SJohn Marino 			r = -EINVAL;
1456*86d7f5d3SJohn Marino 			goto out;
1457*86d7f5d3SJohn Marino 		}
1458*86d7f5d3SJohn Marino 
1459*86d7f5d3SJohn Marino 		r = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, password,
1460*86d7f5d3SJohn Marino 					   passwordLen, &cd->hdr, &mk, cd);
1461*86d7f5d3SJohn Marino 		safe_free(password);
1462*86d7f5d3SJohn Marino 	}
1463*86d7f5d3SJohn Marino 
1464*86d7f5d3SJohn Marino 	if(r < 0)
1465*86d7f5d3SJohn Marino 		goto out;
1466*86d7f5d3SJohn Marino 
1467*86d7f5d3SJohn Marino 	if (new_passphrase) {
1468*86d7f5d3SJohn Marino 		new_password = (char *)new_passphrase;
1469*86d7f5d3SJohn Marino 		new_passwordLen = new_passphrase_size;
1470*86d7f5d3SJohn Marino 	} else {
1471*86d7f5d3SJohn Marino 		key_from_terminal(cd, _("Enter new passphrase for key slot: "),
1472*86d7f5d3SJohn Marino 				  &new_password, &new_passwordLen, 1);
1473*86d7f5d3SJohn Marino 		if(!new_password) {
1474*86d7f5d3SJohn Marino 			r = -EINVAL;
1475*86d7f5d3SJohn Marino 			goto out;
1476*86d7f5d3SJohn Marino 		}
1477*86d7f5d3SJohn Marino 	}
1478*86d7f5d3SJohn Marino 
1479*86d7f5d3SJohn Marino 	r = LUKS_set_key(cd->device, keyslot, new_password, new_passwordLen,
1480*86d7f5d3SJohn Marino 			 &cd->hdr, mk, cd->iteration_time, &cd->PBKDF2_per_sec, cd);
1481*86d7f5d3SJohn Marino 	if(r < 0) goto out;
1482*86d7f5d3SJohn Marino 
1483*86d7f5d3SJohn Marino 	r = 0;
1484*86d7f5d3SJohn Marino out:
1485*86d7f5d3SJohn Marino 	if (!new_passphrase)
1486*86d7f5d3SJohn Marino 		safe_free(new_password);
1487*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
1488*86d7f5d3SJohn Marino 	return r ?: keyslot;
1489*86d7f5d3SJohn Marino }
1490*86d7f5d3SJohn Marino 
crypt_keyslot_add_by_keyfile(struct crypt_device * cd,int keyslot,const char * keyfile,size_t keyfile_size,const char * new_keyfile,size_t new_keyfile_size)1491*86d7f5d3SJohn Marino int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
1492*86d7f5d3SJohn Marino 	int keyslot,
1493*86d7f5d3SJohn Marino 	const char *keyfile,
1494*86d7f5d3SJohn Marino 	size_t keyfile_size,
1495*86d7f5d3SJohn Marino 	const char *new_keyfile,
1496*86d7f5d3SJohn Marino 	size_t new_keyfile_size)
1497*86d7f5d3SJohn Marino {
1498*86d7f5d3SJohn Marino 	struct luks_masterkey *mk=NULL;
1499*86d7f5d3SJohn Marino 	char *password=NULL; unsigned int passwordLen;
1500*86d7f5d3SJohn Marino 	char *new_password = NULL; unsigned int new_passwordLen;
1501*86d7f5d3SJohn Marino 	int r;
1502*86d7f5d3SJohn Marino 
1503*86d7f5d3SJohn Marino 	log_dbg("Adding new keyslot, existing keyfile %s, new keyfile %s.",
1504*86d7f5d3SJohn Marino 		keyfile ?: "[none]", new_keyfile ?: "[none]");
1505*86d7f5d3SJohn Marino 
1506*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
1507*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1508*86d7f5d3SJohn Marino 		return -EINVAL;
1509*86d7f5d3SJohn Marino 	}
1510*86d7f5d3SJohn Marino 
1511*86d7f5d3SJohn Marino 	r = keyslot_verify_or_find_empty(cd, &keyslot);
1512*86d7f5d3SJohn Marino 	if (r)
1513*86d7f5d3SJohn Marino 		return r;
1514*86d7f5d3SJohn Marino 
1515*86d7f5d3SJohn Marino 	if (!LUKS_keyslot_active_count(&cd->hdr)) {
1516*86d7f5d3SJohn Marino 		/* No slots used, try to use pre-generated key in header */
1517*86d7f5d3SJohn Marino 		if (cd->volume_key) {
1518*86d7f5d3SJohn Marino 			mk = LUKS_alloc_masterkey(cd->volume_key->keyLength, cd->volume_key->key);
1519*86d7f5d3SJohn Marino 			r = mk ? 0 : -ENOMEM;
1520*86d7f5d3SJohn Marino 		} else {
1521*86d7f5d3SJohn Marino 			log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided.\n"));
1522*86d7f5d3SJohn Marino 			return -EINVAL;
1523*86d7f5d3SJohn Marino 		}
1524*86d7f5d3SJohn Marino 	} else {
1525*86d7f5d3SJohn Marino 		/* Read password from file of (if NULL) from terminal */
1526*86d7f5d3SJohn Marino 		if (keyfile)
1527*86d7f5d3SJohn Marino 			key_from_file(cd, _("Enter any passphrase: "), &password, &passwordLen,
1528*86d7f5d3SJohn Marino 				      keyfile, keyfile_size);
1529*86d7f5d3SJohn Marino 		else
1530*86d7f5d3SJohn Marino 			key_from_terminal(cd, _("Enter any passphrase: "),
1531*86d7f5d3SJohn Marino 					&password, &passwordLen, 0);
1532*86d7f5d3SJohn Marino 
1533*86d7f5d3SJohn Marino 		if (!password)
1534*86d7f5d3SJohn Marino 			return -EINVAL;
1535*86d7f5d3SJohn Marino 
1536*86d7f5d3SJohn Marino 		r = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, password, passwordLen,
1537*86d7f5d3SJohn Marino 					   &cd->hdr, &mk, cd);
1538*86d7f5d3SJohn Marino 		safe_free(password);
1539*86d7f5d3SJohn Marino 	}
1540*86d7f5d3SJohn Marino 
1541*86d7f5d3SJohn Marino 	if(r < 0)
1542*86d7f5d3SJohn Marino 		goto out;
1543*86d7f5d3SJohn Marino 
1544*86d7f5d3SJohn Marino 	if (new_keyfile)
1545*86d7f5d3SJohn Marino 		key_from_file(cd, _("Enter new passphrase for key slot: "),
1546*86d7f5d3SJohn Marino 			      &new_password, &new_passwordLen, new_keyfile,
1547*86d7f5d3SJohn Marino 			      new_keyfile_size);
1548*86d7f5d3SJohn Marino 	else
1549*86d7f5d3SJohn Marino 		key_from_terminal(cd, _("Enter new passphrase for key slot: "),
1550*86d7f5d3SJohn Marino 				  &new_password, &new_passwordLen, 1);
1551*86d7f5d3SJohn Marino 
1552*86d7f5d3SJohn Marino 	if(!new_password) {
1553*86d7f5d3SJohn Marino 		r = -EINVAL;
1554*86d7f5d3SJohn Marino 		goto out;
1555*86d7f5d3SJohn Marino 	}
1556*86d7f5d3SJohn Marino 
1557*86d7f5d3SJohn Marino 	r = LUKS_set_key(cd->device, keyslot, new_password, new_passwordLen,
1558*86d7f5d3SJohn Marino 			 &cd->hdr, mk, cd->iteration_time, &cd->PBKDF2_per_sec, cd);
1559*86d7f5d3SJohn Marino out:
1560*86d7f5d3SJohn Marino 	safe_free(new_password);
1561*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
1562*86d7f5d3SJohn Marino 	return r < 0 ? r : keyslot;
1563*86d7f5d3SJohn Marino }
1564*86d7f5d3SJohn Marino 
crypt_keyslot_add_by_volume_key(struct crypt_device * cd,int keyslot,const char * volume_key,size_t volume_key_size,const char * passphrase,size_t passphrase_size)1565*86d7f5d3SJohn Marino int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
1566*86d7f5d3SJohn Marino 	int keyslot,
1567*86d7f5d3SJohn Marino 	const char *volume_key,
1568*86d7f5d3SJohn Marino 	size_t volume_key_size,
1569*86d7f5d3SJohn Marino 	const char *passphrase,
1570*86d7f5d3SJohn Marino 	size_t passphrase_size)
1571*86d7f5d3SJohn Marino {
1572*86d7f5d3SJohn Marino 	struct luks_masterkey *mk = NULL;
1573*86d7f5d3SJohn Marino 	int r = -EINVAL;
1574*86d7f5d3SJohn Marino 	char *new_password = NULL; unsigned int new_passwordLen;
1575*86d7f5d3SJohn Marino 
1576*86d7f5d3SJohn Marino 	log_dbg("Adding new keyslot %d using volume key.", keyslot);
1577*86d7f5d3SJohn Marino 
1578*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
1579*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1580*86d7f5d3SJohn Marino 		return -EINVAL;
1581*86d7f5d3SJohn Marino 	}
1582*86d7f5d3SJohn Marino 
1583*86d7f5d3SJohn Marino 	if (volume_key)
1584*86d7f5d3SJohn Marino 		mk = LUKS_alloc_masterkey(volume_key_size, volume_key);
1585*86d7f5d3SJohn Marino 	else if (cd->volume_key)
1586*86d7f5d3SJohn Marino 		mk = LUKS_alloc_masterkey(cd->volume_key->keyLength, cd->volume_key->key);
1587*86d7f5d3SJohn Marino 
1588*86d7f5d3SJohn Marino 	if (!mk)
1589*86d7f5d3SJohn Marino 		return -ENOMEM;
1590*86d7f5d3SJohn Marino 
1591*86d7f5d3SJohn Marino 	r = LUKS_verify_master_key(&cd->hdr, mk);
1592*86d7f5d3SJohn Marino 	if (r < 0) {
1593*86d7f5d3SJohn Marino 		log_err(cd, _("Volume key does not match the volume.\n"));
1594*86d7f5d3SJohn Marino 		goto out;
1595*86d7f5d3SJohn Marino 	}
1596*86d7f5d3SJohn Marino 
1597*86d7f5d3SJohn Marino 	r = keyslot_verify_or_find_empty(cd, &keyslot);
1598*86d7f5d3SJohn Marino 	if (r)
1599*86d7f5d3SJohn Marino 		goto out;
1600*86d7f5d3SJohn Marino 
1601*86d7f5d3SJohn Marino 	if (!passphrase) {
1602*86d7f5d3SJohn Marino 		key_from_terminal(cd, _("Enter new passphrase for key slot: "),
1603*86d7f5d3SJohn Marino 				  &new_password, &new_passwordLen, 1);
1604*86d7f5d3SJohn Marino 		passphrase = new_password;
1605*86d7f5d3SJohn Marino 		passphrase_size = new_passwordLen;
1606*86d7f5d3SJohn Marino 	}
1607*86d7f5d3SJohn Marino 
1608*86d7f5d3SJohn Marino 	r = LUKS_set_key(cd->device, keyslot, passphrase, passphrase_size,
1609*86d7f5d3SJohn Marino 			 &cd->hdr, mk, cd->iteration_time, &cd->PBKDF2_per_sec, cd);
1610*86d7f5d3SJohn Marino out:
1611*86d7f5d3SJohn Marino 	if (new_password)
1612*86d7f5d3SJohn Marino 		safe_free(new_password);
1613*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
1614*86d7f5d3SJohn Marino 	return r ?: keyslot;
1615*86d7f5d3SJohn Marino }
1616*86d7f5d3SJohn Marino 
crypt_keyslot_destroy(struct crypt_device * cd,int keyslot)1617*86d7f5d3SJohn Marino int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot)
1618*86d7f5d3SJohn Marino {
1619*86d7f5d3SJohn Marino 	crypt_keyslot_info ki;
1620*86d7f5d3SJohn Marino 
1621*86d7f5d3SJohn Marino 	log_dbg("Destroying keyslot %d.", keyslot);
1622*86d7f5d3SJohn Marino 
1623*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
1624*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1625*86d7f5d3SJohn Marino 		return -EINVAL;
1626*86d7f5d3SJohn Marino 	}
1627*86d7f5d3SJohn Marino 
1628*86d7f5d3SJohn Marino 	ki = crypt_keyslot_status(cd, keyslot);
1629*86d7f5d3SJohn Marino 	if (ki == CRYPT_SLOT_INVALID) {
1630*86d7f5d3SJohn Marino 		log_err(cd, _("Key slot %d is invalid.\n"), keyslot);
1631*86d7f5d3SJohn Marino 		return -EINVAL;
1632*86d7f5d3SJohn Marino 	}
1633*86d7f5d3SJohn Marino 
1634*86d7f5d3SJohn Marino 	if (ki == CRYPT_SLOT_INACTIVE) {
1635*86d7f5d3SJohn Marino 		log_err(cd, _("Key slot %d is not used.\n"), keyslot);
1636*86d7f5d3SJohn Marino 		return -EINVAL;
1637*86d7f5d3SJohn Marino 	}
1638*86d7f5d3SJohn Marino 
1639*86d7f5d3SJohn Marino 	return LUKS_del_key(cd->device, keyslot, &cd->hdr, cd);
1640*86d7f5d3SJohn Marino }
1641*86d7f5d3SJohn Marino 
1642*86d7f5d3SJohn Marino // activation/deactivation of device mapping
crypt_activate_by_passphrase(struct crypt_device * cd,const char * name,int keyslot,const char * passphrase,size_t passphrase_size,uint32_t flags)1643*86d7f5d3SJohn Marino int crypt_activate_by_passphrase(struct crypt_device *cd,
1644*86d7f5d3SJohn Marino 	const char *name,
1645*86d7f5d3SJohn Marino 	int keyslot,
1646*86d7f5d3SJohn Marino 	const char *passphrase,
1647*86d7f5d3SJohn Marino 	size_t passphrase_size,
1648*86d7f5d3SJohn Marino 	uint32_t flags)
1649*86d7f5d3SJohn Marino {
1650*86d7f5d3SJohn Marino 	crypt_status_info ci;
1651*86d7f5d3SJohn Marino 	struct luks_masterkey *mk = NULL;
1652*86d7f5d3SJohn Marino 	char *prompt = NULL;
1653*86d7f5d3SJohn Marino 	int r;
1654*86d7f5d3SJohn Marino 
1655*86d7f5d3SJohn Marino 	log_dbg("%s volume %s [keyslot %d] using %spassphrase.",
1656*86d7f5d3SJohn Marino 		name ? "Activating" : "Checking", name ?: "",
1657*86d7f5d3SJohn Marino 		keyslot, passphrase ? "" : "[none] ");
1658*86d7f5d3SJohn Marino 
1659*86d7f5d3SJohn Marino 	if (!name)
1660*86d7f5d3SJohn Marino 		return -EINVAL;
1661*86d7f5d3SJohn Marino 
1662*86d7f5d3SJohn Marino 	/* plain, use hashed passphrase */
1663*86d7f5d3SJohn Marino 	if (isPLAIN(cd->type))
1664*86d7f5d3SJohn Marino 		return create_device_helper(cd, name, cd->plain_hdr.hash,
1665*86d7f5d3SJohn Marino 			cd->plain_cipher, cd->plain_cipher_mode, NULL, passphrase, passphrase_size,
1666*86d7f5d3SJohn Marino 			cd->volume_key->keyLength, 0, cd->plain_hdr.skip,
1667*86d7f5d3SJohn Marino 			cd->plain_hdr.offset, cd->plain_uuid, flags & CRYPT_ACTIVATE_READONLY, 0, 0);
1668*86d7f5d3SJohn Marino 
1669*86d7f5d3SJohn Marino 	if (name) {
1670*86d7f5d3SJohn Marino 		ci = crypt_status(NULL, name);
1671*86d7f5d3SJohn Marino 		if (ci == CRYPT_INVALID)
1672*86d7f5d3SJohn Marino 			return -EINVAL;
1673*86d7f5d3SJohn Marino 		else if (ci >= CRYPT_ACTIVE) {
1674*86d7f5d3SJohn Marino 			log_err(cd, _("Device %s already exists.\n"), name);
1675*86d7f5d3SJohn Marino 			return -EEXIST;
1676*86d7f5d3SJohn Marino 		}
1677*86d7f5d3SJohn Marino 	}
1678*86d7f5d3SJohn Marino 
1679*86d7f5d3SJohn Marino 	if(asprintf(&prompt, _("Enter passphrase for %s: "), cd->device) < 0)
1680*86d7f5d3SJohn Marino 		return -ENOMEM;
1681*86d7f5d3SJohn Marino 
1682*86d7f5d3SJohn Marino 	/* provided passphrase, do not retry */
1683*86d7f5d3SJohn Marino 	if (passphrase) {
1684*86d7f5d3SJohn Marino 		r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
1685*86d7f5d3SJohn Marino 					   passphrase_size, &cd->hdr, &mk, cd);
1686*86d7f5d3SJohn Marino 	} else
1687*86d7f5d3SJohn Marino 		r = volume_key_by_terminal_passphrase(cd, keyslot, &mk);
1688*86d7f5d3SJohn Marino 
1689*86d7f5d3SJohn Marino 	if (r >= 0) {
1690*86d7f5d3SJohn Marino 		keyslot = r;
1691*86d7f5d3SJohn Marino 		if (name)
1692*86d7f5d3SJohn Marino 			r = open_from_hdr_and_mk(cd, mk, name, flags);
1693*86d7f5d3SJohn Marino 	}
1694*86d7f5d3SJohn Marino 
1695*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
1696*86d7f5d3SJohn Marino 	free(prompt);
1697*86d7f5d3SJohn Marino 
1698*86d7f5d3SJohn Marino 	return r < 0  ? r : keyslot;
1699*86d7f5d3SJohn Marino }
1700*86d7f5d3SJohn Marino 
crypt_activate_by_keyfile(struct crypt_device * cd,const char * name,int keyslot,const char * keyfile,size_t keyfile_size,uint32_t flags)1701*86d7f5d3SJohn Marino int crypt_activate_by_keyfile(struct crypt_device *cd,
1702*86d7f5d3SJohn Marino 	const char *name,
1703*86d7f5d3SJohn Marino 	int keyslot,
1704*86d7f5d3SJohn Marino 	const char *keyfile,
1705*86d7f5d3SJohn Marino 	size_t keyfile_size,
1706*86d7f5d3SJohn Marino 	uint32_t flags)
1707*86d7f5d3SJohn Marino {
1708*86d7f5d3SJohn Marino 	crypt_status_info ci;
1709*86d7f5d3SJohn Marino 	struct luks_masterkey *mk = NULL;
1710*86d7f5d3SJohn Marino 	char *passphrase_read = NULL;
1711*86d7f5d3SJohn Marino 	unsigned int passphrase_size_read;
1712*86d7f5d3SJohn Marino 	int r;
1713*86d7f5d3SJohn Marino 
1714*86d7f5d3SJohn Marino 	log_dbg("Activating volume %s [keyslot %d] using keyfile %s.",
1715*86d7f5d3SJohn Marino 		name, keyslot, keyfile ?: "[none]");
1716*86d7f5d3SJohn Marino 
1717*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
1718*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1719*86d7f5d3SJohn Marino 		return -EINVAL;
1720*86d7f5d3SJohn Marino 	}
1721*86d7f5d3SJohn Marino 
1722*86d7f5d3SJohn Marino 	if (name) {
1723*86d7f5d3SJohn Marino 		ci = crypt_status(NULL, name);
1724*86d7f5d3SJohn Marino 		if (ci == CRYPT_INVALID)
1725*86d7f5d3SJohn Marino 			return -EINVAL;
1726*86d7f5d3SJohn Marino 		else if (ci >= CRYPT_ACTIVE) {
1727*86d7f5d3SJohn Marino 			log_err(cd, _("Device %s already exists.\n"), name);
1728*86d7f5d3SJohn Marino 			return -EEXIST;
1729*86d7f5d3SJohn Marino 		}
1730*86d7f5d3SJohn Marino 	}
1731*86d7f5d3SJohn Marino 
1732*86d7f5d3SJohn Marino 	if (!keyfile)
1733*86d7f5d3SJohn Marino 		return -EINVAL;
1734*86d7f5d3SJohn Marino 
1735*86d7f5d3SJohn Marino 	key_from_file(cd, _("Enter passphrase: "), &passphrase_read,
1736*86d7f5d3SJohn Marino 		      &passphrase_size_read, keyfile, keyfile_size);
1737*86d7f5d3SJohn Marino 	if(!passphrase_read)
1738*86d7f5d3SJohn Marino 		r = -EINVAL;
1739*86d7f5d3SJohn Marino 	else {
1740*86d7f5d3SJohn Marino 		r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase_read,
1741*86d7f5d3SJohn Marino 					   passphrase_size_read, &cd->hdr, &mk, cd);
1742*86d7f5d3SJohn Marino 		safe_free(passphrase_read);
1743*86d7f5d3SJohn Marino 	}
1744*86d7f5d3SJohn Marino 
1745*86d7f5d3SJohn Marino 	if (r >= 0) {
1746*86d7f5d3SJohn Marino 		keyslot = r;
1747*86d7f5d3SJohn Marino 		r = open_from_hdr_and_mk(cd, mk, name, flags);
1748*86d7f5d3SJohn Marino 	}
1749*86d7f5d3SJohn Marino 
1750*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
1751*86d7f5d3SJohn Marino 
1752*86d7f5d3SJohn Marino 	return r < 0 ? r : keyslot;
1753*86d7f5d3SJohn Marino }
1754*86d7f5d3SJohn Marino 
crypt_activate_by_volume_key(struct crypt_device * cd,const char * name,const char * volume_key,size_t volume_key_size,uint32_t flags)1755*86d7f5d3SJohn Marino int crypt_activate_by_volume_key(struct crypt_device *cd,
1756*86d7f5d3SJohn Marino 	const char *name,
1757*86d7f5d3SJohn Marino 	const char *volume_key,
1758*86d7f5d3SJohn Marino 	size_t volume_key_size,
1759*86d7f5d3SJohn Marino 	uint32_t flags)
1760*86d7f5d3SJohn Marino {
1761*86d7f5d3SJohn Marino 	crypt_status_info ci;
1762*86d7f5d3SJohn Marino 	struct luks_masterkey *mk;
1763*86d7f5d3SJohn Marino 	int r;
1764*86d7f5d3SJohn Marino 
1765*86d7f5d3SJohn Marino 	log_dbg("Activating volume %s by volume key.", name);
1766*86d7f5d3SJohn Marino 
1767*86d7f5d3SJohn Marino 	/* use key directly, no hash */
1768*86d7f5d3SJohn Marino 	if (isPLAIN(cd->type))
1769*86d7f5d3SJohn Marino 		return create_device_helper(cd, name, NULL,
1770*86d7f5d3SJohn Marino 			cd->plain_cipher, cd->plain_cipher_mode, NULL, volume_key, volume_key_size,
1771*86d7f5d3SJohn Marino 			cd->volume_key->keyLength, 0, cd->plain_hdr.skip,
1772*86d7f5d3SJohn Marino 			cd->plain_hdr.offset, cd->plain_uuid, flags & CRYPT_ACTIVATE_READONLY, 0, 0);
1773*86d7f5d3SJohn Marino 
1774*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
1775*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1776*86d7f5d3SJohn Marino 		return -EINVAL;
1777*86d7f5d3SJohn Marino 	}
1778*86d7f5d3SJohn Marino 
1779*86d7f5d3SJohn Marino 	if (name) {
1780*86d7f5d3SJohn Marino 		ci = crypt_status(NULL, name);
1781*86d7f5d3SJohn Marino 		if (ci == CRYPT_INVALID)
1782*86d7f5d3SJohn Marino 			return -EINVAL;
1783*86d7f5d3SJohn Marino 		else if (ci >= CRYPT_ACTIVE) {
1784*86d7f5d3SJohn Marino 			log_err(cd, _("Device %s already exists.\n"), name);
1785*86d7f5d3SJohn Marino 			return -EEXIST;
1786*86d7f5d3SJohn Marino 		}
1787*86d7f5d3SJohn Marino 	}
1788*86d7f5d3SJohn Marino 
1789*86d7f5d3SJohn Marino 	mk = LUKS_alloc_masterkey(volume_key_size, volume_key);
1790*86d7f5d3SJohn Marino 	if (!mk)
1791*86d7f5d3SJohn Marino 		return -ENOMEM;
1792*86d7f5d3SJohn Marino 	r = LUKS_verify_master_key(&cd->hdr, mk);
1793*86d7f5d3SJohn Marino 
1794*86d7f5d3SJohn Marino 	if (r == -EPERM)
1795*86d7f5d3SJohn Marino 		log_err(cd, _("Volume key does not match the volume.\n"));
1796*86d7f5d3SJohn Marino 
1797*86d7f5d3SJohn Marino 	if (!r && name)
1798*86d7f5d3SJohn Marino 		r = open_from_hdr_and_mk(cd, mk, name, flags);
1799*86d7f5d3SJohn Marino 
1800*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
1801*86d7f5d3SJohn Marino 
1802*86d7f5d3SJohn Marino 	return r;
1803*86d7f5d3SJohn Marino }
1804*86d7f5d3SJohn Marino 
crypt_deactivate(struct crypt_device * cd,const char * name)1805*86d7f5d3SJohn Marino int crypt_deactivate(struct crypt_device *cd, const char *name)
1806*86d7f5d3SJohn Marino {
1807*86d7f5d3SJohn Marino 	int r;
1808*86d7f5d3SJohn Marino 
1809*86d7f5d3SJohn Marino 	if (!name)
1810*86d7f5d3SJohn Marino 		return -EINVAL;
1811*86d7f5d3SJohn Marino 
1812*86d7f5d3SJohn Marino 	log_dbg("Deactivating volume %s.", name);
1813*86d7f5d3SJohn Marino 
1814*86d7f5d3SJohn Marino 	if (!cd && dm_init(NULL, 1) < 0)
1815*86d7f5d3SJohn Marino 		return -ENOSYS;
1816*86d7f5d3SJohn Marino 
1817*86d7f5d3SJohn Marino 	switch (crypt_status(cd, name)) {
1818*86d7f5d3SJohn Marino 		case CRYPT_ACTIVE:
1819*86d7f5d3SJohn Marino 			r = dm_remove_device(name, 0, 0);
1820*86d7f5d3SJohn Marino 			break;
1821*86d7f5d3SJohn Marino 		case CRYPT_BUSY:
1822*86d7f5d3SJohn Marino 			log_err(cd, _("Device %s is busy.\n"), name);
1823*86d7f5d3SJohn Marino 			r = -EBUSY;
1824*86d7f5d3SJohn Marino 			break;
1825*86d7f5d3SJohn Marino 		case CRYPT_INACTIVE:
1826*86d7f5d3SJohn Marino 			log_err(cd, _("Device %s is not active.\n"), name);
1827*86d7f5d3SJohn Marino 			r = -ENODEV;
1828*86d7f5d3SJohn Marino 			break;
1829*86d7f5d3SJohn Marino 		default:
1830*86d7f5d3SJohn Marino 			log_err(cd, _("Invalid device %s.\n"), name);
1831*86d7f5d3SJohn Marino 			r = -EINVAL;
1832*86d7f5d3SJohn Marino 	}
1833*86d7f5d3SJohn Marino 
1834*86d7f5d3SJohn Marino 	if (!cd)
1835*86d7f5d3SJohn Marino 		dm_exit();
1836*86d7f5d3SJohn Marino 
1837*86d7f5d3SJohn Marino 	return r;
1838*86d7f5d3SJohn Marino }
1839*86d7f5d3SJohn Marino 
1840*86d7f5d3SJohn Marino // misc helper functions
crypt_volume_key_get(struct crypt_device * cd,int keyslot,char * volume_key,size_t * volume_key_size,const char * passphrase,size_t passphrase_size)1841*86d7f5d3SJohn Marino int crypt_volume_key_get(struct crypt_device *cd,
1842*86d7f5d3SJohn Marino 	int keyslot,
1843*86d7f5d3SJohn Marino 	char *volume_key,
1844*86d7f5d3SJohn Marino 	size_t *volume_key_size,
1845*86d7f5d3SJohn Marino 	const char *passphrase,
1846*86d7f5d3SJohn Marino 	size_t passphrase_size)
1847*86d7f5d3SJohn Marino {
1848*86d7f5d3SJohn Marino 	struct luks_masterkey *mk;
1849*86d7f5d3SJohn Marino 	char *processed_key = NULL;
1850*86d7f5d3SJohn Marino 	int r, key_len;
1851*86d7f5d3SJohn Marino 
1852*86d7f5d3SJohn Marino 	key_len = crypt_get_volume_key_size(cd);
1853*86d7f5d3SJohn Marino 	if (key_len > *volume_key_size) {
1854*86d7f5d3SJohn Marino 		log_err(cd, _("Volume key buffer too small.\n"));
1855*86d7f5d3SJohn Marino 		return -ENOMEM;
1856*86d7f5d3SJohn Marino 	}
1857*86d7f5d3SJohn Marino 
1858*86d7f5d3SJohn Marino 	if (isPLAIN(cd->type) && cd->plain_hdr.hash) {
1859*86d7f5d3SJohn Marino 		processed_key = process_key(cd, cd->plain_hdr.hash, NULL, key_len,
1860*86d7f5d3SJohn Marino 					    passphrase, passphrase_size);
1861*86d7f5d3SJohn Marino 		if (!processed_key) {
1862*86d7f5d3SJohn Marino 			log_err(cd, _("Cannot retrieve volume key for plain device.\n"));
1863*86d7f5d3SJohn Marino 			return -EINVAL;
1864*86d7f5d3SJohn Marino 		}
1865*86d7f5d3SJohn Marino 		memcpy(volume_key, processed_key, key_len);
1866*86d7f5d3SJohn Marino 		*volume_key_size = key_len;
1867*86d7f5d3SJohn Marino 		safe_free(processed_key);
1868*86d7f5d3SJohn Marino 		return 0;
1869*86d7f5d3SJohn Marino 	}
1870*86d7f5d3SJohn Marino 
1871*86d7f5d3SJohn Marino 	if (isLUKS(cd->type)) {
1872*86d7f5d3SJohn Marino 		r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
1873*86d7f5d3SJohn Marino 					passphrase_size, &cd->hdr, &mk, cd);
1874*86d7f5d3SJohn Marino 
1875*86d7f5d3SJohn Marino 		if (r >= 0) {
1876*86d7f5d3SJohn Marino 			memcpy(volume_key, mk->key, mk->keyLength);
1877*86d7f5d3SJohn Marino 			*volume_key_size = mk->keyLength;
1878*86d7f5d3SJohn Marino 		}
1879*86d7f5d3SJohn Marino 
1880*86d7f5d3SJohn Marino 		LUKS_dealloc_masterkey(mk);
1881*86d7f5d3SJohn Marino 		return r;
1882*86d7f5d3SJohn Marino 	}
1883*86d7f5d3SJohn Marino 
1884*86d7f5d3SJohn Marino 	log_err(cd, _("This operation is not supported for %s crypt device.\n"), cd->type ?: "(none)");
1885*86d7f5d3SJohn Marino 	return -EINVAL;
1886*86d7f5d3SJohn Marino }
1887*86d7f5d3SJohn Marino 
crypt_volume_key_verify(struct crypt_device * cd,const char * volume_key,size_t volume_key_size)1888*86d7f5d3SJohn Marino int crypt_volume_key_verify(struct crypt_device *cd,
1889*86d7f5d3SJohn Marino 	const char *volume_key,
1890*86d7f5d3SJohn Marino 	size_t volume_key_size)
1891*86d7f5d3SJohn Marino {
1892*86d7f5d3SJohn Marino 	struct luks_masterkey *mk;
1893*86d7f5d3SJohn Marino 	int r;
1894*86d7f5d3SJohn Marino 
1895*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
1896*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1897*86d7f5d3SJohn Marino 		return -EINVAL;
1898*86d7f5d3SJohn Marino 	}
1899*86d7f5d3SJohn Marino 
1900*86d7f5d3SJohn Marino 	mk = LUKS_alloc_masterkey(volume_key_size, volume_key);
1901*86d7f5d3SJohn Marino 	if (!mk)
1902*86d7f5d3SJohn Marino 		return -ENOMEM;
1903*86d7f5d3SJohn Marino 
1904*86d7f5d3SJohn Marino 	r = LUKS_verify_master_key(&cd->hdr, mk);
1905*86d7f5d3SJohn Marino 
1906*86d7f5d3SJohn Marino 	if (r == -EPERM)
1907*86d7f5d3SJohn Marino 		log_err(cd, _("Volume key does not match the volume.\n"));
1908*86d7f5d3SJohn Marino 
1909*86d7f5d3SJohn Marino 	LUKS_dealloc_masterkey(mk);
1910*86d7f5d3SJohn Marino 
1911*86d7f5d3SJohn Marino 	return r;
1912*86d7f5d3SJohn Marino }
1913*86d7f5d3SJohn Marino 
crypt_set_timeout(struct crypt_device * cd,uint64_t timeout_sec)1914*86d7f5d3SJohn Marino void crypt_set_timeout(struct crypt_device *cd, uint64_t timeout_sec)
1915*86d7f5d3SJohn Marino {
1916*86d7f5d3SJohn Marino 	log_dbg("Timeout set to %" PRIu64 " miliseconds.", timeout_sec);
1917*86d7f5d3SJohn Marino 	cd->timeout = timeout_sec;
1918*86d7f5d3SJohn Marino }
1919*86d7f5d3SJohn Marino 
crypt_set_password_retry(struct crypt_device * cd,int tries)1920*86d7f5d3SJohn Marino void crypt_set_password_retry(struct crypt_device *cd, int tries)
1921*86d7f5d3SJohn Marino {
1922*86d7f5d3SJohn Marino 	log_dbg("Password retry count set to %d.", tries);
1923*86d7f5d3SJohn Marino 	cd->tries = tries;
1924*86d7f5d3SJohn Marino }
1925*86d7f5d3SJohn Marino 
crypt_set_iterarion_time(struct crypt_device * cd,uint64_t iteration_time_ms)1926*86d7f5d3SJohn Marino void crypt_set_iterarion_time(struct crypt_device *cd, uint64_t iteration_time_ms)
1927*86d7f5d3SJohn Marino {
1928*86d7f5d3SJohn Marino 	log_dbg("Iteration time set to %" PRIu64 " miliseconds.", iteration_time_ms);
1929*86d7f5d3SJohn Marino 	cd->iteration_time = iteration_time_ms;
1930*86d7f5d3SJohn Marino }
1931*86d7f5d3SJohn Marino 
crypt_set_password_verify(struct crypt_device * cd,int password_verify)1932*86d7f5d3SJohn Marino void crypt_set_password_verify(struct crypt_device *cd, int password_verify)
1933*86d7f5d3SJohn Marino {
1934*86d7f5d3SJohn Marino 	log_dbg("Password verification %s.", password_verify ? "enabled" : "disabled");
1935*86d7f5d3SJohn Marino 	cd->password_verify = password_verify ? 1 : 0;
1936*86d7f5d3SJohn Marino }
1937*86d7f5d3SJohn Marino 
crypt_memory_lock(struct crypt_device * cd,int lock)1938*86d7f5d3SJohn Marino int crypt_memory_lock(struct crypt_device *cd, int lock)
1939*86d7f5d3SJohn Marino {
1940*86d7f5d3SJohn Marino 	return lock ? crypt_memlock_inc(cd) : crypt_memlock_dec(cd);
1941*86d7f5d3SJohn Marino }
1942*86d7f5d3SJohn Marino 
1943*86d7f5d3SJohn Marino // reporting
crypt_status(struct crypt_device * cd,const char * name)1944*86d7f5d3SJohn Marino crypt_status_info crypt_status(struct crypt_device *cd, const char *name)
1945*86d7f5d3SJohn Marino {
1946*86d7f5d3SJohn Marino 	int r;
1947*86d7f5d3SJohn Marino 
1948*86d7f5d3SJohn Marino 	if (!cd && dm_init(NULL, 1) < 0)
1949*86d7f5d3SJohn Marino 		return CRYPT_INVALID;
1950*86d7f5d3SJohn Marino 
1951*86d7f5d3SJohn Marino 	r = dm_status_device(name);
1952*86d7f5d3SJohn Marino 
1953*86d7f5d3SJohn Marino 	if (!cd)
1954*86d7f5d3SJohn Marino 		dm_exit();
1955*86d7f5d3SJohn Marino 
1956*86d7f5d3SJohn Marino 	if (r < 0 && r != -ENODEV)
1957*86d7f5d3SJohn Marino 		return CRYPT_INVALID;
1958*86d7f5d3SJohn Marino 
1959*86d7f5d3SJohn Marino 	if (r == 0)
1960*86d7f5d3SJohn Marino 		return CRYPT_ACTIVE;
1961*86d7f5d3SJohn Marino 
1962*86d7f5d3SJohn Marino 	if (r > 0)
1963*86d7f5d3SJohn Marino 		return CRYPT_BUSY;
1964*86d7f5d3SJohn Marino 
1965*86d7f5d3SJohn Marino 	return CRYPT_INACTIVE;
1966*86d7f5d3SJohn Marino }
1967*86d7f5d3SJohn Marino 
hexprintICB(struct crypt_device * cd,char * d,int n)1968*86d7f5d3SJohn Marino static void hexprintICB(struct crypt_device *cd, char *d, int n)
1969*86d7f5d3SJohn Marino {
1970*86d7f5d3SJohn Marino 	int i;
1971*86d7f5d3SJohn Marino 	for(i = 0; i < n; i++)
1972*86d7f5d3SJohn Marino 		log_std(cd, "%02hhx ", (char)d[i]);
1973*86d7f5d3SJohn Marino }
1974*86d7f5d3SJohn Marino 
crypt_dump(struct crypt_device * cd)1975*86d7f5d3SJohn Marino int crypt_dump(struct crypt_device *cd)
1976*86d7f5d3SJohn Marino {
1977*86d7f5d3SJohn Marino 	int i;
1978*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) { //FIXME
1979*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
1980*86d7f5d3SJohn Marino 		return -EINVAL;
1981*86d7f5d3SJohn Marino 	}
1982*86d7f5d3SJohn Marino 
1983*86d7f5d3SJohn Marino 	log_std(cd, "LUKS header information for %s\n\n", cd->device);
1984*86d7f5d3SJohn Marino 	log_std(cd, "Version:       \t%d\n", cd->hdr.version);
1985*86d7f5d3SJohn Marino 	log_std(cd, "Cipher name:   \t%s\n", cd->hdr.cipherName);
1986*86d7f5d3SJohn Marino 	log_std(cd, "Cipher mode:   \t%s\n", cd->hdr.cipherMode);
1987*86d7f5d3SJohn Marino 	log_std(cd, "Hash spec:     \t%s\n", cd->hdr.hashSpec);
1988*86d7f5d3SJohn Marino 	log_std(cd, "Payload offset:\t%d\n", cd->hdr.payloadOffset);
1989*86d7f5d3SJohn Marino 	log_std(cd, "MK bits:       \t%d\n", cd->hdr.keyBytes * 8);
1990*86d7f5d3SJohn Marino 	log_std(cd, "MK digest:     \t");
1991*86d7f5d3SJohn Marino 	hexprintICB(cd, cd->hdr.mkDigest, LUKS_DIGESTSIZE);
1992*86d7f5d3SJohn Marino 	log_std(cd, "\n");
1993*86d7f5d3SJohn Marino 	log_std(cd, "MK salt:       \t");
1994*86d7f5d3SJohn Marino 	hexprintICB(cd, cd->hdr.mkDigestSalt, LUKS_SALTSIZE/2);
1995*86d7f5d3SJohn Marino 	log_std(cd, "\n               \t");
1996*86d7f5d3SJohn Marino 	hexprintICB(cd, cd->hdr.mkDigestSalt+LUKS_SALTSIZE/2, LUKS_SALTSIZE/2);
1997*86d7f5d3SJohn Marino 	log_std(cd, "\n");
1998*86d7f5d3SJohn Marino 	log_std(cd, "MK iterations: \t%d\n", cd->hdr.mkDigestIterations);
1999*86d7f5d3SJohn Marino 	log_std(cd, "UUID:          \t%s\n\n", cd->hdr.uuid);
2000*86d7f5d3SJohn Marino 	for(i = 0; i < LUKS_NUMKEYS; i++) {
2001*86d7f5d3SJohn Marino 		if(cd->hdr.keyblock[i].active == LUKS_KEY_ENABLED) {
2002*86d7f5d3SJohn Marino 			log_std(cd, "Key Slot %d: ENABLED\n",i);
2003*86d7f5d3SJohn Marino 			log_std(cd, "\tIterations:         \t%d\n",
2004*86d7f5d3SJohn Marino 				cd->hdr.keyblock[i].passwordIterations);
2005*86d7f5d3SJohn Marino 			log_std(cd, "\tSalt:               \t");
2006*86d7f5d3SJohn Marino 			hexprintICB(cd, cd->hdr.keyblock[i].passwordSalt,
2007*86d7f5d3SJohn Marino 				    LUKS_SALTSIZE/2);
2008*86d7f5d3SJohn Marino 			log_std(cd, "\n\t                      \t");
2009*86d7f5d3SJohn Marino 			hexprintICB(cd, cd->hdr.keyblock[i].passwordSalt +
2010*86d7f5d3SJohn Marino 				    LUKS_SALTSIZE/2, LUKS_SALTSIZE/2);
2011*86d7f5d3SJohn Marino 			log_std(cd, "\n");
2012*86d7f5d3SJohn Marino 
2013*86d7f5d3SJohn Marino 			log_std(cd, "\tKey material offset:\t%d\n",
2014*86d7f5d3SJohn Marino 				cd->hdr.keyblock[i].keyMaterialOffset);
2015*86d7f5d3SJohn Marino 			log_std(cd, "\tAF stripes:            \t%d\n",
2016*86d7f5d3SJohn Marino 				cd->hdr.keyblock[i].stripes);
2017*86d7f5d3SJohn Marino 		}
2018*86d7f5d3SJohn Marino 		else
2019*86d7f5d3SJohn Marino 			log_std(cd, "Key Slot %d: DISABLED\n", i);
2020*86d7f5d3SJohn Marino 	}
2021*86d7f5d3SJohn Marino 	return 0;
2022*86d7f5d3SJohn Marino }
2023*86d7f5d3SJohn Marino 
crypt_get_cipher(struct crypt_device * cd)2024*86d7f5d3SJohn Marino const char *crypt_get_cipher(struct crypt_device *cd)
2025*86d7f5d3SJohn Marino {
2026*86d7f5d3SJohn Marino 	if (isPLAIN(cd->type))
2027*86d7f5d3SJohn Marino 		return cd->plain_cipher;
2028*86d7f5d3SJohn Marino 
2029*86d7f5d3SJohn Marino 	if (isLUKS(cd->type))
2030*86d7f5d3SJohn Marino 		return cd->hdr.cipherName;
2031*86d7f5d3SJohn Marino 
2032*86d7f5d3SJohn Marino 	return NULL;
2033*86d7f5d3SJohn Marino }
2034*86d7f5d3SJohn Marino 
crypt_get_cipher_mode(struct crypt_device * cd)2035*86d7f5d3SJohn Marino const char *crypt_get_cipher_mode(struct crypt_device *cd)
2036*86d7f5d3SJohn Marino {
2037*86d7f5d3SJohn Marino 	if (isPLAIN(cd->type))
2038*86d7f5d3SJohn Marino 		return cd->plain_cipher_mode;
2039*86d7f5d3SJohn Marino 
2040*86d7f5d3SJohn Marino 	if (isLUKS(cd->type))
2041*86d7f5d3SJohn Marino 		return cd->hdr.cipherMode;
2042*86d7f5d3SJohn Marino 
2043*86d7f5d3SJohn Marino 	return NULL;
2044*86d7f5d3SJohn Marino }
2045*86d7f5d3SJohn Marino 
crypt_get_uuid(struct crypt_device * cd)2046*86d7f5d3SJohn Marino const char *crypt_get_uuid(struct crypt_device *cd)
2047*86d7f5d3SJohn Marino {
2048*86d7f5d3SJohn Marino 	if (isLUKS(cd->type))
2049*86d7f5d3SJohn Marino 		return cd->hdr.uuid;
2050*86d7f5d3SJohn Marino 
2051*86d7f5d3SJohn Marino 	return NULL;
2052*86d7f5d3SJohn Marino }
2053*86d7f5d3SJohn Marino 
crypt_get_volume_key_size(struct crypt_device * cd)2054*86d7f5d3SJohn Marino int crypt_get_volume_key_size(struct crypt_device *cd)
2055*86d7f5d3SJohn Marino {
2056*86d7f5d3SJohn Marino 	if (isPLAIN(cd->type))
2057*86d7f5d3SJohn Marino 		return cd->volume_key->keyLength;
2058*86d7f5d3SJohn Marino 
2059*86d7f5d3SJohn Marino 	if (isLUKS(cd->type))
2060*86d7f5d3SJohn Marino 		return cd->hdr.keyBytes;
2061*86d7f5d3SJohn Marino 
2062*86d7f5d3SJohn Marino 	return 0;
2063*86d7f5d3SJohn Marino }
2064*86d7f5d3SJohn Marino 
crypt_get_data_offset(struct crypt_device * cd)2065*86d7f5d3SJohn Marino uint64_t crypt_get_data_offset(struct crypt_device *cd)
2066*86d7f5d3SJohn Marino {
2067*86d7f5d3SJohn Marino 	if (isPLAIN(cd->type))
2068*86d7f5d3SJohn Marino 		return cd->plain_hdr.offset;
2069*86d7f5d3SJohn Marino 
2070*86d7f5d3SJohn Marino 	if (isLUKS(cd->type))
2071*86d7f5d3SJohn Marino 		return cd->hdr.payloadOffset;
2072*86d7f5d3SJohn Marino 
2073*86d7f5d3SJohn Marino 	return 0;
2074*86d7f5d3SJohn Marino }
2075*86d7f5d3SJohn Marino 
crypt_keyslot_status(struct crypt_device * cd,int keyslot)2076*86d7f5d3SJohn Marino crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot)
2077*86d7f5d3SJohn Marino {
2078*86d7f5d3SJohn Marino 	if (!isLUKS(cd->type)) {
2079*86d7f5d3SJohn Marino 		log_err(cd, _("This operation is supported only for LUKS device.\n"));
2080*86d7f5d3SJohn Marino 		return CRYPT_SLOT_INVALID;
2081*86d7f5d3SJohn Marino 	}
2082*86d7f5d3SJohn Marino 
2083*86d7f5d3SJohn Marino 	return LUKS_keyslot_info(&cd->hdr, keyslot);
2084*86d7f5d3SJohn Marino }
2085