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
- Initialize the TE environment with
TEEnvInit(). - Open a connection to a Tricryption Engine (for example with
OpenConnectionWithNativeUser()), obtaining aTE_HANDLEconnection handle that is passed to subsequent calls. - Call functions such as
TEEncryptStringBatch()/TEDecryptStringBatch(), the matrix functions, orHash()with the connection handle to do the work. - Close the connection with
CloseConnection()and shut down the environment withTEEnvClose().
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 againstte_agent_c.lib, build with the multithreaded-DLL runtime, and shipte_agent_c.dllalongside your executable. - Linux: include
teagent_c.hand link againstlibte_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:
- Call
TEEnvInit()to initialize the TE environment. - Open a connection with the appropriate
OpenConnectionWith...function for your authentication method. The returnedTE_HANDLErepresents the connection and is used by most other functions. - Call
CloseConnection()when finished with the connection. - 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;NULLor 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. ANULLor emptyanchorfileis 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 asthe 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
- C-style strings —
TEEncryptStringBatch()andTEDecryptStringBatch()encrypt and decrypt a batch of c-style strings under one T-tag. Every buffer is described by aTE_CSTRING_BUFFERcarrying its own input length and its own writable capacity; at mostTE_MAX_CSTRING_BATCHstrings per call. If any destination is too small the call returnsTE_INSUFFICIENT_BUFFER_SIZE, writes the required capacity into every descriptor'soutput_len, and leaves every one of your buffers untouched, so a batch never lands half-written. Example:c_encryptcstrings.c. - Data matrix — build a
TE_MATRIX_HANDLEwithTEMatrixCreate(), populate it withTEMatrixSetElement()/TEMatrixSetHiddenLink(), then encrypt or decrypt the whole matrix withTEMatrixEncrypt()/TEMatrixDecrypt(). Release it withTEMatrixRelease(). Example:c_encryptmatrix.c. - Hashing —
Hash()hashes a buffer with an optional salt. Example:c_hash.c. - Keys — create keys with
TECreateKey()and export them withTEExportKey()/TEExportMultiKeys(). Examples:c_createkey.c,c_exportkey.c,c_exportmultikeys.c.