]>
Commit | Line | Data |
---|---|---|
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 | ||
8 | int 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 | ||
89 | decrypt: | |
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 | } |