Added support for enterprise attestation.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2022-11-28 17:39:21 +01:00
parent 765db0e98b
commit 8b70c864a4
8 changed files with 47 additions and 21 deletions

View File

@@ -59,7 +59,7 @@ void clearUserVerifiedFlag() {
void clearPinUvAuthTokenPermissionsExceptLbw() {
if (paut.in_use == true)
paut.permissions = FIDO2_PERMISSION_LBW;
paut.permissions = CTAP_PERMISSION_LBW;
}
void stopUsingPinUvAuthToken() {

View File

@@ -188,6 +188,10 @@ int cbor_config(const uint8_t *data, size_t len) {
low_flash_available();
goto err; //No return
}
else if (subcommand == 0x01) {
set_opts(get_opts() | FIDO2_OPT_EA);
goto err;
}
else
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));

View File

@@ -46,7 +46,9 @@ int cbor_get_info() {
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, aaguid, sizeof(aaguid)));
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04));
CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &arrayEncoder, 6));
CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &arrayEncoder, 7));
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "ep"));
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, get_opts() & FIDO2_OPT_EA));
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "rk"));
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true));
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "credMgmt"));

View File

@@ -207,6 +207,9 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
CBOR_ERROR(CTAP2_ERR_PUAT_REQUIRED);
}
if (enterpriseAttestation > 0) {
if (!(get_opts() & FIDO2_OPT_EA)) {
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
}
if (enterpriseAttestation != 1 && enterpriseAttestation != 2) { //9.2.1
CBOR_ERROR(CTAP2_ERR_INVALID_OPTION);
}
@@ -259,14 +262,6 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
CBOR_CHECK(credential_create(&rp.id, &user.id, &user.parent.name, &user.displayName, &options, &extensions, (!ka || ka->use_sign_count == ptrue), alg, curve, cred_id, &cred_id_len));
mbedtls_ecdsa_context ekey;
mbedtls_ecdsa_init(&ekey);
int ret = fido_load_key(curve, cred_id, &ekey);
if (ret != 0) {
mbedtls_ecdsa_free(&ekey);
CBOR_ERROR(CTAP1_ERR_OTHER);
}
if (getUserVerifiedFlagValue())
flags |= FIDO2_AUT_FLAG_UV;
size_t ext_len = 0;
@@ -315,9 +310,18 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
flags |= FIDO2_AUT_FLAG_ED;
}
uint8_t pkey[66];
const mbedtls_ecp_curve_info *cinfo = mbedtls_ecp_curve_info_from_grp_id(ekey.grp.id);
if (cinfo == NULL)
mbedtls_ecdsa_context ekey;
mbedtls_ecdsa_init(&ekey);
int ret = fido_load_key(curve, cred_id, &ekey);
if (ret != 0) {
mbedtls_ecdsa_free(&ekey);
CBOR_ERROR(CTAP1_ERR_OTHER);
}
const mbedtls_ecp_curve_info *cinfo = mbedtls_ecp_curve_info_from_grp_id(ekey.grp.id);
if (cinfo == NULL) {
mbedtls_ecdsa_free(&ekey);
CBOR_ERROR(CTAP1_ERR_OTHER);
}
size_t olen = 0;
uint32_t ctr = get_sign_counter();
uint8_t cbor_buf[1024];
@@ -354,15 +358,17 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
memcpy(pa, cred_id, cred_id_len); pa += cred_id_len;
memcpy(pa, cbor_buf, rs); pa += rs;
memcpy(pa, ext, ext_len); pa += ext_len;
if (pa-aut_data != aut_data_len)
if (pa-aut_data != aut_data_len) {
mbedtls_ecdsa_free(&ekey);
CBOR_ERROR(CTAP1_ERR_OTHER);
}
memcpy(pa, clientDataHash.data, clientDataHash.len);
uint8_t hash[32], sig[MBEDTLS_ECDSA_MAX_LEN];
ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), aut_data, aut_data_len+clientDataHash.len, hash);
bool self_attestation = true;
if (ka && ka->use_self_attestation == pfalse) {
if (enterpriseAttestation == 2 || (ka && ka->use_self_attestation == pfalse)) {
mbedtls_ecdsa_free(&ekey);
mbedtls_ecdsa_init(&ekey);
ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, &ekey, file_get_data(ef_keydev), 32);
@@ -372,7 +378,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
mbedtls_ecdsa_free(&ekey);
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_PACKET_SIZE, 0);
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, 3));
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, 4));
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01));
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "packed"));
@@ -394,6 +400,8 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
}
CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &mapEncoder2));
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04));
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, enterpriseAttestation == 2));
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
resp_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);

View File

@@ -325,6 +325,19 @@ uint32_t get_sign_counter() {
return (*caddr) | (*(caddr + 1) << 8) | (*(caddr + 2) << 16) | (*(caddr + 3) << 24);
}
uint8_t get_opts() {
file_t *ef = search_by_fid(EF_OPTS, NULL, SPECIFY_EF);
if (file_has_data(ef))
return *file_get_data(ef);
return 0;
}
void set_opts(uint8_t opts) {
file_t *ef = search_by_fid(EF_OPTS, NULL, SPECIFY_EF);
flash_write_data_to_file(ef, &opts, sizeof(uint8_t));
low_flash_available();
}
typedef struct cmd
{
uint8_t ins;

View File

@@ -63,12 +63,7 @@ extern int ecdh(uint8_t protocol, const mbedtls_ecp_point *Q, uint8_t *sharedSec
#define FIDO2_AUT_FLAG_AT 0x40
#define FIDO2_AUT_FLAG_ED 0x80
#define FIDO2_PERMISSION_MC 0x1
#define FIDO2_PERMISSION_GA 0x2
#define FIDO2_PERMISSION_CM 0x4
#define FIDO2_PERMISSION_BE 0x8
#define FIDO2_PERMISSION_LBW 0x10
#define FIDO2_PERMISSION_ACFG 0x20
#define FIDO2_OPT_EA 0x01 // Enterprise Attestation
#define MAX_PIN_RETRIES 8
extern bool getUserPresentFlagValue();
@@ -78,6 +73,8 @@ extern void clearUserVerifiedFlag();
extern void clearPinUvAuthTokenPermissionsExceptLbw();
extern void send_keepalive();
extern uint32_t get_sign_counter();
extern uint8_t get_opts();
extern void set_opts(uint8_t);
#define MAX_CREDENTIAL_COUNT_IN_LIST 16
#define MAX_CRED_ID_LENGTH 1024
#define MAX_RESIDENT_CREDENTIALS 256

View File

@@ -27,6 +27,7 @@ file_t file_entries[] = {
{.fid = EF_PIN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // PIN
{.fid = EF_AUTHTOKEN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // AUTH TOKEN
{.fid = EF_MINPINLEN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // MIN PIN LENGTH
{.fid = EF_OPTS, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // Global options
{ .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = {0} } //end
};

View File

@@ -24,6 +24,7 @@
#define EF_KEY_DEV_ENC 0xCC01
#define EF_EE_DEV 0xCE00
#define EF_COUNTER 0xC000
#define EF_OPTS 0xC001
#define EF_PIN 0x1080
#define EF_AUTHTOKEN 0x1090
#define EF_MINPINLEN 0x1100