]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
openssl-util: add helper for converting EVP_PKEY to PEM string
authorLennart Poettering <lennart@poettering.net>
Tue, 18 Feb 2025 23:03:12 +0000 (00:03 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 7 Mar 2025 17:13:16 +0000 (18:13 +0100)
And also give the rverse a bit of love.

src/home/user-record-sign.c
src/shared/openssl-util.c
src/shared/openssl-util.h
src/shared/tpm2-util.c
src/test/test-openssl.c
src/test/test-tpm2.c
src/tpm2-setup/tpm2-setup.c

index 2230b29caff4a7337cdcbd22d7159582234396a1..a50c186d677e5c284f3e365592d2acbc811ce5f7 100644 (file)
@@ -31,13 +31,11 @@ static int user_record_signable_json(UserRecord *ur, char **ret) {
 }
 
 int user_record_sign(UserRecord *ur, EVP_PKEY *private_key, UserRecord **ret) {
-        _cleanup_(memstream_done) MemStream m = {};
         _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
         _cleanup_(user_record_unrefp) UserRecord *signed_ur = NULL;
         _cleanup_free_ char *text = NULL, *key = NULL;
         _cleanup_free_ void *signature = NULL;
         size_t signature_size = 0;
-        FILE *f;
         int r;
 
         assert(ur);
@@ -52,14 +50,7 @@ int user_record_sign(UserRecord *ur, EVP_PKEY *private_key, UserRecord **ret) {
         if (r < 0)
                 return r;
 
-        f = memstream_init(&m);
-        if (!f)
-                return -ENOMEM;
-
-        if (PEM_write_PUBKEY(f, private_key) <= 0)
-                return -EIO;
-
-        r = memstream_finalize(&m, &key, NULL);
+        r = openssl_pubkey_to_pem(private_key, &key);
         if (r < 0)
                 return r;
 
index 92d4f4d955598eb69694a117d70ceddb4975df6a..b19c18e56ed179d914267809d7c096b2ea6456b8 100644 (file)
@@ -8,6 +8,7 @@
 #include "fileio.h"
 #include "hexdecoct.h"
 #include "memory-util.h"
+#include "memstream-util.h"
 #include "openssl-util.h"
 #include "random-util.h"
 #include "string-util.h"
@@ -52,24 +53,41 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(UI_METHOD*, UI_destroy_method, NULL);
                 UNIQ_T(R, u);                                           \
         })
 
-int openssl_pkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret) {
+int openssl_pubkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret) {
         assert(pem);
         assert(ret);
 
+        if (pem_size == SIZE_MAX)
+                pem_size = strlen(pem);
+
         _cleanup_fclose_ FILE *f = NULL;
         f = fmemopen((void*) pem, pem_size, "r");
         if (!f)
                 return log_oom_debug();
 
-        _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL);
+        _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = PEM_read_PUBKEY(f, /* x= */ NULL, /* pam_password_cb= */ NULL, /* userdata= */ NULL);
         if (!pkey)
                 return log_openssl_errors("Failed to parse PEM");
 
         *ret = TAKE_PTR(pkey);
-
         return 0;
 }
 
+int openssl_pubkey_to_pem(EVP_PKEY *pkey, char **ret) {
+        assert(pkey);
+        assert(ret);
+
+        _cleanup_(memstream_done) MemStream m = {};
+        FILE *f = memstream_init(&m);
+        if (!f)
+                return -ENOMEM;
+
+        if (PEM_write_PUBKEY(f, pkey) <= 0)
+                return -EIO;
+
+        return memstream_finalize(&m, ret, /* ret_size= */ NULL);
+}
+
 /* Returns the number of bytes generated by the specified digest algorithm. This can be used only for
  * fixed-size algorithms, e.g. md5, sha1, sha256, etc. Do not use this for variable-sized digest algorithms,
  * e.g. shake128. Returns 0 on success, -EOPNOTSUPP if the algorithm is not supported, or < 0 for any other
index 4ed7a4891f77366d0d2d654457cd1db12374c2fd..d936ef54f442d216b027b36c0247ced52dcfa8f3 100644 (file)
@@ -114,7 +114,8 @@ static inline void sk_X509_free_allp(STACK_OF(X509) **sk) {
         sk_X509_pop_free(*sk, X509_free);
 }
 
-int openssl_pkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret);
+int openssl_pubkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret);
+int openssl_pubkey_to_pem(EVP_PKEY *pkey, char **ret);
 
 int openssl_digest_size(const char *digest_alg, size_t *ret_digest_size);
 
index b4ae74f17ac0c626890db815cea987d938ebf139..18194da3e78b2c8df8ea5a865da1879f4830c350 100644 (file)
@@ -4572,7 +4572,7 @@ int tpm2_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PUBLIC *r
         assert(ret);
 
         _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
-        r = openssl_pkey_from_pem(pem, pem_size, &pkey);
+        r = openssl_pubkey_from_pem(pem, pem_size, &pkey);
         if (r < 0)
                 return r;
 
index d0ea0f0215570cf2a720baf304a3368735094e94..9ad2aa201e67173581b2963e43bcfb7ab6acbe6f 100644 (file)
@@ -7,7 +7,7 @@
 TEST(openssl_pkey_from_pem) {
         DEFINE_HEX_PTR(key_ecc, "2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a30444151634451674145726a6e4575424c73496c3972687068777976584e50686a346a426e500a44586e794a304b395579724e6764365335413532542b6f5376746b436a365a726c34685847337741515558706f426c532b7448717452714c35513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a");
         _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey_ecc = NULL;
-        assert_se(openssl_pkey_from_pem(key_ecc, key_ecc_len, &pkey_ecc) >= 0);
+        assert_se(openssl_pubkey_from_pem(key_ecc, key_ecc_len, &pkey_ecc) >= 0);
 
         _cleanup_free_ void *x = NULL, *y = NULL;
         size_t x_len, y_len;
@@ -23,7 +23,7 @@ TEST(openssl_pkey_from_pem) {
 
         DEFINE_HEX_PTR(key_rsa, "2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b4341514541795639434950652f505852337a436f63787045300a6a575262546c3568585844436b472f584b79374b6d2f4439584942334b734f5a31436a5937375571372f674359363170697838697552756a73413464503165380a593445336c68556d374a332b6473766b626f4b64553243626d52494c2f6675627771694c4d587a41673342575278747234547545443533527a373634554650640a307a70304b68775231496230444c67772f344e67566f314146763378784b4d6478774d45683567676b73733038326332706c354a504e32587677426f744e6b4d0a5471526c745a4a35355244436170696e7153334577376675646c4e735851357746766c7432377a7637344b585165616d704c59433037584f6761304c676c536b0a79754774586b6a50542f735542544a705374615769674d5a6f714b7479563463515a58436b4a52684459614c47587673504233687a766d5671636e6b47654e540a65774944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a");
         _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey_rsa = NULL;
-        assert_se(openssl_pkey_from_pem(key_rsa, key_rsa_len, &pkey_rsa) >= 0);
+        assert_se(openssl_pubkey_from_pem(key_rsa, key_rsa_len, &pkey_rsa) >= 0);
 
         _cleanup_free_ void *n = NULL, *e = NULL;
         size_t n_len, e_len;
@@ -94,7 +94,7 @@ TEST(invalid) {
         _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
 
         DEFINE_HEX_PTR(key, "2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b7b");
-        assert_se(openssl_pkey_from_pem(key, key_len, &pkey) == -EIO);
+        assert_se(openssl_pubkey_from_pem(key, key_len, &pkey) == -EIO);
         ASSERT_NULL(pkey);
 }
 
index 31ef6192b2924049f7c19ce493829153b25794c6..e42fcfe8170859d111661e9c347d9eef8e655b86 100644 (file)
@@ -810,7 +810,7 @@ static void get_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PU
         assert(pem);
         assert(ret);
 
-        assert_se(openssl_pkey_from_pem(pem, pem_size, &pkey) >= 0);
+        assert_se(openssl_pubkey_from_pem(pem, pem_size, &pkey) >= 0);
         assert_se(tpm2_tpm2b_public_from_openssl_pkey(pkey, &p1) >= 0);
         assert_se(tpm2_tpm2b_public_from_pem(pem, pem_size, &p2) >= 0);
         assert_se(memcmp_nn(&p1, sizeof(p1), &p2, sizeof(p2)) == 0);
index 6a9a7852e29cbf85a567ea25fd93e54728e527e2..622cd887f31de6a870f3188b54c94e4c645a39f9 100644 (file)
@@ -186,7 +186,7 @@ static int load_public_key_disk(const char *path, struct public_key_data *ret) {
         } else {
                 log_debug("Loaded SRK public key from '%s'.", path);
 
-                r = openssl_pkey_from_pem(blob, blob_size, &data.pkey);
+                r = openssl_pubkey_from_pem(blob, blob_size, &data.pkey);
                 if (r < 0)
                         return log_error_errno(r, "Failed to parse SRK public key file '%s': %m", path);