Imported Upstream version 2.3.7
[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, Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2022, Ondrej Kozina
6  * Copyright (C) 2022, 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 #include <assert.h>
25
26 #define MAX_STR 64
27
28 struct jtype {
29         enum { JNONE = 0, JSTR, JU64, JX64, JU32 } type;
30         json_object *jobj;
31         const char *id;
32 };
33
34 static size_t sr(struct jtype *j, uint8_t *ptr)
35 {
36         json_object *jobj;
37         size_t len = 0;
38         uint64_t u64;
39         uint32_t u32;
40
41         if (!json_object_is_type(j->jobj, json_type_object))
42                 return 0;
43
44         if (!json_object_object_get_ex(j->jobj, j->id, &jobj))
45                 return 0;
46
47         switch(j->type) {
48         case JSTR: /* JSON string */
49                 if (!json_object_is_type(jobj, json_type_string))
50                         return 0;
51                 len = strlen(json_object_get_string(jobj));
52                 if (len > MAX_STR)
53                         return 0;
54                 if (ptr)
55                         memcpy(ptr, json_object_get_string(jobj), len);
56                 break;
57         case JU64: /* Unsigned 64bit integer stored as string */
58                 if (!json_object_is_type(jobj, json_type_string))
59                         break;
60                 len = sizeof(u64);
61                 if (ptr) {
62                         u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
63                         memcpy(ptr, &u64, len);
64                 }
65                 break;
66         case JX64: /* Unsigned 64bit segment size (allows "dynamic") */
67                 if (!json_object_is_type(jobj, json_type_string))
68                         break;
69                 if (!strcmp(json_object_get_string(jobj), "dynamic")) {
70                         len = strlen("dynamic");
71                         if (ptr)
72                                 memcpy(ptr, json_object_get_string(jobj), len);
73                 } else {
74                         len = sizeof(u64);
75                         u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
76                         if (ptr)
77                                 memcpy(ptr, &u64, len);
78                 }
79                 break;
80         case JU32: /* Unsigned 32bit integer, stored as JSON int */
81                 if (!json_object_is_type(jobj, json_type_int))
82                         return 0;
83                 len =  sizeof(u32);
84                 if (ptr) {
85                         u32 = cpu_to_be32(crypt_jobj_get_uint32(jobj));
86                         memcpy(ptr, &u32, len);
87                 }
88                 break;
89         case JNONE:
90                 return 0;
91         };
92
93         return len;
94 }
95
96 static size_t srs(struct jtype j[], uint8_t *ptr)
97 {
98         size_t l, len = 0;
99
100         while(j->jobj) {
101                 l = sr(j, ptr);
102                 if (!l)
103                         return 0;
104                 len += l;
105                 if (ptr)
106                         ptr += l;
107                 j++;
108         }
109         return len;
110 }
111
112 static size_t segment_linear_serialize(json_object *jobj_segment, uint8_t *buffer)
113 {
114         struct jtype j[] = {
115                 { JSTR, jobj_segment, "type" },
116                 { JU64, jobj_segment, "offset" },
117                 { JX64, jobj_segment, "size" },
118                 {}
119         };
120         return srs(j, buffer);
121 }
122
123 static size_t segment_crypt_serialize(json_object *jobj_segment, uint8_t *buffer)
124 {
125         struct jtype j[] = {
126                 { JSTR, jobj_segment, "type" },
127                 { JU64, jobj_segment, "offset" },
128                 { JX64, jobj_segment, "size" },
129                 { JU64, jobj_segment, "iv_tweak" },
130                 { JSTR, jobj_segment, "encryption" },
131                 { JU32, jobj_segment, "sector_size" },
132                 {}
133         };
134         return srs(j, buffer);
135 }
136
137 static size_t segment_serialize(json_object *jobj_segment, uint8_t *buffer)
138 {
139         json_object *jobj_type;
140         const char *segment_type;
141
142         if (!json_object_object_get_ex(jobj_segment, "type", &jobj_type))
143                 return 0;
144
145         if (!(segment_type = json_object_get_string(jobj_type)))
146                 return 0;
147
148         if (!strcmp(segment_type, "crypt"))
149                 return segment_crypt_serialize(jobj_segment, buffer);
150         else if (!strcmp(segment_type, "linear"))
151                 return segment_linear_serialize(jobj_segment, buffer);
152
153         return 0;
154 }
155
156 static size_t backup_segments_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
157 {
158         json_object *jobj_segment;
159         size_t l, len = 0;
160
161         jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-previous");
162         if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
163                 return 0;
164         len += l;
165         if (buffer)
166                 buffer += l;
167
168         jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-final");
169         if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
170                 return 0;
171         len += l;
172         if (buffer)
173                 buffer += l;
174
175         jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-moved-segment");
176         if (jobj_segment) {
177                 if (!(l = segment_serialize(jobj_segment, buffer)))
178                         return 0;
179                 len += l;
180         }
181
182         return len;
183 }
184
185 static size_t reenc_keyslot_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
186 {
187         json_object *jobj_keyslot, *jobj_area, *jobj_type;
188         const char *area_type;
189         int keyslot_reencrypt;
190
191         keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
192         if (keyslot_reencrypt < 0)
193                 return 0;
194
195         if (!(jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot_reencrypt)))
196                 return 0;
197
198         if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
199                 return 0;
200
201         if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
202                 return 0;
203
204         if (!(area_type = json_object_get_string(jobj_type)))
205                 return 0;
206
207         struct jtype j[] = {
208                 { JSTR, jobj_keyslot, "mode" },
209                 { JSTR, jobj_keyslot, "direction" },
210                 { JSTR, jobj_area,    "type" },
211                 { JU64, jobj_area,    "offset" },
212                 { JU64, jobj_area,    "size" },
213                 {}
214         };
215         struct jtype j_datashift[] = {
216                 { JSTR, jobj_keyslot, "mode" },
217                 { JSTR, jobj_keyslot, "direction" },
218                 { JSTR, jobj_area,    "type" },
219                 { JU64, jobj_area,    "offset" },
220                 { JU64, jobj_area,    "size" },
221                 { JU64, jobj_area,    "shift_size" },
222                 {}
223         };
224         struct jtype j_checksum[] = {
225                 { JSTR, jobj_keyslot, "mode" },
226                 { JSTR, jobj_keyslot, "direction" },
227                 { JSTR, jobj_area,    "type" },
228                 { JU64, jobj_area,    "offset" },
229                 { JU64, jobj_area,    "size" },
230                 { JSTR, jobj_area,    "hash" },
231                 { JU32, jobj_area,    "sector_size" },
232                 {}
233         };
234
235         if (!strcmp(area_type, "datashift"))
236                 return srs(j_datashift, buffer);
237         else if (!strcmp(area_type, "checksum"))
238                 return srs(j_checksum, buffer);
239
240         return srs(j, buffer);
241 }
242
243 static size_t blob_serialize(void *blob, size_t length, uint8_t *buffer)
244 {
245         if (buffer)
246                 memcpy(buffer, blob, length);
247
248         return length;
249 }
250
251 static int reencrypt_assembly_verification_data(struct crypt_device *cd,
252         struct luks2_hdr *hdr,
253         struct volume_key *vks,
254         struct volume_key **verification_data)
255 {
256         uint8_t *ptr;
257         int digest_new, digest_old;
258         struct volume_key *data = NULL, *vk_old = NULL, *vk_new = NULL;
259         size_t keyslot_data_len, segments_data_len, data_len = 2;
260
261         /* Keys - calculate length */
262         digest_new = LUKS2_reencrypt_digest_new(hdr);
263         digest_old = LUKS2_reencrypt_digest_old(hdr);
264
265         if (digest_old >= 0) {
266                 vk_old = crypt_volume_key_by_id(vks, digest_old);
267                 if (!vk_old)
268                         return -EINVAL;
269                 data_len += blob_serialize(vk_old->key, vk_old->keylength, NULL);
270         }
271
272         if (digest_new >= 0 && digest_old != digest_new) {
273                 vk_new = crypt_volume_key_by_id(vks, digest_new);
274                 if (!vk_new)
275                         return -EINVAL;
276                 data_len += blob_serialize(vk_new->key, vk_new->keylength, NULL);
277         }
278
279         if (data_len == 2)
280                 return -EINVAL;
281
282         /* Metadata - calculate length */
283         if (!(keyslot_data_len = reenc_keyslot_serialize(hdr, NULL)))
284                 return -EINVAL;
285         data_len += keyslot_data_len;
286
287         if (!(segments_data_len = backup_segments_serialize(hdr, NULL)))
288                 return -EINVAL;
289         data_len += segments_data_len;
290
291         /* Alloc and fill serialization data */
292         data = crypt_alloc_volume_key(data_len, NULL);
293         if (!data)
294                 return -ENOMEM;
295
296         ptr = (uint8_t*)data->key;
297
298         /* v2 */
299         *ptr++ = 0x76;
300         *ptr++ = 0x32;
301
302         if (vk_old)
303                 ptr += blob_serialize(vk_old->key, vk_old->keylength, ptr);
304
305         if (vk_new)
306                 ptr += blob_serialize(vk_new->key, vk_new->keylength, ptr);
307
308         if (!reenc_keyslot_serialize(hdr, ptr))
309                 goto bad;
310         ptr += keyslot_data_len;
311
312         if (!backup_segments_serialize(hdr, ptr))
313                 goto bad;
314         ptr += segments_data_len;
315
316         assert((size_t)(ptr - (uint8_t*)data->key) == data_len);
317
318         *verification_data = data;
319
320         return 0;
321 bad:
322         crypt_free_volume_key(data);
323         return -EINVAL;
324 }
325
326 int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
327         struct luks2_hdr *hdr,
328         struct volume_key *vks)
329 {
330         int digest_reencrypt, keyslot_reencrypt, r;
331         struct volume_key *data;
332
333         keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
334         if (keyslot_reencrypt < 0)
335                 return keyslot_reencrypt;
336
337         r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
338         if (r < 0)
339                 return r;
340
341         r = LUKS2_digest_create(cd, "pbkdf2", hdr, data);
342         crypt_free_volume_key(data);
343         if (r < 0)
344                 return r;
345
346         digest_reencrypt = r;
347
348         r = LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, CRYPT_ANY_DIGEST, 0, 0);
349         if (r < 0)
350                 return r;
351
352         return LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, digest_reencrypt, 1, 0);
353 }
354
355 int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
356         struct luks2_hdr *hdr,
357         struct volume_key *vks)
358 {
359         int r, keyslot_reencrypt;
360         struct volume_key *data;
361
362         keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
363         if (keyslot_reencrypt < 0)
364                 return keyslot_reencrypt;
365
366         r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
367         if (r < 0)
368                 return r;
369
370         r = LUKS2_digest_verify(cd, hdr, data, keyslot_reencrypt);
371         crypt_free_volume_key(data);
372
373         if (r < 0) {
374                 if (r == -ENOENT)
375                         log_dbg(cd, "Reencryption digest is missing.");
376                 log_err(cd, _("Reencryption metadata is invalid."));
377         } else
378                 log_dbg(cd, "Reencryption metadata verified.");
379
380         return r;
381 }