Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/cbor.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,8 @@ cbor_encode_hmac_secret_param(const char *key, const fido_dev_t *dev,
}

cbor_item_t *
cbor_encode_cred_ext(const fido_cred_extin_t *ext)
cbor_encode_cred_ext(const fido_dev_t *dev, const fido_cred_extin_t *ext,
const fido_blob_t *ecdh, const es256_pk_t *pk)
{
cbor_item_t *item = NULL;
size_t size = 0;
Expand All @@ -700,6 +701,8 @@ cbor_encode_cred_ext(const fido_cred_extin_t *ext)
size++;
if (ext->attr.mask & FIDO_EXT_MINPINLEN)
size++;
if (ext->attr.mask & FIDO_EXT_HMAC_SECRET_MC)
size++;

if (size == 0 || (item = cbor_new_definite_map(size)) == NULL)
return (NULL);
Expand Down Expand Up @@ -737,6 +740,13 @@ cbor_encode_cred_ext(const fido_cred_extin_t *ext)
return (NULL);
}
}
if (ext->attr.mask & FIDO_EXT_HMAC_SECRET_MC) {
if (cbor_encode_hmac_secret_param("hmac-secret-mc", dev, item,
ecdh, pk, &ext->hmac_salt) < 0) {
cbor_decref(&item);
return (NULL);
}
}

return (item);
}
Expand Down Expand Up @@ -1211,6 +1221,12 @@ decode_cred_extension(const cbor_item_t *key, const cbor_item_t *val, void *arg)
}
if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE)
ext->attr.mask |= FIDO_EXT_HMAC_SECRET;
} else if (strcmp(type, "hmac-secret-mc") == 0) {
if (fido_blob_decode(val, &ext->hmac_secret_enc) < 0) {
fido_log_debug("%s: fido_blob_decode", __func__);
goto out;
}
ext->attr.mask |= FIDO_EXT_HMAC_SECRET_MC;
} else if (strcmp(type, "credProtect") == 0) {
if (cbor_isa_uint(val) == false ||
cbor_int_get_width(val) != CBOR_INT_8) {
Expand Down
59 changes: 57 additions & 2 deletions src/cred.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred,

/* extensions */
if (cred->ext.attr.mask)
if ((argv[5] = cbor_encode_cred_ext(&cred->ext)) == NULL) {
if ((argv[5] = cbor_encode_cred_ext(dev, &cred->ext, ecdh,
pk)) == NULL) {
fido_log_debug("%s: cbor_encode_cred_ext", __func__);
r = FIDO_ERR_INTERNAL;
goto fail;
Expand Down Expand Up @@ -187,6 +188,14 @@ fido_dev_make_cred_wait(fido_dev_t *dev, fido_cred_t *cred,
return (FIDO_OK);
}

static int
decrypt_hmac_secret(const fido_dev_t *dev, fido_cred_t *cred,
const fido_blob_t *key)
{
return (aes256_cbc_dec(dev, key, &cred->authdata_ext.hmac_secret_enc,
&cred->hmac_secret));
}

int
fido_dev_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
{
Expand Down Expand Up @@ -214,14 +223,23 @@ fido_dev_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
}

if (pin != NULL || (cred->uv == FIDO_OPT_TRUE &&
fido_dev_supports_permissions(dev))) {
fido_dev_supports_permissions(dev)) ||
(cred->ext.attr.mask & FIDO_EXT_HMAC_SECRET_MC)) {
if ((r = fido_do_ecdh(dev, &pk, &ecdh, &ms)) != FIDO_OK) {
fido_log_debug("%s: fido_do_ecdh", __func__);
goto fail;
}
}

r = fido_dev_make_cred_wait(dev, cred, pk, ecdh, pin, &ms);
if (r == FIDO_OK && (cred->ext.attr.mask & FIDO_EXT_HMAC_SECRET_MC)) {
if (decrypt_hmac_secret(dev, cred, ecdh) < 0) {
fido_log_debug("%s: decrypt_hmac_secret", __func__);
r = FIDO_ERR_INTERNAL;
goto fail;
}
}

fail:
es256_pk_free(&pk);
fido_blob_free(&ecdh);
Expand Down Expand Up @@ -555,6 +573,7 @@ fido_cred_clean_authdata(fido_cred_t *cred)
fido_blob_reset(&cred->authdata_cbor);
fido_blob_reset(&cred->authdata_raw);
fido_blob_reset(&cred->attcred.id);
fido_blob_reset(&cred->authdata_ext.hmac_secret_enc);

memset(&cred->authdata_ext, 0, sizeof(cred->authdata_ext));
memset(&cred->authdata, 0, sizeof(cred->authdata));
Expand Down Expand Up @@ -589,6 +608,7 @@ fido_cred_reset_tx(fido_cred_t *cred)
fido_blob_reset(&cred->cdh);
fido_blob_reset(&cred->user.id);
fido_blob_reset(&cred->ext.blob);
fido_blob_reset(&cred->ext.hmac_salt);

free(cred->rp.id);
free(cred->rp.name);
Expand All @@ -612,6 +632,7 @@ fido_cred_reset_rx(fido_cred_t *cred)
{
fido_cred_clean_attobj(cred);
fido_blob_reset(&cred->largeblob_key);
fido_blob_reset(&cred->hmac_secret);
cred->ea.att = false;
}

Expand Down Expand Up @@ -962,6 +983,40 @@ fido_cred_set_user(fido_cred_t *cred, const unsigned char *user_id,
return (FIDO_ERR_INTERNAL);
}

int
fido_cred_set_hmac_salt(fido_cred_t *cred, const unsigned char *salt,
size_t salt_len)
{
if ((salt_len != 32 && salt_len != 64) ||
fido_blob_set(&cred->ext.hmac_salt, salt, salt_len) < 0)
return (FIDO_ERR_INVALID_ARGUMENT);

return (FIDO_OK);
}

int
fido_cred_set_hmac_secret(fido_cred_t *cred,
const unsigned char *secret, size_t secret_len)
{
if ((secret_len != 32 && secret_len != 64) ||
fido_blob_set(&cred->hmac_secret, secret, secret_len) < 0)
return (FIDO_ERR_INVALID_ARGUMENT);

return (FIDO_OK);
}

const unsigned char *
fido_cred_hmac_secret_ptr(const fido_cred_t *cred)
{
return (cred->hmac_secret.ptr);
}

size_t
fido_cred_hmac_secret_len(const fido_cred_t *cred)
{
return (cred->hmac_secret.len);
}

int
fido_cred_set_extensions(fido_cred_t *cred, int ext)
{
Expand Down
4 changes: 4 additions & 0 deletions src/export.gnu
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@
fido_cred_entattest;
fido_cred_exclude;
fido_cred_flags;
fido_cred_hmac_secret_len;
fido_cred_hmac_secret_ptr;
fido_cred_largeblob_key_len;
fido_cred_largeblob_key_ptr;
fido_cred_sigcount;
Expand Down Expand Up @@ -193,6 +195,8 @@
fido_cred_set_entattest;
fido_cred_set_extensions;
fido_cred_set_fmt;
fido_cred_set_hmac_salt;
fido_cred_set_hmac_secret;
fido_cred_set_id;
fido_cred_set_options;
fido_cred_set_pin_minlen;
Expand Down
4 changes: 4 additions & 0 deletions src/export.llvm
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ _fido_cred_empty_exclude_list
_fido_cred_entattest
_fido_cred_exclude
_fido_cred_flags
_fido_cred_hmac_secret_len
_fido_cred_hmac_secret_ptr
_fido_cred_largeblob_key_len
_fido_cred_largeblob_key_ptr
_fido_cred_sigcount
Expand Down Expand Up @@ -191,6 +193,8 @@ _fido_cred_set_clientdata_hash
_fido_cred_set_entattest
_fido_cred_set_extensions
_fido_cred_set_fmt
_fido_cred_set_hmac_salt
_fido_cred_set_hmac_secret
_fido_cred_set_id
_fido_cred_set_options
_fido_cred_set_pin_minlen
Expand Down
4 changes: 4 additions & 0 deletions src/export.msvc
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ fido_cred_empty_exclude_list
fido_cred_entattest
fido_cred_exclude
fido_cred_flags
fido_cred_hmac_secret_len
fido_cred_hmac_secret_ptr
fido_cred_largeblob_key_len
fido_cred_largeblob_key_ptr
fido_cred_sigcount
Expand Down Expand Up @@ -192,6 +194,8 @@ fido_cred_set_clientdata_hash
fido_cred_set_entattest
fido_cred_set_extensions
fido_cred_set_fmt
fido_cred_set_hmac_salt
fido_cred_set_hmac_secret
fido_cred_set_id
fido_cred_set_options
fido_cred_set_pin_minlen
Expand Down
3 changes: 2 additions & 1 deletion src/extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ cbor_item_t *cbor_flatten_vector(cbor_item_t **, size_t);
cbor_item_t *cbor_encode_assert_opt(fido_opt_t, fido_opt_t);
cbor_item_t *cbor_encode_change_pin_auth(const fido_dev_t *,
const fido_blob_t *, const fido_blob_t *, const fido_blob_t *);
cbor_item_t *cbor_encode_cred_ext(const fido_cred_extin_t *);
cbor_item_t *cbor_encode_cred_ext(const fido_dev_t *, const fido_cred_extin_t *,
const fido_blob_t *, const es256_pk_t *);
cbor_item_t *cbor_encode_assert_ext(fido_dev_t *,
const fido_assert_ext_t *, const fido_blob_t *, const es256_pk_t *);
cbor_item_t *cbor_encode_cred_opt(fido_opt_t, fido_opt_t);
Expand Down
4 changes: 4 additions & 0 deletions src/fido.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ const unsigned char *fido_cred_attstmt_ptr(const fido_cred_t *);
const unsigned char *fido_cred_authdata_ptr(const fido_cred_t *);
const unsigned char *fido_cred_authdata_raw_ptr(const fido_cred_t *);
const unsigned char *fido_cred_clientdata_hash_ptr(const fido_cred_t *);
const unsigned char *fido_cred_hmac_secret_ptr(const fido_cred_t *);
const unsigned char *fido_cred_id_ptr(const fido_cred_t *);
const unsigned char *fido_cred_largeblob_key_ptr(const fido_cred_t *);
const unsigned char *fido_cred_pubkey_ptr(const fido_cred_t *);
Expand Down Expand Up @@ -168,6 +169,8 @@ int fido_cred_set_clientdata_hash(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_entattest(fido_cred_t *, int);
int fido_cred_set_extensions(fido_cred_t *, int);
int fido_cred_set_fmt(fido_cred_t *, const char *);
int fido_cred_set_hmac_salt(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_hmac_secret(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_id(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_options(fido_cred_t *, bool, bool);
int fido_cred_set_pin_minlen(fido_cred_t *, size_t);
Expand Down Expand Up @@ -234,6 +237,7 @@ size_t fido_cred_attstmt_len(const fido_cred_t *);
size_t fido_cred_authdata_len(const fido_cred_t *);
size_t fido_cred_authdata_raw_len(const fido_cred_t *);
size_t fido_cred_clientdata_hash_len(const fido_cred_t *);
size_t fido_cred_hmac_secret_len(const fido_cred_t *);
size_t fido_cred_id_len(const fido_cred_t *);
size_t fido_cred_largeblob_key_len(const fido_cred_t *);
size_t fido_cred_pin_minlen(const fido_cred_t *);
Expand Down
5 changes: 3 additions & 2 deletions src/fido/param.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2024 Yubico AB. All rights reserved.
* Copyright (c) 2018-2025 Yubico AB. All rights reserved.
* SPDX-License-Identifier: BSD-2-Clause
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -131,6 +131,7 @@
#define FIDO_EXT_LARGEBLOB_KEY 0x04
#define FIDO_EXT_CRED_BLOB 0x08
#define FIDO_EXT_MINPINLEN 0x10
#define FIDO_EXT_HMAC_SECRET_MC 0x20

/* Supported credential protection policies. */
#define FIDO_CRED_PROT_UV_OPTIONAL 0x01
Expand All @@ -146,7 +147,7 @@
FIDO_EXT_CRED_BLOB)
#define FIDO_EXT_CRED_MASK (FIDO_EXT_HMAC_SECRET|FIDO_EXT_CRED_PROTECT| \
FIDO_EXT_LARGEBLOB_KEY|FIDO_EXT_CRED_BLOB| \
FIDO_EXT_MINPINLEN)
FIDO_EXT_MINPINLEN|FIDO_EXT_HMAC_SECRET_MC)
#endif /* _FIDO_INTERNAL */

/* Recognised UV modes. */
Expand Down
5 changes: 4 additions & 1 deletion src/fido/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,13 @@ typedef struct fido_cred_ext {

typedef struct fido_cred_extin {
fido_cred_ext_t attr;
fido_blob_t blob; /* CTAP 2.1 credBlob */
fido_blob_t blob; /* CTAP 2.1 credBlob */
fido_blob_t hmac_salt; /* CTAP 2.2 hmac-secret-mc salt */
} fido_cred_extin_t;

typedef struct fido_cred_extout {
fido_cred_ext_t attr;
fido_blob_t hmac_secret_enc; /* CTAP 2.2 hmac-secret-mc, encrypted */
} fido_cred_extout_t;

typedef struct fido_cred_ea {
Expand All @@ -199,6 +201,7 @@ typedef struct fido_cred {
fido_attstmt_t attstmt; /* attestation statement (x509 + sig) */
fido_blob_t largeblob_key; /* decoded large blob key */
fido_cred_ea_t ea; /* enterprise attestation */
fido_blob_t hmac_secret; /* CTAP 2.2 hmac-secret-mc */
} fido_cred_t;

typedef struct fido_assert_extattr {
Expand Down