Merge branch 'upstream' into tizen
[platform/upstream/cryptsetup.git] / lib / luks2 / luks2_reencrypt_digest.c
1 /*
2  * LUKS - Linux Unified Key Setup v2, reencryption digest helpers
3  *
4  * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2022-2023 Ondrej Kozina
6  * Copyright (C) 2022-2023 Milan Broz
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "luks2_internal.h"
24
25 #define MAX_STR 64
26
27 struct jtype {
28         enum { JNONE = 0, JSTR, JU64, JX64, JU32 } type;
29         json_object *jobj;
30         const char *id;
31 };
32
33 static size_t sr(struct jtype *j, uint8_t *ptr)
34 {
35         json_object *jobj;
36         size_t len = 0;
37         uint64_t u64;
38         uint32_t u32;
39
40         if (!json_object_is_type(j->jobj, json_type_object))
41                 return 0;
42
43         if (!json_object_object_get_ex(j->jobj, j->id, &jobj))
44                 return 0;
45
46         switch(j->type) {
47         case JSTR: /* JSON string */
48                 if (!json_object_is_type(jobj, json_type_string))
49                         return 0;
50                 len = strlen(json_object_get_string(jobj));
51                 if (len > MAX_STR)
52                         return 0;
53                 if (ptr)
54                         memcpy(ptr, json_object_get_string(jobj), len);
55                 break;
56         case JU64: /* Unsigned 64bit integer stored as string */
57                 if (!json_object_is_type(jobj, json_type_string))
58                         break;
59                 len = sizeof(u64);
60                 if (ptr) {
61                         u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
62                         memcpy(ptr, &u64, len);
63                 }
64                 break;
65         case JX64: /* Unsigned 64bit segment size (allows "dynamic") */
66                 if (!json_object_is_type(jobj, json_type_string))
67                         break;
68                 if (!strcmp(json_object_get_string(jobj), "dynamic")) {
69                         len = strlen("dynamic");
70                         if (ptr)
71                                 memcpy(ptr, json_object_get_string(jobj), len);
72                 } else {
73                         len = sizeof(u64);
74                         u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
75                         if (ptr)
76                                 memcpy(ptr, &u64, len);
77                 }
78                 break;
79         case JU32: /* Unsigned 32bit integer, stored as JSON int */
80                 if (!json_object_is_type(jobj, json_type_int))
81                         return 0;
82                 len =  sizeof(u32);
83                 if (ptr) {
84                         u32 = cpu_to_be32(crypt_jobj_get_uint32(jobj));
85                         memcpy(ptr, &u32, len);
86                 }
87                 break;
88         case JNONE:
89                 return 0;
90         };
91
92         return len;
93 }
94
95 static size_t srs(struct jtype j[], uint8_t *ptr)
96 {
97         size_t l, len = 0;
98
99         while(j->jobj) {
100                 l = sr(j, ptr);
101                 if (!l)
102                         return 0;
103                 len += l;
104                 if (ptr)
105                         ptr += l;
106                 j++;
107         }
108         return len;
109 }
110
111 static size_t segment_linear_serialize(json_object *jobj_segment, uint8_t *buffer)
112 {
113         struct jtype j[] = {
114                 { JSTR, jobj_segment, "type" },
115                 { JU64, jobj_segment, "offset" },
116                 { JX64, jobj_segment, "size" },
117                 {}
118         };
119         return srs(j, buffer);
120 }
121
122 static size_t segment_crypt_serialize(json_object *jobj_segment, uint8_t *buffer)
123 {
124         struct jtype j[] = {
125                 { JSTR, jobj_segment, "type" },
126                 { JU64, jobj_segment, "offset" },
127                 { JX64, jobj_segment, "size" },
128                 { JU64, jobj_segment, "iv_tweak" },
129                 { JSTR, jobj_segment, "encryption" },
130                 { JU32, jobj_segment, "sector_size" },
131                 {}
132         };
133         return srs(j, buffer);
134 }
135
136 static size_t segment_serialize(json_object *jobj_segment, uint8_t *buffer)
137 {
138         json_object *jobj_type;
139         const char *segment_type;
140
141         if (!json_object_object_get_ex(jobj_segment, "type", &jobj_type))
142                 return 0;
143
144         if (!(segment_type = json_object_get_string(jobj_type)))
145                 return 0;
146
147         if (!strcmp(segment_type, "crypt"))
148                 return segment_crypt_serialize(jobj_segment, buffer);
149         else if (!strcmp(segment_type, "linear"))
150                 return segment_linear_serialize(jobj_segment, buffer);
151
152         return 0;
153 }
154
155 static size_t backup_segments_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
156 {
157         json_object *jobj_segment;
158         size_t l, len = 0;
159
160         jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-previous");
161         if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
162                 return 0;
163         len += l;
164         if (buffer)
165                 buffer += l;
166
167         jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-final");
168         if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
169                 return 0;
170         len += l;
171         if (buffer)
172                 buffer += l;
173
174         jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-moved-segment");
175         if (jobj_segment) {
176                 if (!(l = segment_serialize(jobj_segment, buffer)))
177                         return 0;
178                 len += l;
179         }
180
181         return len;
182 }
183
184 static size_t reenc_keyslot_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
185 {
186         json_object *jobj_keyslot, *jobj_area, *jobj_type;
187         const char *area_type;
188         int keyslot_reencrypt;
189
190         keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
191         if (keyslot_reencrypt < 0)
192                 return 0;
193
194         if (!(jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot_reencrypt)))
195                 return 0;
196
197         if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
198                 return 0;
199
200         if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
201                 return 0;
202
203         if (!(area_type = json_object_get_string(jobj_type)))
204                 return 0;
205
206         struct jtype j[] = {
207                 { JSTR, jobj_keyslot, "mode" },
208                 { JSTR, jobj_keyslot, "direction" },
209                 { JSTR, jobj_area,    "type" },
210                 { JU64, jobj_area,    "offset" },
211                 { JU64, jobj_area,    "size" },
212                 {}
213         };
214         struct jtype j_datashift[] = {
215                 { JSTR, jobj_keyslot, "mode" },
216                 { JSTR, jobj_keyslot, "direction" },
217                 { JSTR, jobj_area,    "type" },
218                 { JU64, jobj_area,    "offset" },
219                 { JU64, jobj_area,    "size" },
220                 { JU64, jobj_area,    "shift_size" },
221                 {}
222         };
223         struct jtype j_checksum[] = {
224                 { JSTR, jobj_keyslot, "mode" },
225                 { JSTR, jobj_keyslot, "direction" },
226                 { JSTR, jobj_area,    "type" },
227                 { JU64, jobj_area,    "offset" },
228                 { JU64, jobj_area,    "size" },
229                 { JSTR, jobj_area,    "hash" },
230                 { JU32, jobj_area,    "sector_size" },
231                 {}
232         };
233         struct jtype j_datashift_checksum[] = {
234                 { JSTR, jobj_keyslot, "mode" },
235                 { JSTR, jobj_keyslot, "direction" },
236                 { JSTR, jobj_area,    "type" },
237                 { JU64, jobj_area,    "offset" },
238                 { JU64, jobj_area,    "size" },
239                 { JSTR, jobj_area,    "hash" },
240                 { JU32, jobj_area,    "sector_size" },
241                 { JU64, jobj_area,    "shift_size" },
242                 {}
243         };
244
245         if (!strcmp(area_type, "datashift-checksum"))
246                 return srs(j_datashift_checksum, buffer);
247         else if (!strcmp(area_type, "datashift") ||
248                  !strcmp(area_type, "datashift-journal"))
249                 return srs(j_datashift, buffer);
250         else if (!strcmp(area_type, "checksum"))
251                 return srs(j_checksum, buffer);
252
253         return srs(j, buffer);
254 }
255
256 static size_t blob_serialize(void *blob, size_t length, uint8_t *buffer)
257 {
258         if (buffer)
259                 memcpy(buffer, blob, length);
260
261         return length;
262 }
263
264 static int reencrypt_assembly_verification_data(struct crypt_device *cd,
265         struct luks2_hdr *hdr,
266         struct volume_key *vks,
267         uint8_t version,
268         struct volume_key **verification_data)
269 {
270         uint8_t *ptr;
271         int digest_new, digest_old;
272         struct volume_key *data = NULL, *vk_old = NULL, *vk_new = NULL;
273         size_t keyslot_data_len, segments_data_len, data_len = 2;
274
275         /*
276          * This works up to (including) version v207.
277          */
278         assert(version < (UINT8_MAX - 0x2F));
279
280         /* Keys - calculate length */
281         digest_new = LUKS2_reencrypt_digest_new(hdr);
282         digest_old = LUKS2_reencrypt_digest_old(hdr);
283
284         if (digest_old >= 0) {
285                 vk_old = crypt_volume_key_by_id(vks, digest_old);
286                 if (!vk_old) {
287                         log_dbg(cd, "Key (digest id %d) required but not unlocked.", digest_old);
288                         return -EINVAL;
289                 }
290                 data_len += blob_serialize(vk_old->key, vk_old->keylength, NULL);
291         }
292
293         if (digest_new >= 0 && digest_old != digest_new) {
294                 vk_new = crypt_volume_key_by_id(vks, digest_new);
295                 if (!vk_new) {
296                         log_dbg(cd, "Key (digest id %d) required but not unlocked.", digest_new);
297                         return -EINVAL;
298                 }
299                 data_len += blob_serialize(vk_new->key, vk_new->keylength, NULL);
300         }
301
302         if (data_len == 2)
303                 return -EINVAL;
304
305         /* Metadata - calculate length */
306         if (!(keyslot_data_len = reenc_keyslot_serialize(hdr, NULL)))
307                 return -EINVAL;
308         data_len += keyslot_data_len;
309
310         if (!(segments_data_len = backup_segments_serialize(hdr, NULL)))
311                 return -EINVAL;
312         data_len += segments_data_len;
313
314         /* Alloc and fill serialization data */
315         data = crypt_alloc_volume_key(data_len, NULL);
316         if (!data)
317                 return -ENOMEM;
318
319         ptr = (uint8_t*)data->key;
320
321         *ptr++ = 0x76;
322         *ptr++ = 0x30 + version;
323
324         if (vk_old)
325                 ptr += blob_serialize(vk_old->key, vk_old->keylength, ptr);
326
327         if (vk_new)
328                 ptr += blob_serialize(vk_new->key, vk_new->keylength, ptr);
329
330         if (!reenc_keyslot_serialize(hdr, ptr))
331                 goto bad;
332         ptr += keyslot_data_len;
333
334         if (!backup_segments_serialize(hdr, ptr))
335                 goto bad;
336         ptr += segments_data_len;
337
338         assert((size_t)(ptr - (uint8_t*)data->key) == data_len);
339
340         *verification_data = data;
341
342         return 0;
343 bad:
344         crypt_free_volume_key(data);
345         return -EINVAL;
346 }
347
348 int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
349         struct luks2_hdr *hdr,
350         uint8_t version,
351         struct volume_key *vks)
352 {
353         int digest_reencrypt, keyslot_reencrypt, r;
354         struct volume_key *data;
355
356         keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
357         if (keyslot_reencrypt < 0)
358                 return keyslot_reencrypt;
359
360         r = reencrypt_assembly_verification_data(cd, hdr, vks, version, &data);
361         if (r < 0)
362                 return r;
363
364         r = LUKS2_digest_create(cd, "pbkdf2", hdr, data);
365         crypt_free_volume_key(data);
366         if (r < 0)
367                 return r;
368
369         digest_reencrypt = r;
370
371         r = LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, CRYPT_ANY_DIGEST, 0, 0);
372         if (r < 0)
373                 return r;
374
375         return LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, digest_reencrypt, 1, 0);
376 }
377
378 int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
379         struct luks2_hdr *hdr,
380         struct volume_key *vks)
381 {
382         int r, keyslot_reencrypt;
383         struct volume_key *data;
384         uint8_t version;
385
386         log_dbg(cd, "Verifying reencryption metadata.");
387
388         keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
389         if (keyslot_reencrypt < 0)
390                 return keyslot_reencrypt;
391
392         if (LUKS2_config_get_reencrypt_version(hdr, &version))
393                 return -EINVAL;
394
395         r = reencrypt_assembly_verification_data(cd, hdr, vks, version, &data);
396         if (r < 0)
397                 return r;
398
399         r = LUKS2_digest_verify(cd, hdr, data, keyslot_reencrypt);
400         crypt_free_volume_key(data);
401
402         if (r < 0) {
403                 if (r == -ENOENT)
404                         log_dbg(cd, "Reencryption digest is missing.");
405                 log_err(cd, _("Reencryption metadata is invalid."));
406         } else
407                 log_dbg(cd, "Reencryption metadata verified.");
408
409         return r;
410 }