Attestation Functions

#include <keychain/keychain_headers.h>

Overview

Attestation functions work with digital signature objects that provide cryptographic proof of data authenticity and integrity. An attestation is an encapsulation of a digital signature and additional metadata that represents the main mechanism by which verifiable data, credentials, and transactions are verified.

The signature of an attestation authenticates: - The original data object’s serialized data - The serialization of all previous attestations in order - The metadata of the current attestation

Object Lifecycle Functions

kc_attestation_construct_from_serialized_string()

int kc_attestation_construct_from_serialized_string(
    kc_attestation_t** out_attestation_ptr,
    const char* serialized_string,
    const unsigned int serialized_string_size,
    const tkc_serialization_format serialization_format
)

Deserializes an attestation from a string representation.

Parameters:

  • out_attestation_ptr - Pointer to attestation pointer (output, caller must free)

  • serialized_string - String serialization of the attestation

  • serialized_string_size - Number of bytes in the serialized string

  • serialization_format - Expected serialization format (JSON, XML, or PROTOBUF)

Returns: Error code (0 = success)

Example:

kc_attestation_t* attestation = NULL;
const char* serialized = "{\"signature\":\"...\",\"timestamp\":1234567890}";
int result = kc_attestation_construct_from_serialized_string(&attestation,
    serialized, strlen(serialized), TKC_SERIALIZATION_FORMAT_JSON);
if (result == 0) {
    // Use attestation...
    kc_attestation_destruct(&attestation);
}

kc_attestation_construct_from_copy()

int kc_attestation_construct_from_copy(
    kc_attestation_t** out_attestation_ptr,
    const kc_attestation_t* rhs_attestation_ptr
)

Creates a deep copy of an attestation object.

Parameters:

  • out_attestation_ptr - Pointer to new attestation pointer (output, caller must free)

  • rhs_attestation_ptr - Attestation object to copy

Returns: Error code (0 = success)

Example:

kc_attestation_t* original_attestation = NULL;
kc_attestation_t* copied_attestation = NULL;

// ... create original_attestation ...

int result = kc_attestation_construct_from_copy(&copied_attestation, original_attestation);
if (result == 0) {
    // Use copied attestation...
    kc_attestation_destruct(&copied_attestation);
}

kc_attestation_destruct()

int kc_attestation_destruct(kc_attestation_t** attestation_ptr)

Destructs an attestation object and frees its resources.

Parameters:

  • attestation_ptr - Pointer to attestation pointer (set to NULL on success)

Returns: Error code (0 = success)

Signature Access Functions

kc_attestation_signature()

int kc_attestation_signature(
    const kc_attestation_t* attestation_ptr,
    char** out_signature_hex,
    unsigned int* out_size
)

Gets the signature from the attestation in hexadecimal format.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_signature_hex - Pointer to signature string pointer (output, caller must free)

  • out_size - Pointer to signature string size (output)

Returns: Error code (0 = success)

Example:

char* signature = NULL;
unsigned int sig_size = 0;
int result = kc_attestation_signature(attestation, &signature, &sig_size);
if (result == 0) {
    printf("Signature: %.*s\n", sig_size, signature);
    kc_common_delete_buffer(&signature);
}

kc_attestation_prev_signature()

int kc_attestation_prev_signature(
    const kc_attestation_t* attestation_ptr,
    char** out_prev_signature_hex,
    unsigned int* out_size
)

Gets the previous signature from the attestation chain in hexadecimal format.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_prev_signature_hex - Pointer to previous signature string pointer (output, caller must free)

  • out_size - Pointer to signature string size (output)

Returns: Error code (0 = success)

Example:

char* prev_signature = NULL;
unsigned int prev_size = 0;
int result = kc_attestation_prev_signature(attestation, &prev_signature, &prev_size);
if (result == 0) {
    printf("Previous signature: %.*s\n", prev_size, prev_signature);
    kc_common_delete_buffer(&prev_signature);
}

kc_attestation_public_key()

int kc_attestation_public_key(
    const kc_attestation_t* attestation_ptr,
    char** out_public_key_hex,
    unsigned int* out_size
)

Gets the public key used to create the signature.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_public_key_hex - Pointer to public key string pointer (output, caller must free)

  • out_size - Pointer to public key string size (output)

Returns: Error code (0 = success)

Example:

char* public_key = NULL;
unsigned int key_size = 0;
int result = kc_attestation_public_key(attestation, &public_key, &key_size);
if (result == 0) {
    printf("Signer public key: %.*s\n", key_size, public_key);
    kc_common_delete_buffer(&public_key);
}

Metadata Access Functions

kc_attestation_index()

int kc_attestation_index(
    const kc_attestation_t* attestation_ptr,
    unsigned int* out_index
)

Gets the sequence number (index) of this attestation in the chain.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_index - Pointer to index number (output)

Returns: Error code (0 = success)

Example:

unsigned int index = 0;
int result = kc_attestation_index(attestation, &index);
if (result == 0) {
    printf("Attestation index: %u\n", index);
}

kc_attestation_timestamp()

int kc_attestation_timestamp(
    const kc_attestation_t* attestation_ptr,
    uint64_t* out_timestamp
)

Gets the timestamp when the attestation was created.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_timestamp - Pointer to timestamp in milliseconds since epoch (output)

Returns: Error code (0 = success)

Example:

uint64_t timestamp = 0;
int result = kc_attestation_timestamp(attestation, &timestamp);
if (result == 0) {
    time_t creation_time = timestamp / 1000;
    printf("Attestation created: %s", ctime(&creation_time));
}

kc_attestation_algorithm()

int kc_attestation_algorithm(
    const kc_attestation_t* attestation_ptr,
    tkc_signature_scheme* out_algorithm
)

Gets the cryptographic algorithm used to produce the signature.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_algorithm - Pointer to signature scheme (output)

Returns: Error code (0 = success)

Example:

tkc_signature_scheme algorithm;
int result = kc_attestation_algorithm(attestation, &algorithm);
if (result == 0) {
    printf("Signature algorithm: %d\n", algorithm);
}

kc_attestation_version()

int kc_attestation_version(
    const kc_attestation_t* attestation_ptr,
    tkc_version* out_version
)

Gets the data format version of the attestation.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_version - Pointer to version information (output)

Returns: Error code (0 = success)

kc_attestation_data_type()

int kc_attestation_data_type(
    const kc_attestation_t* attestation_ptr,
    tkc_data_type* out_data_type
)

Gets the data type value indicating this is an attestation.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_data_type - Pointer to data type value (output)

Returns: Error code (0 = success)

Status and Configuration Functions

kc_attestation_is_approval()

int kc_attestation_is_approval(
    const kc_attestation_t* attestation_ptr,
    bool* out_is_approval
)

Checks whether the attestation signals approval or rejection.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_is_approval - Pointer to approval status (output, true = approval, false = rejection)

Returns: Error code (0 = success)

Example:

bool is_approval = false;
int result = kc_attestation_is_approval(attestation, &is_approval);
if (result == 0) {
    printf("Attestation type: %s\n", is_approval ? "Approval" : "Rejection");
}

kc_attestation_is_reattachable()

int kc_attestation_is_reattachable(
    const kc_attestation_t* attestation_ptr,
    bool* out_is_reattachable
)

Checks whether the attestation can be reattached to another verifiable object.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_is_reattachable - Pointer to reattachable status (output)

Returns: Error code (0 = success)

Example:

bool is_reattachable = false;
int result = kc_attestation_is_reattachable(attestation, &is_reattachable);
if (result == 0) {
    if (is_reattachable) {
        printf("Attestation can be reattached to other objects\n");
    } else {
        printf("Attestation is bound to its current object\n");
    }
}

Tag and Variable Functions

kc_attestation_tags()

int kc_attestation_tags(
    const kc_attestation_t* attestation_ptr,
    kc_tag_set_t** out_tags
)

Gets the tag set containing application-level metadata covered by the signature.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_tags - Pointer to tag set pointer (output, caller must free)

Returns: Error code (0 = success)

Example:

kc_tag_set_t* tags = NULL;
int result = kc_attestation_tags(attestation, &tags);
if (result == 0) {
    unsigned int tag_count = 0;
    kc_tag_set_size(tags, &tag_count);
    printf("Attestation has %u metadata tags\n", tag_count);
    kc_tag_set_destruct(&tags);
}

kc_attestation_variables()

int kc_attestation_variables(
    const kc_attestation_t* attestation_ptr,
    kc_tag_set_t** out_vars
)

Gets the tag set containing mutable application-level stack variables.

Parameters:

  • attestation_ptr - Attestation object to query

  • out_vars - Pointer to variables tag set pointer (output, caller must free)

Returns: Error code (0 = success)

Example:

kc_tag_set_t* vars = NULL;
int result = kc_attestation_variables(attestation, &vars);
if (result == 0) {
    bool has_context = false;
    kc_tag_set_has_key(vars, "execution_context", &has_context);
    if (has_context) {
        char* context = NULL;
        unsigned int context_size = 0;
        kc_tag_set_get_string(vars, "execution_context", &context, &context_size);
        printf("Execution context: %.*s\n", context_size, context);
        kc_common_delete_buffer(&context);
    }
    kc_tag_set_destruct(&vars);
}

Serialization Functions

kc_attestation_serialize()

int kc_attestation_serialize(
    const kc_attestation_t* attestation_ptr,
    char** out_serialized_string,
    unsigned int* out_size
)

Serializes the attestation to a string in protobuf format.

Parameters:

  • attestation_ptr - Attestation object to serialize

  • out_serialized_string - Pointer to serialized string pointer (output, caller must free)

  • out_size - Pointer to string size (output)

Returns: Error code (0 = success)

Example:

char* serialized = NULL;
unsigned int serialized_size = 0;
int result = kc_attestation_serialize(attestation, &serialized, &serialized_size);
if (result == 0) {
    printf("Serialized attestation (%u bytes): %.*s\n",
           serialized_size, serialized_size, serialized);
    kc_common_delete_buffer(&serialized);
}

Query Functions

kc_attestation_equals()

int kc_attestation_equals(
    const kc_attestation_t* lhs_attestation_ptr,
    bool* out_is_equal,
    const kc_attestation_t* rhs_attestation_ptr
)

Tests equality of two attestation objects.

Parameters:

  • lhs_attestation_ptr - First attestation to compare

  • out_is_equal - Pointer to equality result (output)

  • rhs_attestation_ptr - Second attestation to compare

Returns: Error code (0 = success)

Example: Attestation Chain Analysis

void analyze_attestation_chain(kc_verifiable_data_t* verifiable_data) {
    // Get all attestations from verifiable data
    kc_attestation_t** attestations = NULL;
    unsigned int attestation_count = 0;

    int result = kc_verifiable_data_attestations(verifiable_data,
                                               &attestations, &attestation_count);
    if (result != 0) {
        printf("Failed to get attestations: %d\n", result);
        return;
    }

    printf("Analyzing attestation chain with %u attestations:\n", attestation_count);

    for (unsigned int i = 0; i < attestation_count; i++) {
        kc_attestation_t* attestation = attestations[i];

        // Get attestation index
        unsigned int index = 0;
        kc_attestation_index(attestation, &index);

        // Get timestamp
        uint64_t timestamp = 0;
        kc_attestation_timestamp(attestation, &timestamp);
        time_t creation_time = timestamp / 1000;

        // Get approval status
        bool is_approval = false;
        kc_attestation_is_approval(attestation, &is_approval);

        // Get algorithm
        tkc_signature_scheme algorithm;
        kc_attestation_algorithm(attestation, &algorithm);

        // Get public key
        char* public_key = NULL;
        unsigned int key_size = 0;
        kc_attestation_public_key(attestation, &public_key, &key_size);

        printf("\nAttestation #%u:\n", index);
        printf("  Timestamp: %s", ctime(&creation_time));
        printf("  Type: %s\n", is_approval ? "Approval" : "Rejection");
        printf("  Algorithm: %d\n", algorithm);
        printf("  Signer key: %.20s...\n", public_key ? public_key : "Unknown");

        // Check for metadata
        kc_tag_set_t* tags = NULL;
        result = kc_attestation_tags(attestation, &tags);
        if (result == 0) {
            unsigned int tag_count = 0;
            kc_tag_set_size(tags, &tag_count);
            if (tag_count > 0) {
                printf("  Metadata tags: %u\n", tag_count);

                // List tag keys
                char** keys = NULL;
                unsigned int key_count = 0;
                kc_tag_set_keys(tags, &keys, &key_count);
                if (keys) {
                    printf("  Tag keys: ");
                    for (unsigned int j = 0; j < key_count; j++) {
                        printf("%s%s", keys[j], (j < key_count - 1) ? ", " : "");
                    }
                    printf("\n");
                    kc_common_delete_buffer_array(&keys, key_count);
                }
            }
            kc_tag_set_destruct(&tags);
        }

        // Check for variables
        kc_tag_set_t* vars = NULL;
        result = kc_attestation_variables(attestation, &vars);
        if (result == 0) {
            unsigned int var_count = 0;
            kc_tag_set_size(vars, &var_count);
            if (var_count > 0) {
                printf("  Stack variables: %u\n", var_count);
            }
            kc_tag_set_destruct(&vars);
        }

        if (public_key) kc_common_delete_buffer(&public_key);
    }

    // Cleanup attestation array
    if (attestations) {
        for (unsigned int i = 0; i < attestation_count; i++) {
            kc_attestation_destruct(&attestations[i]);
        }
        kc_common_delete_buffer_array((char**)&attestations, attestation_count);
    }

    printf("\nAttestation chain analysis complete.\n");
}

Example: Creating Custom Attestation Metadata

void demonstrate_attestation_metadata(kc_persona_t* approver,
                                    kc_verifiable_data_t* document) {
    // Create approval attestation with custom metadata
    kc_tag_set_t* approval_tags = NULL;
    kc_tag_set_t* approval_vars = NULL;

    // Create tags for approval metadata
    int result = kc_tag_set_construct(&approval_tags);
    if (result != 0) return;

    kc_tag_set_add_string(approval_tags, "approval_type", "legal_review");
    kc_tag_set_add_string(approval_tags, "reviewer_role", "Legal Counsel");
    kc_tag_set_add_string(approval_tags, "review_category", "Contract Approval");
    kc_tag_set_add_bool(approval_tags, "requires_countersignature", true);

    // Create variables for execution context
    result = kc_tag_set_construct(&approval_vars);
    if (result != 0) {
        kc_tag_set_destruct(&approval_tags);
        return;
    }

    kc_tag_set_add_string(approval_vars, "execution_context", "production");
    kc_tag_set_add_string(approval_vars, "client_version", "1.2.3");
    kc_tag_set_add_int64(approval_vars, "process_id", getpid());

    // Sign document with metadata
    kc_verifiable_data_t* approved_document = NULL;
    result = kc_persona_sign_verifiable_data(approver, &approved_document,
                                           document, true, // is_approval
                                           approval_tags, approval_vars);

    if (result == 0) {
        printf("Document approved with comprehensive metadata\n");

        // Retrieve and display the latest attestation
        kc_attestation_t** attestations = NULL;
        unsigned int attestation_count = 0;

        result = kc_verifiable_data_attestations(approved_document,
                                               &attestations, &attestation_count);
        if (result == 0 && attestation_count > 0) {
            kc_attestation_t* latest = attestations[attestation_count - 1];

            // Verify it's an approval
            bool is_approval = false;
            kc_attestation_is_approval(latest, &is_approval);
            printf("Latest attestation is %s\n",
                   is_approval ? "an approval" : "a rejection");

            // Display metadata
            kc_tag_set_t* tags = NULL;
            kc_attestation_tags(latest, &tags);
            if (tags) {
                char* approval_type = NULL;
                unsigned int type_size = 0;
                kc_tag_set_get_string(tags, "approval_type", &approval_type, &type_size);
                if (approval_type) {
                    printf("Approval type: %.*s\n", type_size, approval_type);
                    kc_common_delete_buffer(&approval_type);
                }
                kc_tag_set_destruct(&tags);
            }

            // Cleanup attestations
            for (unsigned int i = 0; i < attestation_count; i++) {
                kc_attestation_destruct(&attestations[i]);
            }
            kc_common_delete_buffer_array((char**)&attestations, attestation_count);
        }

        kc_verifiable_data_destruct(&approved_document);
    }

    kc_tag_set_destruct(&approval_tags);
    kc_tag_set_destruct(&approval_vars);
}

Memory Management

  • Use kc_attestation_destruct() to free attestation objects

  • Use kc_tag_set_destruct() for tag sets returned by metadata functions

  • Use kc_common_delete_buffer() for string outputs (signatures, public keys, serialized data)

  • Use kc_common_delete_buffer_array() for arrays of attestations

  • Always check return codes before using output parameters

Best Practices

  • Examine attestation chains in chronological order by index

  • Verify signatures using the corresponding public keys

  • Use metadata tags for immutable attestation properties

  • Use variables for mutable execution context information

  • Check approval status for workflow-related attestations

  • Preserve attestation order when processing chains

See Also