]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cryptsetup-util: add helper call for extracting/parsing token JSON
authorLennart Poettering <lennart@poettering.net>
Tue, 8 Dec 2020 12:18:28 +0000 (13:18 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 17 Dec 2020 18:58:52 +0000 (19:58 +0100)
src/shared/cryptsetup-util.c
src/shared/cryptsetup-util.h

index b02d95ac55405dd05b118e5db7db1ca232fe19a5..850c79ed12349d6891f128ff2f23eeaedab6af4c 100644 (file)
@@ -5,6 +5,7 @@
 #include "cryptsetup-util.h"
 #include "dlfcn-util.h"
 #include "log.h"
+#include "parse-util.h"
 
 static void *cryptsetup_dl = NULL;
 
@@ -26,6 +27,8 @@ int (*sym_crypt_resize)(struct crypt_device *cd, const char *name, uint64_t new_
 int (*sym_crypt_set_data_device)(struct crypt_device *cd, const char *device);
 void (*sym_crypt_set_debug_level)(int level);
 void (*sym_crypt_set_log_callback)(struct crypt_device *cd, void (*log)(int level, const char *msg, void *usrptr), void *usrptr);
+int (*sym_crypt_token_json_get)(struct crypt_device *cd, int token, const char **json) = NULL;
+int (*sym_crypt_token_json_set)(struct crypt_device *cd, int token, const char *json) = NULL;
 int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
 
 int dlopen_cryptsetup(void) {
@@ -61,6 +64,8 @@ int dlopen_cryptsetup(void) {
                         DLSYM_ARG(crypt_set_data_device),
                         DLSYM_ARG(crypt_set_debug_level),
                         DLSYM_ARG(crypt_set_log_callback),
+                        DLSYM_ARG(crypt_token_json_get),
+                        DLSYM_ARG(crypt_token_json_set),
                         DLSYM_ARG(crypt_volume_key_get),
                         NULL);
         if (r < 0)
@@ -108,4 +113,102 @@ void cryptsetup_enable_logging(struct crypt_device *cd) {
         sym_crypt_set_debug_level(DEBUG_LOGGING ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
 }
 
+int cryptsetup_get_token_as_json(
+                struct crypt_device *cd,
+                int idx,
+                const char *verify_type,
+                JsonVariant **ret) {
+
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        const char *text;
+        int r;
+
+        assert(cd);
+
+        /* Extracts and parses the LUKS2 JSON token data from a LUKS2 device. Optionally verifies the type of
+         * the token. Returns:
+         *
+         *      -EINVAL → token index out of range or "type" field missing
+         *      -ENOENT → token doesn't exist
+         * -EMEDIUMTYPE → "verify_type" specified and doesn't match token's type
+         */
+
+        r = dlopen_cryptsetup();
+        if (r < 0)
+                return r;
+
+        r = sym_crypt_token_json_get(cd, idx, &text);
+        if (r < 0)
+                return r;
+
+        r = json_parse(text, 0, &v, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        if (verify_type) {
+                JsonVariant *w;
+
+                w = json_variant_by_key(v, "type");
+                if (!w)
+                        return -EINVAL;
+
+                if (!streq_ptr(json_variant_string(w), verify_type))
+                        return -EMEDIUMTYPE;
+        }
+
+        if (ret)
+                *ret = TAKE_PTR(v);
+
+        return 0;
+}
+
+int cryptsetup_get_keyslot_from_token(JsonVariant *v) {
+        int keyslot, r;
+        JsonVariant *w;
+
+        /* Parses the "keyslots" field of a LUKS2 token object. The field can be an array, but here we assume
+         * that it contains a single element only, since that's the only way we ever generate it
+         * ourselves. */
+
+        w = json_variant_by_key(v, "keyslots");
+        if (!w)
+                return -ENOENT;
+        if (!json_variant_is_array(w) || json_variant_elements(w) != 1)
+                return -EMEDIUMTYPE;
+
+        w = json_variant_by_index(w, 0);
+        if (!w)
+                return -ENOENT;
+        if (!json_variant_is_string(w))
+                return -EMEDIUMTYPE;
+
+        r = safe_atoi(json_variant_string(w), &keyslot);
+        if (r < 0)
+                return r;
+        if (keyslot < 0)
+                return -EINVAL;
+
+        return keyslot;
+}
+
+int cryptsetup_add_token_json(struct crypt_device *cd, JsonVariant *v) {
+        _cleanup_free_ char *text = NULL;
+        int r;
+
+        r = dlopen_cryptsetup();
+        if (r < 0)
+                return r;
+
+        r = json_variant_format(v, 0, &text);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to format token data for LUKS: %m");
+
+        log_debug("Adding token text <%s>", text);
+
+        r = sym_crypt_token_json_set(cd, CRYPT_ANY_TOKEN, text);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to write token data to LUKS: %m");
+
+        return 0;
+}
 #endif
index b96ffc74e3b59886635d7e3d65097d35054e36a6..c6c56d680173ed7d5cccb0160c88cd7bd13986d0 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include "json.h"
 #include "macro.h"
 
 #if HAVE_LIBCRYPTSETUP
@@ -24,6 +25,8 @@ extern int (*sym_crypt_resize)(struct crypt_device *cd, const char *name, uint64
 extern int (*sym_crypt_set_data_device)(struct crypt_device *cd, const char *device);
 extern void (*sym_crypt_set_debug_level)(int level);
 extern void (*sym_crypt_set_log_callback)(struct crypt_device *cd, void (*log)(int level, const char *msg, void *usrptr), void *usrptr);
+extern int (*sym_crypt_token_json_get)(struct crypt_device *cd, int token, const char **json);
+extern int (*sym_crypt_token_json_set)(struct crypt_device *cd, int token, const char *json);
 extern int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
 
 int dlopen_cryptsetup(void);
@@ -33,4 +36,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct crypt_device *, sym_crypt_free);
 
 void cryptsetup_enable_logging(struct crypt_device *cd);
 
+int cryptsetup_get_token_as_json(struct crypt_device *cd, int idx, const char *verify_type, JsonVariant **ret);
+int cryptsetup_get_keyslot_from_token(JsonVariant *v);
+int cryptsetup_add_token_json(struct crypt_device *cd, JsonVariant *v);
+
 #endif