# `./fio-stl/156 x509.h`

57 public symbols.

### Macros

#### `FIO_X509_OID_SHA256_WITH_RSA`

```c
#define FIO_X509_OID_SHA256_WITH_RSA   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, [15] = 9}}) /* 1.2.840.113549.1.1.11 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_SHA384_WITH_RSA`

```c
#define FIO_X509_OID_SHA384_WITH_RSA   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C, [15] = 9}}) /* 1.2.840.113549.1.1.12 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_SHA512_WITH_RSA`

```c
#define FIO_X509_OID_SHA512_WITH_RSA   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D, [15] = 9}}) /* 1.2.840.113549.1.1.13 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_RSA_PSS`

```c
#define FIO_X509_OID_RSA_PSS   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0A, [15] = 9}}) /* 1.2.840.113549.1.1.10 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_ECDSA_WITH_SHA256`

```c
#define FIO_X509_OID_ECDSA_WITH_SHA256   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, [15] = 8}}) /* 1.2.840.10045.4.3.2 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_ECDSA_WITH_SHA384`

```c
#define FIO_X509_OID_ECDSA_WITH_SHA384   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03, [15] = 8}}) /* 1.2.840.10045.4.3.3 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_ECDSA_WITH_SHA512`

```c
#define FIO_X509_OID_ECDSA_WITH_SHA512   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04, [15] = 8}}) /* 1.2.840.10045.4.3.4 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_ED25519`

```c
#define FIO_X509_OID_ED25519   \
  ((fio_u128){.u8 = {0x2B, 0x65, 0x70, [15] = 3}}) /* 1.3.101.112 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_ED448`

```c
#define FIO_X509_OID_ED448   \
  ((fio_u128){.u8 = {0x2B, 0x65, 0x71, [15] = 3}}) /* 1.3.101.113 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_RSA_ENCRYPTION`

```c
#define FIO_X509_OID_RSA_ENCRYPTION   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, [15] = 9}}) /* 1.2.840.113549.1.1.1 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_EC_PUBLIC_KEY`

```c
#define FIO_X509_OID_EC_PUBLIC_KEY   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, [15] = 7}}) /* 1.2.840.10045.2.1 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_SECP256R1`

```c
#define FIO_X509_OID_SECP256R1   \
  ((fio_u128){.u8 = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, [15] = 8}}) /* 1.2.840.10045.3.1.7 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_SECP384R1`

```c
#define FIO_X509_OID_SECP384R1   \
  ((fio_u128){.u8 = {0x2B, 0x81, 0x04, 0x00, 0x22, [15] = 5}}) /* 1.3.132.0.34 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_SECP521R1`

```c
#define FIO_X509_OID_SECP521R1   \
  ((fio_u128){.u8 = {0x2B, 0x81, 0x04, 0x00, 0x23, [15] = 5}}) /* 1.3.132.0.35 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_X25519`

```c
#define FIO_X509_OID_X25519   \
  ((fio_u128){.u8 = {0x2B, 0x65, 0x6E, [15] = 3}}) /* 1.3.101.110 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_X448`

```c
#define FIO_X509_OID_X448   \
  ((fio_u128){.u8 = {0x2B, 0x65, 0x6F, [15] = 3}}) /* 1.3.101.111 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_SUBJECT_KEY_ID`

```c
#define FIO_X509_OID_SUBJECT_KEY_ID   \
  ((fio_u128){.u8 = {0x55, 0x1D, 0x0E, [15] = 3}}) /* 2.5.29.14 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_KEY_USAGE`

```c
#define FIO_X509_OID_KEY_USAGE   \
  ((fio_u128){.u8 = {0x55, 0x1D, 0x0F, [15] = 3}}) /* 2.5.29.15 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_SUBJECT_ALT_NAME`

```c
#define FIO_X509_OID_SUBJECT_ALT_NAME   \
  ((fio_u128){.u8 = {0x55, 0x1D, 0x11, [15] = 3}}) /* 2.5.29.17 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_BASIC_CONSTRAINTS`

```c
#define FIO_X509_OID_BASIC_CONSTRAINTS   \
  ((fio_u128){.u8 = {0x55, 0x1D, 0x13, [15] = 3}}) /* 2.5.29.19 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_CRL_DIST_POINTS`

```c
#define FIO_X509_OID_CRL_DIST_POINTS   \
  ((fio_u128){.u8 = {0x55, 0x1D, 0x1F, [15] = 3}}) /* 2.5.29.31 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_CERT_POLICIES`

```c
#define FIO_X509_OID_CERT_POLICIES   \
  ((fio_u128){.u8 = {0x55, 0x1D, 0x20, [15] = 3}}) /* 2.5.29.32 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_AUTH_KEY_ID`

```c
#define FIO_X509_OID_AUTH_KEY_ID   \
  ((fio_u128){.u8 = {0x55, 0x1D, 0x23, [15] = 3}}) /* 2.5.29.35 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_EXT_KEY_USAGE`

```c
#define FIO_X509_OID_EXT_KEY_USAGE   \
  ((fio_u128){.u8 = {0x55, 0x1D, 0x25, [15] = 3}}) /* 2.5.29.37 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_EKU_SERVER_AUTH`

```c
#define FIO_X509_OID_EKU_SERVER_AUTH   \
  ((fio_u128){.u8 = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, [15] = 8}}) /* 1.3.6.1.5.5.7.3.1 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_EKU_CLIENT_AUTH`

```c
#define FIO_X509_OID_EKU_CLIENT_AUTH   \
  ((fio_u128){.u8 = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, [15] = 8}}) /* 1.3.6.1.5.5.7.3.2 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_COMMON_NAME`

```c
#define FIO_X509_OID_COMMON_NAME   \
  ((fio_u128){.u8 = {0x55, 0x04, 0x03, [15] = 3}}) /* 2.5.4.3 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_COUNTRY`

```c
#define FIO_X509_OID_COUNTRY   \
  ((fio_u128){.u8 = {0x55, 0x04, 0x06, [15] = 3}}) /* 2.5.4.6 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_LOCALITY`

```c
#define FIO_X509_OID_LOCALITY   \
  ((fio_u128){.u8 = {0x55, 0x04, 0x07, [15] = 3}}) /* 2.5.4.7 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_STATE`

```c
#define FIO_X509_OID_STATE   \
  ((fio_u128){.u8 = {0x55, 0x04, 0x08, [15] = 3}}) /* 2.5.4.8 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_ORGANIZATION`

```c
#define FIO_X509_OID_ORGANIZATION   \
  ((fio_u128){.u8 = {0x55, 0x04, 0x0A, [15] = 3}}) /* 2.5.4.10 */
```



_Symbol type:_ `macro`

#### `FIO_X509_OID_ORG_UNIT`

```c
#define FIO_X509_OID_ORG_UNIT   \
  ((fio_u128){.u8 = {0x55, 0x04, 0x0B, [15] = 3}}) /* 2.5.4.11 */
```



_Symbol type:_ `macro`

#### `FIO_TLS_CERT_PARSE_ERROR`

```c
#define FIO_TLS_CERT_PARSE_ERROR ((size_t)-1)
```

Error value for fio_tls_parse_certificate_message

_Symbol type:_ `macro`

#### `FIO_X509_MAX_CHAIN_DEPTH`

```c
#define FIO_X509_MAX_CHAIN_DEPTH 10
```



_Symbol type:_ `macro`

### Types

#### `fio_x509_key_algo_e`

```c
typedef enum {
FIO_X509_KEY_UNKNOWN = 0,
FIO_X509_KEY_RSA = 1, /**< RSA (any key size) */
FIO_X509_KEY_ECDSA_P256 = 2, /**< ECDSA with P-256/secp256r1 */
FIO_X509_KEY_ECDSA_P384 = 3, /**< ECDSA with P-384/secp384r1 */
FIO_X509_KEY_ED25519 = 4, /**< Ed25519 (EdDSA) */
} fio_x509_key_algo_e
```

Public key algorithm types

_Symbol type:_ `type`

#### `fio_x509_signature_algo_e`

```c
typedef enum {
FIO_X509_SIGNATURE_UNKNOWN = 0,
FIO_X509_SIGNATURE_RSA_PKCS1_SHA256 = 1, /**< sha256WithRSAEncryption */
FIO_X509_SIGNATURE_RSA_PKCS1_SHA384 = 2, /**< sha384WithRSAEncryption */
FIO_X509_SIGNATURE_RSA_PKCS1_SHA512 = 3, /**< sha512WithRSAEncryption */
FIO_X509_SIGNATURE_RSA_PSS_SHA256 = 4, /**< RSA-PSS with SHA-256 */
FIO_X509_SIGNATURE_RSA_PSS_SHA384 = 5, /**< RSA-PSS with SHA-384 */
FIO_X509_SIGNATURE_RSA_PSS_SHA512 = 6, /**< RSA-PSS with SHA-512 */
FIO_X509_SIGNATURE_ECDSA_SHA256 = 7, /**< ecdsa-with-SHA256 */
FIO_X509_SIGNATURE_ECDSA_SHA384 = 8, /**< ecdsa-with-SHA384 */
FIO_X509_SIGNATURE_ED25519 = 9, /**< Ed25519 */
} fio_x509_signature_algo_e
```

Signature algorithm types

_Symbol type:_ `type`

#### `fio_x509_key_usage_e`

```c
typedef enum {
FIO_X509_KU_DIGITAL_SIGNATURE = 0x0080, /* bit 0 = MSB of byte 0 */
FIO_X509_KU_NON_REPUDIATION = 0x0040, /* bit 1 */
FIO_X509_KU_KEY_ENCIPHERMENT = 0x0020, /* bit 2 */
FIO_X509_KU_DATA_ENCIPHERMENT = 0x0010, /* bit 3 */
FIO_X509_KU_KEY_AGREEMENT = 0x0008, /* bit 4 */
FIO_X509_KU_KEY_CERT_SIGN = 0x0004, /* bit 5 */
FIO_X509_KU_CRL_SIGN = 0x0002, /* bit 6 */
FIO_X509_KU_ENCIPHER_ONLY = 0x0001, /* bit 7 */
FIO_X509_KU_DECIPHER_ONLY = 0x8000, /* bit 8 = MSB of byte 1 */
} fio_x509_key_usage_e
```

Key Usage bit flags (RFC 5280 Section 4.2.1.3)

ASN.1 BIT STRING uses MSB-first bit ordering:
- Bit 0 = MSB of first byte (0x80)
- Bit 1 = 0x40, Bit 2 = 0x20, etc.
- Bits 8+ are in the second byte

_Symbol type:_ `type`

#### `fio_x509_error_e`

```c
typedef enum {
FIO_X509_OK = 0, /**< Validation successful */
FIO_X509_ERR_PARSE = -1, /**< Failed to parse certificate */
FIO_X509_ERR_EXPIRED = -2, /**< Certificate expired */
FIO_X509_ERR_NOT_YET_VALID = -3, /**< Certificate not yet valid */
FIO_X509_ERR_SIGNATURE = -4, /**< Signature verification failed */
FIO_X509_ERR_ISSUER_MISMATCH = -5, /**< Issuer DN doesn't match subject DN */
FIO_X509_ERR_NOT_CA = -6, /**< Issuer is not a CA certificate */
FIO_X509_ERR_NO_TRUST_ANCHOR = -7, /**< Certificate not in trust store */
FIO_X509_ERR_HOSTNAME_MISMATCH = -8, /**< Hostname doesn't match cert */
FIO_X509_ERR_EMPTY_CHAIN = -9, /**< Empty certificate chain */
FIO_X509_ERR_CHAIN_TOO_LONG = -10, /**< Chain exceeds maximum depth */
} fio_x509_error_e
```

X.509 chain validation error codes

_Symbol type:_ `type`

#### `fio_x509_trust_store_s`

```c
typedef struct {
const uint8_t **roots; /**< Array of root CA certificate DER data */
const size_t *root_lens; /**< Array of root CA certificate lengths */
size_t root_count; /**< Number of root CAs */
} fio_x509_trust_store_s
```

Trust store for root CA certificates

_Symbol type:_ `type`

#### `fio_tls_cert_entry_s`

```c
typedef struct {
const uint8_t *cert; /**< DER-encoded certificate data */
size_t cert_len; /**< Certificate length */
} fio_tls_cert_entry_s
```

TLS certificate entry (parsed from Certificate message)

_Symbol type:_ `type`

#### `fio_x509_cert_s`

```c
struct fio_x509_cert_s {
/* Buffer views (16 bytes each, 8-byte aligned — no padding) */
/** Raw DER data (points to the original input, NOT a copy) */
fio_ubuf_info_s der;
/** Certificate serial number (raw INTEGER contents, pointer into DER) */
fio_ubuf_info_s serial;
/** Subject Distinguished Name (raw DER for comparison) */
fio_ubuf_info_s subject;
/** Issuer Distinguished Name (raw DER for comparison) */
fio_ubuf_info_s issuer;
/** Subject Common Name (if present, pointer into DER data) */
fio_buf_info_s cn;
/** Public Key Data (union based on key_algo) */
union {
struct {
fio_ubuf_info_s n; /**< RSA modulus (big-endian) */
fio_ubuf_info_s e; /**< RSA exponent (big-endian) */
} rsa;
struct {
fio_ubuf_info_s point; /**< Uncompressed EC point (04 || x || y) */
} ecdsa;
struct {
fio_ubuf_info_s key; /**< 32-byte Ed25519 public key */
} ed25519;
} pubkey;
/** Signature value (pointer into DER data) */
fio_ubuf_info_s signature;
/** TBS Certificate (for signature verification) */
fio_ubuf_info_s tbs;
/** Subject Alternative Name: first DNS name (if present) */
fio_buf_info_s san_dns;
/** Subject Alternative Name extension raw data (for iterating all SANs) */
fio_ubuf_info_s san_ext;
/** Subject Alternative Name: first IP address (if present) */
fio_ubuf_info_s san_ip;
/** Validity period (Unix timestamps) */
int64_t not_before;
int64_t not_after;
/** SHA-256 fingerprint of the DER data (see fio_x509_fingerprint) */
uint8_t fingerprint[32];
/* Small fields grouped at the end (no bitfields — byte access is faster) */
/** Public Key Type */
fio_x509_key_algo_e key_algo;
/** Signature Algorithm */
fio_x509_signature_algo_e signature_algo;
/** Key Usage extension bits */
uint16_t key_usage;
/** Peer chain verification state: non-zero if a TLS backend verified this
* certificate's chain (see fio_io_peer_info_next). Always zero after
* fio_x509_parse — parsing does not verify anything. */
uint8_t verified;
/** Position in the peer certificate chain (0 = leaf certificate).
* Iteration is capped at 128 certificates (max value 127) as a
* deep-nesting / DoS guard. Set by fio_io_peer_info_next.
* Always zero after fio_x509_parse. */
uint8_t chain_index;
/** Certificate version (0=v1, 1=v2, 2=v3) */
uint8_t version;
/** Basic Constraints: is CA */
uint8_t is_ca;
/** Key Usage extension present */
uint8_t has_key_usage;
}
```

Parsed X.509 certificate structure.

All buffer fields are non-owning views (`fio_buf_info_s` /
`fio_ubuf_info_s`) into the original DER data, which must remain valid
while the certificate is in use.

When a certificate is obtained through fio_io_peer_info_next (TLS peer
certificate inspection), the views point into memory owned by the TLS
backend and remain valid until the next fio_io_peer_info_next call (on ANY
connection) or until the connection is closed, whichever comes first.

_Symbol type:_ `type`

#### `fio_x509_keypair_type_e`

```c
typedef enum {
FIO_X509_KEYPAIR_ED25519 = 1, /**< Ed25519 (preferred) */
FIO_X509_KEYPAIR_P256 = 2, /**< ECDSA P-256 */
} fio_x509_keypair_type_e
```

Key pair types for certificate generation

_Symbol type:_ `type`

#### `fio_x509_keypair_s`

```c
typedef struct {
fio_x509_keypair_type_e type; /**< Key type */
uint8_t secret_key[64]; /**< Secret key (32 bytes for Ed25519, P-256) */
uint8_t public_key[65]; /**< Public key (32 for Ed25519, 65 for P-256) */
size_t secret_key_len; /**< Actual secret key length */
size_t public_key_len; /**< Actual public key length */
} fio_x509_keypair_s
```

Key pair structure for certificate generation

_Symbol type:_ `type`

#### `fio_x509_cert_options_s`

```c
typedef struct {
fio_buf_info_s cn; /**< Subject Common Name (required) */
fio_buf_info_s org; /**< Subject Organization (optional) */
fio_buf_info_s ou; /**< Subject Organizational Unit (optional) */
fio_buf_info_s country; /**< Subject Country (optional, 2 chars) */
int64_t not_before; /**< Validity start (Unix timestamp, 0 = now) */
int64_t not_after; /**< Validity end (Unix timestamp, 0 = +1 year) */
const fio_buf_info_s *san_dns; /**< Subject Alternative Names (DNS) */
size_t san_dns_count; /**< Number of SAN DNS entries */
int is_ca; /**< Set CA:TRUE in BasicConstraints */
uint16_t key_usage; /**< Key Usage bits (0 = default for type) */
} fio_x509_cert_options_s
```

Certificate generation options.

All string fields are `fio_buf_info_s` views (non-owning) — a zero `.len`
marks the field as absent. There is NO implicit strlen fallback: callers
wrapping C strings should use `FIO_BUF_INFO2((char *)s, FIO_STRLEN(s))`.

_Symbol type:_ `type`

### Functions

#### `fio_x509_parse`

```c
int fio_x509_parse(fio_x509_cert_s *cert, const uint8_t *der_data, size_t der_len)
```

Parse a DER-encoded X.509 certificate.

The cert structure will contain pointers into the original DER data,
so the DER data must remain valid while the cert is in use.

**Parameters:**
- `cert` - Output certificate structure (will be zeroed first)
- `der_data` - Pointer to DER-encoded certificate
- `der_len` - Length of DER data in bytes

**Returns:**
- 0 on success, -1 on error

_Symbol type:_ `function`

#### `fio_x509_fingerprint`

```c
void fio_x509_fingerprint(fio_x509_cert_s *cert)
```

Computes the SHA-256 fingerprint of the certificate's DER data, storing
the raw 32-byte hash in `cert->fingerprint`.

Call after fio_x509_parse. This is a lazy (on-demand) operation so that
parsing alone never pays the hashing cost.

**Parameters:**
- `cert` - Parsed certificate (must have been filled by fio_x509_parse)

_Symbol type:_ `function`

#### `fio_x509_verify_signature`

```c
int fio_x509_verify_signature(const fio_x509_cert_s *cert, const fio_x509_cert_s *issuer)
```

Verify certificate signature using issuer's public key.

This verifies that the certificate was signed by the issuer.

**Parameters:**
- `cert` - Certificate to verify
- `issuer` - Certificate of the issuer (contains the public key)

**Returns:**
- 0 if valid, -1 if invalid or error

_Symbol type:_ `function`

#### `fio_x509_check_validity`

```c
inline int fio_x509_check_validity(const fio_x509_cert_s *cert, int64_t current_time)
```

Check if certificate is currently valid (not expired, not yet valid).

**Parameters:**
- `cert` - Certificate to check
- `current_time` - Current Unix timestamp (seconds since epoch)

**Returns:**
- 0 if valid, -1 if expired or not yet valid

_Symbol type:_ `function`

#### `fio_x509_match_hostname`

```c
int fio_x509_match_hostname(const fio_x509_cert_s *cert, const char *hostname, size_t hostname_len)
```

Check if hostname matches certificate (CN or SAN).

Supports wildcard matching (*.example.com).
Per RFC 6125, wildcards only match one label.

**Parameters:**
- `cert` - Certificate to check
- `hostname` - Hostname to match
- `hostname_len` - Length of hostname

**Returns:**
- 0 if match, -1 if no match

_Symbol type:_ `function`

#### `fio_x509_verify_chain`

```c
int fio_x509_verify_chain(const fio_ubuf_info_s *certs, size_t cert_count, const char *hostname, int64_t current_time, fio_x509_trust_store_s *trust_store)
```

Validate a certificate chain for TLS 1.3.

The chain should be ordered from end-entity to closest-to-root:
  - certs[0] = server's certificate (end-entity)
  - certs[1] = intermediate CA (signed certs[0])
  - certs[n-1] = closest to root (may be root or intermediate)

Validation performs:
  1. Parse all certificates
  2. Check validity period for all certificates
  3. Verify hostname matches end-entity certificate (if hostname provided)
  4. Verify each certificate's signature using the next certificate's key
  5. Verify issuer DNs match subject DNs in the chain
  6. Verify intermediate/root certificates have CA:TRUE
  7. Verify the chain terminates at a trusted root (if trust store provided)

**Parameters:**
- `certs` - Array of DER-encoded certificate views
- `cert_count` - Number of certificates in chain
- `hostname` - Expected hostname for end-entity (NULL to skip check)
- `current_time` - Current Unix timestamp for validity checking
- `trust_store` - Root CA certificates (NULL to skip trust check)

**Returns:**
- FIO_X509_OK (0) on success, or error code on failure

_Symbol type:_ `function`

#### `fio_x509_is_trusted`

```c
int fio_x509_is_trusted(const fio_x509_cert_s *cert, fio_x509_trust_store_s *trust_store)
```

Check if a certificate is in the trust store.

Comparison is done by matching subject DN.

**Parameters:**
- `cert` - Certificate to check
- `trust_store` - Trust store to search

**Returns:**
- 0 if trusted, -1 if not found

_Symbol type:_ `function`

#### `fio_tls_parse_certificate_message`

```c
size_t fio_tls_parse_certificate_message(fio_tls_cert_entry_s *entries, size_t max_entries, const uint8_t *data, size_t data_len)
```

Parse TLS 1.3 Certificate message into individual certificates.

TLS 1.3 Certificate message format (RFC 8446):
  certificate_request_context<0..2^8-1>
  certificate_list<0..2^24-1>:
    CertificateEntry:
      cert_data<1..2^24-1>
      extensions<0..2^16-1>

**Parameters:**
- `entries` - Output array for certificate entries
- `max_entries` - Maximum entries to parse
- `data` - Raw Certificate message data (after handshake header)
- `data_len` - Length of Certificate message data

**Returns:**
- Number of certificates parsed, or FIO_TLS_CERT_PARSE_ERROR on error

_Symbol type:_ `function`

#### `fio_x509_error_str`

```c
inline const char *fio_x509_error_str(int error)
```

Get human-readable error string for X.509 validation error code.

**Parameters:**
- `error` - Error code from fio_x509_verify_chain

**Returns:**
- Static string describing the error

_Symbol type:_ `function`

#### `fio_x509_keypair_ed25519`

```c
int fio_x509_keypair_ed25519(fio_x509_keypair_s *keypair)
```

Generate an Ed25519 key pair for certificate signing.

**Parameters:**
- `keypair` - Output key pair structure

**Returns:**
- 0 on success, -1 on error

_Symbol type:_ `function`

#### `fio_x509_keypair_p256`

```c
int fio_x509_keypair_p256(fio_x509_keypair_s *keypair)
```

Generate a P-256 key pair for certificate signing.

**Parameters:**
- `keypair` - Output key pair structure

**Returns:**
- 0 on success, -1 on error

_Symbol type:_ `function`

#### `fio_x509_self_signed_cert`

```c
size_t fio_x509_self_signed_cert(uint8_t *buf, size_t buf_len, const fio_x509_keypair_s *keypair, const fio_x509_cert_options_s *options)
```

Generate a self-signed X.509v3 certificate.

The certificate is DER-encoded and written to the output buffer.
Call with buf=NULL to get the maximum possible certificate size.
This returns a worst-case size that accounts for variable-length DER
encoding (e.g., serial numbers with varying leading zeros), ensuring
that a buffer of this size will always be sufficient for the actual
generation call.

**Parameters:**
- `buf` - Output buffer (can be NULL to calculate max size)
- `buf_len` - Buffer size (ignored if buf is NULL)
- `keypair` - Key pair to use for signing
- `options` - Certificate options

**Returns:**
- Number of bytes written (if buf!=NULL) or max needed (if buf==NULL),

or 0 on error

_Symbol type:_ `function`

#### `fio_x509_keypair_clear`

```c
inline void fio_x509_keypair_clear(fio_x509_keypair_s *keypair)
```

Securely clear a key pair structure.

**Parameters:**
- `keypair` - Key pair to clear

_Symbol type:_ `function`

-----------------------------------------------------
