# Synta C API Reference
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Overview](#overview)
- [Header File](#header-file)
- [Linking](#linking)
- [Error Handling](#error-handling)
- [Error Codes](#error-codes)
- [Error Functions](#error-functions)
- [synta_error_message](#syntaerrormessage)
- [synta_get_last_error_message](#syntagetlasterrormessage)
- [synta_clear_last_error](#syntaclearlast_error)
- [Decoder API](#decoder-api)
- [Decoder Lifecycle](#decoder-lifecycle)
- [synta_decoder_new](#syntadecodernew)
- [synta_decoder_new_with_config](#syntadecodernewwithconfig)
- [synta_decoder_free](#syntadecoderfree)
- [Decoder Utilities](#decoder-utilities)
- [synta_decoder_remaining](#syntadecoderremaining)
- [synta_decoder_at_end](#syntadecoderat_end)
- [synta_decoder_peek_tag](#syntadecoderpeek_tag)
- [Primitive Type Decoding](#primitive-type-decoding)
- [synta_decode_boolean](#syntadecodeboolean)
- [synta_decode_integer](#syntadecodeinteger)
- [synta_decode_null](#syntadecodenull)
- [synta_decode_octet_string](#syntadecodeoctet_string)
- [synta_decode_bit_string](#syntadecodebit_string)
- [synta_decode_object_identifier](#syntadecodeobject_identifier)
- [String Type Decoding](#string-type-decoding)
- [synta_decode_utf8_string](#syntadecodeutf8_string)
- [synta_decode_printable_string](#syntadecodeprintable_string)
- [synta_decode_ia5_string](#syntadecodeia5_string)
- [Constructed Type Decoding](#constructed-type-decoding)
- [synta_decoder_enter_sequence](#syntadecoderenter_sequence)
- [synta_decoder_enter_set](#syntadecoderenter_set)
- [synta_decoder_enter_constructed](#syntadecoderenter_constructed)
- [Encoder API](#encoder-api)
- [Encoder Lifecycle](#encoder-lifecycle)
- [synta_encoder_new](#syntaencodernew)
- [synta_encoder_finish](#syntaencoderfinish)
- [synta_encoder_free](#syntaencoderfree)
- [Primitive Type Encoding](#primitive-type-encoding)
- [synta_encode_boolean](#syntaencodeboolean)
- [synta_encode_integer_i64](#syntaencodeinteger_i64)
- [synta_encode_integer](#syntaencodeinteger)
- [synta_encode_null](#syntaencodenull)
- [synta_encode_octet_string](#syntaencodeoctet_string)
- [synta_encode_bit_string](#syntaencodebit_string)
- [synta_encode_object_identifier](#syntaencodeobject_identifier)
- [String Type Encoding](#string-type-encoding)
- [synta_encode_utf8_string](#syntaencodeutf8_string)
- [synta_encode_printable_string](#syntaencodeprintable_string)
- [synta_encode_ia5_string](#syntaencodeia5_string)
- [Constructed Type Encoding](#constructed-type-encoding)
- [synta_encoder_start_sequence](#syntaencoderstart_sequence)
- [synta_encoder_start_set](#syntaencoderstart_set)
- [synta_encoder_start_constructed](#syntaencoderstart_constructed)
- [synta_encoder_end_constructed](#syntaencoderend_constructed)
- [Helper Types](#helper-types)
- [Integer Helpers](#integer-helpers)
- [synta_integer_new_i64](#syntaintegernew_i64)
- [synta_integer_new_u64](#syntaintegernew_u64)
- [synta_integer_new_bytes](#syntaintegernew_bytes)
- [synta_integer_to_i64](#syntaintegerto_i64)
- [synta_integer_to_u64](#syntaintegerto_u64)
- [synta_integer_to_bytes](#syntaintegerto_bytes)
- [synta_integer_is_negative](#syntaintegeris_negative)
- [synta_integer_free](#syntaintegerfree)
- [OctetString Helpers](#octetstring-helpers)
- [synta_octet_string_new](#syntaoctetstring_new)
- [synta_octet_string_data](#syntaoctetstring_data)
- [synta_octet_string_len](#syntaoctetstring_len)
- [synta_octet_string_free](#syntaoctetstring_free)
- [ObjectIdentifier Helpers](#objectidentifier-helpers)
- [synta_oid_new](#syntaoidnew)
- [synta_oid_from_string](#syntaoidfrom_string)
- [synta_oid_to_string](#syntaoidto_string)
- [synta_oid_components](#syntaoidcomponents)
- [synta_oid_equals](#syntaoidequals)
- [synta_oid_free](#syntaoidfree)
- [ByteArray Helpers](#bytearray-helpers)
- [synta_byte_array_free](#syntabytearray_free)
- [synta_byte_array_clone](#syntabytearray_clone)
- [X.509 PKI APIs](#x509-pki-apis)
- [CRL API](#crl-api)
- [synta_crl_parse_der](#syntacrlparse_der)
- [synta_crl_parse_pem](#syntacrlparse_pem)
- [synta_crl_free](#syntacrlfree)
- [synta_crl_get_issuer_der](#syntacrlgetissuerder)
- [synta_crl_get_signature_algorithm_der](#syntacrlgetsignaturealgorithm_der)
- [synta_crl_get_signature_value_der](#syntacrlgetsignaturevalue_der)
- [synta_crl_get_this_update_der](#syntacrlgetthisupdate_der)
- [synta_crl_get_next_update_der](#syntacrlgetnextupdate_der)
- [synta_crl_get_revoked_count](#syntacrlgetrevokedcount)
- [CSR API](#csr-api)
- [synta_csr_parse_der](#syntacsrparse_der)
- [synta_csr_parse_pem](#syntacsrparse_pem)
- [synta_csr_free](#syntacsrfree)
- [synta_csr_get_version](#syntacsrget_version)
- [synta_csr_get_subject_der](#syntacsrgetsubjectder)
- [synta_csr_get_signature_algorithm_der](#syntacsrgetsignaturealgorithm_der)
- [synta_csr_get_signature_der](#syntacsrgetsignatureder)
- [synta_csr_get_public_key_der](#syntacsrgetpublickey_der)
- [OCSP API](#ocsp-api)
- [synta_ocsp_parse_der](#syntaocspparse_der)
- [synta_ocsp_free](#syntaocspfree)
- [synta_ocsp_get_status_code](#syntaocspgetstatuscode)
- [synta_ocsp_get_status](#syntaocspget_status)
- [synta_ocsp_get_response_type_oid](#syntaocspgetresponsetype_oid)
- [synta_ocsp_get_response_bytes_der](#syntaocspgetresponsebytes_der)
- [PEM API](#pem-api)
- [synta_pem_to_der](#syntapemto_der)
- [synta_der_list_free](#syntaderlist_free)
- [synta_der_list_count](#syntaderlist_count)
- [synta_der_list_get_der](#syntaderlistgetder)
- [synta_der_to_pem](#syntaderto_pem)
- [PKCS#7 and PKCS#12 API](#pkcs7-and-pkcs12-api)
- [synta_read_pki_file](#syntareadpki_file)
- [synta_pkcs7_certs_from_der](#syntapkcs7certsfromder)
- [synta_pkcs7_certs_from_pem](#syntapkcs7certsfrompem)
- [synta_pkcs12_certs_from_der](#syntapkcs12certsfromder)
- [CMS API](#cms-api)
- [ContentInfo API](#contentinfo-api)
- [synta_cms_content_info_parse_der](#syntacmscontentinfoparse_der)
- [synta_cms_content_info_free](#syntacmscontentinfofree)
- [synta_cms_content_info_get_content_type](#syntacmscontentinfogetcontenttype)
- [synta_cms_content_info_get0_signed_data](#syntacmscontentinfoget0signeddata)
- [synta_cms_content_info_get0_enveloped_data](#syntacmscontentinfoget0envelopeddata)
- [synta_cms_content_info_get0_encrypted_data](#syntacmscontentinfoget0encrypteddata)
- [synta_cms_content_info_get0_digested_data](#syntacmscontentinfoget0digesteddata)
- [SignedData API](#signeddata-api)
- [SignerInfo API](#signerinfo-api)
- [synta_cms_signer_info_parse_der](#syntacmssignerinfoparse_der)
- [synta_cms_signer_info_free](#syntacmssignerinfofree)
- [EnvelopedData API](#envelopeddata-api)
- [EncryptedData API](#encrypteddata-api)
- [synta_cms_encrypted_data_parse](#syntacmsencrypteddataparse)
- [synta_cms_encrypted_data_free](#syntacmsencrypteddatafree)
- [synta_cms_encrypted_data_decrypt](#syntacmsencrypteddatadecrypt)
- [synta_cms_encrypted_data_create](#syntacmsencrypteddatacreate)
- [DigestedData API](#digesteddata-api)
- [Thread Safety](#thread-safety)
- [See Also](#see-also)
Complete reference for the Synta C Foreign Function Interface (FFI).
## Table of Contents
- [Overview](#overview)
- [Error Handling](#error-handling)
- [Decoder API](#decoder-api)
- [Encoder API](#encoder-api)
- [Helper Types](#helper-types)
- [Thread Safety](#thread-safety)
## Overview
The Synta C API provides a safe, ergonomic interface for ASN.1 encoding and decoding from C and C++ programs. All functions follow consistent patterns for error handling, memory management, and resource cleanup.
### Header File
```c
#include <synta.h>
```
### Linking
```bash
# With pkg-config
gcc myapp.c $(pkg-config --cflags --libs synta) -o myapp
# With CMake
find_package(Synta REQUIRED)
target_link_libraries(myapp Synta::Synta)
# Manual
gcc myapp.c -I/path/to/include -L/path/to/lib -lcsynta -lpthread -ldl -lm -o myapp
```
## Error Handling
### Error Codes
```c
typedef enum SyntaErrorCode {
SyntaErrorCode_Success = 0,
SyntaErrorCode_InvalidTag = 1,
SyntaErrorCode_InvalidLength = 2,
SyntaErrorCode_UnexpectedEof = 3,
SyntaErrorCode_InvalidEncoding = 4,
SyntaErrorCode_InvalidInteger = 5,
SyntaErrorCode_InvalidOid = 6,
SyntaErrorCode_InvalidUtf8 = 7,
SyntaErrorCode_InvalidPrintableString = 8,
SyntaErrorCode_InvalidIA5String = 9,
SyntaErrorCode_InvalidBoolean = 10,
SyntaErrorCode_InvalidTime = 11,
SyntaErrorCode_InvalidBitString = 12,
SyntaErrorCode_MaxDepthExceeded = 13,
SyntaErrorCode_MaxSequenceElementsExceeded = 14,
SyntaErrorCode_MaxLengthExceeded = 15,
SyntaErrorCode_BerViolation = 16,
SyntaErrorCode_DerViolation = 17,
SyntaErrorCode_CerViolation = 18,
SyntaErrorCode_NullPointer = 19,
SyntaErrorCode_InvalidArgument = 20,
SyntaErrorCode_OutOfMemory = 21,
SyntaErrorCode_IntegerOverflow = 22,
SyntaErrorCode_IntegerUnderflow = 23,
SyntaErrorCode_Unknown = 999,
} SyntaErrorCode;
```
### Error Functions
#### synta_error_message
Get a static error message for an error code.
```c
const char *synta_error_message(SyntaErrorCode code);
```
**Parameters:**
- `code` - Error code
**Returns:** Static string describing the error (never NULL)
**Example:**
```c
SyntaErrorCode err = synta_decode_integer(decoder, &integer);
if (err != SyntaErrorCode_Success) {
printf("Error: %s\n", synta_error_message(err));
}
```
#### synta_get_last_error_message
Get detailed error message for the last error (thread-local).
```c
const char *synta_get_last_error_message(void);
```
**Returns:** Detailed error message, or NULL if no error
**Example:**
```c
if (err != SyntaErrorCode_Success) {
const char *msg = synta_get_last_error_message();
if (msg) {
printf("Detailed error: %s\n", msg);
}
}
```
#### synta_clear_last_error
Clear the thread-local error message.
```c
void synta_clear_last_error(void);
```
## Decoder API
### Decoder Lifecycle
#### synta_decoder_new
Create a new decoder from a byte array.
```c
SyntaDecoder *synta_decoder_new(const uint8_t *data,
size_t len,
SyntaEncoding encoding);
```
**Parameters:**
- `data` - Pointer to encoded data (can be NULL if len is 0)
- `len` - Length of data in bytes
- `encoding` - Encoding rules (SyntaEncoding_Der, SyntaEncoding_Ber, or SyntaEncoding_Cer)
**Returns:** Decoder pointer, or NULL on error
**Example:**
```c
const uint8_t data[] = {0x02, 0x01, 0x2A}; // INTEGER 42
SyntaDecoder *decoder = synta_decoder_new(data, sizeof(data), SyntaEncoding_Der);
if (!decoder) {
fprintf(stderr, "Failed to create decoder\n");
return 1;
}
```
**Memory:** Returned decoder must be freed with `synta_decoder_free()`
#### synta_decoder_new_with_config
Create a decoder with custom configuration.
```c
SyntaDecoder *synta_decoder_new_with_config(const uint8_t *data,
size_t len,
SyntaEncoding encoding,
const SyntaDecoderConfig *config);
```
**Parameters:**
- `data` - Pointer to encoded data
- `len` - Length of data
- `encoding` - Encoding rules
- `config` - Decoder configuration
**Example:**
```c
SyntaDecoderConfig config = {
.max_depth = 32,
.max_sequence_elements = 10000,
.max_length = 16 * 1024 * 1024
};
SyntaDecoder *decoder = synta_decoder_new_with_config(
data, len, SyntaEncoding_Der, &config);
```
#### synta_decoder_free
Free a decoder and all associated resources.
```c
void synta_decoder_free(SyntaDecoder *decoder);
```
**Parameters:**
- `decoder` - Decoder to free (can be NULL)
**Example:**
```c
synta_decoder_free(decoder);
decoder = NULL; // Good practice
```
### Decoder Utilities
#### synta_decoder_remaining
Get number of remaining bytes in the decoder.
```c
size_t synta_decoder_remaining(const SyntaDecoder *decoder);
```
**Returns:** Number of unread bytes
#### synta_decoder_at_end
Check if decoder is at end of input.
```c
bool synta_decoder_at_end(const SyntaDecoder *decoder);
```
**Returns:** true if no more data to read
#### synta_decoder_peek_tag
Peek at the next tag without consuming it.
```c
SyntaErrorCode synta_decoder_peek_tag(const SyntaDecoder *decoder,
SyntaTag *out);
```
**Parameters:**
- `decoder` - Decoder to peek
- `out` - Output tag structure
**Returns:** SyntaErrorCode_Success or error code
**Example:**
```c
SyntaTag tag;
if (synta_decoder_peek_tag(decoder, &tag) == SyntaErrorCode_Success) {
if (tag.class_ == SyntaTagClass_ContextSpecific && tag.number == 0) {
// Handle optional [0] field
}
}
```
### Primitive Type Decoding
#### synta_decode_boolean
Decode a BOOLEAN value.
```c
SyntaErrorCode synta_decode_boolean(SyntaDecoder *decoder, bool *out);
```
**Example:**
```c
bool value;
SyntaErrorCode err = synta_decode_boolean(decoder, &value);
if (err == SyntaErrorCode_Success) {
printf("Boolean: %s\n", value ? "true" : "false");
}
```
#### synta_decode_integer
Decode an INTEGER value.
```c
SyntaErrorCode synta_decode_integer(SyntaDecoder *decoder,
SyntaInteger **out);
```
**Example:**
```c
SyntaInteger *integer = NULL;
if (synta_decode_integer(decoder, &integer) == SyntaErrorCode_Success) {
int64_t value;
if (synta_integer_to_i64(integer, &value) == SyntaErrorCode_Success) {
printf("Integer: %lld\n", (long long)value);
}
synta_integer_free(integer);
}
```
**Memory:** Returned integer must be freed with `synta_integer_free()`
#### synta_decode_null
Decode a NULL value.
```c
SyntaErrorCode synta_decode_null(SyntaDecoder *decoder);
```
#### synta_decode_octet_string
Decode an OCTET STRING.
```c
SyntaErrorCode synta_decode_octet_string(SyntaDecoder *decoder,
SyntaOctetString **out);
```
**Memory:** Returned octet string must be freed with `synta_octet_string_free()`
#### synta_decode_bit_string
Decode a BIT STRING.
```c
SyntaErrorCode synta_decode_bit_string(SyntaDecoder *decoder,
SyntaByteArray *out,
uint8_t *unused_bits);
```
**Parameters:**
- `decoder` - Decoder
- `out` - Output byte array
- `unused_bits` - Number of unused bits in last byte (0-7)
**Memory:** Output byte array must be freed with `synta_byte_array_free()`
#### synta_decode_object_identifier
Decode an OBJECT IDENTIFIER.
```c
SyntaErrorCode synta_decode_object_identifier(SyntaDecoder *decoder,
SyntaObjectIdentifier **out);
```
**Memory:** Returned OID must be freed with `synta_oid_free()`
### String Type Decoding
#### synta_decode_utf8_string
Decode a UTF8String.
```c
SyntaErrorCode synta_decode_utf8_string(SyntaDecoder *decoder,
SyntaByteArray *out);
```
**Memory:** Output byte array must be freed with `synta_byte_array_free()`
#### synta_decode_printable_string
Decode a PrintableString.
```c
SyntaErrorCode synta_decode_printable_string(SyntaDecoder *decoder,
SyntaByteArray *out);
```
#### synta_decode_ia5_string
Decode an IA5String.
```c
SyntaErrorCode synta_decode_ia5_string(SyntaDecoder *decoder,
SyntaByteArray *out);
```
### Constructed Type Decoding
#### synta_decoder_enter_sequence
Enter a SEQUENCE and get a new decoder for its contents.
```c
SyntaErrorCode synta_decoder_enter_sequence(SyntaDecoder *decoder,
SyntaDecoder **out);
```
**Example:**
```c
SyntaDecoder *seq_decoder = NULL;
if (synta_decoder_enter_sequence(decoder, &seq_decoder) == SyntaErrorCode_Success) {
// Decode sequence contents
while (!synta_decoder_at_end(seq_decoder)) {
// Decode element
}
synta_decoder_free(seq_decoder);
}
```
**Memory:** Returned decoder must be freed with `synta_decoder_free()`
#### synta_decoder_enter_set
Enter a SET.
```c
SyntaErrorCode synta_decoder_enter_set(SyntaDecoder *decoder,
SyntaDecoder **out);
```
#### synta_decoder_enter_constructed
Enter a constructed type with explicit tag.
```c
SyntaErrorCode synta_decoder_enter_constructed(SyntaDecoder *decoder,
SyntaTag tag,
SyntaDecoder **out);
```
**Example:**
```c
SyntaTag tag;
synta_decoder_peek_tag(decoder, &tag);
if (tag.class_ == SyntaTagClass_ContextSpecific && tag.number == 0) {
SyntaDecoder *inner = NULL;
synta_decoder_enter_constructed(decoder, tag, &inner);
// Decode contents
synta_decoder_free(inner);
}
```
## Encoder API
### Encoder Lifecycle
#### synta_encoder_new
Create a new encoder.
```c
SyntaEncoder *synta_encoder_new(SyntaEncoding encoding);
```
**Example:**
```c
SyntaEncoder *encoder = synta_encoder_new(SyntaEncoding_Der);
if (!encoder) {
fprintf(stderr, "Failed to create encoder\n");
return 1;
}
```
#### synta_encoder_finish
Finish encoding and get the encoded bytes.
```c
SyntaErrorCode synta_encoder_finish(SyntaEncoder *encoder,
SyntaByteArray *out);
```
**Parameters:**
- `encoder` - Encoder to finish (consumed, do not use after)
- `out` - Output byte array
**Returns:** Error code
**Example:**
```c
SyntaByteArray output = {0};
if (synta_encoder_finish(encoder, &output) == SyntaErrorCode_Success) {
// Use output.data and output.len
synta_byte_array_free(&output);
}
// encoder is consumed, do not call synta_encoder_free()
```
**Memory:** Output byte array must be freed with `synta_byte_array_free()`. The encoder is consumed and must not be used or freed after this call.
#### synta_encoder_free
Free an encoder without finishing it.
```c
void synta_encoder_free(SyntaEncoder *encoder);
```
**Note:** Do not call this after `synta_encoder_finish()`.
### Primitive Type Encoding
#### synta_encode_boolean
Encode a BOOLEAN value.
```c
SyntaErrorCode synta_encode_boolean(SyntaEncoder *encoder, bool value);
```
#### synta_encode_integer_i64
Encode an INTEGER from int64_t.
```c
SyntaErrorCode synta_encode_integer_i64(SyntaEncoder *encoder, int64_t value);
```
**Example:**
```c
synta_encode_integer_i64(encoder, 42);
```
#### synta_encode_integer
Encode an INTEGER from Integer object.
```c
SyntaErrorCode synta_encode_integer(SyntaEncoder *encoder,
const SyntaInteger *integer);
```
#### synta_encode_null
Encode a NULL value.
```c
SyntaErrorCode synta_encode_null(SyntaEncoder *encoder);
```
#### synta_encode_octet_string
Encode an OCTET STRING.
```c
SyntaErrorCode synta_encode_octet_string(SyntaEncoder *encoder,
const uint8_t *data,
size_t len);
```
#### synta_encode_bit_string
Encode a BIT STRING.
```c
SyntaErrorCode synta_encode_bit_string(SyntaEncoder *encoder,
const uint8_t *data,
size_t len,
uint8_t unused_bits);
```
#### synta_encode_object_identifier
Encode an OBJECT IDENTIFIER.
```c
SyntaErrorCode synta_encode_object_identifier(SyntaEncoder *encoder,
const SyntaObjectIdentifier *oid);
```
### String Type Encoding
#### synta_encode_utf8_string
Encode a UTF8String.
```c
SyntaErrorCode synta_encode_utf8_string(SyntaEncoder *encoder,
const char *str);
```
#### synta_encode_printable_string
Encode a PrintableString.
```c
SyntaErrorCode synta_encode_printable_string(SyntaEncoder *encoder,
const char *str);
```
#### synta_encode_ia5_string
Encode an IA5String.
```c
SyntaErrorCode synta_encode_ia5_string(SyntaEncoder *encoder,
const char *str);
```
### Constructed Type Encoding
#### synta_encoder_start_sequence
Start encoding a SEQUENCE.
```c
SyntaErrorCode synta_encoder_start_sequence(SyntaEncoder *encoder,
SyntaEncoder **out);
```
**Example:**
```c
SyntaEncoder *seq_encoder = NULL;
synta_encoder_start_sequence(encoder, &seq_encoder);
synta_encode_integer_i64(seq_encoder, 42);
synta_encode_boolean(seq_encoder, true);
synta_encoder_end_constructed(seq_encoder);
```
**Note:** The returned encoder pointer is the same as the input encoder.
#### synta_encoder_start_set
Start encoding a SET.
```c
SyntaErrorCode synta_encoder_start_set(SyntaEncoder *encoder,
SyntaEncoder **out);
```
#### synta_encoder_start_constructed
Start encoding a constructed type with explicit tag.
```c
SyntaErrorCode synta_encoder_start_constructed(SyntaEncoder *encoder,
SyntaTag tag,
SyntaEncoder **out);
```
#### synta_encoder_end_constructed
End the current constructed type.
```c
SyntaErrorCode synta_encoder_end_constructed(SyntaEncoder *encoder);
```
**Important:** Must be called for each `start_*` call to properly encode lengths.
## Helper Types
### Integer Helpers
#### synta_integer_new_i64
Create an Integer from int64_t.
```c
SyntaInteger *synta_integer_new_i64(int64_t value);
```
#### synta_integer_new_u64
Create an Integer from uint64_t.
```c
SyntaInteger *synta_integer_new_u64(uint64_t value);
```
#### synta_integer_new_bytes
Create an Integer from bytes.
```c
SyntaInteger *synta_integer_new_bytes(const uint8_t *data,
size_t len,
bool is_negative);
```
#### synta_integer_to_i64
Convert Integer to int64_t.
```c
SyntaErrorCode synta_integer_to_i64(const SyntaInteger *integer,
int64_t *out);
```
Returns `SyntaErrorCode_IntegerOverflow` if value doesn't fit.
#### synta_integer_to_u64
Convert Integer to uint64_t.
```c
SyntaErrorCode synta_integer_to_u64(const SyntaInteger *integer,
uint64_t *out);
```
#### synta_integer_to_bytes
Get Integer as bytes.
```c
SyntaErrorCode synta_integer_to_bytes(const SyntaInteger *integer,
SyntaByteArray *out);
```
#### synta_integer_is_negative
Check if Integer is negative.
```c
bool synta_integer_is_negative(const SyntaInteger *integer);
```
#### synta_integer_free
Free an Integer.
```c
void synta_integer_free(SyntaInteger *integer);
```
### OctetString Helpers
#### synta_octet_string_new
Create an OctetString.
```c
SyntaOctetString *synta_octet_string_new(const uint8_t *data, size_t len);
```
#### synta_octet_string_data
Get OctetString data pointer.
```c
const uint8_t *synta_octet_string_data(const SyntaOctetString *octet_string);
```
#### synta_octet_string_len
Get OctetString length.
```c
size_t synta_octet_string_len(const SyntaOctetString *octet_string);
```
#### synta_octet_string_free
Free an OctetString.
```c
void synta_octet_string_free(SyntaOctetString *octet_string);
```
### ObjectIdentifier Helpers
#### synta_oid_new
Create an OID from components.
```c
SyntaObjectIdentifier *synta_oid_new(const uint32_t *components, size_t len);
```
#### synta_oid_from_string
Create an OID from string (e.g., "1.2.840.113549.1.1.1").
```c
SyntaObjectIdentifier *synta_oid_from_string(const char *str);
```
#### synta_oid_to_string
Convert OID to string.
```c
size_t synta_oid_to_string(const SyntaObjectIdentifier *oid,
char *buffer,
size_t buffer_len);
```
**Returns:** Number of characters written (excluding null terminator), or 0 if buffer too small.
#### synta_oid_components
Get OID components array.
```c
void synta_oid_components(const SyntaObjectIdentifier *oid,
const uint32_t **components,
size_t *len);
```
#### synta_oid_equals
Compare two OIDs for equality.
```c
bool synta_oid_equals(const SyntaObjectIdentifier *a,
const SyntaObjectIdentifier *b);
```
#### synta_oid_free
Free an OID.
```c
void synta_oid_free(SyntaObjectIdentifier *oid);
```
### ByteArray Helpers
#### synta_byte_array_free
Free a byte array (if owned).
```c
void synta_byte_array_free(SyntaByteArray *array);
```
**Note:** Only frees if `array->owned` is non-zero (1 = owned, 0 = borrowed).
#### synta_byte_array_clone
Clone a byte array.
```c
SyntaByteArray synta_byte_array_clone(const SyntaByteArray *array);
```
## X.509 PKI APIs
### CRL API
Parse and inspect X.509 Certificate Revocation Lists (RFC 5280 §5).
All getter functions return a borrowed `SyntaByteArray` (`owned == 0`) that
points into the parsed CRL object. The slice is valid while the `SyntaCrl *`
handle is alive. Do not call `synta_byte_array_free()` on borrowed arrays.
#### synta_crl_parse_der
Parse an X.509 CRL from DER bytes. Returns NULL on error.
```c
SyntaCrl *synta_crl_parse_der(const uint8_t *data, uintptr_t len);
```
#### synta_crl_parse_pem
Parse an X.509 CRL from PEM bytes (first block only). Returns NULL on error.
```c
SyntaCrl *synta_crl_parse_pem(const uint8_t *data, uintptr_t len);
```
#### synta_crl_free
Free a CRL handle. Must be called exactly once per handle. Safe to call with NULL.
```c
void synta_crl_free(SyntaCrl *crl);
```
#### synta_crl_get_issuer_der
Return the CRL issuer Name as raw DER bytes (SEQUENCE tag).
```c
SyntaErrorCode synta_crl_get_issuer_der(const SyntaCrl *crl, SyntaByteArray *out);
```
#### synta_crl_get_signature_algorithm_der
Return the outer `signatureAlgorithm` AlgorithmIdentifier as raw DER bytes.
```c
SyntaErrorCode synta_crl_get_signature_algorithm_der(const SyntaCrl *crl,
SyntaByteArray *out);
```
#### synta_crl_get_signature_value_der
Return the `signatureValue` BIT STRING (with tag) as raw DER bytes.
```c
SyntaErrorCode synta_crl_get_signature_value_der(const SyntaCrl *crl, SyntaByteArray *out);
```
#### synta_crl_get_this_update_der
Return the `thisUpdate` Time as raw DER bytes (UTCTime or GeneralizedTime tag).
```c
SyntaErrorCode synta_crl_get_this_update_der(const SyntaCrl *crl, SyntaByteArray *out);
```
#### synta_crl_get_next_update_der
Return the `nextUpdate` Time as raw DER bytes, or a zero-length array (`out->len == 0`)
if `nextUpdate` is absent.
```c
SyntaErrorCode synta_crl_get_next_update_der(const SyntaCrl *crl, SyntaByteArray *out);
```
#### synta_crl_get_revoked_count
Return the number of entries in `revokedCertificates` (0 when absent or empty).
```c
SyntaErrorCode synta_crl_get_revoked_count(const SyntaCrl *crl, uintptr_t *out);
```
---
### CSR API
Parse and inspect PKCS#10 Certificate Signing Requests (RFC 2986).
#### synta_csr_parse_der
Parse a CSR from DER bytes. Returns NULL on error.
```c
SyntaCsr *synta_csr_parse_der(const uint8_t *data, uintptr_t len);
```
#### synta_csr_parse_pem
Parse a CSR from PEM bytes (first block only). Returns NULL on error.
```c
SyntaCsr *synta_csr_parse_pem(const uint8_t *data, uintptr_t len);
```
#### synta_csr_free
Free a CSR handle.
```c
void synta_csr_free(SyntaCsr *csr);
```
#### synta_csr_get_version
Return the CSR version field (PKCS#10 defines only version 0).
```c
SyntaErrorCode synta_csr_get_version(const SyntaCsr *csr, int64_t *out);
```
#### synta_csr_get_subject_der
Return the subject Name as raw DER bytes.
```c
SyntaErrorCode synta_csr_get_subject_der(const SyntaCsr *csr, SyntaByteArray *out);
```
#### synta_csr_get_signature_algorithm_der
Return the signature AlgorithmIdentifier as raw DER bytes.
```c
SyntaErrorCode synta_csr_get_signature_algorithm_der(const SyntaCsr *csr,
SyntaByteArray *out);
```
#### synta_csr_get_signature_der
Return the signature BIT STRING (with tag) as raw DER bytes.
```c
SyntaErrorCode synta_csr_get_signature_der(const SyntaCsr *csr, SyntaByteArray *out);
```
#### synta_csr_get_public_key_der
Return the SubjectPublicKeyInfo as raw DER bytes.
```c
SyntaErrorCode synta_csr_get_public_key_der(const SyntaCsr *csr, SyntaByteArray *out);
```
---
### OCSP API
Parse and inspect OCSP responses (RFC 6960).
#### synta_ocsp_parse_der
Parse an OCSP response from DER bytes. Returns NULL on error.
```c
SyntaOcsp *synta_ocsp_parse_der(const uint8_t *data, uintptr_t len);
```
#### synta_ocsp_free
Free an OCSP response handle.
```c
void synta_ocsp_free(SyntaOcsp *ocsp);
```
#### synta_ocsp_get_status_code
Return the numeric `OCSPResponseStatus` value:
`0` = successful, `1` = malformedRequest, `2` = internalError,
`3` = tryLater, `5` = sigRequired, `6` = unauthorized.
```c
SyntaErrorCode synta_ocsp_get_status_code(const SyntaOcsp *ocsp, int32_t *out);
```
#### synta_ocsp_get_status
Return the status as a NUL-terminated string (e.g. `"successful"`) using the
size-query pattern: call with `buffer == NULL` to get the required length (including
NUL), then call again with an allocated buffer. Returns 0 when `ocsp` is NULL.
```c
uintptr_t synta_ocsp_get_status(const SyntaOcsp *ocsp, char *buffer, uintptr_t buffer_len);
```
#### synta_ocsp_get_response_type_oid
Return the `responseType` OID string using the size-query pattern.
Returns 0 when status is not `successful` or `ocsp` is NULL.
```c
uintptr_t synta_ocsp_get_response_type_oid(const SyntaOcsp *ocsp, char *buffer, uintptr_t buffer_len);
```
#### synta_ocsp_get_response_bytes_der
Return the OCTET STRING content of `responseBytes`. `out->len == 0` when absent.
```c
SyntaErrorCode synta_ocsp_get_response_bytes_der(const SyntaOcsp *ocsp, SyntaByteArray *out);
```
---
### PEM API
Dependency-free PEM encode/decode following RFC 7468.
#### synta_pem_to_der
Decode all PEM blocks in `data`. Returns an opaque `SyntaDerList *`; NULL on error.
Free with `synta_der_list_free()`.
```c
SyntaDerList *synta_pem_to_der(const uint8_t *data, uintptr_t len);
```
#### synta_der_list_free
Free a DER list. Safe to call with NULL.
```c
void synta_der_list_free(SyntaDerList *list);
```
#### synta_der_list_count
Return the number of DER entries in the list.
```c
uintptr_t synta_der_list_count(const SyntaDerList *list);
```
#### synta_der_list_get_der
Return the `index`-th DER entry as a borrowed `SyntaByteArray` (`owned == 0`).
Valid while the `SyntaDerList *` is alive.
```c
SyntaErrorCode synta_der_list_get_der(const SyntaDerList *list, uintptr_t index,
SyntaByteArray *out);
```
#### synta_der_to_pem
Encode `der` bytes as a PEM block with `label` (NUL-terminated, e.g. `"CERTIFICATE"`).
Returns an **owned** `SyntaByteArray` (`owned != 0`). Caller must call
`synta_byte_array_free()` when done.
```c
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 the encoding of `data` (PEM, PKCS#7, PKCS#12, or raw DER) and
return every X.509 certificate as a DER blob. This is the recommended
one-stop function when you do not know the input format in advance.
`password` applies to PKCS#12 archives; pass NULL or a zero-length slice for
password-less archives. Encrypted PKCS#12 bags are silently skipped (the C
FFI layer does not bundle an OpenSSL backend); unencrypted certificates in the
same archive are still returned. Returns NULL on hard structural failure.
```c
SyntaDerList *synta_read_pki_file(const uint8_t *data, uintptr_t len,
const uint8_t *password,
uintptr_t password_len);
```
Example:
```c
uint8_t *buf; size_t n; /* ... read file ... */
SyntaDerList *list = synta_read_pki_file(buf, n, NULL, 0);
if (!list) { fprintf(stderr, "%s\n", synta_get_last_error_message()); }
size_t count = synta_der_list_count(list);
for (size_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
Extract DER certificates from a PKCS#7 `SignedData` blob (DER or BER input).
Returns an owned `SyntaDerList *`; NULL on error.
```c
SyntaDerList *synta_pkcs7_certs_from_der(const uint8_t *data, uintptr_t len);
```
#### synta_pkcs7_certs_from_pem
Same as `synta_pkcs7_certs_from_der` but first decodes the first PEM block.
```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 have been built with
the `openssl` feature enabled; without it, encrypted bags return an error.
```c
SyntaDerList *synta_pkcs12_certs_from_der(const uint8_t *data, uintptr_t len,
const uint8_t *password,
uintptr_t password_len);
```
---
## CMS API
Parse and inspect Cryptographic Message Syntax (CMS, RFC 5652) structures:
`SignedData`, `EnvelopedData`, `EncryptedData`, and `DigestedData`.
The recommended entry point is `synta_cms_content_info_parse_der`, which parses the
outer `ContentInfo` SEQUENCE and gives access to the inner content type through
borrowed pointers. Alternatively, `synta_cms_encrypted_data_parse` can parse a
bare `EncryptedData` SEQUENCE directly.
**Ownership model:** Pointers returned by `synta_cms_content_info_get0_*` functions
are **borrowed** from the `SyntaCmsContentInfo` handle. Do not free them separately.
Free only the `SyntaCmsContentInfo` itself with `synta_cms_content_info_free`.
### ContentInfo API
#### synta_cms_content_info_parse_der
Parse a DER-encoded `ContentInfo` SEQUENCE (RFC 5652 §3). Returns NULL on error.
```c
SyntaCmsContentInfo *synta_cms_content_info_parse_der(const uint8_t *data,
uintptr_t len);
```
**Memory:** Must be freed with `synta_cms_content_info_free()`.
**Example:**
```c
SyntaCmsContentInfo *ci = synta_cms_content_info_parse_der(buf, len);
if (!ci) {
fprintf(stderr, "%s\n", synta_get_last_error_message());
return 1;
}
// Access inner data via get0_* functions ...
synta_cms_content_info_free(ci);
```
#### synta_cms_content_info_free
Free a `SyntaCmsContentInfo` handle. Safe to call with NULL.
```c
void synta_cms_content_info_free(SyntaCmsContentInfo *ci);
```
#### synta_cms_content_info_get_content_type
Return the `contentType` OID string using the size-query pattern: call with
`buffer == NULL` to get the required length (including NUL), then call again
with an allocated buffer. Returns 0 when `ci` is NULL.
```c
uintptr_t synta_cms_content_info_get_content_type(const SyntaCmsContentInfo *ci,
char *buffer,
uintptr_t buffer_len);
```
Known content type OIDs:
| `1.2.840.113549.1.7.1` | `id-data` |
| `1.2.840.113549.1.7.2` | `id-signedData` |
| `1.2.840.113549.1.7.3` | `id-envelopedData` |
| `1.2.840.113549.1.7.5` | `id-digestedData` |
| `1.2.840.113549.1.7.6` | `id-encryptedData` |
#### synta_cms_content_info_get0_signed_data
Return a borrowed pointer to the inner `SignedData` when the content type is
`id-signedData`; returns NULL for any other content type. The pointer is valid
until `synta_cms_content_info_free` is called.
```c
const SyntaCmsSignedData *synta_cms_content_info_get0_signed_data(
const SyntaCmsContentInfo *ci);
```
#### synta_cms_content_info_get0_enveloped_data
Return a borrowed pointer to the inner `EnvelopedData` when the content type is
`id-envelopedData`; NULL otherwise.
```c
const SyntaCmsEnvelopedData *synta_cms_content_info_get0_enveloped_data(
const SyntaCmsContentInfo *ci);
```
#### synta_cms_content_info_get0_encrypted_data
Return a borrowed pointer to the inner `EncryptedData` when the content type is
`id-encryptedData`; NULL otherwise.
```c
const SyntaCmsEncryptedData *synta_cms_content_info_get0_encrypted_data(
const SyntaCmsContentInfo *ci);
```
#### synta_cms_content_info_get0_digested_data
Return a borrowed pointer to the inner `DigestedData` when the content type is
`id-digestedData`; NULL otherwise.
```c
const SyntaCmsDigestedData *synta_cms_content_info_get0_digested_data(
const SyntaCmsContentInfo *ci);
```
---
### SignedData API
Inspect a `SignedData` structure (RFC 5652 §5). Obtain a `SyntaCmsSignedData *`
via `synta_cms_content_info_get0_signed_data`; it is a borrowed pointer owned by
the `SyntaCmsContentInfo` and must not be freed separately.
```c
// CMS version field
SyntaErrorCode synta_cms_signed_data_get_version(
const SyntaCmsSignedData *sd, int32_t *out);
// encapContentInfo contentType OID (size-query pattern)
uintptr_t synta_cms_signed_data_get_encap_content_type(
const SyntaCmsSignedData *sd, char *buffer, uintptr_t buffer_len);
// encapContentInfo eContent raw bytes (borrowed SyntaByteArray; out->len==0 if absent)
SyntaErrorCode synta_cms_signed_data_get_encap_content(
const SyntaCmsSignedData *sd, SyntaByteArray *out);
// All embedded certificates as DER (borrowed SyntaByteArray; out->len==0 if absent)
SyntaErrorCode synta_cms_signed_data_get_certificates_der(
const SyntaCmsSignedData *sd, SyntaByteArray *out);
// CRLs DER (borrowed SyntaByteArray; out->len==0 if absent)
SyntaErrorCode synta_cms_signed_data_get_crls_der(
const SyntaCmsSignedData *sd, SyntaByteArray *out);
// Number of SignerInfo entries
SyntaErrorCode synta_cms_signed_data_get_signer_info_count(
const SyntaCmsSignedData *sd, uintptr_t *out);
// DER bytes for the index-th SignerInfo (borrowed; pass to synta_cms_signer_info_parse_der)
SyntaErrorCode synta_cms_signed_data_get_signer_info_der(
const SyntaCmsSignedData *sd, uintptr_t index, SyntaByteArray *out);
```
---
### SignerInfo API
Parse an individual `SignerInfo` structure (RFC 5652 §5.3) from its DER bytes.
Obtain the DER bytes from `synta_cms_signed_data_get_signer_info_der`.
#### synta_cms_signer_info_parse_der
```c
SyntaCmsSignerInfo *synta_cms_signer_info_parse_der(const uint8_t *data, uintptr_t len);
```
**Memory:** Must be freed with `synta_cms_signer_info_free()`.
#### synta_cms_signer_info_free
```c
void synta_cms_signer_info_free(SyntaCmsSignerInfo *si);
```
**Getters** (all return borrowed `SyntaByteArray` unless noted):
```c
SyntaErrorCode synta_cms_signer_info_get_version(
const SyntaCmsSignerInfo *si, int32_t *out);
// SID: IssuerAndSerialNumber or SubjectKeyIdentifier DER
SyntaErrorCode synta_cms_signer_info_get_sid_der(
const SyntaCmsSignerInfo *si, SyntaByteArray *out);
// digestAlgorithm AlgorithmIdentifier DER
SyntaErrorCode synta_cms_signer_info_get_digest_algorithm_der(
const SyntaCmsSignerInfo *si, SyntaByteArray *out);
// digestAlgorithm OID string (size-query pattern)
uintptr_t synta_cms_signer_info_get_digest_algorithm_oid(
const SyntaCmsSignerInfo *si, char *buffer, uintptr_t buffer_len);
// signedAttrs DER (out->len==0 if absent)
SyntaErrorCode synta_cms_signer_info_get_signed_attrs_der(
const SyntaCmsSignerInfo *si, SyntaByteArray *out);
// signatureAlgorithm AlgorithmIdentifier DER
SyntaErrorCode synta_cms_signer_info_get_signature_algorithm_der(
const SyntaCmsSignerInfo *si, SyntaByteArray *out);
// signatureAlgorithm OID string (size-query pattern)
uintptr_t synta_cms_signer_info_get_signature_algorithm_oid(
const SyntaCmsSignerInfo *si, char *buffer, uintptr_t buffer_len);
// signature bytes
SyntaErrorCode synta_cms_signer_info_get_signature(
const SyntaCmsSignerInfo *si, SyntaByteArray *out);
// unsignedAttrs DER (out->len==0 if absent)
SyntaErrorCode synta_cms_signer_info_get_unsigned_attrs_der(
const SyntaCmsSignerInfo *si, SyntaByteArray *out);
```
---
### EnvelopedData API
Inspect an `EnvelopedData` structure (RFC 5652 §6). Obtain via
`synta_cms_content_info_get0_enveloped_data`; the pointer is borrowed.
```c
SyntaErrorCode synta_cms_enveloped_data_get_version(
const SyntaCmsEnvelopedData *ed, int32_t *out);
// All RecipientInfo entries as a single DER blob
SyntaErrorCode synta_cms_enveloped_data_get_recipient_infos_der(
const SyntaCmsEnvelopedData *ed, SyntaByteArray *out);
// encryptedContentInfo contentType OID (size-query pattern)
uintptr_t synta_cms_enveloped_data_get_content_type(
const SyntaCmsEnvelopedData *ed, char *buffer, uintptr_t buffer_len);
// contentEncryptionAlgorithm AlgorithmIdentifier DER
SyntaErrorCode synta_cms_enveloped_data_get_content_encryption_algorithm_der(
const SyntaCmsEnvelopedData *ed, SyntaByteArray *out);
// contentEncryptionAlgorithm OID string (size-query pattern)
uintptr_t synta_cms_enveloped_data_get_content_encryption_algorithm_oid(
const SyntaCmsEnvelopedData *ed, char *buffer, uintptr_t buffer_len);
// encryptedContent bytes (out->len==0 if absent)
SyntaErrorCode synta_cms_enveloped_data_get_encrypted_content(
const SyntaCmsEnvelopedData *ed, SyntaByteArray *out);
```
---
### EncryptedData API
Inspect and operate on an `EncryptedData` structure (RFC 5652 §8). Obtain via
`synta_cms_content_info_get0_encrypted_data` (borrowed) or by parsing a bare
`EncryptedData` SEQUENCE with `synta_cms_encrypted_data_parse`.
#### synta_cms_encrypted_data_parse
Parse a bare `EncryptedData` SEQUENCE directly (without a `ContentInfo` wrapper).
```c
SyntaErrorCode synta_cms_encrypted_data_parse(const uint8_t *data, uintptr_t len,
SyntaCmsEncryptedData **out);
```
**Memory:** Returned handle must be freed with `synta_cms_encrypted_data_free()`.
#### synta_cms_encrypted_data_free
```c
void synta_cms_encrypted_data_free(SyntaCmsEncryptedData *ed);
```
**Getters** (all return borrowed `SyntaByteArray` unless noted):
```c
SyntaErrorCode synta_cms_encrypted_data_get_version(
const SyntaCmsEncryptedData *ed, int32_t *out);
// encryptedContentInfo contentType OID (size-query pattern)
uintptr_t synta_cms_encrypted_data_get_content_type(
const SyntaCmsEncryptedData *ed, char *buffer, uintptr_t buffer_len);
// contentEncryptionAlgorithm AlgorithmIdentifier DER
SyntaErrorCode synta_cms_encrypted_data_get_content_encryption_algorithm_der(
const SyntaCmsEncryptedData *ed, SyntaByteArray *out);
// contentEncryptionAlgorithm OID string (size-query pattern)
uintptr_t synta_cms_encrypted_data_get_content_encryption_algorithm_oid(
const SyntaCmsEncryptedData *ed, char *buffer, uintptr_t buffer_len);
// encryptedContent bytes (out->len==0 if absent)
SyntaErrorCode synta_cms_encrypted_data_get_encrypted_content(
const SyntaCmsEncryptedData *ed, SyntaByteArray *out);
```
#### synta_cms_encrypted_data_decrypt
Decrypt the `EncryptedData` content under a raw symmetric key. Requires the
library to be built with the `openssl` Cargo feature.
```c
SyntaErrorCode synta_cms_encrypted_data_decrypt(const SyntaCmsEncryptedData *ed,
const uint8_t *key, uintptr_t key_len,
SyntaByteArray *out);
```
**Returns:** Plaintext as an owned `SyntaByteArray`. Caller must call
`synta_byte_array_free()` when done.
#### synta_cms_encrypted_data_create
Encrypt `plaintext` under `key` and produce a DER-encoded `EncryptedData` SEQUENCE.
A fresh random IV is generated for each call. Requires the `openssl` feature.
```c
SyntaErrorCode synta_cms_encrypted_data_create(
const uint8_t *plaintext, uintptr_t plaintext_len,
const uint8_t *key, uintptr_t key_len,
const uint8_t *content_type_oid_der, uintptr_t content_type_oid_der_len,
const uint8_t *enc_alg_oid_der, uintptr_t enc_alg_oid_der_len,
SyntaByteArray *der_out);
```
- `content_type_oid_der` — DER-encoded OID TLV for the content type (`id-data` if NULL).
- `enc_alg_oid_der` — DER-encoded OID TLV for the content-encryption algorithm (e.g. AES-128-CBC).
**Returns:** DER as an owned `SyntaByteArray`. Caller must call `synta_byte_array_free()`.
**Example:**
```c
// AES-128-CBC OID: 2.16.840.1.101.3.4.1.2
static const uint8_t AES128_CBC_OID[] = {
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02
};
uint8_t key[16] = { /* 128-bit key */ };
SyntaByteArray der = {0};
SyntaErrorCode rc = synta_cms_encrypted_data_create(
plaintext, plaintext_len, key, sizeof(key),
NULL, 0, // id-data content type
AES128_CBC_OID, sizeof(AES128_CBC_OID),
&der);
if (rc == SyntaErrorCode_Success) {
/* use der.data / der.len */
synta_byte_array_free(&der);
}
```
---
### DigestedData API
Inspect a `DigestedData` structure (RFC 5652 §7). Obtain via
`synta_cms_content_info_get0_digested_data`; the pointer is borrowed.
```c
SyntaErrorCode synta_cms_digested_data_get_version(
const SyntaCmsDigestedData *dd, int32_t *out);
// digestAlgorithm AlgorithmIdentifier DER
SyntaErrorCode synta_cms_digested_data_get_digest_algorithm_der(
const SyntaCmsDigestedData *dd, SyntaByteArray *out);
// digestAlgorithm OID string (size-query pattern)
uintptr_t synta_cms_digested_data_get_digest_algorithm_oid(
const SyntaCmsDigestedData *dd, char *buffer, uintptr_t buffer_len);
// encapContentInfo contentType OID (size-query pattern)
uintptr_t synta_cms_digested_data_get_encap_content_type(
const SyntaCmsDigestedData *dd, char *buffer, uintptr_t buffer_len);
// encapContentInfo eContent raw bytes (out->len==0 if absent)
SyntaErrorCode synta_cms_digested_data_get_encap_content(
const SyntaCmsDigestedData *dd, SyntaByteArray *out);
// digest OCTET STRING bytes
SyntaErrorCode synta_cms_digested_data_get_digest(
const SyntaCmsDigestedData *dd, SyntaByteArray *out);
```
---
## Thread Safety
- **Encoder/Decoder:** Not thread-safe. Each thread must use its own encoder/decoder instances.
- **Error Messages:** Thread-local. `synta_get_last_error_message()` and `synta_clear_last_error()` are thread-safe.
- **Helper Functions:** Thread-safe for read-only operations. Mutations require external synchronization.
## See Also
- [Memory Management Guide](C_MEMORY.md)
- [Migration from OpenSSL](MIGRATION_OPENSSL.md)
- [Migration from libtasn1](MIGRATION_LIBTASN1.md)
- [C Examples](../synta-ffi/examples/c/)
- [C Integration Tests](../tests/c/)