diff options
author | Lennart Poettering <lennart@poettering.net> | 2023-09-05 13:55:41 +0200 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2023-09-06 19:34:21 +0200 |
commit | ef65c0f6ccd0214a5af26617c43cfe7ec7af816b (patch) | |
tree | 9d979af655eae8e743494d48821e4a6e27f71a08 | |
parent | shared/wall: use logind if build without utmp support (diff) | |
download | systemd-ef65c0f6ccd0214a5af26617c43cfe7ec7af816b.tar.xz systemd-ef65c0f6ccd0214a5af26617c43cfe7ec7af816b.zip |
openssl-util: add common implementation of digest+sign
-rw-r--r-- | src/boot/measure.c | 27 | ||||
-rw-r--r-- | src/home/user-record-sign.c | 21 | ||||
-rw-r--r-- | src/shared/openssl-util.c | 43 | ||||
-rw-r--r-- | src/shared/openssl-util.h | 2 |
4 files changed, 52 insertions, 41 deletions
diff --git a/src/boot/measure.c b/src/boot/measure.c index a62caf8a3f..45febe121a 100644 --- a/src/boot/measure.c +++ b/src/boot/measure.c @@ -837,31 +837,12 @@ static int verb_sign(int argc, char *argv[], void *userdata) { if (r < 0) return r; - _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX* mdctx = NULL; - mdctx = EVP_MD_CTX_new(); - if (!mdctx) - return log_oom(); - - if (EVP_DigestSignInit(mdctx, NULL, p->md, NULL, privkey) != 1) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), - "Failed to initialize signature context."); - - if (EVP_DigestSignUpdate(mdctx, pcr_policy_digest.buffer, pcr_policy_digest.size) != 1) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), - "Failed to sign data."); - + _cleanup_free_ void *sig = NULL; size_t ss; - if (EVP_DigestSignFinal(mdctx, NULL, &ss) != 1) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), - "Failed to finalize signature"); - _cleanup_free_ void *sig = malloc(ss); - if (!sig) - return log_oom(); - - if (EVP_DigestSignFinal(mdctx, sig, &ss) != 1) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), - "Failed to acquire signature data"); + r = digest_and_sign(p->md, privkey, pcr_policy_digest.buffer, pcr_policy_digest.size, &sig, &ss); + if (r < 0) + return log_error_errno(r, "Failed to sign PCR policy: %m"); _cleanup_free_ void *pubkey_fp = NULL; size_t pubkey_fp_size = 0; diff --git a/src/home/user-record-sign.c b/src/home/user-record-sign.c index cf72eaa556..dd099a0a6f 100644 --- a/src/home/user-record-sign.c +++ b/src/home/user-record-sign.c @@ -33,7 +33,6 @@ int user_record_sign(UserRecord *ur, EVP_PKEY *private_key, UserRecord **ret) { _cleanup_(memstream_done) MemStream m = {}; _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; _cleanup_(user_record_unrefp) UserRecord *signed_ur = NULL; - _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *md_ctx = NULL; _cleanup_free_ char *text = NULL, *key = NULL; _cleanup_free_ void *signature = NULL; size_t signature_size = 0; @@ -48,23 +47,9 @@ int user_record_sign(UserRecord *ur, EVP_PKEY *private_key, UserRecord **ret) { if (r < 0) return r; - md_ctx = EVP_MD_CTX_new(); - if (!md_ctx) - return -ENOMEM; - - if (EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, private_key) <= 0) - return -EIO; - - /* Request signature size */ - if (EVP_DigestSign(md_ctx, NULL, &signature_size, (uint8_t*) text, strlen(text)) <= 0) - return -EIO; - - signature = malloc(signature_size); - if (!signature) - return -ENOMEM; - - if (EVP_DigestSign(md_ctx, signature, &signature_size, (uint8_t*) text, strlen(text)) <= 0) - return -EIO; + r = digest_and_sign(/* md= */ NULL, private_key, text, SIZE_MAX, &signature, &signature_size); + if (r < 0) + return r; f = memstream_init(&m); if (!f) diff --git a/src/shared/openssl-util.c b/src/shared/openssl-util.c index 3d3d8090f8..31a1a55df7 100644 --- a/src/shared/openssl-util.c +++ b/src/shared/openssl-util.c @@ -545,6 +545,49 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s return 0; } +int digest_and_sign( + const EVP_MD *md, + EVP_PKEY *privkey, + const void *data, size_t size, + void **ret, size_t *ret_size) { + + assert(privkey); + assert(ret); + assert(ret_size); + + if (size == 0) + data = ""; /* make sure to pass a valid pointer to OpenSSL */ + else { + assert(data); + + if (size == SIZE_MAX) /* If SIZE_MAX input is a string whose size we determine automatically */ + size = strlen(data); + } + + _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); + if (!mdctx) + return log_openssl_errors("Failed to create new EVP_MD_CTX"); + + if (EVP_DigestSignInit(mdctx, NULL, md, NULL, privkey) != 1) + return log_openssl_errors("Failed to initialize signature context"); + + /* Determine signature size */ + size_t ss; + if (EVP_DigestSign(mdctx, NULL, &ss, data, size) != 1) + return log_openssl_errors("Failed to determine size of signature"); + + _cleanup_free_ void *sig = malloc(ss); + if (!sig) + return log_oom_debug(); + + if (EVP_DigestSign(mdctx, sig, &ss, data, size) != 1) + return log_openssl_errors("Failed to sign data"); + + *ret = TAKE_PTR(sig); + *ret_size = ss; + return 0; +} + # if PREFER_OPENSSL int string_hashsum( const char *s, diff --git a/src/shared/openssl-util.h b/src/shared/openssl-util.h index 90158f589b..4ea82b5f27 100644 --- a/src/shared/openssl-util.h +++ b/src/shared/openssl-util.h @@ -75,6 +75,8 @@ int ecc_pkey_new(int curve_id, EVP_PKEY **ret); int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_size); +int digest_and_sign(const EVP_MD *md, EVP_PKEY *privkey, const void *data, size_t size, void **ret, size_t *ret_size); + #else typedef struct X509 X509; |