creds-util: implement TPM2 SRK pinning
Stores the TPM2 SRK within the credential header, allowing for parameter decryption to be utilized when decrypting the credential. A new dimension is added to the credential ID matrix to encode this capability. This also allows for usage of TPM2-bound credentials when a TPM owner password is set since `Esys_CreatePrimary` is no longer used for sealing credentials.
This commit is contained in:
@@ -16,6 +16,17 @@ CHANGES WITH 262:
|
||||
have been provided. This clears the way for a new
|
||||
"systemd-sysupdate@.service" unit for varlink activation of sysupdate.
|
||||
|
||||
* TPM-sealed credentials are now pinned to the TPM's SRK. This prevents
|
||||
MITM interposer attacks from stealing the decrypted credentials by
|
||||
ensuring that communication with the TPM is protected by a private key
|
||||
only known to the same TPM the credential was sealed to. Additionally,
|
||||
this allows usage of TPM-sealed credentials when the TPM's owner
|
||||
hierarchy is protected with a PIN.
|
||||
|
||||
TPM-bound credentials minted after this change are not recognized by
|
||||
older systemd versions, however systemd continues to accept TPM-sealed
|
||||
credentials that were created before this change.
|
||||
|
||||
Changes in the system and service manager:
|
||||
|
||||
* The manager now embeds a basic set of unit files (basic.target,
|
||||
|
||||
@@ -346,6 +346,10 @@
|
||||
available but still work on systems lacking support for this. The special value
|
||||
<literal>help</literal> may be used to list supported key types.</para>
|
||||
|
||||
<para>systemd v262 and later additionally pin the encrypted credential to the TPM2's SRK to defend
|
||||
against MITM interposer attacks when decrypting credentials. This makes the resulting
|
||||
credentials incompatible with earlier systemd versions.</para>
|
||||
|
||||
<para>The <option>-H</option> switch is a shortcut for <option>--with-key=host</option>. Similar,
|
||||
<option>-T</option> is a shortcut for <option>--with-key=tpm2</option>.</para>
|
||||
|
||||
|
||||
@@ -48,6 +48,12 @@
|
||||
<match type="string" value="70rBNnmpSA6n22iJf58WX" offset="0"/>
|
||||
<match type="string" value="r0lQqEkTTrGnOEYwT/MMB" offset="0"/>
|
||||
<match type="string" value="rbxMo++2QgG6iBtvLkCV6" offset="0"/>
|
||||
<match type="string" value="1AYt+3GtTIaAS0DvEYDx/" offset="0"/>
|
||||
<match type="string" value="Xi1cdgNyTq+EPG+19kCY9" offset="0"/>
|
||||
<match type="string" value="FBQliBiiQM2QC86GLbXHu" offset="0"/>
|
||||
<match type="string" value="Kh+HekJ1Qxqz+e0fXY9mA" offset="0"/>
|
||||
<match type="string" value="r7/qrOtqSjeVQZ0TXEfze" offset="0"/>
|
||||
<match type="string" value="FuSSlJ+UQAKGdY+Ut8Urx" offset="0"/>
|
||||
<match type="string" value="BYRp2vb1QySABUnaD46i+" offset="0"/>
|
||||
</magic>
|
||||
</mime-type>
|
||||
|
||||
+10
-6
@@ -125,12 +125,12 @@ static sd_id128_t cred_key_id[_CRED_KEY_TYPE_MAX] = {
|
||||
[CRED_KEY_TYPE_AUTO] = _CRED_AUTO,
|
||||
[CRED_KEY_TYPE_AUTO_INITRD] = _CRED_AUTO_INITRD,
|
||||
[CRED_KEY_TYPE_HOST] = CRED_AES256_GCM_BY_HOST,
|
||||
[CRED_KEY_TYPE_TPM2] = CRED_AES256_GCM_BY_TPM2_HMAC,
|
||||
[CRED_KEY_TYPE_TPM2_PUBLIC] = CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK,
|
||||
[CRED_KEY_TYPE_HOST_TPM2] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC,
|
||||
[CRED_KEY_TYPE_TPM2_HOST] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC,
|
||||
[CRED_KEY_TYPE_HOST_TPM2_PUBLIC] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK,
|
||||
[CRED_KEY_TYPE_TPM2_PUBLIC_HOST] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK,
|
||||
[CRED_KEY_TYPE_TPM2] = CRED_AES256_GCM_BY_TPM2_HMAC_PINNED_SRK,
|
||||
[CRED_KEY_TYPE_TPM2_PUBLIC] = CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK_PINNED_SRK,
|
||||
[CRED_KEY_TYPE_HOST_TPM2] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK,
|
||||
[CRED_KEY_TYPE_TPM2_HOST] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK,
|
||||
[CRED_KEY_TYPE_HOST_TPM2_PUBLIC] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK,
|
||||
[CRED_KEY_TYPE_TPM2_PUBLIC_HOST] = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK,
|
||||
[CRED_KEY_TYPE_NULL] = CRED_AES256_GCM_BY_NULL,
|
||||
[CRED_KEY_TYPE_TPM2_ABSENT] = CRED_AES256_GCM_BY_NULL,
|
||||
};
|
||||
@@ -1037,6 +1037,10 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) {
|
||||
arg_with_key = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED;
|
||||
else if (sd_id128_in_set(arg_with_key, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED))
|
||||
arg_with_key = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED;
|
||||
else if (sd_id128_in_set(arg_with_key, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK))
|
||||
arg_with_key = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK;
|
||||
else if (sd_id128_in_set(arg_with_key, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK))
|
||||
arg_with_key = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK;
|
||||
else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Selected key not available in --uid= scoped mode, refusing.");
|
||||
}
|
||||
|
||||
+55
-16
@@ -726,6 +726,12 @@ struct _packed_ tpm2_public_key_credential_header {
|
||||
/* Followed by NUL bytes until next 8 byte boundary */
|
||||
};
|
||||
|
||||
struct _packed_ tpm2_pinned_srk_credential_header {
|
||||
le32_t size; /* Size of pinned SRK */
|
||||
uint8_t data[]; /* Pinned SRK */
|
||||
/* Followed by NUL bytes until next 8 byte boundary */
|
||||
};
|
||||
|
||||
struct _packed_ scoped_credential_header {
|
||||
le64_t flags; /* SCOPE_HASH_DATA_BASE_FLAGS for now */
|
||||
};
|
||||
@@ -866,7 +872,7 @@ int encrypt_credential_and_warn(
|
||||
CredentialFlags flags,
|
||||
struct iovec *ret) {
|
||||
|
||||
_cleanup_(iovec_done) struct iovec tpm2_blob = {}, tpm2_policy_hash = {}, iv = {}, pubkey = {};
|
||||
_cleanup_(iovec_done) struct iovec tpm2_blob = {}, tpm2_srk = {}, tpm2_policy_hash = {}, iv = {}, pubkey = {};
|
||||
_cleanup_(iovec_done_erase) struct iovec tpm2_key = {}, output = {}, host_key = {};
|
||||
_cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *context = NULL;
|
||||
_cleanup_free_ struct metadata_credential_header *m = NULL;
|
||||
@@ -1018,7 +1024,7 @@ int encrypt_credential_and_warn(
|
||||
&blobs,
|
||||
&n_blobs,
|
||||
&tpm2_primary_alg,
|
||||
/* ret_srk= */ NULL);
|
||||
CRED_KEY_WANTS_TPM2_PINNED_SRK(with_key) || CRED_KEY_REQUIRES_TPM2_PINNED_SRK(with_key) ? &tpm2_srk : NULL);
|
||||
if (r < 0) {
|
||||
if (sd_id128_equal(with_key, _CRED_AUTO_INITRD))
|
||||
log_warning("TPM2 present and used, but we didn't manage to talk to it. Credential will be refused if SecureBoot is enabled.");
|
||||
@@ -1036,19 +1042,21 @@ int encrypt_credential_and_warn(
|
||||
|
||||
assert(tpm2_blob.iov_len <= CREDENTIAL_FIELD_SIZE_MAX);
|
||||
assert(tpm2_policy_hash.iov_len <= CREDENTIAL_FIELD_SIZE_MAX);
|
||||
assert(tpm2_srk.iov_len <= CREDENTIAL_FIELD_SIZE_MAX);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CRED_KEY_IS_AUTO(with_key)) {
|
||||
/* Let's settle the key type in auto mode now. */
|
||||
assert(!iovec_is_set(&tpm2_key) || iovec_is_set(&tpm2_srk));
|
||||
|
||||
if (iovec_is_set(&host_key) && iovec_is_set(&tpm2_key))
|
||||
id = iovec_is_set(&pubkey) ? (sd_id128_equal(with_key, _CRED_AUTO_SCOPED) ?
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED : CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK)
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK : CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK)
|
||||
: (sd_id128_equal(with_key, _CRED_AUTO_SCOPED) ?
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED : CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC);
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK : CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK);
|
||||
else if (iovec_is_set(&tpm2_key) && !sd_id128_equal(with_key, _CRED_AUTO_SCOPED))
|
||||
id = iovec_is_set(&pubkey) ? CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK : CRED_AES256_GCM_BY_TPM2_HMAC;
|
||||
id = iovec_is_set(&pubkey) ? CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK_PINNED_SRK : CRED_AES256_GCM_BY_TPM2_HMAC_PINNED_SRK;
|
||||
else if (iovec_is_set(&host_key))
|
||||
id = sd_id128_equal(with_key, _CRED_AUTO_SCOPED) ? CRED_AES256_GCM_BY_HOST_SCOPED : CRED_AES256_GCM_BY_HOST;
|
||||
else if (sd_id128_equal(with_key, _CRED_AUTO_INITRD))
|
||||
@@ -1113,6 +1121,7 @@ int encrypt_credential_and_warn(
|
||||
ALIGN8(offsetof(struct encrypted_credential_header, iv) + ivsz) +
|
||||
ALIGN8(iovec_is_set(&tpm2_key) ? offsetof(struct tpm2_credential_header, policy_hash_and_blob) + tpm2_blob.iov_len + tpm2_policy_hash.iov_len : 0) +
|
||||
ALIGN8(iovec_is_set(&pubkey) ? offsetof(struct tpm2_public_key_credential_header, data) + pubkey.iov_len : 0) +
|
||||
ALIGN8(iovec_is_set(&tpm2_srk) ? offsetof(struct tpm2_pinned_srk_credential_header, data) + tpm2_srk.iov_len : 0) +
|
||||
ALIGN8(uid_is_valid(uid) ? sizeof(struct scoped_credential_header) : 0) +
|
||||
ALIGN8(offsetof(struct metadata_credential_header, name) + strlen_ptr(name)) +
|
||||
input->iov_len + 2U * (size_t) bsz +
|
||||
@@ -1161,6 +1170,16 @@ int encrypt_credential_and_warn(
|
||||
p += ALIGN8(offsetof(struct tpm2_public_key_credential_header, data) + pubkey.iov_len);
|
||||
}
|
||||
|
||||
if (iovec_is_set(&tpm2_srk)) {
|
||||
struct tpm2_pinned_srk_credential_header *z;
|
||||
|
||||
z = (struct tpm2_pinned_srk_credential_header*) ((uint8_t*) output.iov_base + p);
|
||||
z->size = htole32(tpm2_srk.iov_len);
|
||||
memcpy(z->data, tpm2_srk.iov_base, tpm2_srk.iov_len);
|
||||
|
||||
p += ALIGN8(offsetof(struct tpm2_pinned_srk_credential_header, data) + tpm2_srk.iov_len);
|
||||
}
|
||||
|
||||
if (uid_is_valid(uid)) {
|
||||
struct scoped_credential_header *w;
|
||||
|
||||
@@ -1395,6 +1414,7 @@ int decrypt_credential_and_warn(
|
||||
ALIGN8(offsetof(struct encrypted_credential_header, iv) + le32toh(h->iv_size)) +
|
||||
ALIGN8(CRED_KEY_REQUIRES_TPM2(h->id) ? offsetof(struct tpm2_credential_header, policy_hash_and_blob) : 0) +
|
||||
ALIGN8(CRED_KEY_REQUIRES_TPM2_PK(h->id) ? offsetof(struct tpm2_public_key_credential_header, data) : 0) +
|
||||
ALIGN8(CRED_KEY_REQUIRES_TPM2_PINNED_SRK(h->id) ? offsetof(struct tpm2_pinned_srk_credential_header, data) : 0) +
|
||||
ALIGN8(CRED_KEY_IS_SCOPED(h->id) ? sizeof(struct scoped_credential_header) : 0) +
|
||||
ALIGN8(offsetof(struct metadata_credential_header, name)) +
|
||||
le32toh(h->tag_size))
|
||||
@@ -1405,7 +1425,8 @@ int decrypt_credential_and_warn(
|
||||
if (CRED_KEY_REQUIRES_TPM2(h->id)) {
|
||||
#if HAVE_TPM2
|
||||
struct tpm2_credential_header* t = (struct tpm2_credential_header*) ((uint8_t*) input->iov_base + p);
|
||||
struct tpm2_public_key_credential_header *z = NULL;
|
||||
struct tpm2_public_key_credential_header *z_pubkey = NULL;
|
||||
struct tpm2_pinned_srk_credential_header *z_srk = NULL;
|
||||
|
||||
if (!TPM2_PCR_MASK_VALID(t->pcr_mask))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 PCR mask out of range.");
|
||||
@@ -1424,6 +1445,7 @@ int decrypt_credential_and_warn(
|
||||
p +
|
||||
ALIGN8(offsetof(struct tpm2_credential_header, policy_hash_and_blob) + le32toh(t->blob_size) + le32toh(t->policy_hash_size)) +
|
||||
ALIGN8(CRED_KEY_REQUIRES_TPM2_PK(h->id) ? offsetof(struct tpm2_public_key_credential_header, data) : 0) +
|
||||
ALIGN8(CRED_KEY_REQUIRES_TPM2_PINNED_SRK(h->id) ? offsetof(struct tpm2_pinned_srk_credential_header, data) : 0) +
|
||||
ALIGN8(CRED_KEY_IS_SCOPED(h->id) ? sizeof(struct scoped_credential_header) : 0) +
|
||||
ALIGN8(offsetof(struct metadata_credential_header, name)) +
|
||||
le32toh(h->tag_size))
|
||||
@@ -1434,23 +1456,42 @@ int decrypt_credential_and_warn(
|
||||
le32toh(t->policy_hash_size));
|
||||
|
||||
if (CRED_KEY_REQUIRES_TPM2_PK(h->id)) {
|
||||
z = (struct tpm2_public_key_credential_header*) ((uint8_t*) input->iov_base + p);
|
||||
z_pubkey = (struct tpm2_public_key_credential_header*) ((uint8_t*) input->iov_base + p);
|
||||
|
||||
if (!TPM2_PCR_MASK_VALID(le64toh(z->pcr_mask)) || le64toh(z->pcr_mask) == 0)
|
||||
if (!TPM2_PCR_MASK_VALID(le64toh(z_pubkey->pcr_mask)) || le64toh(z_pubkey->pcr_mask) == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "TPM2 PCR mask out of range.");
|
||||
if (le32toh(z->size) > PUBLIC_KEY_MAX)
|
||||
if (le32toh(z_pubkey->size) > PUBLIC_KEY_MAX)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected public key size.");
|
||||
|
||||
if (input->iov_len <
|
||||
p +
|
||||
ALIGN8(offsetof(struct tpm2_public_key_credential_header, data) + le32toh(z->size)) +
|
||||
ALIGN8(offsetof(struct tpm2_public_key_credential_header, data) + le32toh(z_pubkey->size)) +
|
||||
ALIGN8(CRED_KEY_REQUIRES_TPM2_PINNED_SRK(h->id) ? offsetof(struct tpm2_pinned_srk_credential_header, data) : 0) +
|
||||
ALIGN8(CRED_KEY_IS_SCOPED(h->id) ? sizeof(struct scoped_credential_header) : 0) +
|
||||
ALIGN8(offsetof(struct metadata_credential_header, name)) +
|
||||
le32toh(h->tag_size))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
|
||||
|
||||
p += ALIGN8(offsetof(struct tpm2_public_key_credential_header, data) +
|
||||
le32toh(z->size));
|
||||
le32toh(z_pubkey->size));
|
||||
}
|
||||
|
||||
if (CRED_KEY_REQUIRES_TPM2_PINNED_SRK(h->id)) {
|
||||
z_srk = (struct tpm2_pinned_srk_credential_header*) ((uint8_t*) input->iov_base + p);
|
||||
|
||||
if (le32toh(z_srk->size) > CREDENTIAL_FIELD_SIZE_MAX)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected pinned SRK size.");
|
||||
|
||||
if (input->iov_len <
|
||||
p +
|
||||
ALIGN8(offsetof(struct tpm2_pinned_srk_credential_header, data) + le32toh(z_srk->size)) +
|
||||
ALIGN8(CRED_KEY_IS_SCOPED(h->id) ? sizeof(struct scoped_credential_header) : 0) +
|
||||
ALIGN8(offsetof(struct metadata_credential_header, name)) +
|
||||
le32toh(h->tag_size))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Encrypted file too short.");
|
||||
|
||||
p += ALIGN8(offsetof(struct tpm2_pinned_srk_credential_header, data) +
|
||||
le32toh(z_srk->size));
|
||||
}
|
||||
|
||||
_cleanup_(tpm2_context_unrefp) Tpm2Context *tpm2_context = NULL;
|
||||
@@ -1458,14 +1499,12 @@ int decrypt_credential_and_warn(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
// TODO: Add the SRK data to the credential structure so it can be plumbed
|
||||
// through and used to verify the TPM session.
|
||||
r = tpm2_unseal(tpm2_context,
|
||||
le64toh(t->pcr_mask),
|
||||
le16toh(t->pcr_bank),
|
||||
z ? &IOVEC_MAKE(z->data, le32toh(z->size)) : NULL,
|
||||
z_pubkey ? &IOVEC_MAKE(z_pubkey->data, le32toh(z_pubkey->size)) : NULL,
|
||||
/* pubkey_policy_ref= */ NULL,
|
||||
z ? le64toh(z->pcr_mask) : 0,
|
||||
z_pubkey ? le64toh(z_pubkey->pcr_mask) : 0,
|
||||
signature_json,
|
||||
/* pin= */ NULL,
|
||||
/* pcrlock_policy= */ NULL,
|
||||
@@ -1474,7 +1513,7 @@ int decrypt_credential_and_warn(
|
||||
/* n_blobs= */ 1,
|
||||
&IOVEC_MAKE(t->policy_hash_and_blob + le32toh(t->blob_size), le32toh(t->policy_hash_size)),
|
||||
/* n_known_policy_hash= */ 1,
|
||||
/* srk= */ NULL,
|
||||
z_srk ? &IOVEC_MAKE(z_srk->data, le32toh(z_srk->size)) : NULL,
|
||||
&tpm2_key);
|
||||
if (r == -EREMOTE)
|
||||
return log_error_errno(r, "TPM key integrity check failed. Key most likely does not belong to this TPM.");
|
||||
|
||||
+97
-49
@@ -88,12 +88,24 @@ bool credential_boot_policy_accepts_null(CredentialBootPolicy policy, bool first
|
||||
#define CRED_AES256_GCM_BY_TPM2_HMAC SD_ID128_MAKE(0c,7c,c0,7b,11,76,45,91,9c,4b,0b,ea,08,bc,20,fe)
|
||||
#define CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK SD_ID128_MAKE(fa,f7,eb,93,41,e3,41,2c,a1,a4,36,f9,5a,29,36,2f)
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC SD_ID128_MAKE(93,a8,94,09,48,74,44,90,90,ca,f2,fc,93,ca,b5,53)
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED \
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED \
|
||||
SD_ID128_MAKE(ef,4a,c1,36,79,a9,48,0e,a7,db,68,89,7f,9f,16,5d)
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK \
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK \
|
||||
SD_ID128_MAKE(af,49,50,a8,49,13,4e,b1,a7,38,46,30,4f,f3,0c,05)
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED \
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED \
|
||||
SD_ID128_MAKE(ad,bc,4c,a3,ef,b6,42,01,ba,88,1b,6f,2e,40,95,ea)
|
||||
#define CRED_AES256_GCM_BY_TPM2_HMAC_PINNED_SRK \
|
||||
SD_ID128_MAKE(d4,06,2d,fb,71,ad,4c,86,80,4b,40,ef,11,80,f1,fc)
|
||||
#define CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK_PINNED_SRK \
|
||||
SD_ID128_MAKE(5e,2d,5c,76,03,72,4e,af,84,3c,6f,b5,f6,40,98,f5)
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK \
|
||||
SD_ID128_MAKE(14,14,25,88,18,a2,40,cd,90,0b,ce,86,2d,b5,c7,b9)
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK \
|
||||
SD_ID128_MAKE(2a,1f,87,7a,42,75,43,1a,b3,f9,ed,1f,5d,8f,66,01)
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK \
|
||||
SD_ID128_MAKE(af,bf,ea,ac,eb,6a,4a,37,95,41,9d,13,5c,47,f3,7b)
|
||||
#define CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK \
|
||||
SD_ID128_MAKE(16,e4,92,94,9f,94,40,02,86,75,8f,94,b7,c5,2b,c7)
|
||||
#define CRED_AES256_GCM_BY_NULL SD_ID128_MAKE(05,84,69,da,f6,f5,43,24,80,05,49,da,0f,8e,a2,fb)
|
||||
|
||||
/* Five special IDs to pick a general automatic mode. These IDs will never be stored on disk, but are useful
|
||||
@@ -115,63 +127,84 @@ bool credential_boot_policy_accepts_null(CredentialBootPolicy policy, bool first
|
||||
/* Like _CRED_AUTO, but with per-UID scoping */
|
||||
#define _CRED_AUTO_SCOPED SD_ID128_MAKE(23,88,96,85,6f,74,48,8a,9c,78,6f,6a,b0,e7,3b,6a)
|
||||
|
||||
#define CRED_KEY_IS_VALID(key) \
|
||||
sd_id128_in_set((key), \
|
||||
CRED_AES256_GCM_BY_HOST, \
|
||||
CRED_AES256_GCM_BY_HOST_SCOPED, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED, \
|
||||
#define CRED_KEY_IS_VALID(key) \
|
||||
sd_id128_in_set((key), \
|
||||
CRED_AES256_GCM_BY_HOST, \
|
||||
CRED_AES256_GCM_BY_HOST_SCOPED, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK,\
|
||||
CRED_AES256_GCM_BY_NULL)
|
||||
#define CRED_KEY_IS_AUTO(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO, \
|
||||
_CRED_AUTO_TPM2, \
|
||||
_CRED_AUTO_HOST_AND_TPM2, \
|
||||
_CRED_AUTO_INITRD, \
|
||||
#define CRED_KEY_IS_AUTO(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO, \
|
||||
_CRED_AUTO_TPM2, \
|
||||
_CRED_AUTO_HOST_AND_TPM2, \
|
||||
_CRED_AUTO_INITRD, \
|
||||
_CRED_AUTO_SCOPED)
|
||||
#define CRED_KEY_IS_SCOPED(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED)
|
||||
#define CRED_KEY_REQUIRES_HOST(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO_HOST_AND_TPM2, \
|
||||
CRED_AES256_GCM_BY_HOST, \
|
||||
CRED_AES256_GCM_BY_HOST_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED)
|
||||
#define CRED_KEY_IS_SCOPED(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK)
|
||||
#define CRED_KEY_REQUIRES_HOST(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO_HOST_AND_TPM2, \
|
||||
CRED_AES256_GCM_BY_HOST, \
|
||||
CRED_AES256_GCM_BY_HOST_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK)
|
||||
#define CRED_KEY_WANTS_HOST(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO, \
|
||||
_CRED_AUTO_SCOPED)
|
||||
#define CRED_KEY_REQUIRES_TPM2(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO_TPM2, \
|
||||
_CRED_AUTO_HOST_AND_TPM2, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED)
|
||||
#define CRED_KEY_REQUIRES_TPM2(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO_TPM2, \
|
||||
_CRED_AUTO_HOST_AND_TPM2, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK)
|
||||
#define CRED_KEY_WANTS_TPM2(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO, \
|
||||
_CRED_AUTO_INITRD, \
|
||||
_CRED_AUTO_SCOPED)
|
||||
#define CRED_KEY_REQUIRES_TPM2_PK(key) \
|
||||
sd_id128_in_set((key), \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED)
|
||||
#define CRED_KEY_REQUIRES_TPM2_PK(key) \
|
||||
sd_id128_in_set((key), \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK)
|
||||
#define CRED_KEY_WANTS_TPM2_PK(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO, \
|
||||
@@ -179,6 +212,21 @@ bool credential_boot_policy_accepts_null(CredentialBootPolicy policy, bool first
|
||||
_CRED_AUTO_HOST_AND_TPM2, \
|
||||
_CRED_AUTO_INITRD, \
|
||||
_CRED_AUTO_SCOPED)
|
||||
#define CRED_KEY_REQUIRES_TPM2_PINNED_SRK(key) \
|
||||
sd_id128_in_set((key), \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK, \
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK)
|
||||
#define CRED_KEY_WANTS_TPM2_PINNED_SRK(key) \
|
||||
sd_id128_in_set((key), \
|
||||
_CRED_AUTO, \
|
||||
_CRED_AUTO_TPM2, \
|
||||
_CRED_AUTO_HOST_AND_TPM2, \
|
||||
_CRED_AUTO_INITRD, \
|
||||
_CRED_AUTO_SCOPED)
|
||||
|
||||
int encrypt_credential_and_warn(sd_id128_t with_key, const char *name, usec_t timestamp, usec_t not_after, const char *tpm2_device, uint32_t tpm2_hash_pcr_mask, const char *tpm2_pubkey_path, uint32_t tpm2_pubkey_pcr_mask, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret);
|
||||
int decrypt_credential_and_warn(const char *validate_name, usec_t validate_timestamp, const char *tpm2_device, const char *tpm2_signature_path, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret);
|
||||
|
||||
@@ -222,6 +222,9 @@ TEST(credential_encrypt_decrypt) {
|
||||
test_encrypt_decrypt_with(CRED_AES256_GCM_BY_TPM2_HMAC, UID_INVALID);
|
||||
test_encrypt_decrypt_with(CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC, UID_INVALID);
|
||||
test_encrypt_decrypt_with(CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED, 0);
|
||||
test_encrypt_decrypt_with(CRED_AES256_GCM_BY_TPM2_HMAC_PINNED_SRK, UID_INVALID);
|
||||
test_encrypt_decrypt_with(CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK, UID_INVALID);
|
||||
test_encrypt_decrypt_with(CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK, 0);
|
||||
}
|
||||
|
||||
if (ec)
|
||||
@@ -268,6 +271,12 @@ TEST(mime_type_matches) {
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED,
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK,
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED,
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_PINNED_SRK,
|
||||
CRED_AES256_GCM_BY_TPM2_HMAC_WITH_PK_PINNED_SRK,
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_PINNED_SRK,
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED_PINNED_SRK,
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_PINNED_SRK,
|
||||
CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED_PINNED_SRK,
|
||||
CRED_AES256_GCM_BY_NULL,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user