mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
cryptenroll: change class in provided PKCS#11 URI if necessary
cryptenroll accepts only PKCS#11 URIs that match both a certificate and a private key in a token. This patch allows users to provide a PKCS#11 URI that points to a certificate only, and makes possible to use output of some PKCS#11 tools directly. Internally the patch changes 'type=cert' in the provided PKCS#11 URI to 'type=private' before storing in a LUKS2 header. Fixes: #23479
This commit is contained in:
parent
c01a5c0527
commit
85828ef920
@ -313,11 +313,13 @@
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--pkcs11-token-uri=</option><replaceable>URI</replaceable></term>
|
<term><option>--pkcs11-token-uri=</option><replaceable>URI</replaceable></term>
|
||||||
|
|
||||||
<listitem><para>Enroll a PKCS#11 security token or smartcard (e.g. a YubiKey). Expects a PKCS#11
|
<listitem><para>Enroll a PKCS#11 security token or smartcard (e.g. a YubiKey). Expects a PKCS#11 URI
|
||||||
smartcard URI referring to the token. Alternatively the special value <literal>auto</literal> may
|
that allows to find an X.509 certificate on the token. The URI must also be suitable to find
|
||||||
be specified, in order to automatically determine the URI of a currently plugged in security token
|
a related private key after changing the type of object in it. Alternatively the special value
|
||||||
(of which there must be exactly one). The special value <literal>list</literal> may be used to
|
<literal>auto</literal> may be specified, in order to automatically determine the suitable URI if
|
||||||
enumerate all suitable PKCS#11 tokens currently plugged in.</para>
|
a single security token containing a single key pair is plugged in. The special value
|
||||||
|
<literal>list</literal> may be used to enumerate all suitable PKCS#11 tokens currently plugged in.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>The PKCS#11 token must contain an RSA or EC key pair which will be used to unlock a LUKS2 volume.
|
<para>The PKCS#11 token must contain an RSA or EC key pair which will be used to unlock a LUKS2 volume.
|
||||||
For RSA, a randomly generated volume key is encrypted with a public key in the token, and stored in
|
For RSA, a randomly generated volume key is encrypted with a public key in the token, and stored in
|
||||||
|
@ -7,6 +7,30 @@
|
|||||||
#include "openssl-util.h"
|
#include "openssl-util.h"
|
||||||
#include "pkcs11-util.h"
|
#include "pkcs11-util.h"
|
||||||
|
|
||||||
|
static int uri_set_private_class(const char *uri, char **ret_uri) {
|
||||||
|
_cleanup_(sym_p11_kit_uri_freep) P11KitUri *p11kit_uri = NULL;
|
||||||
|
_cleanup_free_ char *private_uri = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = uri_from_string(uri, &p11kit_uri);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse PKCS#11 URI '%s': %m", uri);
|
||||||
|
|
||||||
|
if (sym_p11_kit_uri_get_attribute(p11kit_uri, CKA_CLASS)) {
|
||||||
|
CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
|
||||||
|
CK_ATTRIBUTE attribute = { CKA_CLASS, &class, sizeof(class) };
|
||||||
|
|
||||||
|
if (sym_p11_kit_uri_set_attribute(p11kit_uri, &attribute) != P11_KIT_URI_OK)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set class for URI '%s': %m", uri);
|
||||||
|
|
||||||
|
if (sym_p11_kit_uri_format(p11kit_uri, P11_KIT_URI_FOR_ANY, &private_uri) != P11_KIT_URI_OK)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to format PKCS#11 URI: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret_uri = TAKE_PTR(private_uri);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int enroll_pkcs11(
|
int enroll_pkcs11(
|
||||||
struct crypt_device *cd,
|
struct crypt_device *cd,
|
||||||
const void *volume_key,
|
const void *volume_key,
|
||||||
@ -16,13 +40,13 @@ int enroll_pkcs11(
|
|||||||
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
|
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
|
||||||
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
|
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
|
||||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||||
_cleanup_free_ char *keyslot_as_string = NULL;
|
_cleanup_free_ char *keyslot_as_string = NULL, *private_uri = NULL;
|
||||||
size_t decrypted_key_size, saved_key_size;
|
size_t decrypted_key_size, saved_key_size;
|
||||||
_cleanup_free_ void *saved_key = NULL;
|
_cleanup_free_ void *saved_key = NULL;
|
||||||
_cleanup_(X509_freep) X509 *cert = NULL;
|
_cleanup_(X509_freep) X509 *cert = NULL;
|
||||||
ssize_t base64_encoded_size;
|
ssize_t base64_encoded_size;
|
||||||
const char *node;
|
const char *node;
|
||||||
int keyslot, r;
|
int r;
|
||||||
|
|
||||||
assert_se(cd);
|
assert_se(cd);
|
||||||
assert_se(volume_key);
|
assert_se(volume_key);
|
||||||
@ -49,7 +73,7 @@ int enroll_pkcs11(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
|
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
|
||||||
|
|
||||||
keyslot = crypt_keyslot_add_by_volume_key(
|
int keyslot = crypt_keyslot_add_by_volume_key(
|
||||||
cd,
|
cd,
|
||||||
CRYPT_ANY_SLOT,
|
CRYPT_ANY_SLOT,
|
||||||
volume_key,
|
volume_key,
|
||||||
@ -62,11 +86,17 @@ int enroll_pkcs11(
|
|||||||
if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
|
if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
|
/* Change 'type=cert' in the provided URI to 'type=private' before storing in a LUKS2 header.
|
||||||
|
This allows users to use output of some PKCS#11 tools directly without modifications. */
|
||||||
|
r = uri_set_private_class(uri, &private_uri);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = json_build(&v,
|
r = json_build(&v,
|
||||||
JSON_BUILD_OBJECT(
|
JSON_BUILD_OBJECT(
|
||||||
JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-pkcs11")),
|
JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-pkcs11")),
|
||||||
JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
|
JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))),
|
||||||
JSON_BUILD_PAIR("pkcs11-uri", JSON_BUILD_STRING(uri)),
|
JSON_BUILD_PAIR("pkcs11-uri", JSON_BUILD_STRING(private_uri ?: uri)),
|
||||||
JSON_BUILD_PAIR("pkcs11-key", JSON_BUILD_BASE64(saved_key, saved_key_size))));
|
JSON_BUILD_PAIR("pkcs11-key", JSON_BUILD_BASE64(saved_key, saved_key_size))));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to prepare PKCS#11 JSON token object: %m");
|
return log_error_errno(r, "Failed to prepare PKCS#11 JSON token object: %m");
|
||||||
|
@ -50,6 +50,8 @@ const char *(*sym_p11_kit_strerror)(CK_RV rv);
|
|||||||
int (*sym_p11_kit_uri_format)(P11KitUri *uri, P11KitUriType uri_type, char **string);
|
int (*sym_p11_kit_uri_format)(P11KitUri *uri, P11KitUriType uri_type, char **string);
|
||||||
void (*sym_p11_kit_uri_free)(P11KitUri *uri);
|
void (*sym_p11_kit_uri_free)(P11KitUri *uri);
|
||||||
CK_ATTRIBUTE_PTR (*sym_p11_kit_uri_get_attributes)(P11KitUri *uri, CK_ULONG *n_attrs);
|
CK_ATTRIBUTE_PTR (*sym_p11_kit_uri_get_attributes)(P11KitUri *uri, CK_ULONG *n_attrs);
|
||||||
|
CK_ATTRIBUTE_PTR (*sym_p11_kit_uri_get_attribute)(P11KitUri *uri, CK_ATTRIBUTE_TYPE attr_type);
|
||||||
|
int (*sym_p11_kit_uri_set_attribute)(P11KitUri *uri, CK_ATTRIBUTE_PTR attr);
|
||||||
CK_INFO_PTR (*sym_p11_kit_uri_get_module_info)(P11KitUri *uri);
|
CK_INFO_PTR (*sym_p11_kit_uri_get_module_info)(P11KitUri *uri);
|
||||||
CK_SLOT_INFO_PTR (*sym_p11_kit_uri_get_slot_info)(P11KitUri *uri);
|
CK_SLOT_INFO_PTR (*sym_p11_kit_uri_get_slot_info)(P11KitUri *uri);
|
||||||
CK_TOKEN_INFO_PTR (*sym_p11_kit_uri_get_token_info)(P11KitUri *uri);
|
CK_TOKEN_INFO_PTR (*sym_p11_kit_uri_get_token_info)(P11KitUri *uri);
|
||||||
@ -69,6 +71,8 @@ int dlopen_p11kit(void) {
|
|||||||
DLSYM_ARG(p11_kit_uri_format),
|
DLSYM_ARG(p11_kit_uri_format),
|
||||||
DLSYM_ARG(p11_kit_uri_free),
|
DLSYM_ARG(p11_kit_uri_free),
|
||||||
DLSYM_ARG(p11_kit_uri_get_attributes),
|
DLSYM_ARG(p11_kit_uri_get_attributes),
|
||||||
|
DLSYM_ARG(p11_kit_uri_get_attribute),
|
||||||
|
DLSYM_ARG(p11_kit_uri_set_attribute),
|
||||||
DLSYM_ARG(p11_kit_uri_get_module_info),
|
DLSYM_ARG(p11_kit_uri_get_module_info),
|
||||||
DLSYM_ARG(p11_kit_uri_get_slot_info),
|
DLSYM_ARG(p11_kit_uri_get_slot_info),
|
||||||
DLSYM_ARG(p11_kit_uri_get_token_info),
|
DLSYM_ARG(p11_kit_uri_get_token_info),
|
||||||
|
@ -26,6 +26,8 @@ extern const char *(*sym_p11_kit_strerror)(CK_RV rv);
|
|||||||
extern int (*sym_p11_kit_uri_format)(P11KitUri *uri, P11KitUriType uri_type, char **string);
|
extern int (*sym_p11_kit_uri_format)(P11KitUri *uri, P11KitUriType uri_type, char **string);
|
||||||
extern void (*sym_p11_kit_uri_free)(P11KitUri *uri);
|
extern void (*sym_p11_kit_uri_free)(P11KitUri *uri);
|
||||||
extern CK_ATTRIBUTE_PTR (*sym_p11_kit_uri_get_attributes)(P11KitUri *uri, CK_ULONG *n_attrs);
|
extern CK_ATTRIBUTE_PTR (*sym_p11_kit_uri_get_attributes)(P11KitUri *uri, CK_ULONG *n_attrs);
|
||||||
|
extern CK_ATTRIBUTE_PTR (*sym_p11_kit_uri_get_attribute)(P11KitUri *uri, CK_ATTRIBUTE_TYPE attr_type);
|
||||||
|
extern int (*sym_p11_kit_uri_set_attribute)(P11KitUri *uri, CK_ATTRIBUTE_PTR attr);
|
||||||
extern CK_INFO_PTR (*sym_p11_kit_uri_get_module_info)(P11KitUri *uri);
|
extern CK_INFO_PTR (*sym_p11_kit_uri_get_module_info)(P11KitUri *uri);
|
||||||
extern CK_SLOT_INFO_PTR (*sym_p11_kit_uri_get_slot_info)(P11KitUri *uri);
|
extern CK_SLOT_INFO_PTR (*sym_p11_kit_uri_get_slot_info)(P11KitUri *uri);
|
||||||
extern CK_TOKEN_INFO_PTR (*sym_p11_kit_uri_get_token_info)(P11KitUri *uri);
|
extern CK_TOKEN_INFO_PTR (*sym_p11_kit_uri_get_token_info)(P11KitUri *uri);
|
||||||
|
@ -231,14 +231,26 @@ cryptsetup_start_and_check empty_nokey
|
|||||||
if [[ -r /etc/softhsm2.conf ]]; then
|
if [[ -r /etc/softhsm2.conf ]]; then
|
||||||
# Test unlocking with a PKCS#11 token
|
# Test unlocking with a PKCS#11 token
|
||||||
export SOFTHSM2_CONF="/etc/softhsm2.conf"
|
export SOFTHSM2_CONF="/etc/softhsm2.conf"
|
||||||
|
|
||||||
PIN="1234" systemd-cryptenroll --pkcs11-token-uri="pkcs11:token=TestToken;object=RSATestKey" --unlock-key-file="$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY"
|
PIN="1234" systemd-cryptenroll --pkcs11-token-uri="pkcs11:token=TestToken;object=RSATestKey" --unlock-key-file="$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY"
|
||||||
cryptsetup_start_and_check empty_pkcs11_auto
|
cryptsetup_start_and_check empty_pkcs11_auto
|
||||||
cryptsetup luksKillSlot -q "$IMAGE_EMPTY" 2
|
cryptsetup luksKillSlot -q "$IMAGE_EMPTY" 2
|
||||||
cryptsetup token remove --token-id 0 "$IMAGE_EMPTY"
|
cryptsetup token remove --token-id 0 "$IMAGE_EMPTY"
|
||||||
|
|
||||||
|
PIN="1234" systemd-cryptenroll --pkcs11-token-uri="pkcs11:token=TestToken;object=RSATestKey;type=cert" --unlock-key-file="$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY"
|
||||||
|
cryptsetup_start_and_check empty_pkcs11_auto
|
||||||
|
cryptsetup luksKillSlot -q "$IMAGE_EMPTY" 2
|
||||||
|
cryptsetup token remove --token-id 0 "$IMAGE_EMPTY"
|
||||||
|
|
||||||
PIN="1234" systemd-cryptenroll --pkcs11-token-uri="pkcs11:token=TestToken;object=ECTestKey" --unlock-key-file="$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY"
|
PIN="1234" systemd-cryptenroll --pkcs11-token-uri="pkcs11:token=TestToken;object=ECTestKey" --unlock-key-file="$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY"
|
||||||
cryptsetup_start_and_check empty_pkcs11_auto
|
cryptsetup_start_and_check empty_pkcs11_auto
|
||||||
cryptsetup luksKillSlot -q "$IMAGE_EMPTY" 2
|
cryptsetup luksKillSlot -q "$IMAGE_EMPTY" 2
|
||||||
cryptsetup token remove --token-id 0 "$IMAGE_EMPTY"
|
cryptsetup token remove --token-id 0 "$IMAGE_EMPTY"
|
||||||
|
|
||||||
|
PIN="1234" systemd-cryptenroll --pkcs11-token-uri="pkcs11:token=TestToken;object=ECTestKey;type=cert" --unlock-key-file="$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY"
|
||||||
|
cryptsetup_start_and_check empty_pkcs11_auto
|
||||||
|
cryptsetup luksKillSlot -q "$IMAGE_EMPTY" 2
|
||||||
|
cryptsetup token remove --token-id 0 "$IMAGE_EMPTY"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cryptsetup_start_and_check detached
|
cryptsetup_start_and_check detached
|
||||||
|
Loading…
Reference in New Issue
Block a user