uint64_t timestamp;
uint64_t not_after;
CredentialScope scope;
+ sd_id128_t with_key;
uid_t uid;
} MethodEncryptParameters;
return 0;
}
+static bool normalize_separator(char c) {
+ if (IN_SET(c, '-', '+', '_'))
+ return '_';
+
+ return c;
+}
+
+static bool enum_name_equal(const char *x, const char *y) {
+ if (x == y)
+ return true;
+ if (!x || !y)
+ return false;
+
+ for (;; x++, y++) {
+ char a = normalize_separator(*x), b = normalize_separator(*y);
+ if (a != b)
+ return false;
+ if (a == 0)
+ return true;
+ }
+}
+
+static CredKeyType cred_key_type_from_string_harder(const char *s) {
+ if (!s)
+ return _CRED_KEY_TYPE_INVALID;
+
+ CredKeyType t = cred_key_type_from_string(s);
+ if (t >= 0)
+ return t;
+
+ /* Varlink doesn't like dashes and plusses in enum names. Try to match when considering them equal to underscores */
+ for (t = 0; t < _CRED_KEY_TYPE_MAX; t++)
+ if (enum_name_equal(cred_key_type_table[t], s))
+ return t;
+
+ return _CRED_KEY_TYPE_INVALID;
+}
+
+static int dispatch_credential_key_type(
+ const char *name,
+ sd_json_variant *variant,
+ sd_json_dispatch_flags_t flags,
+ void *userdata) {
+
+ sd_id128_t *id = ASSERT_PTR(userdata);
+
+ if (sd_json_variant_is_null(variant)) {
+ *id = SD_ID128_NULL;
+ return 0;
+ }
+
+ const char *s = sd_json_variant_string(variant);
+ if (isempty(s)) {
+ *id = SD_ID128_NULL;
+ return 0;
+ }
+
+ CredKeyType t = cred_key_type_from_string_harder(s);
+ if (t < 0)
+ return json_log(variant, flags, t, "JSON field '%s' is not a valid key type.", strna(name));
+
+ *id = cred_key_id[t];
+ return 0;
+}
+
static int vl_method_encrypt(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
static const sd_json_dispatch_field dispatch_table[] = {
{ "timestamp", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(MethodEncryptParameters, timestamp), 0 },
{ "notAfter", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(MethodEncryptParameters, not_after), 0 },
{ "scope", SD_JSON_VARIANT_STRING, dispatch_credential_scope, offsetof(MethodEncryptParameters, scope), 0 },
+ { "withKey", SD_JSON_VARIANT_STRING, dispatch_credential_key_type, offsetof(MethodEncryptParameters, with_key), SD_JSON_NULLABLE },
{ "uid", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(MethodEncryptParameters, uid), 0 },
VARLINK_DISPATCH_POLKIT_FIELD,
{}
}
r = encrypt_credential_and_warn(
- p.scope == CREDENTIAL_USER ? _CRED_AUTO_SCOPED : _CRED_AUTO,
+ sd_id128_is_null(p.with_key) ? (p.scope == CREDENTIAL_USER ? _CRED_AUTO_SCOPED : _CRED_AUTO) : p.with_key,
p.name,
p.timestamp,
p.not_after,
SD_VARLINK_FIELD_COMMENT("Generate a system and user bound credential"),
SD_VARLINK_DEFINE_ENUM_VALUE(user));
+static SD_VARLINK_DEFINE_ENUM_TYPE(
+ WithKey,
+ SD_VARLINK_FIELD_COMMENT("Automatically pick the key to bind the credential to"),
+ SD_VARLINK_DEFINE_ENUM_VALUE(auto),
+ SD_VARLINK_FIELD_COMMENT("Automatically pick the key to bind the credential to, but ensure it is accessible in the initrd, thus potentially leaving it unencrypted."),
+ SD_VARLINK_DEFINE_ENUM_VALUE(auto_initrd),
+ SD_VARLINK_FIELD_COMMENT("Bind to the host key only, i.e. not the TPM"),
+ SD_VARLINK_DEFINE_ENUM_VALUE(host),
+ SD_VARLINK_FIELD_COMMENT("Bind to the TPM only, not the host key"),
+ SD_VARLINK_DEFINE_ENUM_VALUE(tpm2),
+ SD_VARLINK_FIELD_COMMENT("Bind to the TPM only (using a public key identifying the UKI), not the host key"),
+ SD_VARLINK_DEFINE_ENUM_VALUE(tpm2_with_public_key),
+ SD_VARLINK_FIELD_COMMENT("Bind to both the TPM and the host key"),
+ SD_VARLINK_DEFINE_ENUM_VALUE(host_tpm2),
+ SD_VARLINK_FIELD_COMMENT("Bind to both the TPM (using a public key identifying the UKI) and the host key"),
+ SD_VARLINK_DEFINE_ENUM_VALUE(host_tpm2_with_public_key),
+ SD_VARLINK_FIELD_COMMENT("Do not bind to either host key nor the TPM, thus using null encryption (this provides no authenticity nor confidentiality guarantees)"),
+ SD_VARLINK_DEFINE_ENUM_VALUE(null));
+
static SD_VARLINK_DEFINE_METHOD(
Encrypt,
SD_VARLINK_FIELD_COMMENT("The name for the encrypted credential, a string suitable for inclusion in a file name. If not specified no name is encoded in the credential. Typically, if this credential is stored on disk, this is how the file should be called, and permits authentication of the filename."),
SD_VARLINK_DEFINE_INPUT(notAfter, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The intended scope for the credential. One of 'system' or 'user'. If not specified defaults to 'system', unless an uid is specified (see below), in which case it default to 'user'."),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(scope, Scope, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Selects the type of key to encrypt this with"),
+ SD_VARLINK_DEFINE_INPUT_BY_TYPE(withKey, WithKey, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The numeric UNIX UID of the user the credential shall be scoped to. Only relevant if 'user' scope is selected (see above). If not specified and 'user' scope is selected defaults to the UID of the calling user, if that can be determined."),
SD_VARLINK_DEFINE_INPUT(uid, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
VARLINK_DEFINE_POLKIT_INPUT,
SD_VARLINK_INTERFACE_COMMENT("APIs for encrypting and decrypting service credentials."),
SD_VARLINK_SYMBOL_COMMENT("The intended scope for the credential."),
&vl_type_Scope,
+ SD_VARLINK_SYMBOL_COMMENT("Selects the key(s) to encrypt the credentials with."),
+ &vl_type_WithKey,
SD_VARLINK_SYMBOL_COMMENT("Encrypts some plaintext data, returns an encrypted credential."),
&vl_method_Encrypt,
SD_VARLINK_SYMBOL_COMMENT("Decrypts an encrypted credential, returns plaintext data."),