]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/home/homework-pkcs11.c
man: Remove OSConfig project mentioning for systemd-confext
[thirdparty/systemd.git] / src / home / homework-pkcs11.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
70a5db58
LP
2
3#include "hexdecoct.h"
4#include "homework-pkcs11.h"
5#include "pkcs11-util.h"
6#include "strv.h"
7
8int pkcs11_callback(
9 CK_FUNCTION_LIST *m,
10 CK_SESSION_HANDLE session,
11 CK_SLOT_ID slot_id,
12 const CK_SLOT_INFO *slot_info,
13 const CK_TOKEN_INFO *token_info,
14 P11KitUri *uri,
15 void *userdata) {
16
17 _cleanup_(erase_and_freep) void *decrypted_key = NULL;
99534007 18 struct pkcs11_callback_data *data = ASSERT_PTR(userdata);
70a5db58
LP
19 _cleanup_free_ char *token_label = NULL;
20 CK_TOKEN_INFO updated_token_info;
21 size_t decrypted_key_size;
22 CK_OBJECT_HANDLE object;
70a5db58
LP
23 CK_RV rv;
24 int r;
25
26 assert(m);
27 assert(slot_info);
28 assert(token_info);
29 assert(uri);
70a5db58
LP
30
31 /* Special return values:
32 *
33 * -ENOANO → if we need a PIN but have none
34 * -ERFKILL → if a "protected authentication path" is needed but we have no OK to use it
35 * -EOWNERDEAD → if the PIN is locked
36 * -ENOLCK → if the supplied PIN is incorrect
37 * -ETOOMANYREFS → ditto, but only a few tries left
38 * -EUCLEAN → ditto, but only a single try left
39 */
40
41 token_label = pkcs11_token_label(token_info);
42 if (!token_label)
43 return log_oom();
44
45 if (FLAGS_SET(token_info->flags, CKF_PROTECTED_AUTHENTICATION_PATH)) {
46
47 if (data->secret->pkcs11_protected_authentication_path_permitted <= 0)
48 return log_error_errno(SYNTHETIC_ERRNO(ERFKILL), "Security token requires authentication through protected authentication path.");
49
50 rv = m->C_Login(session, CKU_USER, NULL, 0);
51 if (rv != CKR_OK)
707de94c 52 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to log into security token '%s': %s", token_label, sym_p11_kit_strerror(rv));
70a5db58 53
80ace4f2 54 log_info("Successfully logged into security token '%s' via protected authentication path.", token_label);
70a5db58
LP
55 goto decrypt;
56 }
57
58 if (!FLAGS_SET(token_info->flags, CKF_LOGIN_REQUIRED)) {
59 log_info("No login into security token '%s' required.", token_label);
60 goto decrypt;
61 }
62
c0bde0d2
LP
63 if (strv_isempty(data->secret->token_pin))
64 return log_error_errno(SYNTHETIC_ERRNO(ENOANO), "Security token requires PIN.");
70a5db58 65
c0bde0d2 66 STRV_FOREACH(i, data->secret->token_pin) {
70a5db58
LP
67 rv = m->C_Login(session, CKU_USER, (CK_UTF8CHAR*) *i, strlen(*i));
68 if (rv == CKR_OK) {
69 log_info("Successfully logged into security token '%s' with PIN.", token_label);
70 goto decrypt;
71 }
72 if (rv == CKR_PIN_LOCKED)
73 return log_error_errno(SYNTHETIC_ERRNO(EOWNERDEAD), "PIN of security token is blocked. Please unblock it first.");
74 if (!IN_SET(rv, CKR_PIN_INCORRECT, CKR_PIN_LEN_RANGE))
707de94c 75 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to log into security token '%s': %s", token_label, sym_p11_kit_strerror(rv));
70a5db58
LP
76 }
77
78 rv = m->C_GetTokenInfo(slot_id, &updated_token_info);
79 if (rv != CKR_OK)
707de94c 80 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to acquire updated security token information for slot %lu: %s", slot_id, sym_p11_kit_strerror(rv));
70a5db58
LP
81
82 if (FLAGS_SET(updated_token_info.flags, CKF_USER_PIN_FINAL_TRY))
83 return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), "PIN of security token incorrect, only a single try left.");
84 if (FLAGS_SET(updated_token_info.flags, CKF_USER_PIN_COUNT_LOW))
85 return log_error_errno(SYNTHETIC_ERRNO(ETOOMANYREFS), "PIN of security token incorrect, only a few tries left.");
86
87 return log_error_errno(SYNTHETIC_ERRNO(ENOLCK), "PIN of security token incorrect.");
88
89decrypt:
90 r = pkcs11_token_find_private_key(m, session, uri, &object);
91 if (r < 0)
92 return r;
93
94 r = pkcs11_token_decrypt_data(m, session, object, data->encrypted_key->data, data->encrypted_key->size, &decrypted_key, &decrypted_key_size);
95 if (r < 0)
96 return r;
97
98 if (base64mem(decrypted_key, decrypted_key_size, &data->decrypted_password) < 0)
99 return log_oom();
100
101 return 1;
102}