Skip to content

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_secret only 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