Make crypt_activate_by_pin_token addition backward compatible.

The crypt_activate_by_pin_token may be used only from new
dynamicly loadable token plugins.

Also refactors code for dynamically loadable plugins so
that it does not use crypt_token_handler structure anymore.

Old structure remains used only in crypt_token_register call.
This commit is contained in:
Ondrej Kozina
2021-01-21 17:23:15 +01:00
parent 81c44b5eee
commit 10e4d8fbac
4 changed files with 137 additions and 52 deletions

View File

@@ -2214,7 +2214,6 @@ typedef struct {
crypt_token_buffer_free_func buffer_free; /**< token handler buffer_free function (optional) */
crypt_token_validate_func validate; /**< token handler validate function (optional) */
crypt_token_dump_func dump; /**< token handler dump function (optional) */
crypt_token_open_pin_func open_pin; /**< open with passphrase function (optional) */
} crypt_token_handler;
/**
@@ -2227,9 +2226,14 @@ typedef struct {
int crypt_token_register(const crypt_token_handler *handler);
/** ABI version for external token in libcryptsetup-token-<name>.so */
#define CRYPT_TOKEN_ABI_VERSION1 "CRYPTSETUP_TOKEN_1.0"
#define CRYPT_TOKEN_ABI_VERSION1 "CRYPTSETUP_TOKEN_1.0"
/** ABI exported symbol for external token */
#define CRYPT_TOKEN_ABI_HANDLER "cryptsetup_token_handler"
#define CRYPT_TOKEN_ABI_OPEN "cryptsetup_token_open" /* mandatory */
#define CRYPT_TOKEN_ABI_OPEN_PIN "cryptsetup_token_open_pin"
#define CRYPT_TOKEN_ABI_BUFFER_FREE "cryptsetup_token_buffer_free"
#define CRYPT_TOKEN_ABI_VALIDATE "cryptsetup_token_validate"
#define CRYPT_TOKEN_ABI_DUMP "cryptsetup_token_dump"
/**
* Activate device or check key using a token.

View File

@@ -164,12 +164,44 @@ typedef struct {
digest_dump_func dump;
} digest_handler;
typedef struct {
/* public token handler */
const crypt_token_handler *h;
/* dynamic loadable plugin dlopen handle */
const void *dlhandle;
} token_handler;
int keyring_open(struct crypt_device *cd,
int token,
char **buffer,
size_t *buffer_len,
void *usrptr);
void keyring_dump(struct crypt_device *cd, const char *json);
int keyring_validate(struct crypt_device *cd, const char *json);
struct crypt_token_handler_v2 {
const char *name;
crypt_token_open_func open;
crypt_token_buffer_free_func buffer_free;
crypt_token_validate_func validate;
crypt_token_dump_func dump;
/* here ends v1. Do not touch anything above */
crypt_token_open_pin_func open_pin;
void *dlhandle;
};
/*
* Initial sequence of structure members in union 'u' must be always
* identical. Version 4 must fully contain version 3 which must
* subsequently fully contain version 2, etc.
*
* See C standard, section 6.5.2.3, item 5.
*/
struct crypt_token_handler_internal {
uint32_t version;
union {
crypt_token_handler v1; /* deprecated public structure */
struct crypt_token_handler_v2 v2; /* internal helper v2 structure */
} u;
};
int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
size_t keylength, uint64_t *area_offset, uint64_t *area_length);

View File

@@ -25,29 +25,72 @@
#include "luks2_internal.h"
/* Builtin tokens */
extern const crypt_token_handler keyring_handler;
static token_handler token_handlers[LUKS2_TOKENS_MAX] = {
static struct crypt_token_handler_internal token_handlers[LUKS2_TOKENS_MAX] = {
/* keyring builtin token */
{
.h = &keyring_handler
.version = 1,
.u = {
.v1 = { .name = LUKS2_TOKEN_KEYRING,
.open = keyring_open,
.validate = keyring_validate,
.dump = keyring_dump }
}
}
};
#if USE_EXTERNAL_TOKENS
static void *token_dlvsym(struct crypt_device *cd,
void *handle,
const char *symbol,
const char *version)
{
char *error;
void *sym;
log_dbg(cd, "Loading symbol %s@%s.", symbol, version);
sym = dlvsym(handle, symbol, version);
error = dlerror();
if (error)
log_dbg(cd, "Error: %s.", error);
return sym;
}
#endif
static bool token_validate_v1(struct crypt_device *cd, const crypt_token_handler *h)
{
if (!h)
return false;
if (!h->name) {
log_dbg(cd, "Token handler does not provide name attribute.");
return false;
}
if (!h->open) {
log_dbg(cd, "Token handler does not provide open function.");
return false;
}
return true;
}
static int
crypt_token_load_external(struct crypt_device *cd, const char *name, token_handler *ret)
crypt_token_load_external(struct crypt_device *cd, const char *name, struct crypt_token_handler_internal *ret)
{
#if USE_EXTERNAL_TOKENS
const crypt_token_handler *token = NULL;
void *handle;
char *error;
struct crypt_token_handler_v2 *token;
void *h;
char buf[512];
int i, r;
if (!ret || !name || strlen(name) > 64)
return -EINVAL;
token = &ret->u.v2;
for (i = 0; name[i]; i++)
if (!isalnum(name[i]))
return -EINVAL;
@@ -58,25 +101,35 @@ crypt_token_load_external(struct crypt_device *cd, const char *name, token_handl
log_dbg(cd, "Trying to load %s.", buf);
handle = dlopen(buf, RTLD_LAZY);
if (!handle) {
h = dlopen(buf, RTLD_LAZY);
if (!h) {
log_dbg(NULL, "%s", dlerror());
return -EINVAL;
}
dlerror();
token = dlvsym(handle, CRYPT_TOKEN_ABI_HANDLER, CRYPT_TOKEN_ABI_VERSION1);
error = dlerror();
if (error) {
log_dbg(cd, "%s", error);
dlclose(handle);
return -EINVAL;
token->name = strdup(name);
token->open = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_OPEN, CRYPT_TOKEN_ABI_VERSION1);
token->buffer_free = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_BUFFER_FREE, CRYPT_TOKEN_ABI_VERSION1);
token->validate = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_VALIDATE, CRYPT_TOKEN_ABI_VERSION1);
token->dump = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_DUMP, CRYPT_TOKEN_ABI_VERSION1);
token->open_pin = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_OPEN_PIN, CRYPT_TOKEN_ABI_VERSION1);
if (!token_validate_v1(cd, &ret->u.v1)) {
r = -EINVAL;
goto err;
}
ret->h = token;
ret->dlhandle = handle;
token->dlhandle = h;
ret->version = 2;
return 0;
err:
free(CONST_CAST(void *)token->name);
dlclose(h);
memset(token, 0, sizeof(*token));
return r;
#else
return -ENOTSUP;
#endif
@@ -96,8 +149,8 @@ static int crypt_token_find_free(struct crypt_device *cd, const char *name, int
return -EINVAL;
}
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].h; i++) {
if (!strcmp(token_handlers[i].h->name, name)) {
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].u.v1.name; i++) {
if (!strcmp(token_handlers[i].u.v1.name, name)) {
log_dbg(cd, "Keyslot handler %s is already registered.", name);
return -EINVAL;
}
@@ -116,14 +169,15 @@ int crypt_token_register(const crypt_token_handler *handler)
{
int i, r;
if (!handler->name || !handler->open)
if (!token_validate_v1(NULL, handler))
return -EINVAL;
r = crypt_token_find_free(NULL, handler->name, &i);
if (r < 0)
return r;
token_handlers[i].h = handler;
token_handlers[i].version = 1;
token_handlers[i].u.v1 = *handler;
return 0;
}
@@ -132,24 +186,26 @@ void crypt_token_unload_external_all(struct crypt_device *cd)
int i;
for (i = LUKS2_TOKENS_MAX - 1; i >= 0; i--) {
if (!token_handlers[i].dlhandle)
if (token_handlers[i].version < 2)
continue;
log_dbg(cd, "Unloading %s token handler.", token_handlers[i].h->name);
log_dbg(cd, "Unloading %s token handler.", token_handlers[i].u.v2.name);
if (dlclose(CONST_CAST(void *)token_handlers[i].dlhandle))
free(CONST_CAST(void *)token_handlers[i].u.v2.name);
if (dlclose(CONST_CAST(void *)token_handlers[i].u.v2.dlhandle))
log_dbg(cd, "%s", dlerror());
}
}
static const crypt_token_handler
static const void
*LUKS2_token_handler_type(struct crypt_device *cd, const char *type)
{
int i;
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].h; i++)
if (!strcmp(token_handlers[i].h->name, type))
return token_handlers[i].h;
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].u.v1.name; i++)
if (!strcmp(token_handlers[i].u.v1.name, type))
return &token_handlers[i].u;
if (i >= LUKS2_TOKENS_MAX)
return NULL;
@@ -160,10 +216,10 @@ static const crypt_token_handler
if (crypt_token_load_external(cd, type, &token_handlers[i]))
return NULL;
return token_handlers[i].h;
return &token_handlers[i].u;
}
static const crypt_token_handler
static const void
*LUKS2_token_handler(struct crypt_device *cd, int token)
{
struct luks2_hdr *hdr;
@@ -305,7 +361,7 @@ static int LUKS2_token_open(struct crypt_device *cd,
void *usrptr)
{
const char *json;
const crypt_token_handler *h;
const struct crypt_token_handler_v2 *h;
int r;
if (!(h = LUKS2_token_handler(cd, token)))

View File

@@ -23,7 +23,7 @@
#include "luks2_internal.h"
static int keyring_open(struct crypt_device *cd,
int keyring_open(struct crypt_device *cd,
int token,
char **buffer,
size_t *buffer_len,
@@ -54,7 +54,7 @@ static int keyring_open(struct crypt_device *cd,
return 0;
}
static int keyring_validate(struct crypt_device *cd __attribute__((unused)),
int keyring_validate(struct crypt_device *cd __attribute__((unused)),
const char *json)
{
enum json_tokener_error jerr;
@@ -92,7 +92,7 @@ out:
return r;
}
static void keyring_dump(struct crypt_device *cd, const char *json)
void keyring_dump(struct crypt_device *cd, const char *json)
{
enum json_tokener_error jerr;
json_object *jobj_token, *jobj_key;
@@ -135,10 +135,3 @@ int LUKS2_token_keyring_get(struct crypt_device *cd, struct luks2_hdr *hdr, int
return token;
}
const crypt_token_handler keyring_handler = {
.name = LUKS2_TOKEN_KEYRING,
.open = keyring_open,
.validate = keyring_validate,
.dump = keyring_dump
};