static int _crypt_load_luks(struct crypt_device *cd, const char *requested_type,
			    int require_header, int repair)
{
	char *cipher_spec;
	struct luks_phdr hdr = {};
	int r, version;

	r = init_crypto(cd);
	if (r < 0)
		return r;

	/* This will return 0 if primary LUKS2 header is damaged */
	version = LUKS2_hdr_version_unlocked(cd, NULL);

	if ((isLUKS1(requested_type) && version == 2) ||
	    (isLUKS2(requested_type) && version == 1))
		return -EINVAL;

	if (requested_type)
		version = 0;

	if (isLUKS1(requested_type) || version == 1) {
		if (isLUKS2(cd->type)) {
			log_dbg(cd, "Context is already initialized to type %s", cd->type);
			return -EINVAL;
		}

		if (verify_pbkdf_params(cd, &cd->pbkdf)) {
			r = init_pbkdf_type(cd, NULL, CRYPT_LUKS1);
			if (r)
				return r;
		}

		r = LUKS_read_phdr(&hdr, require_header, repair, cd);
		if (r)
			goto out;

		if (!cd->type && !(cd->type = strdup(CRYPT_LUKS1))) {
			r = -ENOMEM;
			goto out;
		}

		/* Set hash to the same as in the loaded header */
		if (!cd->pbkdf.hash || strcmp(cd->pbkdf.hash, hdr.hashSpec)) {
			free(CONST_CAST(void*)cd->pbkdf.hash);
			cd->pbkdf.hash = strdup(hdr.hashSpec);
			if (!cd->pbkdf.hash) {
				r = -ENOMEM;
				goto out;
			}
		}

		if (asprintf(&cipher_spec, "%s-%s", hdr.cipherName, hdr.cipherMode) < 0) {
			r = -ENOMEM;
			goto out;
		}

		free(cd->u.luks1.cipher_spec);
		cd->u.luks1.cipher_spec = cipher_spec;

		memcpy(&cd->u.luks1.hdr, &hdr, sizeof(hdr));
	} else if (isLUKS2(requested_type) || version == 2 || version == 0) {
		if (isLUKS1(cd->type)) {
			log_dbg(cd, "Context is already initialized to type %s", cd->type);
			return -EINVAL;
		}

		/*
		 * Current LUKS2 repair just overrides blkid probes
		 * and perform auto-recovery if possible. This is safe
		 * unless future LUKS2 repair code do something more
		 * sophisticated. In such case we would need to check
		 * for LUKS2 requirements and decide if it's safe to
		 * perform repair.
		 */
		r =  _crypt_load_luks2(cd, cd->type != NULL, repair);
		if (!r)
			device_set_block_size(crypt_data_device(cd), LUKS2_get_sector_size(&cd->u.luks2.hdr));
	} else {
		if (version > 2)
			log_err(cd, _("Unsupported LUKS version %d."), version);
		r = -EINVAL;
	}
out:
	crypt_safe_memzero(&hdr, sizeof(hdr));

	return r;
}
static int _crypt_load_luks(struct crypt_device *cd, const char *requested_type,
			    int require_header, int repair)
{
	char *cipher_spec;
	struct luks_phdr hdr = {};
	int r, version;

	r = init_crypto(cd);
	if (r < 0)
		return r;

	 
	version = LUKS2_hdr_version_unlocked(cd, NULL);

	if ((isLUKS1(requested_type) && version == 2) ||
	    (isLUKS2(requested_type) && version == 1))
		return -EINVAL;

	if (requested_type)
		version = 0;

	if (isLUKS1(requested_type) || version == 1) {
		if (isLUKS2(cd->type)) {
			log_dbg(cd, "Context is already initialized to type %s", cd->type);
			return -EINVAL;
		}

		if (verify_pbkdf_params(cd, &cd->pbkdf)) {
			r = init_pbkdf_type(cd, NULL, CRYPT_LUKS1);
			if (r)
				return r;
		}

		r = LUKS_read_phdr(&hdr, require_header, repair, cd);
		if (r)
			goto out;

		if (!cd->type && !(cd->type = strdup(CRYPT_LUKS1))) {
			r = -ENOMEM;
			goto out;
		}

		 
		if (!cd->pbkdf.hash || strcmp(cd->pbkdf.hash, hdr.hashSpec)) {
			free(CONST_CAST(void*)cd->pbkdf.hash);
			cd->pbkdf.hash = strdup(hdr.hashSpec);
			if (!cd->pbkdf.hash) {
				r = -ENOMEM;
				goto out;
			}
		}

		if (asprintf(&cipher_spec, "%s-%s", hdr.cipherName, hdr.cipherMode) < 0) {
			r = -ENOMEM;
			goto out;
		}

		free(cd->u.luks1.cipher_spec);
		cd->u.luks1.cipher_spec = cipher_spec;

		memcpy(&cd->u.luks1.hdr, &hdr, sizeof(hdr));
	} else if (isLUKS2(requested_type) || version == 2 || version == 0) {
		if (isLUKS1(cd->type)) {
			log_dbg(cd, "Context is already initialized to type %s", cd->type);
			return -EINVAL;
		}

		 
		r =  _crypt_load_luks2(cd, cd->type != NULL, repair);
		if (!r)
			device_set_block_size(crypt_data_device(cd), LUKS2_get_sector_size(&cd->u.luks2.hdr));
	} else {
		if (version > 2)
			log_err(cd, _("Unsupported LUKS version %d."), version);
		r = -EINVAL;
	}
out:
	crypt_safe_memzero(&hdr, sizeof(hdr));

	return r;
}