448ad45c5766c439f5de767453929cb72a6e9ea6
[platform/upstream/cryptsetup.git] / lib / luks2 / luks2_token_keyring.c
1 /*
2  * LUKS - Linux Unified Key Setup v2, kernel keyring token
3  *
4  * Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2016-2020 Ondrej Kozina
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <assert.h>
23
24 #include "luks2_internal.h"
25
26 static int keyring_open(struct crypt_device *cd,
27                                 int token,
28                                 char **buffer,
29                                 size_t *buffer_len,
30                                 void *usrptr __attribute__((unused)))
31 {
32         json_object *jobj_token, *jobj_key;
33         struct luks2_hdr *hdr;
34         int r;
35
36         if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
37                 return -EINVAL;
38
39         jobj_token = LUKS2_get_token_jobj(hdr, token);
40         if (!jobj_token)
41                 return -EINVAL;
42
43         json_object_object_get_ex(jobj_token, "key_description", &jobj_key);
44
45         r = keyring_get_passphrase(json_object_get_string(jobj_key), buffer, buffer_len);
46         if (r == -ENOTSUP) {
47                 log_dbg(cd, "Kernel keyring features disabled.");
48                 return -EINVAL;
49         } else if (r < 0) {
50                 log_dbg(cd, "keyring_get_passphrase failed (error %d)", r);
51                 return -EINVAL;
52         }
53
54         return 0;
55 }
56
57 static int keyring_validate(struct crypt_device *cd __attribute__((unused)),
58                                     const char *json)
59 {
60         enum json_tokener_error jerr;
61         json_object *jobj_token, *jobj_key;
62         int r = 1;
63
64         log_dbg(cd, "Validating keyring token json");
65
66         jobj_token = json_tokener_parse_verbose(json, &jerr);
67         if (!jobj_token) {
68                 log_dbg(cd, "Keyring token JSON parse failed.");
69                 return r;
70         }
71
72         if (json_object_object_length(jobj_token) != 3) {
73                 log_dbg(cd, "Keyring token is expected to have exactly 3 fields.");
74                 goto out;
75         }
76
77         if (!json_object_object_get_ex(jobj_token, "key_description", &jobj_key)) {
78                 log_dbg(cd, "missing key_description field.");
79                 goto out;
80         }
81
82         if (!json_object_is_type(jobj_key, json_type_string)) {
83                 log_dbg(cd, "key_description is not a string.");
84                 goto out;
85         }
86
87         /* TODO: perhaps check that key description is in '%s:%s'
88          * format where both strings are not empty */
89         r = !strlen(json_object_get_string(jobj_key));
90 out:
91         json_object_put(jobj_token);
92         return r;
93 }
94
95 static void keyring_dump(struct crypt_device *cd, const char *json)
96 {
97         enum json_tokener_error jerr;
98         json_object *jobj_token, *jobj_key;
99
100         jobj_token = json_tokener_parse_verbose(json, &jerr);
101         if (!jobj_token)
102                 return;
103
104         if (!json_object_object_get_ex(jobj_token, "key_description", &jobj_key)) {
105                 json_object_put(jobj_token);
106                 return;
107         }
108
109         log_std(cd, "\tKey description: %s\n", json_object_get_string(jobj_key));
110
111         json_object_put(jobj_token);
112 }
113
114 int token_keyring_set(json_object **jobj_builtin_token,
115         const void *params)
116 {
117         json_object *jobj_token, *jobj;
118         const struct crypt_token_params_luks2_keyring *keyring_params = (const struct crypt_token_params_luks2_keyring *) params;
119
120         jobj_token = json_object_new_object();
121         if (!jobj_token)
122                 return -ENOMEM;
123
124         jobj = json_object_new_string(LUKS2_TOKEN_KEYRING);
125         if (!jobj) {
126                 json_object_put(jobj_token);
127                 return -ENOMEM;
128         }
129         json_object_object_add(jobj_token, "type", jobj);
130
131         jobj = json_object_new_array();
132         if (!jobj) {
133                 json_object_put(jobj_token);
134                 return -ENOMEM;
135         }
136         json_object_object_add(jobj_token, "keyslots", jobj);
137
138         jobj = json_object_new_string(keyring_params->key_description);
139         if (!jobj) {
140                 json_object_put(jobj_token);
141                 return -ENOMEM;
142         }
143         json_object_object_add(jobj_token, "key_description", jobj);
144
145         *jobj_builtin_token = jobj_token;
146         return 0;
147 }
148
149 int token_keyring_get(json_object *jobj_token,
150         void *params)
151 {
152         json_object *jobj;
153         struct crypt_token_params_luks2_keyring *keyring_params = (struct crypt_token_params_luks2_keyring *) params;
154
155         json_object_object_get_ex(jobj_token, "type", &jobj);
156         assert(!strcmp(json_object_get_string(jobj), LUKS2_TOKEN_KEYRING));
157
158         json_object_object_get_ex(jobj_token, "key_description", &jobj);
159
160         keyring_params->key_description = json_object_get_string(jobj);
161
162         return 0;
163 }
164
165 const crypt_token_handler keyring_handler = {
166         .name = LUKS2_TOKEN_KEYRING,
167         .open = keyring_open,
168         .validate = keyring_validate,
169         .dump = keyring_dump
170 };