Added support for setMinPinLength.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -369,7 +369,11 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
uint8_t pin_len = 0;
|
uint8_t pin_len = 0;
|
||||||
while (paddedNewPin[pin_len] != 0 && pin_len < sizeof(paddedNewPin))
|
while (paddedNewPin[pin_len] != 0 && pin_len < sizeof(paddedNewPin))
|
||||||
pin_len++;
|
pin_len++;
|
||||||
if (pin_len < 4)
|
uint8_t minPin = 4;
|
||||||
|
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||||
|
if (file_has_data(ef_minpin))
|
||||||
|
minPin = *file_get_data(ef_minpin);
|
||||||
|
if (pin_len < minPin)
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||||
uint8_t hsh[34];
|
uint8_t hsh[34];
|
||||||
hsh[0] = MAX_PIN_RETRIES;
|
hsh[0] = MAX_PIN_RETRIES;
|
||||||
@@ -448,13 +452,26 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
uint8_t pin_len = 0;
|
uint8_t pin_len = 0;
|
||||||
while (paddedNewPin[pin_len] != 0 && pin_len < sizeof(paddedNewPin))
|
while (paddedNewPin[pin_len] != 0 && pin_len < sizeof(paddedNewPin))
|
||||||
pin_len++;
|
pin_len++;
|
||||||
if (pin_len < 4)
|
uint8_t minPin = 4;
|
||||||
|
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||||
|
if (file_has_data(ef_minpin))
|
||||||
|
minPin = *file_get_data(ef_minpin);
|
||||||
|
if (pin_len < minPin)
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||||
uint8_t hsh[33];
|
uint8_t hsh[33];
|
||||||
hsh[0] = MAX_PIN_RETRIES;
|
hsh[0] = MAX_PIN_RETRIES;
|
||||||
hsh[1] = pin_len;
|
hsh[1] = pin_len;
|
||||||
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin, pin_len, hsh + 2);
|
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin, pin_len, hsh + 2);
|
||||||
|
if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1 && memcmp(hsh+2, file_get_data(ef_pin)+2, 16) == 0)
|
||||||
|
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||||
flash_write_data_to_file(ef_pin, hsh, 2+16);
|
flash_write_data_to_file(ef_pin, hsh, 2+16);
|
||||||
|
if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1) {
|
||||||
|
uint8_t *tmp = (uint8_t *)calloc(1, file_get_size(ef_minpin));
|
||||||
|
memcpy(tmp, file_get_data(ef_minpin), file_get_size(ef_minpin));
|
||||||
|
tmp[1] = 0;
|
||||||
|
flash_write_data_to_file(ef_minpin, tmp, file_get_size(ef_minpin));
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
resetPinUvAuthToken();
|
resetPinUvAuthToken();
|
||||||
goto err; // No return
|
goto err; // No return
|
||||||
@@ -518,6 +535,10 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
new_pin_mismatches = 0;
|
new_pin_mismatches = 0;
|
||||||
flash_write_data_to_file(ef_pin, pin_data, sizeof(pin_data));
|
flash_write_data_to_file(ef_pin, pin_data, sizeof(pin_data));
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
|
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||||
|
if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1)
|
||||||
|
CBOR_ERROR(CTAP2_ERR_PIN_INVALID);
|
||||||
|
resetPinUvAuthToken();
|
||||||
beginUsingPinUvAuthToken(false);
|
beginUsingPinUvAuthToken(false);
|
||||||
if (subcommand == 0x05)
|
if (subcommand == 0x05)
|
||||||
permissions = CTAP_PERMISSION_MC | CTAP_PERMISSION_GA;
|
permissions = CTAP_PERMISSION_MC | CTAP_PERMISSION_GA;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "mbedtls/ecdh.h"
|
#include "mbedtls/ecdh.h"
|
||||||
#include "mbedtls/chachapoly.h"
|
#include "mbedtls/chachapoly.h"
|
||||||
#include "mbedtls/hkdf.h"
|
#include "mbedtls/sha256.h"
|
||||||
|
|
||||||
extern uint8_t keydev_dec[32];
|
extern uint8_t keydev_dec[32];
|
||||||
extern bool has_keydev_dec;
|
extern bool has_keydev_dec;
|
||||||
@@ -36,11 +36,13 @@ int cbor_config(const uint8_t *data, size_t len) {
|
|||||||
CborParser parser;
|
CborParser parser;
|
||||||
CborValue map;
|
CborValue map;
|
||||||
CborError error = CborNoError;
|
CborError error = CborNoError;
|
||||||
uint64_t subcommand = 0, pinUvAuthProtocol = 0, vendorCommandId = 0;
|
uint64_t subcommand = 0, pinUvAuthProtocol = 0, vendorCommandId = 0, newMinPinLength = 0;
|
||||||
CborByteString pinUvAuthParam = {0}, vendorAutCt = {0};
|
CborByteString pinUvAuthParam = {0}, vendorAutCt = {0};
|
||||||
size_t resp_size = 0, raw_subpara_len = 0;
|
CborCharString minPinLengthRPIDs[32] = {0};
|
||||||
|
size_t resp_size = 0, raw_subpara_len = 0, minPinLengthRPIDs_len = 0;
|
||||||
CborEncoder encoder, mapEncoder;
|
CborEncoder encoder, mapEncoder;
|
||||||
uint8_t *raw_subpara = NULL;
|
uint8_t *raw_subpara = NULL;
|
||||||
|
const bool *forceChangePin = NULL;
|
||||||
|
|
||||||
CBOR_CHECK(cbor_parser_init(data, len, 0, &parser, &map));
|
CBOR_CHECK(cbor_parser_init(data, len, 0, &parser, &map));
|
||||||
uint64_t val_c = 1;
|
uint64_t val_c = 1;
|
||||||
@@ -68,6 +70,24 @@ int cbor_config(const uint8_t *data, size_t len) {
|
|||||||
CBOR_FIELD_GET_BYTES(vendorAutCt, 2);
|
CBOR_FIELD_GET_BYTES(vendorAutCt, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (subcommand == 0x03) {
|
||||||
|
CBOR_FIELD_GET_UINT(subpara, 2);
|
||||||
|
if (subpara == 0x01) {
|
||||||
|
CBOR_FIELD_GET_UINT(newMinPinLength, 2);
|
||||||
|
}
|
||||||
|
else if (subpara == 0x02) {
|
||||||
|
CBOR_PARSE_ARRAY_START(_f2, 3) {
|
||||||
|
CBOR_FIELD_GET_TEXT(minPinLengthRPIDs[minPinLengthRPIDs_len], 3);
|
||||||
|
minPinLengthRPIDs_len++;
|
||||||
|
if (minPinLengthRPIDs_len >= 32)
|
||||||
|
CBOR_ERROR(CTAP2_ERR_KEY_STORE_FULL);
|
||||||
|
}
|
||||||
|
CBOR_PARSE_ARRAY_END(_f2, 3);
|
||||||
|
}
|
||||||
|
else if (subpara == 0x03) {
|
||||||
|
CBOR_FIELD_GET_BOOL(forceChangePin, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CBOR_PARSE_MAP_END(_f1, 2);
|
CBOR_PARSE_MAP_END(_f1, 2);
|
||||||
raw_subpara_len = cbor_value_get_next_byte(&_f1) - raw_subpara;
|
raw_subpara_len = cbor_value_get_next_byte(&_f1) - raw_subpara;
|
||||||
@@ -145,6 +165,29 @@ int cbor_config(const uint8_t *data, size_t len) {
|
|||||||
}
|
}
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
else if (subcommand == 0x03) {
|
||||||
|
uint8_t currentMinPinLen = 4;
|
||||||
|
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||||
|
if (file_has_data(ef_minpin))
|
||||||
|
currentMinPinLen = *file_get_data(ef_minpin);
|
||||||
|
if (newMinPinLength == 0)
|
||||||
|
newMinPinLength = currentMinPinLen;
|
||||||
|
else if (newMinPinLength > 0 && newMinPinLength < currentMinPinLen)
|
||||||
|
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||||
|
if (forceChangePin == ptrue && !file_has_data(ef_pin))
|
||||||
|
CBOR_ERROR(CTAP2_ERR_PIN_NOT_SET);
|
||||||
|
if (file_has_data(ef_pin) && file_get_data(ef_pin)[1] < newMinPinLength)
|
||||||
|
forceChangePin = ptrue;
|
||||||
|
uint8_t *data = (uint8_t *)calloc(1, 2 + minPinLengthRPIDs_len * 32);
|
||||||
|
data[0] = newMinPinLength;
|
||||||
|
data[1] = forceChangePin == ptrue ? 1 : 0;
|
||||||
|
for (int m = 0; m < minPinLengthRPIDs_len; m++) {
|
||||||
|
mbedtls_sha256((uint8_t *)minPinLengthRPIDs[m].data, minPinLengthRPIDs[m].len, data + 2 + m*32, 0);
|
||||||
|
}
|
||||||
|
flash_write_data_to_file(ef_minpin, data, 2 + minPinLengthRPIDs_len * 32);
|
||||||
|
low_flash_available();
|
||||||
|
goto err; //No return
|
||||||
|
}
|
||||||
else
|
else
|
||||||
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
|
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
|
||||||
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
||||||
@@ -153,12 +196,16 @@ int cbor_config(const uint8_t *data, size_t len) {
|
|||||||
err:
|
err:
|
||||||
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
||||||
CBOR_FREE_BYTE_STRING(vendorAutCt);
|
CBOR_FREE_BYTE_STRING(vendorAutCt);
|
||||||
|
for (int i = 0; i < minPinLengthRPIDs_len; i++) {
|
||||||
if (error != CborNoError) {
|
CBOR_FREE_BYTE_STRING(minPinLengthRPIDs[i]);
|
||||||
if (error == CborErrorImproperValue)
|
|
||||||
return CTAP2_ERR_CBOR_UNEXPECTED_TYPE;
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error != CborNoError)
|
||||||
|
{
|
||||||
|
if (error == CborErrorImproperValue)
|
||||||
|
return CTAP2_ERR_CBOR_UNEXPECTED_TYPE;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
res_APDU_size = resp_size;
|
res_APDU_size = resp_size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ int cbor_get_info() {
|
|||||||
CborEncoder encoder, mapEncoder, arrayEncoder;
|
CborEncoder encoder, mapEncoder, arrayEncoder;
|
||||||
CborError error = CborNoError;
|
CborError error = CborNoError;
|
||||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_PACKET_SIZE, 0);
|
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_PACKET_SIZE, 0);
|
||||||
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, 10));
|
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, 11));
|
||||||
|
|
||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01));
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01));
|
||||||
CBOR_CHECK(cbor_encoder_create_array(&mapEncoder, &arrayEncoder, 3));
|
CBOR_CHECK(cbor_encoder_create_array(&mapEncoder, &arrayEncoder, 3));
|
||||||
@@ -45,7 +45,7 @@ int cbor_get_info() {
|
|||||||
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, aaguid, sizeof(aaguid)));
|
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, aaguid, sizeof(aaguid)));
|
||||||
|
|
||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04));
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04));
|
||||||
CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &arrayEncoder, 5));
|
CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &arrayEncoder, 6));
|
||||||
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "rk"));
|
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "rk"));
|
||||||
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true));
|
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true));
|
||||||
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "credMgmt"));
|
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "credMgmt"));
|
||||||
@@ -59,6 +59,8 @@ int cbor_get_info() {
|
|||||||
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, false));
|
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, false));
|
||||||
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "pinUvAuthToken"));
|
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "pinUvAuthToken"));
|
||||||
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true));
|
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true));
|
||||||
|
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "setMinPINLength"));
|
||||||
|
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true));
|
||||||
CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &arrayEncoder));
|
CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &arrayEncoder));
|
||||||
|
|
||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x06));
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x06));
|
||||||
@@ -73,8 +75,17 @@ int cbor_get_info() {
|
|||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x08));
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x08));
|
||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, MAX_CRED_ID_LENGTH)); // MAX_CRED_ID_MAX_LENGTH
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, MAX_CRED_ID_LENGTH)); // MAX_CRED_ID_MAX_LENGTH
|
||||||
|
|
||||||
|
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||||
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0C));
|
||||||
|
if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1)
|
||||||
|
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, true));
|
||||||
|
else
|
||||||
|
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, false));
|
||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0D));
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0D));
|
||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 4)); // minPINLength
|
if (file_has_data(ef_minpin))
|
||||||
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, *file_get_data(ef_minpin))); // minPINLength
|
||||||
|
else
|
||||||
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 4)); // minPINLength
|
||||||
|
|
||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0E));
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0E));
|
||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, PICO_FIDO_VERSION)); // firmwareVersion
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, PICO_FIDO_VERSION)); // firmwareVersion
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ file_t file_entries[] = {
|
|||||||
{.fid = EF_COUNTER, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // Global counter
|
{.fid = EF_COUNTER, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // Global counter
|
||||||
{.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_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_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 = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = {0} } //end
|
{ .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = {0} } //end
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#define EF_COUNTER 0xC000
|
#define EF_COUNTER 0xC000
|
||||||
#define EF_PIN 0x1080
|
#define EF_PIN 0x1080
|
||||||
#define EF_AUTHTOKEN 0x1090
|
#define EF_AUTHTOKEN 0x1090
|
||||||
|
#define EF_MINPINLEN 0x1100
|
||||||
#define EF_CRED 0xCF00 // Creds at 0xCF00 - 0xCFFF
|
#define EF_CRED 0xCF00 // Creds at 0xCF00 - 0xCFFF
|
||||||
#define EF_RP 0xD000 // RPs at 0xD000 - 0xD0FF
|
#define EF_RP 0xD000 // RPs at 0xD000 - 0xD0FF
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user