]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/creds-util.c
Merge pull request #22563 from grigorig/cryptenroll-tpm2-pin
[thirdparty/systemd.git] / src / shared / creds-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <sys/file.h>
4
5 #if HAVE_OPENSSL
6 #include <openssl/err.h>
7 #endif
8
9 #include "sd-id128.h"
10
11 #include "blockdev-util.h"
12 #include "chattr-util.h"
13 #include "creds-util.h"
14 #include "env-util.h"
15 #include "fd-util.h"
16 #include "fileio.h"
17 #include "fs-util.h"
18 #include "io-util.h"
19 #include "memory-util.h"
20 #include "mkdir.h"
21 #include "openssl-util.h"
22 #include "path-util.h"
23 #include "random-util.h"
24 #include "sparse-endian.h"
25 #include "stat-util.h"
26 #include "tpm2-util.h"
27 #include "virt.h"
28
29 bool credential_name_valid(const char *s) {
30 /* We want that credential names are both valid in filenames (since that's our primary way to pass
31 * them around) and as fdnames (which is how we might want to pass them around eventually) */
32 return filename_is_valid(s) && fdname_is_valid(s);
33 }
34
35 int get_credentials_dir(const char **ret) {
36 const char *e;
37
38 assert(ret);
39
40 e = secure_getenv("CREDENTIALS_DIRECTORY");
41 if (!e)
42 return -ENXIO;
43
44 if (!path_is_absolute(e) || !path_is_normalized(e))
45 return -EINVAL;
46
47 *ret = e;
48 return 0;
49 }
50
51 int read_credential(const char *name, void **ret, size_t *ret_size) {
52 _cleanup_free_ char *fn = NULL;
53 const char *d;
54 int r;
55
56 assert(ret);
57
58 if (!credential_name_valid(name))
59 return -EINVAL;
60
61 r = get_credentials_dir(&d);
62 if (r < 0)
63 return r;
64
65 fn = path_join(d, name);
66 if (!fn)
67 return -ENOMEM;
68
69 return read_full_file_full(
70 AT_FDCWD, fn,
71 UINT64_MAX, SIZE_MAX,
72 READ_FULL_FILE_SECURE,
73 NULL,
74 (char**) ret, ret_size);
75 }
76
77 #if HAVE_OPENSSL
78
79 #define CREDENTIAL_HOST_SECRET_SIZE 4096
80
81 static const sd_id128_t credential_app_id =
82 SD_ID128_MAKE(d3,ac,ec,ba,0d,ad,4c,df,b8,c9,38,15,28,93,6c,58);
83
84 struct credential_host_secret_format {
85 /* The hashed machine ID of the machine this belongs to. Why? We want to ensure that each machine
86 * gets its own secret, even if people forget to flush out this secret file. Hence we bind it to the
87 * machine ID, for which there's hopefully a better chance it will be flushed out. We use a hashed
88 * machine ID instead of the literal one, because it's trivial to, and it might be a good idea not
89 * being able to directly associate a secret key file with a host. */
90 sd_id128_t machine_id;
91
92 /* The actual secret key */
93 uint8_t data[CREDENTIAL_HOST_SECRET_SIZE];
94 } _packed_;
95
96 static int make_credential_host_secret(
97 int dfd,
98 const sd_id128_t machine_id,
99 const char *fn,
100 void **ret_data,
101 size_t *ret_size) {
102
103 struct credential_host_secret_format buf;
104 _cleanup_free_ char *t = NULL;
105 _cleanup_close_ int fd = -1;
106 int r;
107
108 assert(dfd >= 0);
109 assert(fn);
110
111 fd = openat(dfd, ".", O_CLOEXEC|O_WRONLY|O_TMPFILE, 0400);
112 if (fd < 0) {
113 log_debug_errno(errno, "Failed to create temporary credential file with O_TMPFILE, proceeding without: %m");
114
115 if (asprintf(&t, "credential.secret.%016" PRIx64, random_u64()) < 0)
116 return -ENOMEM;
117
118 fd = openat(dfd, t, O_CLOEXEC|O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0400);
119 if (fd < 0)
120 return -errno;
121 }
122
123 r = chattr_secret(fd, 0);
124 if (r < 0)
125 log_debug_errno(r, "Failed to set file attributes for secrets file, ignoring: %m");
126
127 buf = (struct credential_host_secret_format) {
128 .machine_id = machine_id,
129 };
130
131 r = genuine_random_bytes(buf.data, sizeof(buf.data), RANDOM_BLOCK);
132 if (r < 0)
133 goto finish;
134
135 r = loop_write(fd, &buf, sizeof(buf), false);
136 if (r < 0)
137 goto finish;
138
139 if (fsync(fd) < 0) {
140 r = -errno;
141 goto finish;
142 }
143
144 if (t) {
145 r = rename_noreplace(dfd, t, dfd, fn);
146 if (r < 0)
147 goto finish;
148
149 t = mfree(t);
150 } else if (linkat(fd, "", dfd, fn, AT_EMPTY_PATH) < 0) {
151 r = -errno;
152 goto finish;
153 }
154
155 if (fsync(dfd) < 0) {
156 r = -errno;
157 goto finish;
158 }
159
160 if (ret_data) {
161 void *copy;
162
163 copy = memdup(buf.data, sizeof(buf.data));
164 if (!copy) {
165 r = -ENOMEM;
166 goto finish;
167 }
168
169 *ret_data = copy;
170 }
171
172 if (ret_size)
173 *ret_size = sizeof(buf.data);
174
175 r = 0;
176
177 finish:
178 if (t && unlinkat(dfd, t, 0) < 0)
179 log_debug_errno(errno, "Failed to remove temporary credential key: %m");
180
181 explicit_bzero_safe(&buf, sizeof(buf));
182 return r;
183 }
184
185 int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *ret_size) {
186 _cleanup_free_ char *_dirname = NULL, *_filename = NULL;
187 _cleanup_close_ int dfd = -1;
188 sd_id128_t machine_id;
189 const char *dirname, *filename;
190 int r;
191
192 r = sd_id128_get_machine_app_specific(credential_app_id, &machine_id);
193 if (r < 0)
194 return r;
195
196 const char *e = secure_getenv("SYSTEMD_CREDENTIAL_SECRET");
197 if (e) {
198 if (!path_is_normalized(e))
199 return -EINVAL;
200 if (!path_is_absolute(e))
201 return -EINVAL;
202
203 r = path_extract_directory(e, &_dirname);
204 if (r < 0)
205 return r;
206
207 r = path_extract_filename(e, &_filename);
208 if (r < 0)
209 return r;
210
211 dirname = _dirname;
212 filename = _filename;
213 } else {
214 dirname = "/var/lib/systemd";
215 filename = "credential.secret";
216 }
217
218 mkdir_parents(dirname, 0755);
219 dfd = open_mkdir_at(AT_FDCWD, dirname, O_CLOEXEC, 0755);
220 if (dfd < 0)
221 return log_debug_errno(dfd, "Failed to create or open directory '%s': %m", dirname);
222
223 if (FLAGS_SET(flags, CREDENTIAL_SECRET_FAIL_ON_TEMPORARY_FS)) {
224 r = fd_is_temporary_fs(dfd);
225 if (r < 0)
226 return log_debug_errno(r, "Failed to check directory '%s': %m", dirname);
227 if (r > 0)
228 return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
229 "Directory '%s' is on a temporary file system, refusing.", dirname);
230 }
231
232 for (unsigned attempt = 0;; attempt++) {
233 _cleanup_(erase_and_freep) struct credential_host_secret_format *f = NULL;
234 _cleanup_close_ int fd = -1;
235 size_t l = 0;
236 ssize_t n = 0;
237 struct stat st;
238
239 if (attempt >= 3) /* Somebody is playing games with us */
240 return log_debug_errno(SYNTHETIC_ERRNO(EIO),
241 "All attempts to create secret store in %s failed.", dirname);
242
243 fd = openat(dfd, filename, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_NOFOLLOW);
244 if (fd < 0) {
245 if (errno != ENOENT || !FLAGS_SET(flags, CREDENTIAL_SECRET_GENERATE))
246 return log_debug_errno(errno,
247 "Failed to open %s/%s: %m", dirname, filename);
248
249
250 r = make_credential_host_secret(dfd, machine_id, filename, ret, ret_size);
251 if (r == -EEXIST) {
252 log_debug_errno(r, "Credential secret %s/%s appeared while we were creating it, rereading.",
253 dirname, filename);
254 continue;
255 }
256 if (r < 0)
257 return log_debug_errno(r, "Failed to create credential secret %s/%s: %m",
258 dirname, filename);
259
260 return 0;
261 }
262
263 if (fstat(fd, &st) < 0)
264 return log_debug_errno(errno, "Failed to stat %s/%s: %m", dirname, filename);
265
266 r = stat_verify_regular(&st);
267 if (r < 0)
268 return log_debug_errno(r, "%s/%s is not a regular file: %m", dirname, filename);
269 if (st.st_nlink == 0) /* Deleted by now, try again */
270 continue;
271 if (st.st_nlink > 1)
272 /* Our deletion check won't work if hardlinked somewhere else */
273 return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
274 "%s/%s has too many links, refusing.",
275 dirname, filename);
276 if ((st.st_mode & 07777) != 0400)
277 /* Don't use file if not 0400 access mode */
278 return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
279 "%s/%s has permissive access mode, refusing.",
280 dirname, filename);
281 l = st.st_size;
282 if (l < offsetof(struct credential_host_secret_format, data) + 1)
283 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
284 "%s/%s is too small, refusing.", dirname, filename);
285 if (l > 16*1024*1024)
286 return log_debug_errno(SYNTHETIC_ERRNO(E2BIG),
287 "%s/%s is too big, refusing.", dirname, filename);
288
289 f = malloc(l+1);
290 if (!f)
291 return log_oom_debug();
292
293 n = read(fd, f, l+1);
294 if (n < 0)
295 return log_debug_errno(errno,
296 "Failed to read %s/%s: %m", dirname, filename);
297 if ((size_t) n != l) /* What? The size changed? */
298 return log_debug_errno(SYNTHETIC_ERRNO(EIO),
299 "Failed to read %s/%s: %m", dirname, filename);
300
301 if (sd_id128_equal(machine_id, f->machine_id)) {
302 size_t sz;
303
304 if (FLAGS_SET(flags, CREDENTIAL_SECRET_WARN_NOT_ENCRYPTED)) {
305 r = fd_is_encrypted(fd);
306 if (r < 0)
307 log_debug_errno(r, "Failed to determine if credential secret file '%s/%s' is encrypted.",
308 dirname, filename);
309 else if (r == 0)
310 log_warning("Credential secret file '%s/%s' is not located on encrypted media, using anyway.",
311 dirname, filename);
312 }
313
314 sz = l - offsetof(struct credential_host_secret_format, data);
315 assert(sz > 0);
316
317 if (ret) {
318 void *copy;
319
320 assert(sz <= sizeof(f->data)); /* Ensure we don't read past f->data bounds */
321
322 copy = memdup(f->data, sz);
323 if (!copy)
324 return log_oom_debug();
325
326 *ret = copy;
327 }
328
329 if (ret_size)
330 *ret_size = sz;
331
332 return 0;
333 }
334
335 /* Hmm, this secret is from somewhere else. Let's delete the file. Let's first acquire a lock
336 * to ensure we are the only ones accessing the file while we delete it. */
337
338 if (flock(fd, LOCK_EX) < 0)
339 return log_debug_errno(errno,
340 "Failed to flock %s/%s: %m", dirname, filename);
341
342 /* Before we delete it check that the file is still linked into the file system */
343 if (fstat(fd, &st) < 0)
344 return log_debug_errno(errno, "Failed to stat %s/%s: %m", dirname, filename);
345 if (st.st_nlink == 0) /* Already deleted by now? */
346 continue;
347 if (st.st_nlink != 1) /* Safety check, someone is playing games with us */
348 return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
349 "%s/%s unexpectedly has too many links.",
350 dirname, filename);
351 if (unlinkat(dfd, filename, 0) < 0)
352 return log_debug_errno(errno, "Failed to unlink %s/%s: %m", dirname, filename);
353
354 /* And now try again */
355 }
356 }
357
358 /* Construction is like this:
359 *
360 * A symmetric encryption key is derived from:
361 *
362 * 1. Either the "host" key (a key stored in /var/lib/credential.secret)
363 *
364 * 2. A key generated by letting the TPM2 calculate an HMAC hash of some nonce we pass to it, keyed
365 * by a key derived from its internal seed key.
366 *
367 * 3. The concatenation of the above.
368 *
369 * The above is hashed with SHA256 which is then used as encryption key for AES256-GCM. The encrypted
370 * credential is a short (unencrypted) header describing which of the three keys to use, the IV to use for
371 * AES256-GCM and some more meta information (sizes of certain objects) that is strictly speaking redundant,
372 * but kinda nice to have since we can have a more generic parser. If the TPM2 key is used this is followed
373 * by another (unencrypted) header, with information about the TPM2 policy used (specifically: the PCR mask
374 * to bind against, and a hash of the resulting policy — the latter being redundant, but speeding up things a
375 * bit, since we can more quickly refuse PCR state), followed by a sealed/exported TPM2 HMAC key. This is
376 * then followed by the encrypted data, which begins with a metadata header (which contains validity
377 * timestamps as well as the credential name), followed by the actual credential payload. The file ends in
378 * the AES256-GCM tag. To make things simple, the AES256-GCM AAD covers the main and the TPM2 header in
379 * full. This means the whole file is either protected by AAD, or is ciphertext, or is the tag. No
380 * unprotected data is included.
381 */
382
383 struct _packed_ encrypted_credential_header {
384 sd_id128_t id;
385 le32_t key_size;
386 le32_t block_size;
387 le32_t iv_size;
388 le32_t tag_size;
389 uint8_t iv[];
390 /* Followed by NUL bytes until next 8 byte boundary */
391 };
392
393 struct _packed_ tpm2_credential_header {
394 le64_t pcr_mask; /* Note that the spec for PC Clients only mandates 24 PCRs, and that's what systems
395 * generally have. But keep the door open for more. */
396 le16_t pcr_bank; /* For now, either TPM2_ALG_SHA256 or TPM2_ALG_SHA1 */
397 le16_t primary_alg; /* Primary key algorithm (either TPM2_ALG_RSA or TPM2_ALG_ECC for now) */
398 le32_t blob_size;
399 le32_t policy_hash_size;
400 uint8_t policy_hash_and_blob[];
401 /* Followed by NUL bytes until next 8 byte boundary */
402 };
403
404 struct _packed_ metadata_credential_header {
405 le64_t timestamp;
406 le64_t not_after;
407 le32_t name_size;
408 char name[];
409 /* Followed by NUL bytes until next 8 byte boundary */
410 };
411
412 /* Some generic limit for parts of the encrypted credential for which we don't know the right size ahead of
413 * time, but where we are really sure it won't be larger than this. Should be larger than any possible IV,
414 * padding, tag size and so on. This is purely used for early filtering out of invalid sizes. */
415 #define CREDENTIAL_FIELD_SIZE_MAX (16U*1024U)
416
417 static int sha256_hash_host_and_tpm2_key(
418 const void *host_key,
419 size_t host_key_size,
420 const void *tpm2_key,
421 size_t tpm2_key_size,
422 uint8_t ret[static SHA256_DIGEST_LENGTH]) {
423
424 _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *md = NULL;
425 unsigned l;
426
427 assert(host_key_size == 0 || host_key);
428 assert(tpm2_key_size == 0 || tpm2_key);
429 assert(ret);
430
431 /* Combines the host key and the TPM2 HMAC hash into a SHA256 hash value we'll use as symmetric encryption key. */
432
433 md = EVP_MD_CTX_new();
434 if (!md)
435 return log_oom();
436
437 if (EVP_DigestInit_ex(md, EVP_sha256(), NULL) != 1)
438 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initial SHA256 context.");
439
440 if (host_key && EVP_DigestUpdate(md, host_key, host_key_size) != 1)
441 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to hash host key.");
442
443 if (tpm2_key && EVP_DigestUpdate(md, tpm2_key, tpm2_key_size) != 1)
444 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to hash TPM2 key.");
445
446 assert(EVP_MD_CTX_size(md) == SHA256_DIGEST_LENGTH);
447
448 if (EVP_DigestFinal_ex(md, ret, &l) != 1)
449 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finalize SHA256 hash.");
450
451 assert(l == SHA256_DIGEST_LENGTH);
452 return 0;
453 }
454
455 int encrypt_credential_and_warn(
456 sd_id128_t with_key,
457 const char *name,
458 usec_t timestamp,
459 usec_t not_after,
460 const char *tpm2_device,
461 uint32_t tpm2_pcr_mask,
462 const void *input,
463 size_t input_size,
464 void **ret,
465 size_t *ret_size) {
466
467 _cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *context = NULL;
468 _cleanup_(erase_and_freep) void *host_key = NULL, *tpm2_key = NULL;
469 size_t host_key_size = 0, tpm2_key_size = 0, tpm2_blob_size = 0, tpm2_policy_hash_size = 0, output_size, p, ml;
470 _cleanup_free_ void *tpm2_blob = NULL, *tpm2_policy_hash = NULL, *iv = NULL, *output = NULL;
471 _cleanup_free_ struct metadata_credential_header *m = NULL;
472 uint16_t tpm2_pcr_bank = 0, tpm2_primary_alg = 0;
473 struct encrypted_credential_header *h;
474 int ksz, bsz, ivsz, tsz, added, r;
475 uint8_t md[SHA256_DIGEST_LENGTH];
476 const EVP_CIPHER *cc;
477 #if HAVE_TPM2
478 bool try_tpm2 = false;
479 #endif
480 sd_id128_t id;
481
482 assert(input || input_size == 0);
483 assert(ret);
484 assert(ret_size);
485
486 if (name && !credential_name_valid(name))
487 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid credential name: %s", name);
488
489 if (not_after != USEC_INFINITY && timestamp != USEC_INFINITY && not_after < timestamp)
490 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential is invalidated before it is valid (" USEC_FMT " < " USEC_FMT ").", not_after, timestamp);
491
492 if (DEBUG_LOGGING) {
493 char buf[FORMAT_TIMESTAMP_MAX];
494
495 if (name)
496 log_debug("Including credential name '%s' in encrypted credential.", name);
497 if (timestamp != USEC_INFINITY)
498 log_debug("Including timestamp '%s' in encrypted credential.", format_timestamp(buf, sizeof(buf), timestamp));
499 if (not_after != USEC_INFINITY)
500 log_debug("Including not-after timestamp '%s' in encrypted credential.", format_timestamp(buf, sizeof(buf), not_after));
501 }
502
503 if (sd_id128_is_null(with_key) ||
504 sd_id128_in_set(with_key, CRED_AES256_GCM_BY_HOST, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC)) {
505
506 r = get_credential_host_secret(
507 CREDENTIAL_SECRET_GENERATE|
508 CREDENTIAL_SECRET_WARN_NOT_ENCRYPTED|
509 (sd_id128_is_null(with_key) ? CREDENTIAL_SECRET_FAIL_ON_TEMPORARY_FS : 0),
510 &host_key,
511 &host_key_size);
512 if (r == -ENOMEDIUM && sd_id128_is_null(with_key))
513 log_debug_errno(r, "Credential host secret location on temporary file system, not using.");
514 else if (r < 0)
515 return log_error_errno(r, "Failed to determine local credential host secret: %m");
516 }
517
518 #if HAVE_TPM2
519 if (sd_id128_is_null(with_key)) {
520 /* If automatic mode is selected and we are running in a container, let's not try TPM2. OTOH
521 * if user picks TPM2 explicitly, let's always honour the request and try. */
522
523 r = detect_container();
524 if (r < 0)
525 log_debug_errno(r, "Failed to determine whether we are running in a container, ignoring: %m");
526 else if (r > 0)
527 log_debug("Running in container, not attempting to use TPM2.");
528
529 try_tpm2 = r <= 0;
530 }
531
532 if (try_tpm2 ||
533 sd_id128_in_set(with_key, CRED_AES256_GCM_BY_TPM2_HMAC, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC)) {
534
535 r = tpm2_seal(tpm2_device,
536 tpm2_pcr_mask,
537 NULL,
538 &tpm2_key,
539 &tpm2_key_size,
540 &tpm2_blob,
541 &tpm2_blob_size,
542 &tpm2_policy_hash,
543 &tpm2_policy_hash_size,
544 &tpm2_pcr_bank,
545 &tpm2_primary_alg);
546 if (r < 0) {
547 if (!sd_id128_is_null(with_key))
548 return r;
549
550 log_debug_errno(r, "TPM2 sealing didn't work, not using: %m");
551 }
552
553 assert(tpm2_blob_size <= CREDENTIAL_FIELD_SIZE_MAX);
554 assert(tpm2_policy_hash_size <= CREDENTIAL_FIELD_SIZE_MAX);
555 }
556 #endif
557
558 if (sd_id128_is_null(with_key)) {
559 /* Let's settle the key type in auto mode now. */
560
561 if (host_key && tpm2_key)
562 id = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC;
563 else if (tpm2_key)
564 id = CRED_AES256_GCM_BY_TPM2_HMAC;
565 else if (host_key)
566 id = CRED_AES256_GCM_BY_HOST;
567 else
568 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
569 "TPM2 not available and host key located on temporary file system, no encryption key available.");
570 } else
571 id = with_key;
572
573 /* Let's now take the host key and the TPM2 key and hash it together, to use as encryption key for the data */
574 r = sha256_hash_host_and_tpm2_key(host_key, host_key_size, tpm2_key, tpm2_key_size, md);
575 if (r < 0)
576 return r;
577
578 assert_se(cc = EVP_aes_256_gcm());
579
580 ksz = EVP_CIPHER_key_length(cc);
581 assert(ksz == sizeof(md));
582
583 bsz = EVP_CIPHER_block_size(cc);
584 assert(bsz > 0);
585 assert((size_t) bsz <= CREDENTIAL_FIELD_SIZE_MAX);
586
587 ivsz = EVP_CIPHER_iv_length(cc);
588 if (ivsz > 0) {
589 assert((size_t) ivsz <= CREDENTIAL_FIELD_SIZE_MAX);
590
591 iv = malloc(ivsz);
592 if (!iv)
593 return log_oom();
594
595 r = genuine_random_bytes(iv, ivsz, RANDOM_BLOCK);
596 if (r < 0)
597 return log_error_errno(r, "Failed to acquired randomized IV: %m");
598 }
599
600 tsz = 16; /* FIXME: On OpenSSL 3 there is EVP_CIPHER_CTX_get_tag_length(), until then let's hardcode this */
601
602 context = EVP_CIPHER_CTX_new();
603 if (!context)
604 return log_error_errno(SYNTHETIC_ERRNO(ENOMEM), "Failed to allocate encryption object: %s",
605 ERR_error_string(ERR_get_error(), NULL));
606
607 if (EVP_EncryptInit_ex(context, cc, NULL, md, iv) != 1)
608 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize encryption context: %s",
609 ERR_error_string(ERR_get_error(), NULL));
610
611 /* Just an upper estimate */
612 output_size =
613 ALIGN8(offsetof(struct encrypted_credential_header, iv) + ivsz) +
614 ALIGN8(tpm2_key ? offsetof(struct tpm2_credential_header, policy_hash_and_blob) + tpm2_blob_size + tpm2_policy_hash_size : 0) +
615 ALIGN8(offsetof(struct metadata_credential_header, name) + strlen_ptr(name)) +
616 input_size + 2U * (size_t) bsz +
617 tsz;
618
619 output = malloc0(output_size);
620 if (!output)
621 return log_oom();
622
623 h = (struct encrypted_credential_header*) output;
624 h->id = id;
625 h->block_size = htole32(bsz);
626 h->key_size = htole32(ksz);
627 h->tag_size = htole32(tsz);
628 h->iv_size = htole32(ivsz);
629 memcpy(h->iv, iv, ivsz);
630
631 p = ALIGN8(offsetof(struct encrypted_credential_header, iv) + ivsz);
632
633 if (tpm2_key) {
634 struct tpm2_credential_header *t;
635
636 t = (struct tpm2_credential_header*) ((uint8_t*) output + p);
637 t->pcr_mask = htole64(tpm2_pcr_mask);
638 t->pcr_bank = htole16(tpm2_pcr_bank);
639 t->primary_alg = htole16(tpm2_primary_alg);
640 t->blob_size = htole32(tpm2_blob_size);
641 t->policy_hash_size = htole32(tpm2_policy_hash_size);
642 memcpy(t->policy_hash_and_blob, tpm2_blob, tpm2_blob_size);
643 memcpy(t->policy_hash_and_blob + tpm2_blob_size, tpm2_policy_hash, tpm2_policy_hash_size);
644
645 p += ALIGN8(offsetof(struct tpm2_credential_header, policy_hash_and_blob) + tpm2_blob_size + tpm2_policy_hash_size);
646 }
647
648 /* Pass the encrypted + TPM2 header as AAD */
649 if (EVP_EncryptUpdate(context, NULL, &added, output, p) != 1)
650 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to write AAD data: %s",
651 ERR_error_string(ERR_get_error(), NULL));
652
653 /* Now construct the metadata header */
654 ml = strlen_ptr(name);
655 m = malloc0(ALIGN8(offsetof(struct metadata_credential_header, name) + ml));
656 if (!m)
657 return log_oom();
658
659 m->timestamp = htole64(timestamp);
660 m->not_after = htole64(not_after);
661 m->name_size = htole32(ml);
662 memcpy_safe(m->name, name, ml);
663
664 /* And encrypt the metadata header */
665 if (EVP_EncryptUpdate(context, (uint8_t*) output + p, &added, (const unsigned char*) m, ALIGN8(offsetof(struct metadata_credential_header, name) + ml)) != 1)
666 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to encrypt metadata header: %s",
667 ERR_error_string(ERR_get_error(), NULL));
668
669 assert(added >= 0);
670 assert((size_t) added <= output_size - p);
671 p += added;
672
673 /* Then encrypt the plaintext */
674 if (EVP_EncryptUpdate(context, (uint8_t*) output + p, &added, input, input_size) != 1)
675 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to encrypt data: %s",
676 ERR_error_string(ERR_get_error(), NULL));
677
678 assert(added >= 0);
679 assert((size_t) added <= output_size - p);
680 p += added;
681
682 /* Finalize */
683 if (EVP_EncryptFinal_ex(context, (uint8_t*) output + p, &added) != 1)
684 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finalize data encryption: %s",
685 ERR_error_string(ERR_get_error(), NULL));
686
687 assert(added >= 0);
688 assert((size_t) added <= output_size - p);
689 p += added;
690
691 assert(p <= output_size - tsz);
692
693 /* Append tag */
694 if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_GET_TAG, tsz, (uint8_t*) output + p) != 1)
695 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get tag: %s",
696 ERR_error_string(ERR_get_error(), NULL));
697
698 p += tsz;
699 assert(p <= output_size);
700
701 if (DEBUG_LOGGING && input_size > 0) {
702 size_t base64_size;
703
704 base64_size = DIV_ROUND_UP(p * 4, 3); /* Include base64 size increase in debug output */
705 assert(base64_size >= input_size);
706 log_debug("Input of %zu bytes grew to output of %zu bytes (+%2zu%%).", input_size, base64_size, base64_size * 100 / input_size - 100);
707 }
708
709 *ret = TAKE_PTR(output);
710 *ret_size = p;
711
712 return 0;
713 }
714
715 int decrypt_credential_and_warn(
716 const char *validate_name,
717 usec_t validate_timestamp,
718 const char *tpm2_device,
719 const void *input,
720 size_t input_size,
721 void **ret,
722 size_t *ret_size) {
723
724 _cleanup_(erase_and_freep) void *host_key = NULL, *tpm2_key = NULL, *plaintext = NULL;
725 _cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *context = NULL;
726 size_t host_key_size = 0, tpm2_key_size = 0, plaintext_size, p, hs;
727 struct encrypted_credential_header *h;
728 struct metadata_credential_header *m;
729 uint8_t md[SHA256_DIGEST_LENGTH];
730 bool with_tpm2, with_host_key;
731 const EVP_CIPHER *cc;
732 int r, added;
733
734 assert(input || input_size == 0);
735 assert(ret);
736 assert(ret_size);
737
738 h = (struct encrypted_credential_header*) input;
739
740 /* The ID must fit in, for the current and all future formats */
741 if (input_size < sizeof(h->id))
742 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
743
744 with_host_key = sd_id128_in_set(h->id, CRED_AES256_GCM_BY_HOST, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC);
745 with_tpm2 = sd_id128_in_set(h->id, CRED_AES256_GCM_BY_TPM2_HMAC, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC);
746
747 if (!with_host_key && !with_tpm2)
748 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unknown encryption format, or corrupted data: %m");
749
750 /* Now we know the minimum header size */
751 if (input_size < offsetof(struct encrypted_credential_header, iv))
752 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
753
754 /* Verify some basic header values */
755 if (le32toh(h->key_size) != sizeof(md))
756 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected key size in header.");
757 if (le32toh(h->block_size) <= 0 || le32toh(h->block_size) > CREDENTIAL_FIELD_SIZE_MAX)
758 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected block size in header.");
759 if (le32toh(h->iv_size) > CREDENTIAL_FIELD_SIZE_MAX)
760 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "IV size too large.");
761 if (le32toh(h->tag_size) != 16) /* FIXME: On OpenSSL 3, let's verify via EVP_CIPHER_CTX_get_tag_length() */
762 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected tag size in header.");
763
764 /* Ensure we have space for the full header now (we don't know the size of the name hence this is a
765 * lower limit only) */
766 if (input_size <
767 ALIGN8(offsetof(struct encrypted_credential_header, iv) + le32toh(h->iv_size)) +
768 ALIGN8((with_tpm2 ? offsetof(struct tpm2_credential_header, policy_hash_and_blob) : 0)) +
769 ALIGN8(offsetof(struct metadata_credential_header, name)) +
770 le32toh(h->tag_size))
771 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
772
773 p = ALIGN8(offsetof(struct encrypted_credential_header, iv) + le32toh(h->iv_size));
774
775 if (with_tpm2) {
776 #if HAVE_TPM2
777 struct tpm2_credential_header* t = (struct tpm2_credential_header*) ((uint8_t*) input + p);
778
779 if (le64toh(t->pcr_mask) >= (UINT64_C(1) << TPM2_PCRS_MAX))
780 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 PCR mask out of range.");
781 if (!tpm2_pcr_bank_to_string(le16toh(t->pcr_bank)))
782 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 PCR bank invalid or not supported");
783 if (!tpm2_primary_alg_to_string(le16toh(t->primary_alg)))
784 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 primary key algorithm invalid or not supported.");
785 if (le32toh(t->blob_size) > CREDENTIAL_FIELD_SIZE_MAX)
786 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected TPM2 blob size.");
787 if (le32toh(t->policy_hash_size) > CREDENTIAL_FIELD_SIZE_MAX)
788 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected TPM2 policy hash size.");
789
790 /* Ensure we have space for the full TPM2 header now (still don't know the name, and its size
791 * though, hence still just a lower limit test only) */
792 if (input_size <
793 ALIGN8(offsetof(struct encrypted_credential_header, iv) + le32toh(h->iv_size)) +
794 ALIGN8(offsetof(struct tpm2_credential_header, policy_hash_and_blob) + le32toh(t->blob_size) + le32toh(t->policy_hash_size)) +
795 ALIGN8(offsetof(struct metadata_credential_header, name)) +
796 le32toh(h->tag_size))
797 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
798
799 r = tpm2_unseal(tpm2_device,
800 le64toh(t->pcr_mask),
801 le16toh(t->pcr_bank),
802 le16toh(t->primary_alg),
803 t->policy_hash_and_blob,
804 le32toh(t->blob_size),
805 t->policy_hash_and_blob + le32toh(t->blob_size),
806 le32toh(t->policy_hash_size),
807 NULL,
808 &tpm2_key,
809 &tpm2_key_size);
810 if (r < 0)
811 return r;
812
813 p += ALIGN8(offsetof(struct tpm2_credential_header, policy_hash_and_blob) +
814 le32toh(t->blob_size) +
815 le32toh(t->policy_hash_size));
816 #else
817 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Credential requires TPM2 support, but TPM2 support not available.");
818 #endif
819 }
820
821 if (with_host_key) {
822 r = get_credential_host_secret(
823 0,
824 &host_key,
825 &host_key_size);
826 if (r < 0)
827 return log_error_errno(r, "Failed to determine local credential key: %m");
828 }
829
830 sha256_hash_host_and_tpm2_key(host_key, host_key_size, tpm2_key, tpm2_key_size, md);
831
832 assert_se(cc = EVP_aes_256_gcm());
833
834 /* Make sure cipher expectations match the header */
835 if (EVP_CIPHER_key_length(cc) != (int) le32toh(h->key_size))
836 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected key size in header.");
837 if (EVP_CIPHER_block_size(cc) != (int) le32toh(h->block_size))
838 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected block size in header.");
839
840 context = EVP_CIPHER_CTX_new();
841 if (!context)
842 return log_error_errno(SYNTHETIC_ERRNO(ENOMEM), "Failed to allocate decryption object: %s",
843 ERR_error_string(ERR_get_error(), NULL));
844
845 if (EVP_DecryptInit_ex(context, cc, NULL, NULL, NULL) != 1)
846 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize decryption context: %s",
847 ERR_error_string(ERR_get_error(), NULL));
848
849 if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_IVLEN, le32toh(h->iv_size), NULL) != 1)
850 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set IV size on decryption context: %s",
851 ERR_error_string(ERR_get_error(), NULL));
852
853 if (EVP_DecryptInit_ex(context, NULL, NULL, md, h->iv) != 1)
854 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set IV and key: %s",
855 ERR_error_string(ERR_get_error(), NULL));
856
857 if (EVP_DecryptUpdate(context, NULL, &added, input, p) != 1)
858 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to write AAD data: %s",
859 ERR_error_string(ERR_get_error(), NULL));
860
861 plaintext = malloc(input_size - p - le32toh(h->tag_size));
862 if (!plaintext)
863 return -ENOMEM;
864
865 if (EVP_DecryptUpdate(
866 context,
867 plaintext,
868 &added,
869 (uint8_t*) input + p,
870 input_size - p - le32toh(h->tag_size)) != 1)
871 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to decrypt data: %s",
872 ERR_error_string(ERR_get_error(), NULL));
873
874 assert(added >= 0);
875 assert((size_t) added <= input_size - p - le32toh(h->tag_size));
876 plaintext_size = added;
877
878 if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_TAG, le32toh(h->tag_size), (uint8_t*) input + input_size - le32toh(h->tag_size)) != 1)
879 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set tag: %s",
880 ERR_error_string(ERR_get_error(), NULL));
881
882 if (EVP_DecryptFinal_ex(context, (uint8_t*) plaintext + plaintext_size, &added) != 1)
883 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Decryption failed (incorrect key?): %s",
884 ERR_error_string(ERR_get_error(), NULL));
885
886 plaintext_size += added;
887
888 if (plaintext_size < ALIGN8(offsetof(struct metadata_credential_header, name)))
889 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Metadata header incomplete.");
890
891 m = plaintext;
892
893 if (le64toh(m->timestamp) != USEC_INFINITY &&
894 le64toh(m->not_after) != USEC_INFINITY &&
895 le64toh(m->timestamp) >= le64toh(m->not_after))
896 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Timestamps of credential are not in order, refusing.");
897
898 if (le32toh(m->name_size) > CREDENTIAL_NAME_MAX)
899 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Embedded credential name too long, refusing.");
900
901 hs = ALIGN8(offsetof(struct metadata_credential_header, name) + le32toh(m->name_size));
902 if (plaintext_size < hs)
903 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Metadata header incomplete.");
904
905 if (le32toh(m->name_size) > 0) {
906 _cleanup_free_ char *embedded_name = NULL;
907
908 if (memchr(m->name, 0, le32toh(m->name_size)))
909 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Embedded credential name contains NUL byte, refusing.");
910
911 embedded_name = memdup_suffix0(m->name, le32toh(m->name_size));
912 if (!embedded_name)
913 return log_oom();
914
915 if (!credential_name_valid(embedded_name))
916 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Embedded credential name is not valid, refusing.");
917
918 if (validate_name && !streq(embedded_name, validate_name)) {
919
920 r = getenv_bool_secure("SYSTEMD_CREDENTIAL_VALIDATE_NAME");
921 if (r < 0 && r != -ENXIO)
922 log_debug_errno(r, "Failed to parse $SYSTEMD_CREDENTIAL_VALIDATE_NAME: %m");
923 if (r != 0)
924 return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "Embedded credential name '%s' does not match filename '%s', refusing.", embedded_name, validate_name);
925
926 log_debug("Embedded credential name '%s' does not match expected name '%s', but configured to use credential anyway.", embedded_name, validate_name);
927 }
928 }
929
930 if (validate_timestamp != USEC_INFINITY) {
931 if (le64toh(m->timestamp) != USEC_INFINITY && le64toh(m->timestamp) > validate_timestamp)
932 log_debug("Credential timestamp is from the future, assuming clock skew.");
933
934 if (le64toh(m->not_after) != USEC_INFINITY && le64toh(m->not_after) < validate_timestamp) {
935
936 r = getenv_bool_secure("SYSTEMD_CREDENTIAL_VALIDATE_NOT_AFTER");
937 if (r < 0 && r != -ENXIO)
938 log_debug_errno(r, "Failed to parse $SYSTEMD_CREDENTIAL_VALIDATE_NOT_AFTER: %m");
939 if (r != 0)
940 return log_error_errno(SYNTHETIC_ERRNO(ESTALE), "Credential's time passed, refusing to use.");
941
942 log_debug("Credential not-after timestamp has passed, but configured to use credential anyway.");
943 }
944 }
945
946 if (ret) {
947 char *without_metadata;
948
949 without_metadata = memdup((uint8_t*) plaintext + hs, plaintext_size - hs);
950 if (!without_metadata)
951 return log_oom();
952
953 *ret = without_metadata;
954 }
955
956 if (ret_size)
957 *ret_size = plaintext_size - hs;
958
959 return 0;
960 }
961
962 #else
963
964 int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *ret_size) {
965 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Support for encrypted credentials not available.");
966 }
967
968 int encrypt_credential_and_warn(sd_id128_t with_key, const char *name, usec_t timestamp, usec_t not_after, const char *tpm2_device, uint32_t tpm2_pcr_mask, const void *input, size_t input_size, void **ret, size_t *ret_size) {
969 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Support for encrypted credentials not available.");
970 }
971
972 int decrypt_credential_and_warn(const char *validate_name, usec_t validate_timestamp, const char *tpm2_device, const void *input, size_t input_size, void **ret, size_t *ret_size) {
973 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Support for encrypted credentials not available.");
974 }
975
976 #endif