]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
repart: Move verity sig formatting into data partition functions
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 9 Oct 2022 20:30:05 +0000 (22:30 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 15 Nov 2022 19:23:47 +0000 (20:23 +0100)
Refactoring to make implementing rootless repart easier.

src/partition/repart.c

index 6056655f47458b74a93fb1e05bf2b66243fe25e7..ba7fcc5e7a973ccda2e1cceda32355e2647827ff 100644 (file)
@@ -3306,6 +3306,123 @@ static int partition_format_verity_hash(
 #endif
 }
 
+static int sign_verity_roothash(
+                const uint8_t *roothash,
+                size_t roothash_size,
+                uint8_t **ret_signature,
+                size_t *ret_signature_size) {
+
+#if HAVE_OPENSSL
+        _cleanup_(BIO_freep) BIO *rb = NULL;
+        _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL;
+        _cleanup_free_ char *hex = NULL;
+        _cleanup_free_ uint8_t *sig = NULL;
+        int sigsz;
+
+        assert(roothash);
+        assert(roothash_size > 0);
+        assert(ret_signature);
+        assert(ret_signature_size);
+
+        hex = hexmem(roothash, roothash_size);
+        if (!hex)
+                return log_oom();
+
+        rb = BIO_new_mem_buf(hex, -1);
+        if (!rb)
+                return log_oom();
+
+        p7 = PKCS7_sign(arg_certificate, arg_private_key, NULL, rb, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
+        if (!p7)
+                return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to calculate PKCS7 signature: %s",
+                                       ERR_error_string(ERR_get_error(), NULL));
+
+        sigsz = i2d_PKCS7(p7, &sig);
+        if (sigsz < 0)
+                return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert PKCS7 signature to DER: %s",
+                                       ERR_error_string(ERR_get_error(), NULL));
+
+        *ret_signature = TAKE_PTR(sig);
+        *ret_signature_size = sigsz;
+
+        return 0;
+#else
+        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "openssl is not supported, cannot setup verity signature: %m");
+#endif
+}
+
+static int partition_format_verity_sig(Context *context, Partition *p) {
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        _cleanup_free_ uint8_t *sig = NULL;
+        _cleanup_free_ char *text = NULL;
+        Partition *hp;
+        uint8_t fp[X509_FINGERPRINT_SIZE];
+        size_t sigsz = 0, padsz; /* avoid false maybe-uninitialized warning */
+        int whole_fd, r;
+
+        assert(p->verity == VERITY_SIG);
+
+        if (p->dropped)
+                return 0;
+
+        if (PARTITION_EXISTS(p))
+                return 0;
+
+        if (partition_skip(p))
+                return 0;
+
+        assert_se(hp = p->siblings[VERITY_HASH]);
+        assert(!hp->dropped);
+
+        assert(arg_certificate);
+
+        assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
+
+        r = sign_verity_roothash(hp->roothash, hp->roothash_size, &sig, &sigsz);
+        if (r < 0)
+                return r;
+
+        r = x509_fingerprint(arg_certificate, fp);
+        if (r < 0)
+                return log_error_errno(r, "Unable to calculate X509 certificate fingerprint: %m");
+
+        r = json_build(&v,
+                        JSON_BUILD_OBJECT(
+                                JSON_BUILD_PAIR("rootHash", JSON_BUILD_HEX(hp->roothash, hp->roothash_size)),
+                                JSON_BUILD_PAIR(
+                                        "certificateFingerprint",
+                                        JSON_BUILD_HEX(fp, sizeof(fp))
+                                ),
+                                JSON_BUILD_PAIR("signature", JSON_BUILD_BASE64(sig, sigsz))
+                        )
+        );
+        if (r < 0)
+                return log_error_errno(r, "Failed to build JSON object: %m");
+
+        r = json_variant_format(v, 0, &text);
+        if (r < 0)
+                return log_error_errno(r, "Failed to format JSON object: %m");
+
+        padsz = round_up_size(strlen(text), 4096);
+        assert_se(padsz <= p->new_size);
+
+        r = strgrowpad0(&text, padsz);
+        if (r < 0)
+                return log_error_errno(r, "Failed to pad string to %s", FORMAT_BYTES(padsz));
+
+        if (lseek(whole_fd, p->offset, SEEK_SET) == (off_t) -1)
+                return log_error_errno(errno, "Failed to seek to partition offset: %m");
+
+        r = loop_write(whole_fd, text, padsz, /*do_poll=*/ false);
+        if (r < 0)
+                return log_error_errno(r, "Failed to write verity signature to partition: %m");
+
+        if (fsync(whole_fd) < 0)
+                return log_error_errno(errno, "Failed to synchronize verity signature JSON: %m");
+
+        return 0;
+}
+
 static int context_copy_blocks(Context *context) {
         int whole_fd = -1, r;
 
@@ -3372,6 +3489,12 @@ static int context_copy_blocks(Context *context) {
                         if (r < 0)
                                 return r;
                 }
+
+                if (p->siblings[VERITY_SIG]) {
+                        r = partition_format_verity_sig(context, p->siblings[VERITY_SIG]);
+                        if (r < 0)
+                                return r;
+                }
         }
 
         return 0;
@@ -3737,6 +3860,12 @@ static int context_mkfs(Context *context) {
                         if (r < 0)
                                 return r;
                 }
+
+                if (p->siblings[VERITY_SIG]) {
+                        r = partition_format_verity_sig(context, p->siblings[VERITY_SIG]);
+                        if (r < 0)
+                                return r;
+                }
         }
 
         return 0;
@@ -3796,130 +3925,6 @@ static int parse_private_key(const char *key, size_t key_size, EVP_PKEY **ret) {
 #endif
 }
 
-static int sign_verity_roothash(
-                const uint8_t *roothash,
-                size_t roothash_size,
-                uint8_t **ret_signature,
-                size_t *ret_signature_size) {
-
-#if HAVE_OPENSSL
-        _cleanup_(BIO_freep) BIO *rb = NULL;
-        _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL;
-        _cleanup_free_ char *hex = NULL;
-        _cleanup_free_ uint8_t *sig = NULL;
-        int sigsz;
-
-        assert(roothash);
-        assert(roothash_size > 0);
-        assert(ret_signature);
-        assert(ret_signature_size);
-
-        hex = hexmem(roothash, roothash_size);
-        if (!hex)
-                return log_oom();
-
-        rb = BIO_new_mem_buf(hex, -1);
-        if (!rb)
-                return log_oom();
-
-        p7 = PKCS7_sign(arg_certificate, arg_private_key, NULL, rb, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
-        if (!p7)
-                return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to calculate PKCS7 signature: %s",
-                                       ERR_error_string(ERR_get_error(), NULL));
-
-        sigsz = i2d_PKCS7(p7, &sig);
-        if (sigsz < 0)
-                return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert PKCS7 signature to DER: %s",
-                                       ERR_error_string(ERR_get_error(), NULL));
-
-        *ret_signature = TAKE_PTR(sig);
-        *ret_signature_size = sigsz;
-
-        return 0;
-#else
-        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "openssl is not supported, cannot setup verity signature: %m");
-#endif
-}
-
-static int context_verity_sig(Context *context) {
-        int fd = -1, r;
-
-        assert(context);
-
-        LIST_FOREACH(partitions, p, context->partitions) {
-                _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
-                _cleanup_free_ uint8_t *sig = NULL;
-                _cleanup_free_ char *text = NULL;
-                Partition *hp;
-                uint8_t fp[X509_FINGERPRINT_SIZE];
-                size_t sigsz = 0, padsz; /* avoid false maybe-uninitialized warning */
-
-                if (p->dropped)
-                        continue;
-
-                if (PARTITION_EXISTS(p))
-                        continue;
-
-                if (p->verity != VERITY_SIG)
-                        continue;
-
-                if (partition_skip(p))
-                        continue;
-
-                assert_se(hp = p->siblings[VERITY_HASH]);
-                assert(!hp->dropped);
-
-                assert(arg_certificate);
-
-                if (fd < 0)
-                        assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
-
-                r = sign_verity_roothash(hp->roothash, hp->roothash_size, &sig, &sigsz);
-                if (r < 0)
-                        return r;
-
-                r = x509_fingerprint(arg_certificate, fp);
-                if (r < 0)
-                        return log_error_errno(r, "Unable to calculate X509 certificate fingerprint: %m");
-
-                r = json_build(&v,
-                               JSON_BUILD_OBJECT(
-                                        JSON_BUILD_PAIR("rootHash", JSON_BUILD_HEX(hp->roothash, hp->roothash_size)),
-                                        JSON_BUILD_PAIR(
-                                                "certificateFingerprint",
-                                                JSON_BUILD_HEX(fp, sizeof(fp))
-                                        ),
-                                        JSON_BUILD_PAIR("signature", JSON_BUILD_BASE64(sig, sigsz))
-                               )
-                );
-                if (r < 0)
-                        return log_error_errno(r, "Failed to build JSON object: %m");
-
-                r = json_variant_format(v, 0, &text);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to format JSON object: %m");
-
-                padsz = round_up_size(strlen(text), 4096);
-                assert_se(padsz <= p->new_size);
-
-                r = strgrowpad0(&text, padsz);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to pad string to %s", FORMAT_BYTES(padsz));
-
-                if (lseek(fd, p->offset, SEEK_SET) == (off_t) -1)
-                        return log_error_errno(errno, "Failed to seek to partition offset: %m");
-
-                r = loop_write(fd, text, padsz, /*do_poll=*/ false);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to write verity signature to partition: %m");
-
-                if (fsync(fd) < 0)
-                        return log_error_errno(errno, "Failed to synchronize verity signature JSON: %m");
-        }
-
-        return 0;
-}
-
 static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *ret) {
         struct {
                 sd_id128_t type_uuid;
@@ -4491,10 +4496,6 @@ static int context_write_partition_table(
         if (r < 0)
                 return r;
 
-        r = context_verity_sig(context);
-        if (r < 0)
-                return r;
-
         r = context_mangle_partitions(context);
         if (r < 0)
                 return r;