FIDO_CRED_NEW(3)

πŸ’– FIDO_CRED_NEW πŸ’–

okay bestie, gather round, because this is the FIDO_CRED_NEW(3) page from the Library Functions Manual and it's literally the whole ✨inspect-a-credential✨ starter pack πŸŽ€


🌸 NAME 🌸

The gang's all here β€” say hi to:

  • fido_cred_new, fido_cred_free, fido_cred_payment, fido_cred_pin_minlen, fido_cred_prot
  • fido_cred_fmt, fido_cred_rp_id, fido_cred_rp_name, fido_cred_user_name, fido_cred_display_name
  • fido_cred_authdata_ptr, fido_cred_authdata_raw_ptr, fido_cred_clientdata_hash_ptr, fido_cred_id_ptr, fido_cred_aaguid_ptr
  • fido_cred_hmac_secret_ptr, fido_cred_largeblob_key_ptr, fido_cred_pubkey_ptr, fido_cred_sig_ptr, fido_cred_user_id_ptr
  • fido_cred_x5c_list_count, fido_cred_x5c_list_ptr, fido_cred_x5c_ptr, fido_cred_attstmt_ptr
  • fido_cred_authdata_len, fido_cred_authdata_raw_len, fido_cred_clientdata_hash_len, fido_cred_id_len, fido_cred_aaguid_len
  • fido_cred_hmac_secret_len, fido_cred_largeblob_key_len, fido_cred_pubkey_len, fido_cred_sig_len, fido_cred_user_id_len
  • fido_cred_x5c_list_len, fido_cred_x5c_len, fido_cred_attstmt_len
  • fido_cred_entattest, fido_cred_type, fido_cred_flags, fido_cred_sigcount

…and together they're the FIDO2 credential API. slay πŸ’…


✨ SYNOPSIS ✨

first things first, you gotta pull in the header:

#include <fido.h>

and here's the whole roster of signatures, verbatim, no cap:

fido_cred_t *
fido_cred_new(void);

void
fido_cred_free(fido_cred_t **cred_p);

bool
fido_cred_payment(const fido_cred_t *cred);

size_t
fido_cred_pin_minlen(const fido_cred_t *cred);

int
fido_cred_prot(const fido_cred_t *cred);

const char *
fido_cred_fmt(const fido_cred_t *cred);

const char *
fido_cred_rp_id(const fido_cred_t *cred);

const char *
fido_cred_rp_name(const fido_cred_t *cred);

const char *
fido_cred_user_name(const fido_cred_t *cred);

const char *
fido_cred_display_name(const fido_cred_t *cred);

const unsigned char *
fido_cred_authdata_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_authdata_raw_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_clientdata_hash_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_id_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_aaguid_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_hmac_secret_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_largeblob_key_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_pubkey_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_sig_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_user_id_ptr(const fido_cred_t *cred);

size_t
fido_cred_x5c_list_count(const fido_cred_t *cred);

const unsigned char *
fido_cred_x5c_list_ptr(const fido_cred_t *cred, size_t idx);

const unsigned char *
fido_cred_x5c_ptr(const fido_cred_t *cred);

const unsigned char *
fido_cred_attstmt_ptr(const fido_cred_t *cred);

size_t
fido_cred_authdata_len(const fido_cred_t *cred);

size_t
fido_cred_authdata_raw_len(const fido_cred_t *cred);

size_t
fido_cred_clientdata_hash_len(const fido_cred_t *cred);

size_t
fido_cred_id_len(const fido_cred_t *cred);

size_t
fido_cred_aaguid_len(const fido_cred_t *cred);

size_t
fido_cred_hmac_secret_len(const fido_cred_t *cred);

size_t
fido_cred_largeblob_key_len(const fido_cred_t *cred);

size_t
fido_cred_pubkey_len(const fido_cred_t *cred);

size_t
fido_cred_sig_len(const fido_cred_t *cred);

size_t
fido_cred_user_id_len(const fido_cred_t *cred);

size_t
fido_cred_x5c_list_len(const fido_cred_t *cred, size_t idx);

size_t
fido_cred_x5c_len(const fido_cred_t *cred);

size_t
fido_cred_attstmt_len(const fido_cred_t *cred);

bool
fido_cred_entattest(const fido_cred_t *cred);

int
fido_cred_type(const fido_cred_t *cred);

uint8_t
fido_cred_flags(const fido_cred_t *cred);

uint32_t
fido_cred_sigcount(const fido_cred_t *cred);

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so. FIDO2 credentials in libfido2 are abstracted as the fido_cred_t type, right? and every function on this page is here to allocate, deallocate, or inspect one of those bad boys. that's the whole vibe. 🫢

if you wanna do other stuff with a fido_cred_t, this page is not the one β€” go check out fido_cred_set_authdata(3), fido_cred_exclude(3), fido_cred_verify(3), and fido_dev_make_cred(3) instead. iykyk.

fido_cred_new() hands you a pointer to a freshly allocated, totally empty fido_cred_t. and if memory can't be allocated? it returns NULL. sad but true 😭

fido_cred_free() releases the memory backing *cred_p, and *cred_p had better have been previously allocated by fido_cred_new() or else bestie what are we doing. on return, *cred_p gets set to NULL. and here's the chill part: either cred_p or *cred_p may be NULL, and in that case fido_cred_free() is a NOP. no drama. πŸ’…

fido_cred_payment() returns true if the CTAP 2.2 FIDO_EXT_PAYMENT extension is enabled on cred. and since that extension has no output, this function is only actually useful if cred was retrieved via fido_credman_rk(3). that's the tea πŸ“

fido_cred_pin_minlen() returns the minimum PIN length of cred if the CTAP 2.1 FIDO_EXT_MINPINLEN extension is enabled on it. otherwise? it returns zero. see fido_cred_set_pin_minlen(3) for how to turn that extension on. ✨

fido_cred_prot() returns the protection of cred if the CTAP 2.1 FIDO_EXT_CRED_PROTECT extension is enabled on it. otherwise it returns zero. and if you wanna know which protection policies libfido2 even understands, that's fido_cred_set_prot(3). πŸ’–

fido_cred_fmt() gives you a pointer to a NUL-terminated string holding the attestation statement format identifier of cred β€” or NULL if cred doesn't have a format set. simple as.

fido_cred_rp_id(), fido_cred_rp_name(), fido_cred_user_name(), and fido_cred_display_name() return pointers to NUL-terminated strings holding the relying party ID, relying party name, user name, and user display name attributes of cred β€” or NULL if the respective entry isn't set. ✨

fido_cred_authdata_ptr(), fido_cred_authdata_raw_ptr(), fido_cred_clientdata_hash_ptr(), fido_cred_id_ptr(), fido_cred_aaguid_ptr(), fido_cred_largeblob_key_ptr(), fido_cred_pubkey_ptr(), fido_cred_sig_ptr(), fido_cred_user_id_ptr(), fido_cred_x5c_ptr(), and fido_cred_attstmt_ptr() return pointers to the CBOR-encoded and raw authenticator data, client data hash, ID, authenticator attestation GUID, "largeBlobKey", public key, signature, user ID, x509 leaf certificate, and attestation statement parts of cred β€” or NULL if the respective entry isn't set. iconic lineup honestly πŸ‘‘

fido_cred_hmac_secret_ptr() returns a pointer to the hmac-secret attribute of cred. heads up: the HMAC Secret MC Extension (hmac-secret-mc) is a CTAP 2.2 extension. and note that the resulting hmac-secret varies according to whether user verification was performed by the authenticator. important detail, don't skip it 🧚

fido_cred_authdata_len(), fido_cred_authdata_raw_len(), fido_cred_clientdata_hash_len(), fido_cred_id_len(), fido_cred_aaguid_len(), fido_cred_hmac_secret_len(), fido_cred_largeblob_key_len(), fido_cred_pubkey_len(), fido_cred_sig_len(), fido_cred_user_id_len(), fido_cred_x5c_len(), and fido_cred_attstmt_len() return the length of the given attribute. yes, all of them. matching sets, we love to see it πŸ’•

fido_cred_x5c_list_count() returns the length of the x509 certificate chain in cred, and fido_cred_x5c_list_ptr() and fido_cred_x5c_list_len() return a pointer to, and the length of, the x509 certificate at index idx respectively. now listen closely bestie: the leaf certificate has an idx (index) value of 0, and calling fido_cred_x5c_list_ptr(cred, 0) and fido_cred_x5c_list_len(cred, 0) is equivalent to fido_cred_x5c_ptr(cred) and fido_cred_x5c_len(cred) respectively. and if idx exceeds the return value of fido_cred_x5c_list_count(), then fido_cred_x5c_list_ptr() returns NULL and fido_cred_x5c_list_len() returns 0. got it? good. πŸ’œ

also, the authenticator data, x509 certificate, and signature parts of a credential are typically passed to a FIDO2 server for verification. that's their whole moment to shine ✨

fido_cred_entattest() returns true if an enterprise attestation was returned for cred.

fido_cred_type() returns the COSE algorithm of cred.

fido_cred_flags() returns the authenticator data flags of cred.

fido_cred_sigcount() returns the authenticator data signature counter of cred.


πŸŽ€ RETURN VALUES πŸŽ€

okay so the authenticator data you get from fido_cred_authdata_ptr() is a CBOR-encoded byte string, exactly as it came off the authenticator. want the decoded byte string instead? that's what fido_cred_authdata_raw_ptr() is for. 🫢

and for the lifetime girlies: if not NULL, the pointers returned by fido_cred_fmt(), fido_cred_authdata_ptr(), fido_cred_clientdata_hash_ptr(), fido_cred_id_ptr(), fido_cred_aaguid_ptr(), fido_cred_largeblob_key_ptr(), fido_cred_pubkey_ptr(), fido_cred_sig_ptr(), and fido_cred_x5c_ptr() are guaranteed to exist until any API function that takes cred without the const qualifier is invoked. so like… don't go handing cred to a non-const function and then act surprised, ok? πŸ™ˆ

⚠️ real talk: that guarantee dies the second a non-const function touches cred. read it twice, bestie.

🌈 SEE ALSO 🌈


and that's the page!! this one's from Debian, dated March 26, 2026, and it lives under FIDO_CRED_NEW(3). go forth and inspect those credentials, you absolute main character πŸ‘‘πŸ’–

periodt. πŸ’…βœ¨

πŸ“¦ where this page comes from