Coverage Report

Created: 2025-06-13 06:35

/src/cryptsetup/lib/volumekey.c
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * cryptsetup volume key implementation
4
 *
5
 * Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
6
 * Copyright (C) 2010-2025 Red Hat, Inc. All rights reserved.
7
 */
8
9
#include <string.h>
10
#include <stdint.h>
11
#include <stdlib.h>
12
#include <errno.h>
13
14
#include "internal.h"
15
16
struct volume_key {
17
  int id;
18
  size_t keylength; /* length in bytes */
19
  const char *key_description; /* keyring key name/description */
20
  key_type_t keyring_key_type; /* kernel keyring key type */
21
  key_serial_t key_id; /* kernel key id of volume key representation linked in thread keyring */
22
  struct volume_key *next;
23
  char *key;
24
};
25
26
struct volume_key *crypt_alloc_volume_key(size_t keylength, const char *key)
27
1.74k
{
28
1.74k
  struct volume_key *vk;
29
30
1.74k
  if (keylength > (SIZE_MAX - sizeof(*vk)))
31
0
    return NULL;
32
33
1.74k
  vk = crypt_zalloc(sizeof(*vk));
34
1.74k
  if (!vk)
35
0
    return NULL;
36
37
1.74k
  vk->keyring_key_type = INVALID_KEY;
38
1.74k
  vk->key_id = -1;
39
1.74k
  vk->keylength = keylength;
40
1.74k
  vk->id = KEY_NOT_VERIFIED;
41
42
  /* keylength 0 is valid => no key */
43
1.74k
  if (vk->keylength && key) {
44
741
    vk->key = crypt_safe_alloc(keylength);
45
741
    if (!vk->key) {
46
0
      free(vk);
47
0
      return NULL;
48
0
    }
49
741
    crypt_safe_memcpy(vk->key, key, keylength);
50
741
  }
51
52
1.74k
  return vk;
53
1.74k
}
54
55
struct volume_key *crypt_alloc_volume_key_by_safe_alloc(void **safe_alloc)
56
151
{
57
151
  size_t keylength;
58
151
  struct volume_key *vk;
59
60
151
  if (!safe_alloc)
61
0
    return NULL;
62
63
151
  keylength = crypt_safe_alloc_size(*safe_alloc);
64
151
  if (!keylength)
65
0
    return NULL;
66
67
151
  vk = crypt_alloc_volume_key(keylength, NULL);
68
151
  if (!vk)
69
0
    return NULL;
70
71
151
  vk->key = *safe_alloc;
72
151
  *safe_alloc = NULL;
73
74
151
  return vk;
75
151
}
76
77
void crypt_volume_key_pass_safe_alloc(struct volume_key *vk, void **safe_alloc)
78
0
{
79
0
  assert(vk);
80
0
  assert(vk->keylength);
81
0
  assert(safe_alloc);
82
0
  assert(crypt_safe_alloc_size(*safe_alloc) == vk->keylength);
83
84
0
  crypt_safe_free(vk->key);
85
0
  vk->key = *safe_alloc;
86
0
  *safe_alloc = NULL;
87
0
}
88
89
const char *crypt_volume_key_get_key(const struct volume_key *vk)
90
29
{
91
29
  assert(vk && vk->key);
92
93
29
  return vk->key;
94
29
}
95
96
size_t crypt_volume_key_length(const struct volume_key *vk)
97
0
{
98
0
  assert(vk);
99
100
0
  return vk->keylength;
101
0
}
102
103
int crypt_volume_key_set_description(struct volume_key *vk,
104
             const char *key_description, key_type_t keyring_key_type)
105
0
{
106
0
  if (!vk)
107
0
    return -EINVAL;
108
109
0
  free(CONST_CAST(void*)vk->key_description);
110
0
  vk->key_description = NULL;
111
0
  vk->keyring_key_type = keyring_key_type;
112
0
  if (key_description && !(vk->key_description = strdup(key_description)))
113
0
    return -ENOMEM;
114
115
0
  return 0;
116
0
}
117
118
int crypt_volume_key_set_description_by_name(struct volume_key *vk, const char *key_name)
119
0
{
120
0
  const char *key_description = NULL;
121
0
  key_type_t keyring_key_type = keyring_type_and_name(key_name, &key_description);
122
123
0
  if (keyring_key_type == INVALID_KEY)
124
0
    return -EINVAL;
125
126
0
  return crypt_volume_key_set_description(vk, key_description, keyring_key_type);
127
0
}
128
129
const char *crypt_volume_key_description(const struct volume_key *vk)
130
0
{
131
0
  assert(vk);
132
133
0
  return vk->key_description;
134
0
}
135
136
137
key_type_t crypt_volume_key_kernel_key_type(const struct volume_key *vk)
138
0
{
139
0
  assert(vk);
140
141
0
  return vk->keyring_key_type;
142
0
}
143
144
void crypt_volume_key_set_id(struct volume_key *vk, int id)
145
0
{
146
0
  if (vk && id >= 0)
147
0
    vk->id = id;
148
0
}
149
150
int crypt_volume_key_get_id(const struct volume_key *vk)
151
0
{
152
0
  return vk ? vk->id : -1;
153
0
}
154
155
struct volume_key *crypt_volume_key_by_id(struct volume_key *vks, int id)
156
0
{
157
0
  struct volume_key *vk = vks;
158
159
0
  if (id < 0)
160
0
    return NULL;
161
162
0
  while (vk && vk->id != id)
163
0
    vk = vk->next;
164
165
0
  return vk;
166
0
}
167
168
void crypt_volume_key_add_next(struct volume_key **vks, struct volume_key *vk)
169
1.53k
{
170
1.53k
  struct volume_key *tmp;
171
172
1.53k
  if (!vks)
173
0
    return;
174
175
1.53k
  if (!*vks) {
176
471
    *vks = vk;
177
471
    return;
178
471
  }
179
180
1.06k
  tmp = *vks;
181
182
52.4k
  while (tmp->next)
183
51.3k
    tmp = tmp->next;
184
185
1.06k
  tmp->next = vk;
186
1.06k
}
187
188
struct volume_key *crypt_volume_key_next(struct volume_key *vk)
189
0
{
190
0
  return vk ? vk->next : NULL;
191
0
}
192
193
void crypt_free_volume_key(struct volume_key *vk)
194
8.36k
{
195
8.36k
  struct volume_key *vk_next;
196
197
10.1k
  while (vk) {
198
1.74k
    free(CONST_CAST(void*)vk->key_description);
199
1.74k
    crypt_safe_free(vk->key);
200
1.74k
    vk_next = vk->next;
201
1.74k
    free(vk);
202
1.74k
    vk = vk_next;
203
1.74k
  }
204
8.36k
}
205
206
struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, size_t keylength,
207
               key_quality_info quality)
208
0
{
209
0
  int r;
210
0
  void *key;
211
0
  struct volume_key *vk = NULL;
212
213
0
  key = crypt_safe_alloc(keylength);
214
0
  if (!key)
215
0
    return NULL;
216
217
0
  switch (quality) {
218
0
  case KEY_QUALITY_KEY:
219
0
    r = crypt_random_get(cd, key, keylength, CRYPT_RND_KEY);
220
0
    break;
221
0
  case KEY_QUALITY_NORMAL:
222
0
    r = crypt_random_get(cd, key, keylength, CRYPT_RND_NORMAL);
223
0
    break;
224
0
  case KEY_QUALITY_EMPTY:
225
0
    r = 0;
226
0
    break;
227
0
  default:
228
0
    abort();
229
0
  }
230
231
0
  if (!r)
232
0
    vk = crypt_alloc_volume_key(keylength, NULL);
233
0
  if (vk)
234
0
    vk->key = key;
235
0
  else
236
0
    crypt_safe_free(key);
237
238
0
  return vk;
239
0
}
240
241
bool crypt_volume_key_is_set(const struct volume_key *vk)
242
0
{
243
0
  return vk && vk->key;
244
0
}
245
246
bool crypt_volume_key_upload_kernel_key(struct volume_key *vk)
247
0
{
248
0
  key_serial_t kid;
249
250
0
  assert(vk && vk->key && vk->key_description && vk->keyring_key_type != INVALID_KEY);
251
252
0
  kid = keyring_add_key_in_thread_keyring(vk->keyring_key_type, vk->key_description,
253
0
           vk->key, vk->keylength);
254
0
  if (kid >= 0) {
255
0
    vk->key_id = kid;
256
0
    return true;
257
0
  }
258
259
0
  return false;
260
0
}
261
262
void crypt_volume_key_drop_kernel_key(struct crypt_device *cd, struct volume_key *vk)
263
0
{
264
0
  assert(vk);
265
0
  assert(vk->key_description || vk->keyring_key_type == INVALID_KEY);
266
0
  assert(!vk->key_description || vk->keyring_key_type != INVALID_KEY);
267
268
0
  crypt_unlink_key_by_description_from_thread_keyring(cd,
269
0
                  vk->key_description,
270
0
                  vk->keyring_key_type);
271
0
}
272
273
void crypt_volume_key_drop_uploaded_kernel_key(struct crypt_device *cd, struct volume_key *vk)
274
0
{
275
0
  assert(vk);
276
277
0
  if (vk->key_id < 0)
278
0
    return;
279
280
0
  crypt_unlink_key_from_thread_keyring(cd, vk->key_id);
281
0
  vk->key_id = -1;
282
0
}