Add crypt_resume_by_token_pin API.

This commit is contained in:
Ondrej Kozina
2021-08-25 15:20:54 +02:00
parent 416f1343fe
commit ce6f6a48e8
4 changed files with 80 additions and 0 deletions

View File

@@ -899,6 +899,43 @@ int crypt_resume_by_volume_key(struct crypt_device *cd,
const char *name,
const char *volume_key,
size_t volume_key_size);
/**
* Resume crypt device using LUKS2 token.
*
* @param cd LUKS2 crypt device handle
* @param name name of device to resume
* @param type restrict type of token, if @e NULL all types are allowed
* @param pin passphrase (or PIN) to unlock token (may be binary data)
* @param pin_size size of @e pin
* @param usrptr provided identification in callback
*
* @return unlocked key slot number or negative errno otherwise.
*
* @note EPERM errno means token provided passphrase successfully, but
* passphrase did not unlock any keyslot associated with the token.
*
* @note ENOENT errno means no token (or subsequently assigned keyslot) was
* eligible to resume LUKS2 device.
*
* @note ENOANO errno means that token is PIN protected and was either missing
* (NULL) or wrong.
*
* @note Negative EAGAIN errno means token handler requires additional hardware
* not present in the system to unlock keyslot.
*
* @note with @param token set to CRYPT_ANY_TOKEN libcryptsetup runs best effort loop
* to resume device using any available token. It may happen that various token handlers
* return different error codes. At the end loop returns error codes in the following
* order (from the most significant to the least) any negative errno except those
* listed below, non negative token id (success), -ENOANO, -EAGAIN, -EPERM, -ENOENT.
*/
int crypt_resume_by_token_pin(struct crypt_device *cd,
const char *name,
const char *type,
int token,
const char *pin,
size_t pin_size,
void *usrptr);
/** @} */
/**

View File

@@ -149,4 +149,5 @@ CRYPTSETUP_2.5 {
global:
crypt_get_label;
crypt_get_subsystem;
crypt_resume_by_token_pin;
} CRYPTSETUP_2.4;

View File

@@ -3401,6 +3401,40 @@ int crypt_resume_by_volume_key(struct crypt_device *cd,
return r;
}
int crypt_resume_by_token_pin(struct crypt_device *cd, const char *name,
const char *type, int token, const char *pin, size_t pin_size,
void *usrptr)
{
struct volume_key *vk = NULL;
int r, keyslot;
if (!name)
return -EINVAL;
log_dbg(cd, "Resuming volume %s by token (%s type) %d.",
name, type ?: "any", token);
if ((r = _onlyLUKS2(cd, CRYPT_CD_QUIET, 0)))
return r;
r = dm_status_suspended(cd, name);
if (r < 0)
return r;
if (!r) {
log_err(cd, _("Volume %s is not suspended."), name);
return -EINVAL;
}
r = LUKS2_token_unlock_volume_key(cd, &cd->u.luks2.hdr, token, type, pin, pin_size, 0, usrptr, &vk);
keyslot = r;
if (r >= 0)
r = resume_by_volume_key(cd, vk, name);
crypt_free_volume_key(vk);
return r < 0 ? r : keyslot;
}
/*
* Keyslot manipulation
*/

View File

@@ -1910,6 +1910,7 @@ static void Tokens(void)
const char *cipher_mode = "xts-plain64";
char passptr[] = PASSPHRASE;
char passptr1[] = PASSPHRASE1;
struct crypt_active_device cad;
static const crypt_token_handler th = {
.name = "test_token",
@@ -2121,6 +2122,13 @@ static void Tokens(void)
EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 11, NULL, 0, passptr, 0), -ENOENT);
EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 11, NULL, 0, passptr, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), -ENOENT);
// test crypt_resume_by_token_pin
EQ_(crypt_activate_by_token_pin(cd, CDEVICE_1, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr, 0), 5);
OK_(crypt_suspend(cd, CDEVICE_1));
EQ_(crypt_resume_by_token_pin(cd, CDEVICE_1, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr), 5);
OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
OK_(crypt_deactivate(cd, CDEVICE_1));
CRYPT_FREE(cd);
EQ_(crypt_token_max(CRYPT_LUKS2), 32);