Esempio n. 1
0
static char * _volume_device_name( const char * mapper,char * ( *function )( const char * ) )
{
	struct crypt_device * cd ;
	const char * e = crypt_get_dir() ;
	char * f = NULL ;

	if( zuluCryptTrueCryptOrVeraCryptVolume( mapper ) ){

		return _device_name( mapper,function ) ;
	}else{
		if( crypt_init_by_name( &cd,mapper ) == 0 ){

			e = crypt_get_device_name( cd ) ;

			if( e != NULL ){

				f = function( e ) ;
			}

			crypt_free( cd ) ;
		}

		return f ;
	}
}
Esempio n. 2
0
/**
 * Opens the device with the specified flags.
 *
 * The length parameter is set to the amount of space in the gap between the
 * end of the last slot and the start of the encrypted data.
 *
 * The function returns either the file descriptor positioned to the start of
 * the hole or a negative errno.
 */
static int
open_hole(struct crypt_device *cd, int flags, uint32_t *length)
{
    const char *name = NULL;
    const char *type = NULL;
    uint64_t hole = 0;
    uint64_t data = 0;
    int fd = 0;
    int r = 0;

    type = crypt_get_type(cd);
    if (!type || strcmp(CRYPT_LUKS1, type) != 0)
        return -ENOTSUP;

    data = crypt_get_data_offset(cd) * 512;
    if (data < 4096)
        return -ENOSPC;

    for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
        uint64_t off = 0;
        uint64_t len = 0;

        r = crypt_keyslot_area(cd, slot, &off, &len);
        if (r < 0)
            return r;

        if (hole < off + len)
            hole = ALIGN(off + len, true);
    }

    if (hole == 0)
        return -ENOTSUP;

    if (hole >= data)
        return -ENOSPC;

    name = crypt_get_device_name(cd);
    if (!name)
        return -ENOTSUP;

    fd = open(name, flags);
    if (fd < 0)
        return -errno;

    if (lseek(fd, hole, SEEK_SET) == -1) {
        close(fd);
        return -errno;
    }

    *length = ALIGN(data - hole, false);
    return fd;
}
Esempio n. 3
0
static string_t _get_crypto_info_from_cryptsetup( const char * mapper )
{
	char buff[ SIZE ] ;
	char * buffer = buff ;

	const char * z ;
	const char * type ;

	uint64_t e ;

	string_t q ;
	string_t p ;

	int k ;
	int i = 0 ;
	int j ;

	crypt_status_info info ;

	struct crypt_device * cd ;

	struct crypt_active_device cad ;

	if( crypt_init_by_name( &cd,mapper ) != 0 ){

		return StringVoid ;
	}

	p = String( mapper ) ;

	info = crypt_status( cd,mapper ) ;

	switch( info ){
	case CRYPT_INACTIVE :
		StringAppend( p," is inactive.\n" ) ;
		break ;
	case CRYPT_INVALID  :
		StringAppend( p," is invalid.\n" ) ;
		break ;
	case CRYPT_ACTIVE   :
		StringAppend( p," is active.\n" ) ;
		break ;
	case CRYPT_BUSY     :
		StringAppend( p," is active and is in use.\n" ) ;
		break ;
	default :
		StringAppend( p," is invalid.\n" ) ;
	}

	if( info == CRYPT_ACTIVE || info == CRYPT_BUSY ){

		StringAppend( p," type:   \t" ) ;

		type = crypt_get_type( cd ) ;

		if( type != NULL ){

			q = String( type ) ;
			StringAppend( p,StringToLowerCase( q ) ) ;
			StringDelete( &q ) ;
		}else{
			q = _get_type_from_udev_1( mapper ) ;

			StringAppendString( p,q ) ;

			StringDelete( &q ) ;
		}

		z = crypt_get_cipher( cd ) ;

		if( z != NULL ){

			StringMultipleAppend( p,"\n cipher:\t",z,"-",NULL ) ;
		}else{
			StringAppend( p,"\n cipher:\tNil-" ) ;
		}

		z = crypt_get_cipher_mode( cd ) ;

		if( z != NULL ){

			StringAppend( p,z ) ;
		}else{
			StringAppend( p,"Nil" ) ;
		}

		z = StringIntToString_1( buffer,SIZE,8 * crypt_get_volume_key_size( cd ) ) ;
		StringMultipleAppend( p,"\n keysize:\t",z," bits",NULL ) ;

		e = crypt_get_data_offset( cd ) ;

		z = StringIntToString_1( buffer,SIZE,e ) ;
		StringMultipleAppend( p,"\n offset:\t",z," sectors",NULL ) ;

		zuluCryptFormatSize( e * 512,buffer,SIZE ) ;
		StringMultipleAppend( p," / ",buffer,NULL ) ;

		_device_info( p,crypt_get_device_name( cd ) ) ;

		crypt_get_active_device( NULL,mapper,&cad ) ;

		if( cad.flags == 1 ){

			StringAppend( p,"\n mode:   \tread only" ) ;
		}else{
			StringAppend( p,"\n mode:   \tread and write" ) ;
		}

		k = crypt_keyslot_max( crypt_get_type( cd ) ) ;

		if( k > 0 ){

			i = 0 ;

			for( j = 0 ; j < k ; j++ ){

				switch( crypt_keyslot_status( cd,j ) ){

					case CRYPT_SLOT_ACTIVE_LAST : i++ ; break ;
					case CRYPT_SLOT_ACTIVE      : i++ ; break ;
					default : ;
				}
			}

			StringMultipleAppend( p,"\n active slots:\t",StringIntToString_1( buffer,SIZE,i ),NULL ) ;

			StringMultipleAppend( p," / ",StringIntToString_1( buffer,SIZE,k ),NULL ) ;
		}else{
			StringAppend( p,"\n active slots:\tNil" ) ;
		}
	}

	crypt_free( cd ) ;

	return p ;
}
Esempio n. 4
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;
}
Esempio n. 5
0
static int activate_and_check_status(const char *path, const char *device_name)
{
	struct crypt_device *cd;
	struct crypt_active_device cad;
	int r;

	/*
	 * LUKS device activation example.
	 * It's sequence of sub-steps: device initialization, LUKS header load
	 * and the device activation itself.
	 */
	r = crypt_init(&cd, path);
	if (r < 0 ) {
		printf("crypt_init() failed for %s.\n", path);
		return r;
	}

	/*
	 * crypt_load() is used to load the LUKS header from block device
	 * into crypt_device context.
	 */
	r = crypt_load(cd,		/* crypt context */
		       CRYPT_LUKS1,	/* requested type */
		       NULL);		/* additional parameters (not used) */

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

	/*
	 * Device activation creates device-mapper devie mapping with name device_name.
	 */
	r = crypt_activate_by_passphrase(cd,		/* crypt context */
					 device_name,	/* device name to activate */
					 CRYPT_ANY_SLOT,/* which slot use (ANY - try all) */
					 "foo", 3,	/* passphrase */
					 CRYPT_ACTIVATE_READONLY); /* flags */
	if (r < 0) {
		printf("Device %s activation failed.\n", device_name);
		crypt_free(cd);
		return r;
	}

	printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name);
	printf("\tcipher used: %s\n", crypt_get_cipher(cd));
	printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
	printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));

	/*
	 * Get info about active device (query DM backend)
	 */
	r = crypt_get_active_device(cd, device_name, &cad);
	if (r < 0) {
		printf("Get info about active device %s failed.\n", device_name);
		crypt_deactivate(cd, device_name);
		crypt_free(cd);
		return r;
	}

	printf("Active device parameters for %s:\n"
		"\tDevice offset (in sectors): %" PRIu64 "\n"
		"\tIV offset (in sectors)    : %" PRIu64 "\n"
		"\tdevice size (in sectors)  : %" PRIu64 "\n"
		"\tread-only flag            : %s\n",
		device_name, cad.offset, cad.iv_offset, cad.size,
		cad.flags & CRYPT_ACTIVATE_READONLY ? "1" : "0");

	crypt_free(cd);
	return 0;
}
Esempio n. 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);
}