Merge pull request #19797 from oniko/systemd-fido2-pkcs11-plugins
Add support for remaining systemd fido2 and pkcs11 libcryptsetup plugins
This commit is contained in:
+132
-37
@@ -175,6 +175,55 @@ char *pkcs11_token_model(const CK_TOKEN_INFO *token_info) {
|
||||
return t;
|
||||
}
|
||||
|
||||
int pkcs11_token_login_by_pin(
|
||||
CK_FUNCTION_LIST *m,
|
||||
CK_SESSION_HANDLE session,
|
||||
const CK_TOKEN_INFO *token_info,
|
||||
const char *token_label,
|
||||
const void *pin,
|
||||
size_t pin_size) {
|
||||
|
||||
CK_RV rv;
|
||||
|
||||
assert(m);
|
||||
assert(token_info);
|
||||
|
||||
if (FLAGS_SET(token_info->flags, CKF_PROTECTED_AUTHENTICATION_PATH)) {
|
||||
rv = m->C_Login(session, CKU_USER, NULL, 0);
|
||||
if (rv != CKR_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
|
||||
|
||||
log_info("Successfully logged into security token '%s' via protected authentication path.", token_label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!FLAGS_SET(token_info->flags, CKF_LOGIN_REQUIRED)) {
|
||||
log_info("No login into security token '%s' required.", token_label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!pin)
|
||||
return -ENOANO;
|
||||
|
||||
rv = m->C_Login(session, CKU_USER, (CK_UTF8CHAR*) pin, pin_size);
|
||||
if (rv == CKR_OK) {
|
||||
log_info("Successfully logged into security token '%s'.", token_label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rv == CKR_PIN_LOCKED)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
|
||||
"PIN has been locked, please reset PIN of security token '%s'.", token_label);
|
||||
if (!IN_SET(rv, CKR_PIN_INCORRECT, CKR_PIN_LEN_RANGE))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
|
||||
|
||||
log_notice("PIN for token '%s' is incorrect, please try again.", token_label);
|
||||
|
||||
return -ENOLCK;
|
||||
}
|
||||
|
||||
int pkcs11_token_login(
|
||||
CK_FUNCTION_LIST *m,
|
||||
CK_SESSION_HANDLE session,
|
||||
@@ -209,24 +258,12 @@ int pkcs11_token_login(
|
||||
if (uri_result != P11_KIT_URI_OK)
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EAGAIN), "Failed to format slot URI: %s", p11_kit_uri_message(uri_result));
|
||||
|
||||
if (FLAGS_SET(token_info->flags, CKF_PROTECTED_AUTHENTICATION_PATH)) {
|
||||
rv = m->C_Login(session, CKU_USER, NULL, 0);
|
||||
if (rv != CKR_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
|
||||
r = pkcs11_token_login_by_pin(m, session, token_info, token_label, /* pin= */ NULL, 0);
|
||||
if (r == 0 && ret_used_pin)
|
||||
*ret_used_pin = NULL;
|
||||
|
||||
log_info("Successfully logged into security token '%s' via protected authentication path.", token_label);
|
||||
if (ret_used_pin)
|
||||
*ret_used_pin = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!FLAGS_SET(token_info->flags, CKF_LOGIN_REQUIRED)) {
|
||||
log_info("No login into security token '%s' required.", token_label);
|
||||
if (ret_used_pin)
|
||||
*ret_used_pin = NULL;
|
||||
return 0;
|
||||
}
|
||||
if (r != -ENOANO) /* pin required */
|
||||
return r;
|
||||
|
||||
token_uri_escaped = cescape(token_uri_string);
|
||||
if (!token_uri_escaped)
|
||||
@@ -278,28 +315,19 @@ int pkcs11_token_login(
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, passwords) {
|
||||
rv = m->C_Login(session, CKU_USER, (CK_UTF8CHAR*) *i, strlen(*i));
|
||||
if (rv == CKR_OK) {
|
||||
r = pkcs11_token_login_by_pin(m, session, token_info, token_label, *i, strlen(*i));
|
||||
if (r == 0 && ret_used_pin) {
|
||||
char *c;
|
||||
|
||||
if (ret_used_pin) {
|
||||
char *c;
|
||||
c = strdup(*i);
|
||||
if (!c)
|
||||
return log_oom();
|
||||
|
||||
c = strdup(*i);
|
||||
if (!c)
|
||||
return log_oom();
|
||||
|
||||
*ret_used_pin = c;
|
||||
}
|
||||
|
||||
log_info("Successfully logged into security token '%s'.", token_label);
|
||||
return 0;
|
||||
*ret_used_pin = c;
|
||||
}
|
||||
if (rv == CKR_PIN_LOCKED)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
|
||||
"PIN has been locked, please reset PIN of security token '%s'.", token_label);
|
||||
if (!IN_SET(rv, CKR_PIN_INCORRECT, CKR_PIN_LEN_RANGE))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
|
||||
|
||||
if (r != -ENOLCK)
|
||||
return r;
|
||||
|
||||
/* Referesh the token info, so that we can prompt knowing the new flags if they changed. */
|
||||
rv = m->C_GetTokenInfo(slotid, &updated_token_info);
|
||||
@@ -309,7 +337,6 @@ int pkcs11_token_login(
|
||||
slotid, p11_kit_strerror(rv));
|
||||
|
||||
token_info = &updated_token_info;
|
||||
log_notice("PIN for token '%s' is incorrect, please try again.", token_label);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1154,3 +1181,71 @@ int pkcs11_find_token_auto(char **ret) {
|
||||
"PKCS#11 tokens not supported on this build.");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_P11KIT
|
||||
void pkcs11_crypt_device_callback_data_release(pkcs11_crypt_device_callback_data *data) {
|
||||
erase_and_free(data->decrypted_key);
|
||||
|
||||
if (data->free_encrypted_key)
|
||||
free(data->encrypted_key);
|
||||
}
|
||||
|
||||
int pkcs11_crypt_device_callback(
|
||||
CK_FUNCTION_LIST *m,
|
||||
CK_SESSION_HANDLE session,
|
||||
CK_SLOT_ID slot_id,
|
||||
const CK_SLOT_INFO *slot_info,
|
||||
const CK_TOKEN_INFO *token_info,
|
||||
P11KitUri *uri,
|
||||
void *userdata) {
|
||||
|
||||
pkcs11_crypt_device_callback_data *data = userdata;
|
||||
CK_OBJECT_HANDLE object;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(slot_info);
|
||||
assert(token_info);
|
||||
assert(uri);
|
||||
assert(data);
|
||||
|
||||
/* Called for every token matching our URI */
|
||||
|
||||
r = pkcs11_token_login(
|
||||
m,
|
||||
session,
|
||||
slot_id,
|
||||
token_info,
|
||||
data->friendly_name,
|
||||
"drive-harddisk",
|
||||
"pkcs11-pin",
|
||||
"cryptsetup.pkcs11-pin",
|
||||
data->until,
|
||||
data->headless,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* We are likely called during early boot, where entropy is scarce. Mix some data from the PKCS#11
|
||||
* token, if it supports that. It should be cheap, given that we already are talking to it anyway and
|
||||
* shouldn't hurt. */
|
||||
(void) pkcs11_token_acquire_rng(m, session);
|
||||
|
||||
r = pkcs11_token_find_private_key(m, session, uri, &object);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pkcs11_token_decrypt_data(
|
||||
m,
|
||||
session,
|
||||
object,
|
||||
data->encrypted_key,
|
||||
data->encrypted_key_size,
|
||||
&data->decrypted_key,
|
||||
&data->decrypted_key_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,7 @@ char *pkcs11_token_label(const CK_TOKEN_INFO *token_info);
|
||||
char *pkcs11_token_manufacturer_id(const CK_TOKEN_INFO *token_info);
|
||||
char *pkcs11_token_model(const CK_TOKEN_INFO *token_info);
|
||||
|
||||
int pkcs11_token_login_by_pin(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, const CK_TOKEN_INFO *token_info, const char *token_label, const void *pin, size_t pin_size);
|
||||
int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *key_name, const char *credential_name, usec_t until, bool headless, char **ret_used_pin);
|
||||
|
||||
int pkcs11_token_find_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object);
|
||||
@@ -49,7 +50,35 @@ int pkcs11_find_token(const char *pkcs11_uri, pkcs11_find_token_callback_t callb
|
||||
int pkcs11_acquire_certificate(const char *uri, const char *askpw_friendly_name, const char *askpw_icon_name, X509 **ret_cert, char **ret_pin_used);
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char *friendly_name;
|
||||
usec_t until;
|
||||
void *encrypted_key;
|
||||
size_t encrypted_key_size;
|
||||
void *decrypted_key;
|
||||
size_t decrypted_key_size;
|
||||
bool free_encrypted_key;
|
||||
bool headless;
|
||||
} pkcs11_crypt_device_callback_data;
|
||||
|
||||
void pkcs11_crypt_device_callback_data_release(pkcs11_crypt_device_callback_data *data);
|
||||
|
||||
int pkcs11_crypt_device_callback(
|
||||
CK_FUNCTION_LIST *m,
|
||||
CK_SESSION_HANDLE session,
|
||||
CK_SLOT_ID slot_id,
|
||||
const CK_SLOT_INFO *slot_info,
|
||||
const CK_TOKEN_INFO *token_info,
|
||||
P11KitUri *uri,
|
||||
void *userdata);
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char *friendly_name;
|
||||
usec_t until;
|
||||
bool headless;
|
||||
} systemd_pkcs11_plugin_params;
|
||||
|
||||
int pkcs11_list_tokens(void);
|
||||
int pkcs11_find_token_auto(char **ret);
|
||||
|
||||
Reference in New Issue
Block a user