/* Try to open a particular key slot */ static int LUKS_open_key(unsigned int keyIndex, const char *password, size_t passwordLen, struct luks_phdr *hdr, struct volume_key *vk, struct crypt_device *ctx) { crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyIndex); struct volume_key *derived_key; char *AfKey; size_t AFEKSize; int r; log_dbg("Trying to open key slot %d [%s].", keyIndex, dbg_slot_state(ki)); if (ki < CRYPT_SLOT_ACTIVE) return -ENOENT; derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL); if (!derived_key) return -ENOMEM; assert(vk->keylength == hdr->keyBytes); AFEKSize = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE; AfKey = crypt_safe_alloc(AFEKSize); if (!AfKey) { r = -ENOMEM; goto out; } r = crypt_pbkdf("pbkdf2", hdr->hashSpec, password, passwordLen, hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE, derived_key->key, hdr->keyBytes, hdr->keyblock[keyIndex].passwordIterations); if (r < 0) goto out; log_dbg("Reading key slot %d area.", keyIndex); r = LUKS_decrypt_from_storage(AfKey, AFEKSize, hdr->cipherName, hdr->cipherMode, derived_key, hdr->keyblock[keyIndex].keyMaterialOffset, ctx); if (r < 0) goto out; r = AF_merge(AfKey,vk->key,vk->keylength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec); if (r < 0) goto out; r = LUKS_verify_volume_key(hdr, vk); if (!r) log_verbose(ctx, _("Key slot %d unlocked.\n"), keyIndex); out: crypt_safe_free(AfKey); crypt_free_volume_key(derived_key); return r; }
/* Check that kernel supports requested cipher by decryption of one sector */ static int LUKS_check_cipher(struct luks_phdr *hdr, struct crypt_device *ctx) { int r; struct volume_key *empty_key; char buf[SECTOR_SIZE]; log_dbg("Checking if cipher %s-%s is usable.", hdr->cipherName, hdr->cipherMode); empty_key = crypt_alloc_volume_key(hdr->keyBytes, NULL); if (!empty_key) return -ENOMEM; r = LUKS_decrypt_from_storage(buf, sizeof(buf), hdr->cipherName, hdr->cipherMode, empty_key, 0, ctx); crypt_free_volume_key(empty_key); crypt_memzero(buf, sizeof(buf)); return r; }
/* Check that kernel supports requested cipher by decryption of one sector */ int LUKS_check_cipher(struct crypt_device *ctx, size_t keylength, const char *cipher, const char *cipher_mode) { int r; struct volume_key *empty_key; char buf[SECTOR_SIZE]; log_dbg("Checking if cipher %s-%s is usable.", cipher, cipher_mode); empty_key = crypt_alloc_volume_key(keylength, NULL); if (!empty_key) return -ENOMEM; /* No need to get KEY quality random but it must avoid known weak keys. */ r = crypt_random_get(ctx, empty_key->key, empty_key->keylength, CRYPT_RND_NORMAL); if (!r) r = LUKS_decrypt_from_storage(buf, sizeof(buf), cipher, cipher_mode, empty_key, 0, ctx); crypt_free_volume_key(empty_key); crypt_memzero(buf, sizeof(buf)); return r; }
int decryptFromStorage( char *dst, size_t dstLength, const char *cipher, const char *cipher_mode, const char *vkey, size_t vkLength, unsigned int sector, struct crypt_device *ctx) { struct volume_key* vk = malloc(sizeof(struct volume_key) + vkLength); vk->keylength = vkLength; memcpy(&vk->key, vkey, vkLength); const int r = LUKS_decrypt_from_storage ( dst, dstLength, cipher, cipher_mode, vk, sector, ctx ); free(vk); return r; }