---
ell/pem-private.h | 5 +++++
ell/pem.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/ell/pem-private.h b/ell/pem-private.h
index 6e9458d..10f918f 100644
--- a/ell/pem-private.h
+++ b/ell/pem-private.h
@@ -27,6 +27,8 @@
#define _GNU_SOURCE
#include <sys/types.h>
+struct l_certchain;
+
const char *pem_next(const void *buf, size_t buf_len, char **type_label,
size_t *base64_len,
const char **endp, bool strict);
@@ -37,3 +39,6 @@ struct l_key *pem_key_from_pkcs8_private_key_info(const uint8_t *der,
struct l_key *pem_key_from_pkcs8_encrypted_private_key_info(const uint8_t *der,
size_t der_len,
const char *passphrase);
+
+int pem_write_certificate_chain(const struct l_certchain *cert,
+ const char *filename);
diff --git a/ell/pem.c b/ell/pem.c
index 1b995d5..321bc3e 100644
--- a/ell/pem.c
+++ b/ell/pem.c
@@ -45,6 +45,7 @@
#include "cipher.h"
#include "cert-private.h"
#include "missing.h"
+#include "io.h"
#include "pem-private.h"
#define PEM_START_BOUNDARY "-----BEGIN "
@@ -364,6 +365,55 @@ LIB_EXPORT struct l_certchain *l_pem_load_certificate_chain(
return pem_list_to_chain(list);
}
+static bool pem_write_one_cert(struct l_cert *cert, void *user_data)
+{
+ int *fd = user_data;
+ const uint8_t *der;
+ size_t der_len;
+ struct iovec iov[3];
+ ssize_t r;
+
+ der = l_cert_get_der_data(cert, &der_len);
+
+ iov[0].iov_base = "-----BEGIN CERTIFICATE-----\n";
+ iov[0].iov_len = strlen(iov[0].iov_base);
+ iov[1].iov_base = l_base64_encode(der, der_len, 64, &iov[1].iov_len);
+ iov[2].iov_base = "\n-----END CERTIFICATE-----\n";
+ iov[2].iov_len = strlen(iov[2].iov_base);
+ r = L_TFR(writev(*fd, iov, 3));
+
+ if (r == (ssize_t) (iov[0].iov_len + iov[1].iov_len + iov[2].iov_len))
+ return false;
+
+ close(*fd);
+
+ if (r < 0)
+ *fd = -errno;
+ else
+ *fd = -EIO;
+
+ return true;
+}
+
+int pem_write_certificate_chain(const struct l_certchain *chain,
+ const char *filename)
+{
+ int fd = L_TFR(open(filename, O_CREAT | O_WRONLY | O_CLOEXEC, 0600));
+ int err = fd;
+
+ if (err < 0)
+ return -errno;
+
+ l_certchain_walk_from_leaf((struct l_certchain *) chain,
+ pem_write_one_cert, &err);
+
+ if (err < 0)
+ return err;
+
+ close(fd);
+ return 0;
+}
+
LIB_EXPORT struct l_queue *l_pem_load_certificate_list_from_data(
const void *buf, size_t len)
{
--
2.27.0