diff --git a/pico-hsm-sdk b/pico-hsm-sdk index 4a8a672..3def9bf 160000 --- a/pico-hsm-sdk +++ b/pico-hsm-sdk @@ -1 +1 @@ -Subproject commit 4a8a6728c79f9a6ef5500ea6c1fa889a8e49ba69 +Subproject commit 3def9bff4fb9e3e79e497392897deaf7c9bb5f29 diff --git a/src/fido/cbor_client_pin.c b/src/fido/cbor_client_pin.c index d8373a8..c8a4ac1 100644 --- a/src/fido/cbor_client_pin.c +++ b/src/fido/cbor_client_pin.c @@ -453,13 +453,20 @@ int cbor_client_pin(const uint8_t *data, size_t len) { resetPinUvAuthToken(); goto err; // No return } - else if (subcommand == 0x9 || subcommand == 0x5) { //getUVRgetPinUvAuthTokenUsingPinWithPermissionsetries + else if (subcommand == 0x9 || subcommand == 0x5) { //getPinUvAuthTokenUsingPinWithPermissions if (kax.present == false || kay.present == false || pinUvAuthProtocol == 0 || alg == 0 || pinHashEnc.present == false) CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER); if (pinUvAuthProtocol != 1 && pinUvAuthProtocol != 2) CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER); - if ((subcommand == 0x9 && permissions == 0) || (subcommand == 0x5 && (permissions != 0 || rpId.present == true))) + if (subcommand == 0x5 && (permissions != 0 || rpId.present == true)) CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER); + if (subcommand == 0x9) { + if (permissions == 0) + CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER); + if ((permissions & CTAP_PERMISSION_BE) || (permissions & CTAP_PERMISSION_LBW)) // Not supported yet + CBOR_ERROR(CTAP2_ERR_UNAUTHORIZED_PERMISSION); + + } if (!file_has_data(ef_pin)) CBOR_ERROR(CTAP2_ERR_PIN_NOT_SET); if (*file_get_data(ef_pin) == 0) @@ -503,11 +510,13 @@ int cbor_client_pin(const uint8_t *data, size_t len) { flash_write_data_to_file(ef_pin, &retries, 1); low_flash_available(); beginUsingPinUvAuthToken(false); + if (subcommand == 0x05) + permissions = CTAP_PERMISSION_MC | CTAP_PERMISSION_GA; paut.permissions = permissions; - if (rpId.present == true) + if (rpId.present == true) { memcpy(paut.rp_id_hash, rpId.data, 32); - else - memset(paut.rp_id_hash, 0, sizeof(paut.rp_id_hash)); + paut.has_rp_id = true; + } uint8_t pinUvAuthToken_enc[32+IV_SIZE]; encrypt(pinUvAuthProtocol, sharedSecret, paut.data, 32, pinUvAuthToken_enc); CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, 1)); diff --git a/src/fido/cbor_cred_mgmt.c b/src/fido/cbor_cred_mgmt.c index 6011103..fb9a488 100644 --- a/src/fido/cbor_cred_mgmt.c +++ b/src/fido/cbor_cred_mgmt.c @@ -115,6 +115,8 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) { if(subcommand == 0x01) { if (verify(pinUvAuthProtocol, paut.data, (const uint8_t *)"\x01", 1, pinUvAuthParam.data) != CborNoError) CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); + if (!(paut.permissions & CTAP_PERMISSION_CM) || paut.has_rp_id == true) + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); uint8_t existing = 0; for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) { if (file_has_data(search_dynamic_file(EF_CRED + i))) @@ -131,6 +133,8 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) { if (subcommand == 0x02) { if (verify(pinUvAuthProtocol, paut.data, (const uint8_t *)"\x02", 1, pinUvAuthParam.data) != CborNoError) CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); + if (!(paut.permissions & CTAP_PERMISSION_CM) || paut.has_rp_id == true) + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); rp_counter = 1; rp_total = 0; } @@ -175,6 +179,8 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) { *(raw_subpara-1) = 0x04; if (verify(pinUvAuthProtocol, paut.data, raw_subpara-1, raw_subpara_len+1, pinUvAuthParam.data) != CborNoError) CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); + if (!(paut.permissions & CTAP_PERMISSION_CM) || (paut.has_rp_id == true && memcmp(paut.rp_id_hash, rpIdHash.data, 32) != 0)) + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); cred_counter = 1; cred_total = 0; } @@ -284,6 +290,8 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) { *(raw_subpara - 1) = 0x06; if (verify(pinUvAuthProtocol, paut.data, raw_subpara-1, raw_subpara_len+1, pinUvAuthParam.data) != CborNoError) CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); + if (!(paut.permissions & CTAP_PERMISSION_CM) || (paut.has_rp_id == true && memcmp(paut.rp_id_hash, rpIdHash.data, 32) != 0)) + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) { file_t *ef = search_dynamic_file(EF_CRED + i); if (file_has_data(ef) && memcmp(file_get_data(ef)+32, credentialId.id.data, MIN(file_get_size(ef)-32, credentialId.id.len)) == 0) { @@ -316,6 +324,8 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) { *(raw_subpara - 1) = 0x07; if (verify(pinUvAuthProtocol, paut.data, raw_subpara-1, raw_subpara_len+1, pinUvAuthParam.data) != CborNoError) CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); + if (!(paut.permissions & CTAP_PERMISSION_CM) || (paut.has_rp_id == true && memcmp(paut.rp_id_hash, rpIdHash.data, 32) != 0)) + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) { file_t *ef = search_dynamic_file(EF_CRED + i); if (file_has_data(ef) && memcmp(file_get_data(ef)+32, credentialId.id.data, MIN(file_get_size(ef)-32, credentialId.id.len)) == 0) { diff --git a/src/fido/cbor_get_assertion.c b/src/fido/cbor_get_assertion.c index a46f7be..5179992 100644 --- a/src/fido/cbor_get_assertion.c +++ b/src/fido/cbor_get_assertion.c @@ -245,6 +245,10 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) { CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); if (getUserVerifiedFlagValue() == false) CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); + if (!(paut.permissions & CTAP_PERMISSION_GA)) + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); + if (paut.has_rp_id == true && memcmp(paut.rp_id_hash, rp_id_hash, 32) != 0) + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); flags |= FIDO2_AUT_FLAG_UV; // Check pinUvAuthToken permissions. See 6.2.2.4 } diff --git a/src/fido/cbor_make_credential.c b/src/fido/cbor_make_credential.c index ad3d349..011bc20 100644 --- a/src/fido/cbor_make_credential.c +++ b/src/fido/cbor_make_credential.c @@ -215,10 +215,17 @@ int cbor_make_credential(const uint8_t *data, size_t len) { int ret = verify(pinUvAuthProtocol, paut.data, clientDataHash.data, clientDataHash.len, pinUvAuthParam.data); if (ret != CborNoError) CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); + if (!(paut.permissions & CTAP_PERMISSION_MC)) + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); + if (paut.has_rp_id == true && memcmp(paut.rp_id_hash, rp_id_hash, 32) != 0) + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); if (getUserVerifiedFlagValue() == false) CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); flags |= FIDO2_AUT_FLAG_UV; - // Check pinUvAuthToken permissions. See 6.1.2.11 + if (paut.has_rp_id == false) { + memcpy(paut.rp_id_hash, rp_id_hash, 32); + paut.has_rp_id = true; + } } for (int e = 0; e < excludeList_len; e++) { //12.1 diff --git a/src/fido/ctap.h b/src/fido/ctap.h index 57ed43f..4614349 100644 --- a/src/fido/ctap.h +++ b/src/fido/ctap.h @@ -125,6 +125,13 @@ typedef struct { #define CTAP_VENDOR_MSE 0x02 #define CTAP_VENDOR_UNLOCK 0x03 +#define CTAP_PERMISSION_MC 0x01 // MakeCredential +#define CTAP_PERMISSION_GA 0x02 // GetAssertion +#define CTAP_PERMISSION_CM 0x04 // CredentialManagement +#define CTAP_PERMISSION_BE 0x08 // BioEnrollment +#define CTAP_PERMISSION_LBW 0x10 // LargeBlobWrite +#define CTAP_PERMISSION_ACFG 0x20 // AuthenticatorConfiguration + typedef struct mse { uint8_t Qpt[65]; uint8_t key_enc[12 + 32]; diff --git a/src/fido/fido.h b/src/fido/fido.h index 41209e4..0762e0c 100644 --- a/src/fido/fido.h +++ b/src/fido/fido.h @@ -101,6 +101,7 @@ typedef struct pinUvAuthToken { bool in_use; uint8_t permissions; uint8_t rp_id_hash[32]; + bool has_rp_id; bool user_present; bool user_verified; } pinUvAuthToken_t;