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:
Lennart Poettering
2021-08-19 16:37:55 +02:00
committed by GitHub
15 changed files with 1273 additions and 161 deletions
+132 -37
View File
@@ -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
+29
View File
@@ -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);