Skip to main content

C API Programming Guide

© Pi Soft, 2018-2026 · Tricryption Engine 8.1

The C TEAgent package provides functionality such as encrypting, decrypting and hashing data. The full function reference is in teagent_c.h; this guide covers the overall workflow and points to runnable examples.

General procedure​

  1. Initialize the TE environment with TEEnvInit().
  2. Open a connection to a Tricryption Engine (for example with OpenConnectionWithNativeUser()), obtaining a TE_HANDLE connection handle that is passed to subsequent calls.
  3. Call functions such as TEEncryptStringBatch() / TEDecryptStringBatch(), the matrix functions, or Hash() with the connection handle to do the work.
  4. Close the connection with CloseConnection() and shut down the environment with TEEnvClose().

When an error occurs, call GetLastTEError() to retrieve a detailed description of the last error.

Environment settings​

teagent_c.h is the only header you need to include, and it is the same on all platforms.

  • Windows (Microsoft Visual C++): include teagent_c.h, link against te_agent_c.lib, build with the multithreaded-DLL runtime, and ship te_agent_c.dll alongside your executable.
  • Linux: include teagent_c.h and link against libte_agent_c.so.

FIPS mode​

Call TEEnableFipsMode() once, before any connection is opened, to run every cryptographic operation of the agent through the CMVP-validated OpenSSL FIPS provider 3.1.2 (certificate #4985). The provider module and its configuration are loaded from the ossl-modules directory installed beside the agent library (fips.so and fipsmodule.cnf; fips.dll on Windows) – ship that directory with your application exactly as the SDK package lays it out, unmodified, since the configuration carries an integrity value computed over the module. No environment variable is read.

The call is fail-closed. It returns TE_SUCCESS when FIPS mode is in force, and TE_FIPS_MODE_UNAVAILABLE otherwise – a missing directory, a missing configuration, or a module whose integrity check or self-test fails – with the cause available from GetLastTEError(). After a refusal the agent serves no algorithm outside the module, so do not continue as if the call had succeeded.

In FIPS mode TLS offers the NIST curves P-384 and P-256 only, and the algorithms the module does not provide – ML-KEM, ML-DSA, X25519 and MD5 among them – are unavailable. RSA keys are 2048 bits or more.

if (TEEnableFipsMode() != TE_SUCCESS) {
char err[256]; uint32_t len = sizeof(err);
GetLastTEError(err, &len);
fprintf(stderr, "FIPS mode unavailable: %.*s\n", (int)len, err);
return 1;
}
TEEnvInit();

Creating a connection​

Follow these steps to connect:

  1. Call TEEnvInit() to initialize the TE environment.
  2. Open a connection with the appropriate OpenConnectionWith... function for your authentication method. The returned TE_HANDLE represents the connection and is used by most other functions.
  3. Call CloseConnection() when finished with the connection.
  4. Call TEEnvClose() to shut down the TE environment before exiting.

A connection is opened as either a normal (TE_NORMAL_CONNECTION) or a secure TLS (TE_SSL_CONNECTION) socket. Authentication helpers include OpenConnectionWithNativeUser(), OpenConnectionWithLDAPUser(), OpenConnectionWithToken(), OpenConnectionWithPKCS12File(), OpenConnectionWithPrivateKeyAndCertificateChainFiles(), their anchored forms OpenConnectionWithPKCS12FileAnchored() and OpenConnectionWithPrivateKeyAndCertificateChainFilesAnchored() (which name the certificate the connection trusts the Key Server by), and OpenConnectionWithKerberos() (see Kerberos login).

Examples: c_connect.c, c_connect_cert.c, c_connect_ldap.c, c_connect_token.c.

Kerberos login​

OpenConnectionWithKerberos() opens a TLS connection to the Key Server and logs in with a Kerberos ticket the caller already holds, through the Key Server's GSSAPIAuthentication module (AM10). The Key Server must have the module enabled; the operator steps are in the repository's docs/KERBEROS_AM10.md.

TE_HANDLE OpenConnectionWithKerberos(const char* svrName,
int32_t svrPort,
const char* servicePrincipal,
const char* ccache,
const char* anchorfile);
  • svrName, svrPort — the Key Server's name or address and its TLS port. There is no connection-type argument: the connection is always TLS.
  • servicePrincipal — the Key Server's acceptor principal, the name its keytab holds, e.g. te/ks.example.com@EXAMPLE.COM. A ticket for any other service is refused.
  • ccache — the Kerberos credential cache to initiate from, e.g. FILE:/run/user/1000/krb5cc; NULL or empty for the library's default cache.
  • anchorfile — required: a file holding the certificate the connection trusts the Key Server by (one or more PEM certificates, or one DER certificate — normally the Key Server's CA). The Key Server's chain is verified against it, with no error forgiven, before any Kerberos token is sent; an anchor that is not self-signed pins that certificate. A NULL or empty anchorfile is refused by name: Kerberos: no key server anchor named (anchorfile) -- a Kerberos login names the key server it trusts. A chain that does not reach it is refused as the key server's certificate did not verify: <reason>.

The function returns a non-zero TE_HANDLE on success and zero on failure; call GetLastTEError() for the message, which names the check that refused (the same messages as the C++ context's — Kerberos login).

The exchange carries the connection's RFC 9266 channel binding (tls-exporter) with mutual authentication requested; the caller supplies nothing for it. The caller's Kerberos profile (krb5.conf, or KRB5_CONFIG) must declare client_aware_channel_bindings = true under [libdefaults], or the Key Server refuses the login as unbound. On Windows, te_agent_c.dll imports gssapi64.dll from the product's MIT Kerberos package; ship it, with krb5_64.dll, comerr64.dll and k5sprt64.dll, on the application's PATH.

#include <stdio.h>
#include "teagent_c.h"

void PrintError(const char * msg)
{
char szErr[1024];
uint32_t nLength = 1024;
uint32_t nCode = GetLastTEError(szErr, &nLength);
printf("%s Code = 0x%x, Message = %s\n", msg, nCode, szErr);
}

int main()
{
TE_HANDLE h;
char * szServerName = "ks.example.com"; /* server name */
long lPort = 8888; /* TLS port */
char * szService = "te/ks.example.com@EXAMPLE.COM"; /* Key Server's service principal */
char * szAnchor = "/etc/te/ks-ca.pem"; /* the Key Server's CA */

/* Initialize the TE environment */
TEEnvInit();

/* Open a connection, logging in with the default credential cache */
h = OpenConnectionWithKerberos(
szServerName, /* TE server name */
lPort, /* TE server port */
szService, /* service principal */
NULL, /* credential cache: the default */
szAnchor /* anchor: required */
);

if (h == 0)
{
PrintError("Connection error:");
}
else
{
printf("Connected to %s at %ld with Kerberos\n\n", szServerName, lPort);

/* Close a connection */
CloseConnection(h);
}

/* Uninitialize the TE environment */
TEEnvClose();

return 0;
}

Encrypting, decrypting and hashing​