]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
openssl-util: add common implementation of digest+sign
authorLennart Poettering <lennart@poettering.net>
Tue, 5 Sep 2023 11:55:41 +0000 (13:55 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Wed, 6 Sep 2023 17:34:21 +0000 (18:34 +0100)
src/boot/measure.c
src/home/user-record-sign.c
src/shared/openssl-util.c
src/shared/openssl-util.h

index a62caf8a3ff0a1c6238774cd899717dbc5f08ae3..45febe121a5efc684fb1820160e9b354711a9584 100644 (file)
@@ -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;
index cf72eaa55675c401ec9f54d25bf4d81b133a518d..dd099a0a6f79a8aad97fc02af3601d9ab5ef1b3e 100644 (file)
@@ -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)
index 3d3d8090f8c81064b01524dca050b5d04bd7e569..31a1a55df7963b7b9ac9f8b93e8e84195d4e0082 100644 (file)
@@ -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,
index 90158f589bb95b6bf776e9604949ec00cd354aef..4ea82b5f27c50283716e21e81668df107edfc958 100644 (file)
@@ -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;