mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-06 16:30: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_buffer_free_func buffer_free; /**< token handler buffer_free function (optional) */
|
||||||
crypt_token_validate_func validate; /**< token handler validate function (optional) */
|
crypt_token_validate_func validate; /**< token handler validate function (optional) */
|
||||||
crypt_token_dump_func dump; /**< token handler dump 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;
|
} crypt_token_handler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2227,9 +2226,14 @@ typedef struct {
|
|||||||
int crypt_token_register(const crypt_token_handler *handler);
|
int crypt_token_register(const crypt_token_handler *handler);
|
||||||
|
|
||||||
/** ABI version for external token in libcryptsetup-token-<name>.so */
|
/** 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 */
|
/** 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.
|
* Activate device or check key using a token.
|
||||||
|
|||||||
@@ -164,12 +164,44 @@ typedef struct {
|
|||||||
digest_dump_func dump;
|
digest_dump_func dump;
|
||||||
} digest_handler;
|
} digest_handler;
|
||||||
|
|
||||||
typedef struct {
|
int keyring_open(struct crypt_device *cd,
|
||||||
/* public token handler */
|
int token,
|
||||||
const crypt_token_handler *h;
|
char **buffer,
|
||||||
/* dynamic loadable plugin dlopen handle */
|
size_t *buffer_len,
|
||||||
const void *dlhandle;
|
void *usrptr);
|
||||||
} token_handler;
|
|
||||||
|
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,
|
int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||||||
size_t keylength, uint64_t *area_offset, uint64_t *area_length);
|
size_t keylength, uint64_t *area_offset, uint64_t *area_length);
|
||||||
|
|||||||
@@ -25,29 +25,72 @@
|
|||||||
|
|
||||||
#include "luks2_internal.h"
|
#include "luks2_internal.h"
|
||||||
|
|
||||||
/* Builtin tokens */
|
static struct crypt_token_handler_internal token_handlers[LUKS2_TOKENS_MAX] = {
|
||||||
extern const crypt_token_handler keyring_handler;
|
|
||||||
|
|
||||||
static token_handler token_handlers[LUKS2_TOKENS_MAX] = {
|
|
||||||
/* keyring builtin token */
|
/* 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
|
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
|
#if USE_EXTERNAL_TOKENS
|
||||||
const crypt_token_handler *token = NULL;
|
struct crypt_token_handler_v2 *token;
|
||||||
void *handle;
|
void *h;
|
||||||
char *error;
|
|
||||||
char buf[512];
|
char buf[512];
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
if (!ret || !name || strlen(name) > 64)
|
if (!ret || !name || strlen(name) > 64)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
token = &ret->u.v2;
|
||||||
|
|
||||||
for (i = 0; name[i]; i++)
|
for (i = 0; name[i]; i++)
|
||||||
if (!isalnum(name[i]))
|
if (!isalnum(name[i]))
|
||||||
return -EINVAL;
|
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);
|
log_dbg(cd, "Trying to load %s.", buf);
|
||||||
|
|
||||||
handle = dlopen(buf, RTLD_LAZY);
|
h = dlopen(buf, RTLD_LAZY);
|
||||||
if (!handle) {
|
if (!h) {
|
||||||
log_dbg(NULL, "%s", dlerror());
|
log_dbg(NULL, "%s", dlerror());
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
dlerror();
|
dlerror();
|
||||||
|
|
||||||
token = dlvsym(handle, CRYPT_TOKEN_ABI_HANDLER, CRYPT_TOKEN_ABI_VERSION1);
|
token->name = strdup(name);
|
||||||
error = dlerror();
|
token->open = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_OPEN, CRYPT_TOKEN_ABI_VERSION1);
|
||||||
if (error) {
|
token->buffer_free = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_BUFFER_FREE, CRYPT_TOKEN_ABI_VERSION1);
|
||||||
log_dbg(cd, "%s", error);
|
token->validate = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_VALIDATE, CRYPT_TOKEN_ABI_VERSION1);
|
||||||
dlclose(handle);
|
token->dump = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_DUMP, CRYPT_TOKEN_ABI_VERSION1);
|
||||||
return -EINVAL;
|
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;
|
token->dlhandle = h;
|
||||||
ret->dlhandle = handle;
|
ret->version = 2;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
err:
|
||||||
|
free(CONST_CAST(void *)token->name);
|
||||||
|
dlclose(h);
|
||||||
|
memset(token, 0, sizeof(*token));
|
||||||
|
|
||||||
|
return r;
|
||||||
#else
|
#else
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
#endif
|
#endif
|
||||||
@@ -96,8 +149,8 @@ static int crypt_token_find_free(struct crypt_device *cd, const char *name, int
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].h; i++) {
|
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].u.v1.name; i++) {
|
||||||
if (!strcmp(token_handlers[i].h->name, name)) {
|
if (!strcmp(token_handlers[i].u.v1.name, name)) {
|
||||||
log_dbg(cd, "Keyslot handler %s is already registered.", name);
|
log_dbg(cd, "Keyslot handler %s is already registered.", name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -116,14 +169,15 @@ int crypt_token_register(const crypt_token_handler *handler)
|
|||||||
{
|
{
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
if (!handler->name || !handler->open)
|
if (!token_validate_v1(NULL, handler))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
r = crypt_token_find_free(NULL, handler->name, &i);
|
r = crypt_token_find_free(NULL, handler->name, &i);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
token_handlers[i].h = handler;
|
token_handlers[i].version = 1;
|
||||||
|
token_handlers[i].u.v1 = *handler;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,24 +186,26 @@ void crypt_token_unload_external_all(struct crypt_device *cd)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = LUKS2_TOKENS_MAX - 1; i >= 0; i--) {
|
for (i = LUKS2_TOKENS_MAX - 1; i >= 0; i--) {
|
||||||
if (!token_handlers[i].dlhandle)
|
if (token_handlers[i].version < 2)
|
||||||
continue;
|
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());
|
log_dbg(cd, "%s", dlerror());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const crypt_token_handler
|
static const void
|
||||||
*LUKS2_token_handler_type(struct crypt_device *cd, const char *type)
|
*LUKS2_token_handler_type(struct crypt_device *cd, const char *type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].h; i++)
|
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].u.v1.name; i++)
|
||||||
if (!strcmp(token_handlers[i].h->name, type))
|
if (!strcmp(token_handlers[i].u.v1.name, type))
|
||||||
return token_handlers[i].h;
|
return &token_handlers[i].u;
|
||||||
|
|
||||||
if (i >= LUKS2_TOKENS_MAX)
|
if (i >= LUKS2_TOKENS_MAX)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -160,10 +216,10 @@ static const crypt_token_handler
|
|||||||
if (crypt_token_load_external(cd, type, &token_handlers[i]))
|
if (crypt_token_load_external(cd, type, &token_handlers[i]))
|
||||||
return NULL;
|
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)
|
*LUKS2_token_handler(struct crypt_device *cd, int token)
|
||||||
{
|
{
|
||||||
struct luks2_hdr *hdr;
|
struct luks2_hdr *hdr;
|
||||||
@@ -305,7 +361,7 @@ static int LUKS2_token_open(struct crypt_device *cd,
|
|||||||
void *usrptr)
|
void *usrptr)
|
||||||
{
|
{
|
||||||
const char *json;
|
const char *json;
|
||||||
const crypt_token_handler *h;
|
const struct crypt_token_handler_v2 *h;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!(h = LUKS2_token_handler(cd, token)))
|
if (!(h = LUKS2_token_handler(cd, token)))
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "luks2_internal.h"
|
#include "luks2_internal.h"
|
||||||
|
|
||||||
static int keyring_open(struct crypt_device *cd,
|
int keyring_open(struct crypt_device *cd,
|
||||||
int token,
|
int token,
|
||||||
char **buffer,
|
char **buffer,
|
||||||
size_t *buffer_len,
|
size_t *buffer_len,
|
||||||
@@ -54,7 +54,7 @@ static int keyring_open(struct crypt_device *cd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int keyring_validate(struct crypt_device *cd __attribute__((unused)),
|
int keyring_validate(struct crypt_device *cd __attribute__((unused)),
|
||||||
const char *json)
|
const char *json)
|
||||||
{
|
{
|
||||||
enum json_tokener_error jerr;
|
enum json_tokener_error jerr;
|
||||||
@@ -92,7 +92,7 @@ out:
|
|||||||
return r;
|
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;
|
enum json_tokener_error jerr;
|
||||||
json_object *jobj_token, *jobj_key;
|
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;
|
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