openssl-util: add helper for converting EVP_PKEY to PEM string

And also give the rverse a bit of love.
This commit is contained in:
Lennart Poettering
2025-03-07 18:13:16 +01:00
parent 7fd5979b83
commit 6a2097dd78
7 changed files with 30 additions and 20 deletions
+1 -10
View 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;
+21 -3
View 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
+2 -1
View 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);
+1 -1
View 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;
+3 -3
View 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);
}
+1 -1
View 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);
+1 -1
View 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);