1 /* SPDX-License-Identifier: LGPL-2.1+ */
7 #include <p11-kit/p11-kit.h>
8 #include <p11-kit/uri.h>
10 #include "alloc-util.h"
11 #include "ask-password-api.h"
12 #include "cryptsetup-pkcs11.h"
15 #include "format-util.h"
17 #include "memory-util.h"
18 #include "pkcs11-util.h"
19 #include "stat-util.h"
22 #define KEY_FILE_SIZE_MAX (16U*1024U*1024U) /* 16 MiB */
24 static int load_key_file(
27 uint64_t key_file_offset
,
28 void **ret_encrypted_key
,
29 size_t *ret_encrypted_key_size
) {
31 _cleanup_(erase_and_freep
) char *buffer
= NULL
;
32 _cleanup_close_
int fd
= -1;
37 assert(ret_encrypted_key
);
38 assert(ret_encrypted_key_size
);
40 fd
= open(key_file
, O_RDONLY
|O_CLOEXEC
);
42 return log_error_errno(errno
, "Failed to load encrypted PKCS#11 key: %m");
44 if (key_file_size
== 0) {
47 if (fstat(fd
, &st
) < 0)
48 return log_error_errno(errno
, "Failed to stat key file: %m");
50 r
= stat_verify_regular(&st
);
52 return log_error_errno(r
, "Key file is not a regular file: %m");
55 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Key file is empty, refusing.");
56 if ((uint64_t) st
.st_size
> KEY_FILE_SIZE_MAX
) {
57 char buf1
[FORMAT_BYTES_MAX
], buf2
[FORMAT_BYTES_MAX
];
58 return log_error_errno(SYNTHETIC_ERRNO(ERANGE
),
59 "Key file larger (%s) than allowed maximum size (%s), refusing.",
60 format_bytes(buf1
, sizeof(buf1
), st
.st_size
),
61 format_bytes(buf2
, sizeof(buf2
), KEY_FILE_SIZE_MAX
));
64 if (key_file_offset
>= (uint64_t) st
.st_size
)
65 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Key file offset too large for file, refusing.");
67 key_file_size
= st
.st_size
- key_file_offset
;
70 buffer
= malloc(key_file_size
);
74 if (key_file_offset
> 0)
75 n
= pread(fd
, buffer
, key_file_size
, key_file_offset
);
77 n
= read(fd
, buffer
, key_file_size
);
79 return log_error_errno(errno
, "Failed to read PKCS#11 key file: %m");
81 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Empty encrypted key found, refusing.");
83 *ret_encrypted_key
= TAKE_PTR(buffer
);
84 *ret_encrypted_key_size
= (size_t) n
;
89 struct pkcs11_callback_data
{
90 const char *friendly_name
;
93 size_t encrypted_key_size
;
95 size_t decrypted_key_size
;
98 static void pkcs11_callback_data_release(struct pkcs11_callback_data
*data
) {
99 free(data
->decrypted_key
);
100 free(data
->encrypted_key
);
103 static int pkcs11_callback(
105 CK_SESSION_HANDLE session
,
107 const CK_SLOT_INFO
*slot_info
,
108 const CK_TOKEN_INFO
*token_info
,
112 struct pkcs11_callback_data
*data
= userdata
;
113 CK_OBJECT_HANDLE object
;
122 /* Called for every token matching our URI */
124 r
= pkcs11_token_login(
137 /* We are likely called during early boot, where entropy is scarce. Mix some data from the PKCS#11
138 * token, if it supports that. It should be cheap, given that we already are talking to it anyway and
140 (void) pkcs11_token_acquire_rng(m
, session
);
142 r
= pkcs11_token_find_private_key(m
, session
, uri
, &object
);
146 r
= pkcs11_token_decrypt_data(
151 data
->encrypted_key_size
,
152 &data
->decrypted_key
,
153 &data
->decrypted_key_size
);
160 int decrypt_pkcs11_key(
161 const char *friendly_name
,
162 const char *pkcs11_uri
,
163 const char *key_file
,
164 size_t key_file_size
,
165 uint64_t key_file_offset
,
167 void **ret_decrypted_key
,
168 size_t *ret_decrypted_key_size
) {
170 _cleanup_(pkcs11_callback_data_release
) struct pkcs11_callback_data data
= {
171 .friendly_name
= friendly_name
,
176 assert(friendly_name
);
179 assert(ret_decrypted_key
);
180 assert(ret_decrypted_key_size
);
182 /* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */
184 r
= load_key_file(key_file
, key_file_size
, key_file_offset
, &data
.encrypted_key
, &data
.encrypted_key_size
);
188 r
= pkcs11_find_token(pkcs11_uri
, pkcs11_callback
, &data
);
192 *ret_decrypted_key
= TAKE_PTR(data
.decrypted_key
);
193 *ret_decrypted_key_size
= data
.decrypted_key_size
;