mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-06 00:10:04 +01:00
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:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user