Secrets
gln_secret_t is the ABI wrapper for sensitive bytes passed into backend open
and resume calls. The library copies the bytes into a wiping buffer and zeroes
that buffer when the handle is destroyed.
Functions
GLN_API gln_status_t GLN_CALL gln_create_secret(
const uint8_t* in_bytes,
size_t in_len,
gln_secret_t** out_secret);
GLN_API void GLN_CALL gln_destroy_secret(gln_secret_t* in_secret);
gln_create_secret treats the input as opaque bytes. The input does not need to
be NUL-terminated and may contain zero bytes. in_bytes may be NULL only
when in_len is zero. On success, *out_secret receives a caller-owned handle.
gln_destroy_secret wipes the wrapped bytes and frees the handle. It accepts
NULL.
Where Secrets Are Used
Current entry points take secrets in these places:
GLN_API gln_status_t GLN_CALL gln_open_fints_backend(
const gln_fints_config_t* in_config,
gln_state_store_t* in_state_store,
gln_continuation_store_t* in_continuation_store_or_null,
gln_secret_t* in_pin,
gln_backend_t** out_backend,
gln_error_t* out_error);
GLN_API gln_status_t GLN_CALL gln_open_revolut_backend(
const gln_revolut_config_t* in_config,
const gln_secret_t* in_client_assertion_key_pem,
gln_state_store_t* in_state_store,
gln_revolut_token_store_t* in_token_store,
gln_backend_t** out_backend,
gln_error_t* out_error);
GLN_API gln_status_t GLN_CALL gln_resume_continuation(
gln_backend_t* in_backend,
gln_continuation_t* in_continuation,
gln_secret_t* in_interactive_secret_or_null,
const gln_continuation_input_t* in_input,
gln_backend_result_t** out_result);
Use a secret for a FinTS PIN, a Revolut client assertion key PEM, and a TAN or
other interactive secret supplied during resume. EBICS long-lived key material
does not use gln_secret_t; it goes through the EBICS key-store vtable.
Lifetime Guidance
- Construct the secret close to the call site.
- Destroy it immediately after the consuming call returns unless the same operation explicitly needs to retry with the same in-memory value.
- Wipe or release the host-language source buffer too when the runtime permits
it;
gln_destroy_secretonly wipes the library-owned copy. - Do not share a secret handle across threads.
- Use explicit pointer-plus-length parameters for general binary buffers. Store callbacks and key-store callbacks use that shape directly.
PIN Example
const char pin_text[] = "1234";
gln_secret_t* pin = NULL;
gln_status_t s = gln_create_secret(
(const uint8_t*)pin_text,
strlen(pin_text),
&pin);
if (s != GLN_OK) {
return 1;
}
gln_error_t error = {0};
gln_default_error(&error);
gln_backend_t* backend = NULL;
s = gln_open_fints_backend(
&config,
state_store,
NULL,
pin,
&backend,
&error);
gln_destroy_secret(pin);
if (s != GLN_OK) {
fprintf(stderr, "%s\n", error.message ? error.message : "");
gln_release_error(&error);
return 1;
}
The PIN handle only needs to outlive gln_open_fints_backend; the backend keeps
what it needs.
TAN Resume Example
const char tan_text[] = "123456";
gln_secret_t* tan = NULL;
gln_status_t s = gln_create_secret(
(const uint8_t*)tan_text,
strlen(tan_text),
&tan);
if (s != GLN_OK) {
return 1;
}
gln_continuation_input_t input = {0};
gln_default_continuation_input(&input);
gln_backend_result_t* resumed = NULL;
s = gln_resume_continuation(backend, continuation, tan, &input, &resumed);
gln_destroy_secret(tan);
if (s == GLN_OK) {
/* Inspect resumed, then destroy it. */
gln_destroy_backend_result(resumed);
}
When an HHD_UC response accompanies the TAN, set
input.kind = GLN_CONTINUATION_INPUT_KIND_HHDUC_RESPONSE and
input.hhduc_response_or_null to the response string. The TAN itself still
travels through gln_secret_t.
See Also
- Conventions - ownership and threading.
- Continuations - resume input combinations.
- Key store - EBICS key material, which uses callbacks instead.