]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tpm2: move openssl-required ifdef code out of policy-building function
authorDan Streetman <ddstreet@ieee.org>
Thu, 8 Dec 2022 21:57:47 +0000 (16:57 -0500)
committerLuca Boccassi <luca.boccassi@gmail.com>
Sun, 30 Apr 2023 23:52:28 +0000 (00:52 +0100)
src/shared/tpm2-util.c

index 3ccbbbcaf9081e5074ea59d702d6548231b7039f..530a454c6a4d3c8445c102646b5a8d0c0f8be211 100644 (file)
@@ -1476,21 +1476,38 @@ static int tpm2_make_encryption_session(
         return 0;
 }
 
+static int openssl_pubkey_to_tpm2_pubkey(
+                const void *pubkey,
+                size_t pubkey_size,
+                TPM2B_PUBLIC *output,
+                void **ret_fp,
+                size_t *ret_fp_size) {
+
 #if HAVE_OPENSSL
-static int openssl_pubkey_to_tpm2_pubkey(EVP_PKEY *input, TPM2B_PUBLIC *output) {
 #if OPENSSL_VERSION_MAJOR >= 3
         _cleanup_(BN_freep) BIGNUM *n = NULL, *e = NULL;
 #else
         const BIGNUM *n = NULL, *e = NULL;
         const RSA *rsa = NULL;
 #endif
-        int n_bytes, e_bytes;
+        int r, n_bytes, e_bytes;
 
-        assert(input);
+        assert(pubkey);
+        assert(pubkey_size > 0);
         assert(output);
 
         /* Converts an OpenSSL public key to a structure that the TPM chip can process. */
 
+        _cleanup_fclose_ FILE *f = NULL;
+        f = fmemopen((void*) pubkey, pubkey_size, "r");
+        if (!f)
+                return log_oom();
+
+        _cleanup_(EVP_PKEY_freep) EVP_PKEY *input = NULL;
+        input = PEM_read_PUBKEY(f, NULL, NULL, NULL);
+        if (!input)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PEM public key.");
+
         if (EVP_PKEY_base_id(input) != EVP_PKEY_RSA)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Provided public key is not an RSA key.");
 
@@ -1557,22 +1574,38 @@ static int openssl_pubkey_to_tpm2_pubkey(EVP_PKEY *input, TPM2B_PUBLIC *output)
         if (BN_bn2bin(e, (unsigned char*) &output->publicArea.parameters.rsaDetail.exponent) <= 0)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to convert RSA exponent.");
 
+        if (ret_fp) {
+                _cleanup_free_ void *fp = NULL;
+                size_t fp_size;
+
+                assert(ret_fp_size);
+
+                r = pubkey_fingerprint(input, EVP_sha256(), &fp, &fp_size);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to calculate public key fingerprint: %m");
+
+                *ret_fp = TAKE_PTR(fp);
+                *ret_fp_size = fp_size;
+        }
+
         return 0;
+#else /* HAVE_OPENSSL */
+        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
+#endif
 }
 
 static int find_signature(
                 JsonVariant *v,
-                uint16_t pcr_bank,
-                uint32_t pcr_mask,
-                EVP_PKEY *pk,
+                const TPML_PCR_SELECTION *pcr_selection,
+                const void *fp,
+                size_t fp_size,
                 const void *policy,
                 size_t policy_size,
                 void *ret_signature,
                 size_t *ret_signature_size) {
 
-        _cleanup_free_ void *fp = NULL;
+#if HAVE_OPENSSL
         JsonVariant *b, *i;
-        size_t fp_size;
         const char *k;
         int r;
 
@@ -1582,6 +1615,12 @@ static int find_signature(
         if (!json_variant_is_object(v))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Signature is not a JSON object.");
 
+        uint16_t pcr_bank = pcr_selection->pcrSelections[0].hash;
+        uint32_t pcr_mask;
+        r = tpm2_tpml_pcr_selection_to_mask(pcr_selection, pcr_bank, &pcr_mask);
+        if (r < 0)
+                return r;
+
         k = tpm2_hash_alg_to_string(pcr_bank);
         if (!k)
                 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Don't know PCR bank %" PRIu16, pcr_bank);
@@ -1625,12 +1664,6 @@ static int find_signature(
                 if (r < 0)
                         return log_error_errno(r, "Failed to decode fingerprint in JSON data: %m");
 
-                if (!fp) {
-                        r = pubkey_fingerprint(pk, EVP_sha256(), &fp, &fp_size);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to calculate public key fingerprint: %m");
-                }
-
                 if (memcmp_nn(fp, fp_size, fpj_data, fpj_size) != 0)
                         continue; /* Not for this public key */
 
@@ -1655,8 +1688,10 @@ static int find_signature(
         }
 
         return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
-}
+#else /* HAVE_OPENSSL */
+        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
 #endif
+}
 
 static int tpm2_make_policy_session(
                 Tpm2Context *c,
@@ -1718,21 +1753,6 @@ static int tpm2_make_policy_session(
                 }
         }
 
-#if HAVE_OPENSSL
-        _cleanup_(EVP_PKEY_freep) EVP_PKEY *pk = NULL;
-        if (pubkey_size > 0) {
-                /* If a pubkey is specified, load it to validate it, even if the PCR mask for this is
-                 * actually zero, and we are thus not going to use it. */
-                _cleanup_fclose_ FILE *f = fmemopen((void*) pubkey, pubkey_size, "r");
-                if (!f)
-                        return log_oom();
-
-                pk = PEM_read_PUBKEY(f, NULL, NULL, NULL);
-                if (!pk)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PEM public key.");
-        }
-#endif
-
         _cleanup_tpm2_handle_ Tpm2Handle *session = NULL;
         r = tpm2_handle_new(c, &session);
         if (r < 0)
@@ -1755,12 +1775,14 @@ static int tpm2_make_policy_session(
                                        "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
 
         if (pubkey_pcr_mask != 0) {
-#if HAVE_OPENSSL
+                _cleanup_free_ void *fp = NULL;
+                size_t fp_size = 0;
+                TPM2B_PUBLIC pubkey_tpm2;
+
                 log_debug("Configuring public key based PCR policy.");
 
-                /* First: load public key into the TPM */
-                TPM2B_PUBLIC pubkey_tpm2;
-                r = openssl_pubkey_to_tpm2_pubkey(pk, &pubkey_tpm2);
+                /* Convert the PEM key to TPM2 format */
+                r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, &fp, &fp_size);
                 if (r < 0)
                         return r;
 
@@ -1828,9 +1850,8 @@ static int tpm2_make_policy_session(
 
                         r = find_signature(
                                         signature_json,
-                                        pcr_bank,
-                                        pubkey_pcr_mask,
-                                        pk,
+                                        &pcr_selection,
+                                        fp, fp_size,
                                         approved_policy->buffer,
                                         approved_policy->size,
                                         &signature_raw,
@@ -1894,9 +1915,6 @@ static int tpm2_make_policy_session(
                 if (rc != TSS2_RC_SUCCESS)
                         return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
                                                "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
-#else
-                return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
-#endif
         }
 
         if (hash_pcr_mask != 0) {