2 * Example of LUKS2 ssh token handler (EXPERIMENTAL)
4 * Copyright (C) 2016-2023 Milan Broz
5 * Copyright (C) 2020-2023 Vojtech Trefny
8 * - generate LUKS device
9 * - store passphrase used in previous step remotely (single line w/o \r\n)
10 * - add new token using this example
11 * - activate device by token
13 * This file is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
18 * This file is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this file; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <json-c/json.h>
33 #include "libcryptsetup.h"
34 #include "ssh-utils.h"
36 #define TOKEN_NAME "ssh"
37 #define TOKEN_VERSION_MAJOR "1"
38 #define TOKEN_VERSION_MINOR "0"
40 #define SERVER_ARG "plugin-ssh-server"
41 #define USER_ARG "plugin-ssh-user"
42 #define PATH_ARG "plugin-ssh-path"
43 #define KEYPATH_ARG "plugin-ssh-keypath"
45 #define l_dbg(cd, x...) crypt_logf(cd, CRYPT_LOG_DEBUG, x)
48 const char *cryptsetup_token_version(void);
49 int cryptsetup_token_open_pin(struct crypt_device *cd, int token, const char *pin,
50 size_t pin_size, char **password, size_t *password_len, void *usrptr);
51 int cryptsetup_token_open(struct crypt_device *cd, int token,
52 char **password, size_t *password_len, void *usrptr);
53 void cryptsetup_token_dump(struct crypt_device *cd, const char *json);
54 int cryptsetup_token_validate(struct crypt_device *cd, const char *json);
57 const char *cryptsetup_token_version(void)
59 return TOKEN_VERSION_MAJOR "." TOKEN_VERSION_MINOR;
62 static json_object *get_token_jobj(struct crypt_device *cd, int token)
64 const char *json_slot;
66 /* libcryptsetup API call */
67 if (crypt_token_json_get(cd, token, &json_slot))
70 return json_tokener_parse(json_slot);
73 int cryptsetup_token_open_pin(struct crypt_device *cd, int token, const char *pin,
74 size_t pin_size __attribute__((unused)), char **password, size_t *password_len,
75 void *usrptr __attribute__((unused)))
78 json_object *jobj_server, *jobj_user, *jobj_path, *jobj_token, *jobj_keypath;
82 jobj_token = get_token_jobj(cd, token);
86 json_object_object_get_ex(jobj_token, "ssh_server", &jobj_server);
87 json_object_object_get_ex(jobj_token, "ssh_user", &jobj_user);
88 json_object_object_get_ex(jobj_token, "ssh_path", &jobj_path);
89 json_object_object_get_ex(jobj_token, "ssh_keypath",&jobj_keypath);
91 r = ssh_pki_import_privkey_file(json_object_get_string(jobj_keypath), pin, NULL, NULL, &pkey);
93 json_object_put(jobj_token);
95 crypt_log(cd, CRYPT_LOG_ERROR, "Failed to open and import private key.\n");
98 crypt_log(cd, CRYPT_LOG_ERROR, "Failed to import private key (password protected?).\n");
102 ssh = sshplugin_session_init(cd, json_object_get_string(jobj_server),
103 json_object_get_string(jobj_user));
105 json_object_put(jobj_token);
110 r = sshplugin_public_key_auth(cd, ssh, pkey);
113 if (r == SSH_AUTH_SUCCESS)
114 r = sshplugin_download_password(cd, ssh, json_object_get_string(jobj_path),
115 password, password_len);
119 json_object_put(jobj_token);
121 return r ? -EINVAL : r;
124 int cryptsetup_token_open(struct crypt_device *cd, int token,
125 char **password, size_t *password_len, void *usrptr)
127 return cryptsetup_token_open_pin(cd, token, NULL, 0, password, password_len, usrptr);
130 void cryptsetup_token_dump(struct crypt_device *cd, const char *json)
132 json_object *jobj_token, *jobj_server, *jobj_user, *jobj_path, *jobj_keypath;
135 jobj_token = json_tokener_parse(json);
139 json_object_object_get_ex(jobj_token, "ssh_server", &jobj_server);
140 json_object_object_get_ex(jobj_token, "ssh_user", &jobj_user);
141 json_object_object_get_ex(jobj_token, "ssh_path", &jobj_path);
142 json_object_object_get_ex(jobj_token, "ssh_keypath",&jobj_keypath);
144 if (snprintf(buf, sizeof(buf) - 1, "\tssh_server: %s\n\tssh_user: %s\n"
145 "\tssh_path: %s\n\tssh_key_path: %s\n",
146 json_object_get_string(jobj_server),
147 json_object_get_string(jobj_user),
148 json_object_get_string(jobj_path),
149 json_object_get_string(jobj_keypath)) > 0)
150 crypt_log(cd, CRYPT_LOG_NORMAL, buf);
152 json_object_put(jobj_token);
155 int cryptsetup_token_validate(struct crypt_device *cd, const char *json)
157 enum json_tokener_error jerr;
158 json_object *jobj_token, *jobj;
161 jobj_token = json_tokener_parse_verbose(json, &jerr);
165 if (!json_object_object_get_ex(jobj_token, "ssh_server", &jobj) ||
166 !json_object_is_type(jobj, json_type_string)) {
167 l_dbg(cd, "ssh_server element is missing or not string.");
171 if (!json_object_object_get_ex(jobj_token, "ssh_user", &jobj) ||
172 !json_object_is_type(jobj, json_type_string)) {
173 l_dbg(cd, "ssh_user element is missing or not string.");
177 if (!json_object_object_get_ex(jobj_token, "ssh_path", &jobj) ||
178 !json_object_is_type(jobj, json_type_string)) {
179 l_dbg(cd, "ssh_path element is missing or not string.");
183 if (!json_object_object_get_ex(jobj_token, "ssh_keypath", &jobj) ||
184 !json_object_is_type(jobj, json_type_string)) {
185 l_dbg(cd, "ssh_keypath element is missing or not string.");
191 json_object_put(jobj_token);