]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
openssl-util: introduce openssl_extract_public_key() helper function
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 24 Nov 2025 01:30:07 +0000 (10:30 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 24 Nov 2025 13:49:55 +0000 (22:49 +0900)
This splits out common logic in keyutil and systemd-measure.

Note, previously d2i_PUBKEY_fp() was used, but now it is replaced with
d2i_PUBKEY(), as musl seems to not support reading from memstream.

src/keyutil/keyutil.c
src/measure/measure-tool.c
src/shared/openssl-util.c
src/shared/openssl-util.h

index d94d2153c2a701fb0722d6adce12f8b53d8d2865..f19718a11f261c1d69bd683f004e225fcc94444f 100644 (file)
@@ -10,7 +10,6 @@
 #include "fs-util.h"
 #include "log.h"
 #include "main-func.h"
-#include "memstream-util.h"
 #include "openssl-util.h"
 #include "parse-argument.h"
 #include "pretty-print.h"
@@ -303,21 +302,9 @@ static int verb_public(int argc, char *argv[], void *userdata) {
                 if (r < 0)
                         return log_error_errno(r, "Failed to load private key from %s: %m", arg_private_key);
 
-                _cleanup_(memstream_done) MemStream m = {};
-                FILE *tf = memstream_init(&m);
-                if (!tf)
-                        return log_oom();
-
-                if (i2d_PUBKEY_fp(tf, private_key) != 1)
-                        return log_error_errno(SYNTHETIC_ERRNO(EIO),
-                                               "Failed to extract public key from private key file '%s'.", arg_private_key);
-
-                fflush(tf);
-                rewind(tf);
-
-                if (!d2i_PUBKEY_fp(tf, &public_key))
-                        return log_error_errno(SYNTHETIC_ERRNO(EIO),
-                                               "Failed to parse extracted public key of private key file '%s'.", arg_private_key);
+                r = openssl_extract_public_key(private_key, &public_key);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to extract public key from private key file '%s': %m", arg_private_key);
         } else
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "One of --certificate=, or --private-key= must be specified");
 
index 0d5ceb9faff57294092397bd4302df1bd8ec549d..3c8acf641767cefc320be75c2d792cf615ae6812 100644 (file)
@@ -15,7 +15,6 @@
 #include "hexdecoct.h"
 #include "log.h"
 #include "main-func.h"
-#include "memstream-util.h"
 #include "openssl-util.h"
 #include "pager.h"
 #include "parse-argument.h"
@@ -890,25 +889,10 @@ static int build_policy_digest(bool sign) {
                                         "Failed to extract public key from certificate %s.",
                                         arg_certificate);
         } else if (sign) {
-                _cleanup_(memstream_done) MemStream m = {};
-                FILE *tf;
-
                 /* No public key was specified, let's derive it automatically, if we can, when signing */
-
-                tf = memstream_init(&m);
-                if (!tf)
-                        return log_oom();
-
-                if (i2d_PUBKEY_fp(tf, privkey) != 1)
-                        return log_error_errno(SYNTHETIC_ERRNO(EIO),
-                                               "Failed to extract public key from private key file '%s'.", arg_private_key);
-
-                fflush(tf);
-                rewind(tf);
-
-                if (!d2i_PUBKEY_fp(tf, &pubkey))
-                        return log_error_errno(SYNTHETIC_ERRNO(EIO),
-                                               "Failed to parse extracted public key of private key file '%s'.", arg_private_key);
+                r = openssl_extract_public_key(privkey, &pubkey);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to extract public key from private key file '%s': %m", arg_private_key);
         }
 
         r = pcr_states_allocate(&pcr_states);
index 8fb23a8f923443a1c130674964ce42fc67d212e1..b8911c1b3035f2a9fc0ce8d5c003384c97378274 100644 (file)
@@ -1753,6 +1753,33 @@ int openssl_load_private_key(
 
         return 0;
 }
+
+int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret) {
+        int r;
+
+        assert(private_key);
+        assert(ret);
+
+        _cleanup_(memstream_done) MemStream m = {};
+        FILE *tf = memstream_init(&m);
+        if (!tf)
+                return log_oom();
+
+        if (i2d_PUBKEY_fp(tf, private_key) != 1)
+                return -EIO;
+
+        _cleanup_(erase_and_freep) char *buf = NULL;
+        size_t len;
+        r = memstream_finalize(&m, &buf, &len);
+        if (r < 0)
+                return r;
+
+        const unsigned char *t = (unsigned char*) buf;
+        if (!d2i_PUBKEY(ret, &t, len))
+                return -EIO;
+
+        return 0;
+}
 #endif
 
 int parse_openssl_certificate_source_argument(
index 72b9cfcc90228cb7bdc6807716d43e3e1ffcd702..cb48ea8bfd3200cbb9a39bfd2af27b2429fb7139 100644 (file)
@@ -195,6 +195,8 @@ int openssl_load_private_key(
                 EVP_PKEY **ret_private_key,
                 OpenSSLAskPasswordUI **ret_user_interface);
 
+int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret);
+
 struct OpenSSLAskPasswordUI {
         AskPasswordRequest request;
 #ifndef OPENSSL_NO_UI_CONSOLE