From: Daan De Meyer Date: Sun, 9 Oct 2022 20:30:05 +0000 (+0200) Subject: repart: Move verity sig formatting into data partition functions X-Git-Tag: v253-rc1~520^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4ecd39c5114fe7662a0abc374278138eaa1d5eae;p=thirdparty%2Fsystemd.git repart: Move verity sig formatting into data partition functions Refactoring to make implementing rootless repart easier. --- diff --git a/src/partition/repart.c b/src/partition/repart.c index 6056655f474..ba7fcc5e7a9 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -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;