facil.io

#PEM Parser

c
#define FIO_PEM
#include "fio-stl.h"

PEM wraps DER bytes in Base64 armor:

text
-----BEGIN <label>-----
<base64 DER>
-----END <label>-----

This module extracts PEM blocks, decodes certificates, and parses private keys used by the TLS/X.509 helpers.

Limit: encrypted private keys are not supported. If the key asks for a password, this parser politely leaves the room.

#Supported Labels

  • CERTIFICATE
  • PRIVATE KEY (PKCS#8)
  • RSA PRIVATE KEY (legacy PKCS#1)
  • EC PRIVATE KEY (legacy SEC1)

Private-key parsing supports RSA, P-256, and Ed25519 where the required crypto modules are available.

#Types

#fio_pem_key_type_e

c
typedef enum {
  FIO_PEM_KEY_UNKNOWN = 0,
  FIO_PEM_KEY_RSA = 1,
  FIO_PEM_KEY_ECDSA_P256 = 2,
  FIO_PEM_KEY_ED25519 = 3,
} fio_pem_key_type_e;

#fio_pem_s

c
typedef struct {
  const uint8_t *der;
  size_t der_len;
  const char *label;
  size_t label_len;
} fio_pem_s;

A decoded PEM block. der points into the caller-provided DER output buffer. label points into the original PEM input.

#fio_pem_private_key_s

c
typedef struct fio_pem_private_key_s fio_pem_private_key_s;

Parsed private-key material. The active union member depends on type:

  • RSA: fixed-size byte arrays for n, e, d, optional p, q, dP, dQ, and qInv, each with a length.
  • P-256: 32-byte private scalar, optional 65-byte uncompressed public key.
  • Ed25519: 32-byte seed, optional 32-byte public key.

Call fio_pem_private_key_clear when done.

#API

#fio_pem_parse

c
SFUNC size_t fio_pem_parse(fio_pem_s *out,
                           uint8_t *der_buf,
                           size_t der_buf_len,
                           const char *pem_data,
                           size_t pem_len);

Finds the next PEM block, decodes its Base64 body into der_buf, and fills out.

Returns the number of bytes consumed from pem_data, or 0 on error. To parse a file with multiple PEM blocks, advance by the returned count and call again.

#fio_pem_parse_certificate

c
SFUNC int fio_pem_parse_certificate(fio_x509_cert_s *cert,
                                    const char *pem_data,
                                    size_t pem_len);

Finds a CERTIFICATE block, decodes it, and parses the DER certificate with the X.509 parser. Returns 0 on success, -1 on error.

Requires the X.509 module for the certificate parse.

#fio_pem_parse_private_key

c
SFUNC int fio_pem_parse_private_key(fio_pem_private_key_s *key,
                                    const char *pem_data,
                                    size_t pem_len);

Parses a PEM private key into key.

Supported forms:

PEM label Format Supported keys
PRIVATE KEY PKCS#8 RSA, P-256, Ed25519
RSA PRIVATE KEY PKCS#1 RSA
EC PRIVATE KEY SEC1 P-256

Returns 0 on success, -1 on unsupported format, missing dependency, encrypted key, or malformed input.

#fio_pem_get_certificate_der

c
SFUNC size_t fio_pem_get_certificate_der(uint8_t *der_out,
                                         size_t der_out_len,
                                         const char *pem_data,
                                         size_t pem_len);

Extracts a CERTIFICATE block as raw DER without parsing the X.509 structure. Returns the DER length written, or 0 on error.

#fio_pem_private_key_clear

c
FIO_IFUNC void fio_pem_private_key_clear(fio_pem_private_key_s *key);

Securely zeros a parsed private-key structure.

#Example: Extract Certificate DER

c
#define FIO_PEM
#include "fio-stl.h"

size_t load_der(uint8_t *der, size_t der_cap, const char *pem, size_t pem_len) {
  return fio_pem_get_certificate_der(der, der_cap, pem, pem_len);
}

#Example: Parse Multiple Blocks

c
#define FIO_PEM
#include "fio-stl.h"

void scan_pem(const char *pem, size_t len) {
  uint8_t der[8192];
  while (len) {
    fio_pem_s block;
    size_t used = fio_pem_parse(&block, der, sizeof(der), pem, len);
    if (!used)
      break;

    /* block.label / block.label_len name the PEM type. */
    /* block.der / block.der_len hold the decoded DER bytes. */

    pem += used;
    len -= used;
  }
}

#Dependency Notes

  • Generic fio_pem_parse needs only the PEM/base64 helpers.
  • Certificate parsing needs X.509 support.
  • Private key parsing uses ASN.1, and RSA/P-256/Ed25519 support depends on the matching crypto headers.