示例#1
0
static int _open_plain( const char * device,const char * mapper,const char * mode,const char * pass,size_t pass_size )
{
	int flags ;
	
	struct crypt_device * cd ;
	struct crypt_params_plain params ;
	
	memset( &params,'\0',sizeof( struct crypt_params_plain ) ) ;
	
	params.hash = "ripemd160";
	params.skip = 0;
	params.offset = 0;
	
	if( zuluCryptPathIsNotValid( device ) ){
		return 3 ;
	}
	if( StringHasComponent( mode,"ro" ) ){
		flags = 1 ;
	}else{
		flags = 0 ;
	}
	if( crypt_init( &cd,device ) != 0 ){
		return 2 ;
	}
	if( crypt_format( cd,CRYPT_PLAIN,"aes","cbc-essiv:sha256",NULL,NULL,32,&params ) != 0 ){
		return zuluExit( 2,cd ) ;
	}
	if( crypt_activate_by_passphrase( cd,mapper,CRYPT_ANY_SLOT,pass,pass_size,flags ) < 0 ){
		return zuluExit( 2,cd ) ;
	}else{
		return zuluExit( 0,cd ) ;
	}
}
示例#2
0
static int _open_plain( const char * device,const open_struct_t * opt )
{
	uint32_t flags ;

	struct crypt_device * cd ;
	struct crypt_params_plain params ;

	memset( &params,'\0',sizeof( struct crypt_params_plain ) ) ;

	params.hash = "ripemd160" ;

	if( zuluCryptPathIsNotValid( device ) ){
		return 3 ;
	}
	if( crypt_init( &cd,device ) != 0 ){
		return 2 ;
	}

	params.offset = _offset( opt->offset ) ;

	if( StringHasComponent( opt->m_opts,"ro" ) ){
		flags = CRYPT_ACTIVATE_READONLY ;
	}else{
		flags = CRYPT_ACTIVATE_ALLOW_DISCARDS ;
	}
	if( crypt_format( cd,CRYPT_PLAIN,"aes","cbc-essiv:sha256",NULL,NULL,32,&params ) != 0 ){
		return zuluExit( 2,cd ) ;
	}
	if( crypt_activate_by_passphrase( cd,opt->mapper_name,CRYPT_ANY_SLOT,
		opt->key,opt->key_len,flags ) < 0 ){
		return zuluExit( 2,cd ) ;
	}else{
		return zuluExit( 0,cd ) ;
	}
}
示例#3
0
static int _open_plain( const char * device,const resolve_path_t * opts )
{
	uint32_t flags ;

	struct crypt_device * cd ;
	struct crypt_params_plain params ;

	size_t size ;
	/*
	 * open_struct_t is defined in includes.h
	 */
	const open_struct_t * opt = opts->args ;

	const args * e = opt->variables ;

	memset( &params,'\0',sizeof( struct crypt_params_plain ) ) ;

	params.hash = e->hash ;

	if( zuluCryptPathIsNotValid( device ) ){

		return 3 ;
	}
	if( crypt_init( &cd,device ) != 0 ){

		return 2 ;
	}

	params.offset = _offset( e->offset ) ;

	if( opts->open_mode == O_RDONLY ){

		flags = CRYPT_ACTIVATE_READONLY ;
	}else{
		flags = CRYPT_ACTIVATE_ALLOW_DISCARDS ;
	}

	size = ( size_t ) StringConvertToInt( e->keySize ) / 8 ;

	if( crypt_format( cd,CRYPT_PLAIN,e->algo,e->cipher,NULL,NULL,size,&params ) != 0 ){

		return zuluExit( 2,cd ) ;
	}
	if( crypt_activate_by_passphrase( cd,opt->mapper_name,CRYPT_ANY_SLOT,
		opt->key,opt->key_len,flags ) < 0 ){

		return zuluExit( 2,cd ) ;
	}else{
		return zuluExit( 0,cd ) ;
	}
}
static int create_new_header(struct reenc_ctx *rc, const char *cipher,
			     const char *cipher_mode, const char *uuid,
			     const char *key, int key_size,
			     struct crypt_params_luks1 *params)
{
	struct crypt_device *cd_new = NULL;
	int i, r;

	if ((r = crypt_init(&cd_new, rc->header_file_new)))
		goto out;

	if (opt_random)
		crypt_set_rng_type(cd_new, CRYPT_RNG_RANDOM);
	else if (opt_urandom)
		crypt_set_rng_type(cd_new, CRYPT_RNG_URANDOM);

	if (opt_iteration_time)
		crypt_set_iteration_time(cd_new, opt_iteration_time);

	if ((r = crypt_format(cd_new, CRYPT_LUKS1, cipher, cipher_mode,
			      uuid, key, key_size, params)))
		goto out;
	log_verbose(_("New LUKS header for device %s created.\n"), rc->device);

	for (i = 0; i < MAX_SLOT; i++) {
		if (!rc->p[i].password)
			continue;
		if ((r = crypt_keyslot_add_by_volume_key(cd_new, i,
			NULL, 0, rc->p[i].password, rc->p[i].passwordLen)) < 0)
			goto out;
		log_verbose(_("Activated keyslot %i.\n"), r);
		r = 0;
	}
out:
	crypt_free(cd_new);
	return r;
}
示例#5
0
static int format_and_add_keyslots(const char *path)
{
	struct crypt_device *cd;
	struct crypt_params_luks1 params;
	int r;

	/*
	 * crypt_init() call precedes most of operations of cryptsetup API. The call is used
	 * to initialize crypt device context stored in structure referenced by _cd_ in
	 * the example. Second parameter is used to pass underlaying device path.
	 *
	 * Note:
	 * If path refers to a regular file it'll be attached to a first free loop device.
	 * crypt_init() operation fails in case there's no more loop device available.
	 * Also, loop device will have the AUTOCLEAR flag set, so the file loopback will
	 * be detached automatically.
	 */

	r = crypt_init(&cd, path);
	if (r < 0 ) {
		printf("crypt_init() failed for %s.\n", path);
		return r;
	}

	printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));

	/*
	 * So far no data were written on your device. This will change with call of
	 * crypt_format() only if you specify CRYPT_LUKS1 as device type.
	 */
	printf("Device %s will be formatted to LUKS device after 5 seconds.\n"
	       "Press CTRL+C now if you want to cancel this operation.\n", path);
	sleep(5);


	/*
	 * Prepare LUKS format parameters
	 *
	 * hash parameter defines PBKDF2 hash algorithm used in LUKS header.
	 * For compatibility reason we use SHA1 here.
	 */
	params.hash = "sha1";

	/*
	 * data_alignment parameter is relevant only in case of the luks header
	 * and the payload are both stored on same device.
	 *
	 * if you set data_alignment = 0, cryptsetup will autodetect
	 * data_alignment according to underlaying device topology.
	 */
	params.data_alignment = 0;

	/*
	 * data_device parameter defines that no external device
	 * for luks header will be used
	 */
	params.data_device = NULL;

	/*
	 * NULLs for uuid and volume_key means that these attributes will be
	 * generated during crypt_format(). Volume key is generated with respect
	 * to key size parameter passed to function.
	 *
	 * crypt_format() checks device size (LUKS header must fit there).
	 */
	r = crypt_format(cd,		/* crypt context */
			 CRYPT_LUKS1,	/* LUKS1 is standard LUKS header */
			 "aes",		/* used cipher */
			 "xts-plain64",	/* used block mode and IV generator*/
			 NULL,		/* generate UUID */
			 NULL,		/* generate volume key from RNG */
			 256 / 8,	/* 256bit key - here AES-128 in XTS mode, size is in bytes */
			 &params);	/* parameters above */

	if(r < 0) {
		printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
		crypt_free(cd);
		return r;
	}

	/*
	 * The device now contains LUKS1 header, but there is
	 * no active keyslot with encrypted volume key yet.
	 */

	/*
	 * cryptt_kesylot_add_* call stores volume_key in encrypted form into keyslot.
	 * Without keyslot you can't manipulate with LUKS device after the context will be freed.
	 *
	 * To create a new keyslot you need to supply the existing one (to get the volume key from) or
	 * you need to supply the volume key.
	 *
	 * After format, we have volume key stored internally in context so add new keyslot
	 * using this internal volume key.
	 */
	r = crypt_keyslot_add_by_volume_key(cd,			/* crypt context */
					    CRYPT_ANY_SLOT,	/* just use first free slot */
					    NULL,		/* use internal volume key */
					    0,			/* unused (size of volume key) */
					    "foo",		/* passphrase - NULL means query*/
					    3);			/* size of passphrase */

	if (r < 0) {
		printf("Adding keyslot failed.\n");
		crypt_free(cd);
		return r;
	}

	printf("The first keyslot is initialized.\n");

	/*
	 * Add another keyslot, now using the first keyslot.
	 * It will decrypt volume key from the first keyslot and creates new one with another passphrase.
	 */
	r = crypt_keyslot_add_by_passphrase(cd,			/* crypt context */
					    CRYPT_ANY_SLOT,	/* just use first free slot */
					    "foo", 3,		/* passphrase for the old keyslot */
					    "bar", 3);		/* passphrase for the new kesylot */
	if (r < 0) {
		printf("Adding keyslot failed.\n");
		crypt_free(cd);
		return r;
	}

	printf("The second keyslot is initialized.\n");

	crypt_free(cd);
	return 0;
}
示例#6
0
static int action_format(int arg)
{
	struct crypt_device *cd = NULL;
	struct crypt_params_integrity params = {
		.journal_size = opt_journal_size,
		.interleave_sectors = opt_interleave_sectors,
		/* in bitmap mode we have to overload these values... */
		.journal_watermark = opt_integrity_bitmap ? opt_bitmap_sectors_per_bit : opt_journal_watermark,
		.journal_commit_time = opt_integrity_bitmap ? opt_bitmap_flush_time : opt_journal_commit_time,
		.buffer_sectors = opt_buffer_sectors,
		.tag_size = opt_tag_size,
		.sector_size = opt_sector_size ?: SECTOR_SIZE,
	};
	char integrity[MAX_CIPHER_LEN], journal_integrity[MAX_CIPHER_LEN], journal_crypt[MAX_CIPHER_LEN];
	char *integrity_key = NULL, *msg = NULL;
	int r;
	size_t signatures;

	if (opt_integrity) {
		r = crypt_parse_hash_integrity_mode(opt_integrity, integrity);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.integrity = integrity;
	}

	if (opt_journal_integrity) {
		r = crypt_parse_hash_integrity_mode(opt_journal_integrity, journal_integrity);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.journal_integrity = journal_integrity;
	}

	if (opt_journal_crypt) {
		r = crypt_parse_hash_integrity_mode(opt_journal_crypt, journal_crypt);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.journal_crypt = journal_crypt;
	}

	r = _read_keys(&integrity_key, &params);
	if (r)
		goto out;

	r = crypt_init_data_device(&cd, action_argv[0], opt_data_device);
	if (r < 0)
		goto out;

	r = asprintf(&msg, _("This will overwrite data on %s irrevocably."), action_argv[0]);
	if (r == -1) {
		r = -ENOMEM;
		goto out;
	}

	r = yesDialog(msg, _("Operation aborted.\n")) ? 0 : -EINVAL;
	free(msg);
	if (r < 0)
		goto out;

	r = tools_detect_signatures(action_argv[0], 0, &signatures);
	if (r < 0)
		goto out;

	/* Signature candidates found */
	if (signatures && ((r =	tools_wipe_all_signatures(action_argv[0])) < 0))
		goto out;

	r = crypt_format(cd, CRYPT_INTEGRITY, NULL, NULL, NULL, NULL, 0, &params);
	if (r < 0) /* FIXME: call wipe signatures again */
		goto out;

	if (!opt_batch_mode)
		log_std(_("Formatted with tag size %u, internal integrity %s.\n"), opt_tag_size, opt_integrity);

	if (!opt_no_wipe)
		r = _wipe_data_device(cd, integrity_key);
out:
	crypt_safe_free(integrity_key);
	crypt_safe_free(CONST_CAST(void*)params.journal_integrity_key);
	crypt_safe_free(CONST_CAST(void*)params.journal_crypt_key);
	crypt_free(cd);
	return r;
}

static int action_open(int arg)
{
	struct crypt_device *cd = NULL;
	struct crypt_params_integrity params = {
		/* in bitmap mode we have to overload these values... */
		.journal_watermark = opt_integrity_bitmap ? opt_bitmap_sectors_per_bit : opt_journal_watermark,
		.journal_commit_time = opt_integrity_bitmap ? opt_bitmap_flush_time : opt_journal_commit_time,
		.buffer_sectors = opt_buffer_sectors,
	};
	uint32_t activate_flags = 0;
	char integrity[MAX_CIPHER_LEN], journal_integrity[MAX_CIPHER_LEN], journal_crypt[MAX_CIPHER_LEN];
	char *integrity_key = NULL;
	int r;

	if (opt_integrity) {
		r = crypt_parse_hash_integrity_mode(opt_integrity, integrity);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.integrity = integrity;
	}

	if (opt_journal_integrity) {
		r = crypt_parse_hash_integrity_mode(opt_journal_integrity, journal_integrity);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;

		}
		params.journal_integrity = journal_integrity;
	}

	if (opt_journal_crypt) {
		r = crypt_parse_hash_integrity_mode(opt_journal_crypt, journal_crypt);
		if (r < 0) {
			log_err(_("No known integrity specification pattern detected."));
			return r;
		}
		params.journal_crypt = journal_crypt;
	}

	if (opt_integrity_nojournal || opt_integrity_bitmap)
		activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
	if (opt_integrity_recovery)
		activate_flags |= CRYPT_ACTIVATE_RECOVERY;
	if (opt_integrity_bitmap)
		activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP;

	if (opt_integrity_recalculate)
		activate_flags |= CRYPT_ACTIVATE_RECALCULATE;

	r = _read_keys(&integrity_key, &params);
	if (r)
		goto out;

	if ((r = crypt_init_data_device(&cd, action_argv[0], opt_data_device)))
		goto out;

	r = crypt_load(cd, CRYPT_INTEGRITY, &params);
	if (r)
		goto out;

	r = crypt_activate_by_volume_key(cd, action_argv[1], integrity_key,
					 opt_integrity_key_size, activate_flags);
out:
	crypt_safe_free(integrity_key);
	crypt_safe_free(CONST_CAST(void*)params.journal_integrity_key);
	crypt_safe_free(CONST_CAST(void*)params.journal_crypt_key);
	crypt_free(cd);
	return r;
}

static int action_close(int arg)
{
	struct crypt_device *cd = NULL;
	int r;

	r = crypt_init_by_name(&cd, action_argv[0]);
	if (r == 0)
		r = crypt_deactivate(cd, action_argv[0]);

	crypt_free(cd);
	return r;
}

static int action_status(int arg)
{
	crypt_status_info ci;
	struct crypt_active_device cad;
	struct crypt_params_integrity ip = {};
	struct crypt_device *cd = NULL;
	char *backing_file;
	const char *device, *metadata_device;
	int path = 0, r = 0;

	/* perhaps a path, not a dm device name */
	if (strchr(action_argv[0], '/'))
		path = 1;

	ci = crypt_status(NULL, action_argv[0]);
	switch (ci) {
	case CRYPT_INVALID:
		r = -EINVAL;
		break;
	case CRYPT_INACTIVE:
		if (path)
			log_std("%s is inactive.\n", action_argv[0]);
		else
			log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
		r = -ENODEV;
		break;
	case CRYPT_ACTIVE:
	case CRYPT_BUSY:
		if (path)
			log_std("%s is active%s.\n", action_argv[0],
				ci == CRYPT_BUSY ? " and is in use" : "");
		else
			log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
				ci == CRYPT_BUSY ? " and is in use" : "");

		r = crypt_init_by_name_and_header(&cd, action_argv[0], NULL);
		if (r < 0)
			goto out;

		log_std("  type:    %s\n", crypt_get_type(cd) ?: "n/a");

		r = crypt_get_active_device(cd, action_argv[0], &cad);
		if (r < 0)
			goto out;

		r = crypt_get_integrity_info(cd, &ip);
		if (r < 0)
			goto out;

		log_std("  tag size: %u\n", ip.tag_size);
		log_std("  integrity: %s\n", ip.integrity ?: "(none)");
		device = crypt_get_device_name(cd);
		metadata_device = crypt_get_metadata_device_name(cd);
		log_std("  device:  %s%s\n", device, metadata_device ? " (detached)" : "");
		if (crypt_loop_device(device)) {
			backing_file = crypt_loop_backing_file(device);
			log_std("  loop:    %s\n", backing_file);
			free(backing_file);
		}
		if (metadata_device) {
			log_std("  metadata device:  %s\n", metadata_device);
			if (crypt_loop_device(metadata_device)) {
				backing_file = crypt_loop_backing_file(metadata_device);
				log_std("  loop:    %s\n", backing_file);
				free(backing_file);
			}
		}
		log_std("  sector size:  %u bytes\n", crypt_get_sector_size(cd));
		log_std("  interleave sectors: %u\n", ip.interleave_sectors);
		log_std("  size:    %" PRIu64 " sectors\n", cad.size);
		log_std("  mode:    %s%s\n",
			cad.flags & CRYPT_ACTIVATE_READONLY ? "readonly" : "read/write",
			cad.flags & CRYPT_ACTIVATE_RECOVERY ? " recovery" : "");
		log_std("  failures: %" PRIu64 "\n",
			crypt_get_active_integrity_failures(cd, action_argv[0]));
		if (cad.flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) {
			log_std("  bitmap 512-byte sectors per bit: %u\n", ip.journal_watermark);
			log_std("  bitmap flush interval: %u ms\n", ip.journal_commit_time);
		} if (cad.flags & CRYPT_ACTIVATE_NO_JOURNAL) {
			log_std("  journal: not active\n");
		} else {
			log_std("  journal size: %" PRIu64 " bytes\n", ip.journal_size);
			log_std("  journal watermark: %u%%\n", ip.journal_watermark);
			log_std("  journal commit time: %u ms\n", ip.journal_commit_time);
			if (ip.journal_integrity)
				log_std("  journal integrity MAC: %s\n", ip.journal_integrity);
			if (ip.journal_crypt)
				log_std("  journal encryption: %s\n", ip.journal_crypt);
		}
	}
out:
	crypt_free(cd);
	if (r == -ENOTSUP)
		r = 0;
	return r;
	return -EINVAL;
}

static int action_dump(int arg)
{
	struct crypt_device *cd = NULL;
	struct crypt_params_integrity params = {};
	int r;

	if ((r = crypt_init(&cd, action_argv[0])))
		return r;

	r = crypt_load(cd, CRYPT_INTEGRITY, &params);
	if (!r)
		crypt_dump(cd);

	crypt_free(cd);
	return r;
}

static struct action_type {
	const char *type;
	int (*handler)(int);
	int required_action_argc;
	const char *arg_desc;
	const char *desc;
} action_types[] = {
	{ "format",	action_format, 1, N_("<integrity_device>"),N_("format device") },
	{ "open",	action_open,   2, N_("<integrity_device> <name>"),N_("open device as <name>") },
	{ "close",	action_close,  1, N_("<name>"),N_("close device (deactivate and remove mapping)") },
	{ "status",	action_status, 1, N_("<name>"),N_("show active device status") },
	{ "dump",	action_dump,   1, N_("<integrity_device>"),N_("show on-disk information") },
	{ NULL, NULL, 0, NULL, NULL }
};

static void help(poptContext popt_context,
		 enum poptCallbackReason reason __attribute__((unused)),
		 struct poptOption *key,
		 const char *arg __attribute__((unused)),
		 void *data __attribute__((unused)))
{
	struct action_type *action;

	if (key->shortName == '?') {
		log_std("%s %s\n", PACKAGE_INTEGRITY, PACKAGE_VERSION);
		poptPrintHelp(popt_context, stdout, 0);
		log_std(_("\n"
			 "<action> is one of:\n"));
		for(action = action_types; action->type; action++)
			log_std("\t%s %s - %s\n", action->type, _(action->arg_desc), _(action->desc));
		log_std(_("\n"
			 "<name> is the device to create under %s\n"
			 "<integrity_device> is the device containing data with integrity tags\n"),
			crypt_get_dir());

		log_std(_("\nDefault compiled-in dm-integrity parameters:\n"
			  "\tTag size: %u bytes, Checksum algorithm: %s\n"),
			  DEFAULT_TAG_SIZE, DEFAULT_ALG_NAME);
		exit(EXIT_SUCCESS);
	} else
		usage(popt_context, EXIT_SUCCESS, NULL, NULL);
}

static int run_action(struct action_type *action)
{
	int r;

	log_dbg("Running command %s.", action->type);

	r = action->handler(0);

	show_status(r);
	return translate_errno(r);
}
/* Create fake header for original device */
static int backup_fake_header(struct reenc_ctx *rc)
{
	struct crypt_device *cd_new = NULL;
	struct crypt_params_luks1 params = {0};
	char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
	const char *header_file_fake;
	int r;

	log_dbg("Creating fake (cipher_null) header for %s device.",
		(rc->reencrypt_mode == DECRYPT) ? "new" : "original");

	header_file_fake = (rc->reencrypt_mode == DECRYPT) ? rc->header_file_new : rc->header_file_org;

	if (!opt_key_size)
		opt_key_size = DEFAULT_LUKS1_KEYBITS;

	if (opt_cipher) {
		r = crypt_parse_name_and_mode(opt_cipher, cipher, NULL, cipher_mode);
		if (r < 0) {
			log_err(_("No known cipher specification pattern detected.\n"));
			goto out;
		}
	}

	r = create_empty_header(header_file_fake, NULL, MAX_BCK_SECTORS);
	if (r < 0)
		return r;

	params.hash = opt_hash ?: DEFAULT_LUKS1_HASH;
	params.data_alignment = 0;
	params.data_device = rc->device;

	r = crypt_init(&cd_new, header_file_fake);
	if (r < 0)
		return r;

	r = crypt_format(cd_new, CRYPT_LUKS1, "cipher_null", "ecb",
			 NO_UUID, NULL, opt_key_size / 8, &params);
	if (r < 0)
		goto out;

	r = crypt_keyslot_add_by_volume_key(cd_new, rc->keyslot, NULL, 0,
			rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
	if (r < 0)
		goto out;

	/* The real header is backup header created in backup_luks_headers() */
	if (rc->reencrypt_mode == DECRYPT)
		goto out;

	r = create_empty_header(rc->header_file_new, rc->header_file_org, 0);
	if (r < 0)
		goto out;

	params.data_alignment = ROUND_SECTOR(opt_reduce_size);
	r = create_new_header(rc,
		opt_cipher ? cipher : DEFAULT_LUKS1_CIPHER,
		opt_cipher ? cipher_mode : DEFAULT_LUKS1_MODE,
		NULL, NULL,
		(opt_key_size ? opt_key_size : DEFAULT_LUKS1_KEYBITS) / 8,
		&params);
out:
	crypt_free(cd_new);
	return r;
}