From: Lennart Poettering Date: Tue, 18 Feb 2025 23:03:12 +0000 (+0100) Subject: openssl-util: add helper for converting EVP_PKEY to PEM string X-Git-Tag: v258-rc1~1143^2~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6a2097dd78a3084d436d88a5ea5f3c9340f4a569;p=thirdparty%2Fsystemd.git openssl-util: add helper for converting EVP_PKEY to PEM string And also give the rverse a bit of love. --- diff --git a/src/home/user-record-sign.c b/src/home/user-record-sign.c index 2230b29caff..a50c186d677 100644 --- a/src/home/user-record-sign.c +++ b/src/home/user-record-sign.c @@ -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; diff --git a/src/shared/openssl-util.c b/src/shared/openssl-util.c index 92d4f4d9555..b19c18e56ed 100644 --- a/src/shared/openssl-util.c +++ b/src/shared/openssl-util.c @@ -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 diff --git a/src/shared/openssl-util.h b/src/shared/openssl-util.h index 4ed7a4891f7..d936ef54f44 100644 --- a/src/shared/openssl-util.h +++ b/src/shared/openssl-util.h @@ -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); diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index b4ae74f17ac..18194da3e78 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -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; diff --git a/src/test/test-openssl.c b/src/test/test-openssl.c index d0ea0f02155..9ad2aa201e6 100644 --- a/src/test/test-openssl.c +++ b/src/test/test-openssl.c @@ -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); } diff --git a/src/test/test-tpm2.c b/src/test/test-tpm2.c index 31ef6192b29..e42fcfe8170 100644 --- a/src/test/test-tpm2.c +++ b/src/test/test-tpm2.c @@ -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); diff --git a/src/tpm2-setup/tpm2-setup.c b/src/tpm2-setup/tpm2-setup.c index 6a9a7852e29..622cd887f31 100644 --- a/src/tpm2-setup/tpm2-setup.c +++ b/src/tpm2-setup/tpm2-setup.c @@ -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);