# X.509 PKI
This page documents the X.509 PKI APIs: certificates, CRLs, CSRs, OCSP
responses, PEM encoding/decoding, and PKCS#7 / PKCS#12 container formats.
All getter functions that return `SyntaByteArray` with `owned == 0` return
**borrowed** slices pointing directly into the parsed object. The data is
valid while the parent handle is alive. Do not call `synta_byte_array_free()`
on borrowed arrays.
## Certificate API
### synta_certificate_parse_der
Parse an X.509 certificate from DER bytes. Returns NULL on error.
```c
SyntaCertificate *synta_certificate_parse_der(const uint8_t *data, uintptr_t len);
```
**Memory:** Must be freed with `synta_certificate_free()`.
### synta_certificate_free
```c
void synta_certificate_free(SyntaCertificate *cert);
```
### Certificate Getters
```c
/* Version: v1=0, v2=1, v3=2 */
SyntaErrorCode synta_certificate_get_version(const SyntaCertificate *cert,
int64_t *out);
/* Serial number, issuer DN, subject DN โ borrowed SyntaByteArray (owned == 0) */
SyntaErrorCode synta_certificate_get_serial_number(const SyntaCertificate *cert,
SyntaByteArray *out);
SyntaErrorCode synta_certificate_get_issuer_der(const SyntaCertificate *cert,
SyntaByteArray *out);
SyntaErrorCode synta_certificate_get_subject_der(const SyntaCertificate *cert,
SyntaByteArray *out);
/* Signature algorithm OID as a dotted-decimal string.
Pass (cert, NULL, 0) to query the required buffer length (including NUL).
The OID is computed and cached on first call; repeated calls are allocation-free. */
uintptr_t synta_certificate_get_signature_algorithm(const SyntaCertificate *cert,
char *buffer,
uintptr_t buffer_len);
/* Raw DER bytes of the signature AlgorithmIdentifier โ borrowed SyntaByteArray */
SyntaErrorCode synta_certificate_get_signature_algorithm_der(
const SyntaCertificate *cert, SyntaByteArray *out);
SyntaErrorCode synta_certificate_get_outer_signature_algorithm_der(
const SyntaCertificate *cert, SyntaByteArray *out);
```
**Example:**
```c
SyntaCertificate *cert = synta_certificate_parse_der(der, der_len);
if (!cert) {
fprintf(stderr, "%s\n", synta_get_last_error_message());
return 1;
}
SyntaByteArray subject = {0};
synta_certificate_get_subject_der(cert, &subject);
/* subject.owned == 0: do not free */
uintptr_t needed = synta_certificate_get_signature_algorithm(cert, NULL, 0);
char sig_alg[64];
if (needed <= sizeof(sig_alg))
synta_certificate_get_signature_algorithm(cert, sig_alg, sizeof(sig_alg));
synta_certificate_free(cert);
```
## CRL API
Parse and inspect X.509 Certificate Revocation Lists (RFC 5280 ยง5).
```c
/* Parse from DER or PEM (first block only); returns NULL on error */
SyntaCrl *synta_crl_parse_der(const uint8_t *data, uintptr_t len);
SyntaCrl *synta_crl_parse_pem(const uint8_t *data, uintptr_t len);
void synta_crl_free(SyntaCrl *crl);
/* All getters return borrowed SyntaByteArray (owned == 0) */
SyntaErrorCode synta_crl_get_issuer_der(const SyntaCrl *crl, SyntaByteArray *out);
SyntaErrorCode synta_crl_get_signature_algorithm_der(const SyntaCrl *crl,
SyntaByteArray *out);
SyntaErrorCode synta_crl_get_signature_value_der(const SyntaCrl *crl,
SyntaByteArray *out);
SyntaErrorCode synta_crl_get_this_update_der(const SyntaCrl *crl, SyntaByteArray *out);
/* nextUpdate: out->len == 0 when absent */
SyntaErrorCode synta_crl_get_next_update_der(const SyntaCrl *crl, SyntaByteArray *out);
/* Number of revokedCertificates entries (0 when absent or empty) */
SyntaErrorCode synta_crl_get_revoked_count(const SyntaCrl *crl, uintptr_t *out);
```
## CSR API
Parse and inspect PKCS#10 Certificate Signing Requests (RFC 2986).
```c
/* Parse from DER or PEM (first block only); returns NULL on error */
SyntaCsr *synta_csr_parse_der(const uint8_t *data, uintptr_t len);
SyntaCsr *synta_csr_parse_pem(const uint8_t *data, uintptr_t len);
void synta_csr_free(SyntaCsr *csr);
/* All getters return borrowed SyntaByteArray (owned == 0) */
SyntaErrorCode synta_csr_get_version(const SyntaCsr *csr, int64_t *out);
SyntaErrorCode synta_csr_get_subject_der(const SyntaCsr *csr, SyntaByteArray *out);
SyntaErrorCode synta_csr_get_signature_algorithm_der(const SyntaCsr *csr,
SyntaByteArray *out);
SyntaErrorCode synta_csr_get_signature_der(const SyntaCsr *csr, SyntaByteArray *out);
SyntaErrorCode synta_csr_get_public_key_der(const SyntaCsr *csr, SyntaByteArray *out);
```
## OCSP API
Parse and inspect OCSP responses (RFC 6960).
```c
/* Parse from DER; returns NULL on error */
SyntaOcsp *synta_ocsp_parse_der(const uint8_t *data, uintptr_t len);
void synta_ocsp_free(SyntaOcsp *ocsp);
/* Numeric status: 0=successful, 1=malformedRequest, 2=internalError,
3=tryLater, 5=sigRequired, 6=unauthorized */
SyntaErrorCode synta_ocsp_get_status_code(const SyntaOcsp *ocsp, int32_t *out);
/* Status as NUL-terminated string โ size-query pattern (pass NULL to get length) */
uintptr_t synta_ocsp_get_status(const SyntaOcsp *ocsp,
char *buffer, uintptr_t buffer_len);
/* responseType OID string (size-query pattern; absent when status != successful) */
uintptr_t synta_ocsp_get_response_type_oid(const SyntaOcsp *ocsp,
char *buffer, uintptr_t buffer_len);
/* OCTET STRING content of responseBytes (out->len == 0 when absent) */
SyntaErrorCode synta_ocsp_get_response_bytes_der(const SyntaOcsp *ocsp,
SyntaByteArray *out);
```
## PEM API
Dependency-free PEM encode/decode following RFC 7468.
```c
/* Decode all PEM blocks; returns opaque SyntaDerList, or NULL on error */
SyntaDerList *synta_pem_to_der(const uint8_t *data, uintptr_t len);
void synta_der_list_free(SyntaDerList *list);
uintptr_t synta_der_list_count(const SyntaDerList *list);
/* Get the index-th DER entry as a borrowed SyntaByteArray */
SyntaErrorCode synta_der_list_get_der(const SyntaDerList *list, uintptr_t index,
SyntaByteArray *out);
/* Encode DER as a PEM block; returns owned SyntaByteArray (must free) */
SyntaByteArray synta_der_to_pem(const uint8_t *data, uintptr_t len,
const char *label);
```
## PKCS#7 and PKCS#12 API
Extract X.509 certificates from container formats.
### synta_read_pki_file
Auto-detect encoding (PEM, PKCS#7, PKCS#12, or raw DER) and return every
X.509 certificate as a DER blob. Recommended when the input format is
unknown in advance.
```c
SyntaDerList *synta_read_pki_file(const uint8_t *data, uintptr_t len,
const uint8_t *password,
uintptr_t password_len);
```
**Example:**
```c
SyntaDerList *list = synta_read_pki_file(buf, n, NULL, 0);
if (!list) { fprintf(stderr, "%s\n", synta_get_last_error_message()); }
uintptr_t count = synta_der_list_count(list);
for (uintptr_t i = 0; i < count; i++) {
SyntaByteArray der = {0};
synta_der_list_get_der(list, i, &der);
/* use der.data / der.len */
}
synta_der_list_free(list);
```
### synta_pkcs7_certs_from_der
```c
SyntaDerList *synta_pkcs7_certs_from_der(const uint8_t *data, uintptr_t len);
```
### synta_pkcs7_certs_from_pem
```c
SyntaDerList *synta_pkcs7_certs_from_pem(const uint8_t *data, uintptr_t len);
```
### synta_pkcs12_certs_from_der
Extract DER certificates from a PKCS#12 PFX archive. `password` may be NULL
for unencrypted archives. Encrypted bags require the library to be built with
the `openssl` feature.
```c
SyntaDerList *synta_pkcs12_certs_from_der(const uint8_t *data, uintptr_t len,
const uint8_t *password,
uintptr_t password_len);
```