mirror of
https://github.com/polhenarejos/pico-fido.git
synced 2025-12-18 09:30:04 +08:00
Add support to PIN POLICY URL via VendorConfig.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -40,7 +40,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
CborError error = CborNoError;
|
||||
uint64_t subcommand = 0, pinUvAuthProtocol = 0, vendorCommandId = 0, newMinPinLength = 0, vendorParamInt = 0;
|
||||
CborByteString pinUvAuthParam = { 0 }, vendorParamByteString = { 0 };
|
||||
CborCharString minPinLengthRPIDs[32] = { 0 };
|
||||
CborCharString minPinLengthRPIDs[32] = { 0 }, vendorParamTextString = { 0 };
|
||||
size_t resp_size = 0, raw_subpara_len = 0, minPinLengthRPIDs_len = 0;
|
||||
CborEncoder encoder;
|
||||
//CborEncoder mapEncoder;
|
||||
@@ -79,6 +79,9 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
else if (subpara == 0x03) {
|
||||
CBOR_FIELD_GET_UINT(vendorParamInt, 2);
|
||||
}
|
||||
else if (subpara == 0x04) {
|
||||
CBOR_FIELD_GET_TEXT(vendorParamTextString, 2);
|
||||
}
|
||||
}
|
||||
else if (subcommand == 0x03) { // Extensions
|
||||
CBOR_FIELD_GET_UINT(subpara, 2);
|
||||
@@ -224,6 +227,21 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
}
|
||||
low_flash_available();
|
||||
}
|
||||
else if (vendorCommandId == CTAP_CONFIG_PIN_POLICY) {
|
||||
file_t *ef_pin_policy = file_new(EF_PIN_COMPLEXITY_POLICY);
|
||||
if (ef_pin_policy) {
|
||||
uint8_t *val = calloc(1, 2 + vendorParamByteString.len);
|
||||
if (val) {
|
||||
// Not ready yet for integer param
|
||||
// val[0] = (uint8_t)(vendorParamInt >> 8);
|
||||
// val[1] = (uint8_t)(vendorParamInt & 0xFF);
|
||||
memcpy(val + 2, vendorParamByteString.data, vendorParamByteString.len);
|
||||
file_put_data(ef_pin_policy, val, 2 + vendorParamByteString.len);
|
||||
free(val);
|
||||
}
|
||||
}
|
||||
low_flash_available();
|
||||
}
|
||||
else {
|
||||
CBOR_ERROR(CTAP2_ERR_INVALID_SUBCOMMAND);
|
||||
}
|
||||
@@ -275,6 +293,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
err:
|
||||
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
||||
CBOR_FREE_BYTE_STRING(vendorParamByteString);
|
||||
CBOR_FREE_BYTE_STRING(vendorParamTextString);
|
||||
for (size_t i = 0; i < minPinLengthRPIDs_len; i++) {
|
||||
CBOR_FREE_BYTE_STRING(minPinLengthRPIDs[i]);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ int cbor_get_info() {
|
||||
#else
|
||||
lfields++;
|
||||
#endif
|
||||
file_t *ef_pin_policy = search_by_fid(EF_PIN_COMPLEXITY_POLICY, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_pin_policy)) {
|
||||
lfields += 2;
|
||||
}
|
||||
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, lfields));
|
||||
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01));
|
||||
@@ -164,7 +168,7 @@ int cbor_get_info() {
|
||||
if (phy_data.vid != 0x1050) {
|
||||
#endif
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x15));
|
||||
uint8_t enabled_cmds = 3;
|
||||
uint8_t enabled_cmds = 4;
|
||||
#ifndef ENABLE_EMULATION
|
||||
enabled_cmds += 4;
|
||||
#endif
|
||||
@@ -172,6 +176,7 @@ int cbor_get_info() {
|
||||
CBOR_CHECK(cbor_encode_uint(&arrayEncoder, CTAP_CONFIG_AUT_ENABLE));
|
||||
CBOR_CHECK(cbor_encode_uint(&arrayEncoder, CTAP_CONFIG_AUT_DISABLE));
|
||||
CBOR_CHECK(cbor_encode_uint(&arrayEncoder, CTAP_CONFIG_EA_UPLOAD));
|
||||
CBOR_CHECK(cbor_encode_uint(&arrayEncoder, CTAP_CONFIG_PIN_POLICY));
|
||||
#ifndef ENABLE_EMULATION
|
||||
CBOR_CHECK(cbor_encode_uint(&arrayEncoder, CTAP_CONFIG_PHY_VIDPID));
|
||||
CBOR_CHECK(cbor_encode_uint(&arrayEncoder, CTAP_CONFIG_PHY_LED_BTNESS));
|
||||
@@ -181,6 +186,13 @@ int cbor_get_info() {
|
||||
CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &arrayEncoder));
|
||||
#ifndef ENABLE_EMULATION
|
||||
}
|
||||
if (file_has_data(ef_pin_policy)) {
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x1B));
|
||||
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, true));
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x1C));
|
||||
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, file_get_data(ef_pin_policy) + 2, file_get_size(ef_pin_policy) - 2));
|
||||
}
|
||||
|
||||
#endif
|
||||
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
||||
err:
|
||||
|
||||
@@ -44,6 +44,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
int64_t kty = 2, hmac_alg = 0, crv = 0;
|
||||
CborByteString kax = { 0 }, kay = { 0 }, salt_enc = { 0 }, salt_auth = { 0 };
|
||||
bool hmac_secret_mc = false;
|
||||
const bool *pin_complexity_policy = NULL;
|
||||
uint8_t *aut_data = NULL;
|
||||
size_t resp_size = 0;
|
||||
CredExtensions extensions = { 0 };
|
||||
@@ -162,6 +163,8 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
CBOR_FIELD_KEY_TEXT_VAL_BYTES(2, "credBlob", extensions.credBlob);
|
||||
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "largeBlobKey", extensions.largeBlobKey);
|
||||
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "thirdPartyPayment", extensions.thirdPartyPayment);
|
||||
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "pinComplexityPolicy", pin_complexity_policy);
|
||||
|
||||
CBOR_ADVANCE(2);
|
||||
}
|
||||
CBOR_PARSE_MAP_END(_f1, 2);
|
||||
@@ -440,6 +443,9 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
if (hmac_secret_mc) {
|
||||
l++;
|
||||
}
|
||||
if (pin_complexity_policy == ptrue) {
|
||||
l++;
|
||||
}
|
||||
if (l > 0) {
|
||||
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, l));
|
||||
if (extensions.credBlob.present == true) {
|
||||
@@ -451,12 +457,10 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, extensions.credProtect));
|
||||
}
|
||||
if (extensions.hmac_secret == ptrue) {
|
||||
|
||||
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "hmac-secret"));
|
||||
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, true));
|
||||
}
|
||||
if (minPinLen > 0) {
|
||||
|
||||
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "minPinLength"));
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, minPinLen));
|
||||
}
|
||||
@@ -511,6 +515,11 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
encrypt((uint8_t)hmacSecretPinUvAuthProtocol, sharedSecret, out1, (uint16_t)(salt_enc.len - poff), hmac_res);
|
||||
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, hmac_res, salt_enc.len));
|
||||
}
|
||||
if (pin_complexity_policy == ptrue) {
|
||||
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "pinComplexityPolicy"));
|
||||
file_t *ef_pin_complexity_policy = search_by_fid(EF_PIN_COMPLEXITY_POLICY, NULL, SPECIFY_EF);
|
||||
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, file_has_data(ef_pin_complexity_policy)));
|
||||
}
|
||||
|
||||
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
|
||||
ext_len = cbor_encoder_get_buffer_size(&encoder, ext);
|
||||
|
||||
@@ -115,6 +115,7 @@ typedef struct {
|
||||
#define CTAP_CONFIG_AUT_ENABLE 0x03e43f56b34285e2
|
||||
#define CTAP_CONFIG_AUT_DISABLE 0x1831a40f04a25ed9
|
||||
#define CTAP_CONFIG_EA_UPLOAD 0x66f2a674c29a8dcf
|
||||
#define CTAP_CONFIG_PIN_POLICY 0x6c07d70fe96c3897
|
||||
#ifndef ENABLE_EMULATION
|
||||
#define CTAP_CONFIG_PHY_VIDPID 0x6fcb19b0cbe3acfa
|
||||
#define CTAP_CONFIG_PHY_LED_BTNESS 0x76a85945985d02fd
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define EF_AUTHTOKEN 0x1090
|
||||
#define EF_PAUTHTOKEN 0x1091
|
||||
#define EF_MINPINLEN 0x1100
|
||||
#define EF_PIN_COMPLEXITY_POLICY 0x1102
|
||||
#define EF_DEV_CONF 0x1122
|
||||
#define EF_CRED 0xCF00 // Creds at 0xCF00 - 0xCFFF
|
||||
#define EF_RP 0xD000 // RPs at 0xD000 - 0xD0FF
|
||||
|
||||
@@ -24,7 +24,7 @@ import argparse
|
||||
import platform
|
||||
from binascii import hexlify
|
||||
from threading import Event
|
||||
from typing import Mapping, Any, Optional, Callable
|
||||
from typing import List, Mapping, Any, Optional, Callable
|
||||
import struct
|
||||
import urllib.request
|
||||
import json
|
||||
@@ -77,6 +77,7 @@ class VendorConfig(Config):
|
||||
VENDOR_COMMAND_ID = 0x01
|
||||
VENDOR_PARAM_BYTESTRING = 0x02
|
||||
VENDOR_PARAM_INT = 0x03
|
||||
VENDOR_PARAM_TEXTSTRING = 0x04
|
||||
|
||||
class CMD(IntEnum):
|
||||
CONFIG_AUT_ENABLE = 0x03e43f56b34285e2
|
||||
@@ -86,6 +87,7 @@ class VendorConfig(Config):
|
||||
CONFIG_PHY_LED_BTNESS = 0x76a85945985d02fd
|
||||
CONFIG_PHY_LED_GPIO = 0x7b392a394de9f948
|
||||
CONFIG_PHY_OPTS = 0x969f3b09eceb805f
|
||||
CONFIG_PIN_POLICY = 0x6c07d70fe96c3897
|
||||
|
||||
class RESP(IntEnum):
|
||||
KEY_AGREEMENT = 0x01
|
||||
@@ -155,6 +157,20 @@ class VendorConfig(Config):
|
||||
},
|
||||
)
|
||||
|
||||
def pin_policy(self, url: bytes|str = None, policy: int = None):
|
||||
if (url is not None or policy is not None):
|
||||
params = { VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_PIN_POLICY }
|
||||
if (url is not None):
|
||||
if (isinstance(url, str)):
|
||||
url = url.encode()
|
||||
params[VendorConfig.PARAM.VENDOR_PARAM_BYTESTRING] = url
|
||||
if (policy is not None):
|
||||
params[VendorConfig.PARAM.VENDOR_PARAM_INT] = policy
|
||||
self._call(
|
||||
Config.CMD.VENDOR_PROTOTYPE,
|
||||
params,
|
||||
)
|
||||
|
||||
class Ctap2Vendor(Ctap2):
|
||||
def __init__(self, device: CtapDevice, strict_cbor: bool = True):
|
||||
super().__init__(device=device, strict_cbor=strict_cbor)
|
||||
@@ -486,6 +502,18 @@ class Vendor:
|
||||
def enable_enterprise_attestation(self):
|
||||
self.vcfg.enable_enterprise_attestation()
|
||||
|
||||
def set_min_pin_length(self, length, rpids: list[str] = None, url=None):
|
||||
params = {
|
||||
Config.PARAM.NEW_MIN_PIN_LENGTH: length,
|
||||
Config.PARAM.MIN_PIN_LENGTH_RPIDS: rpids if rpids else None,
|
||||
}
|
||||
self.vcfg.set_min_pin_length(
|
||||
min_pin_length=length,
|
||||
rp_ids=rpids if rpids else None,
|
||||
)
|
||||
self.vcfg.pin_policy(url=url.encode() if url else None)
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser()
|
||||
subparser = parser.add_subparsers(title="commands", dest="command")
|
||||
@@ -516,6 +544,11 @@ def parse_args():
|
||||
|
||||
parser_mem = subparser.add_parser('memory', help='Get current memory usage.')
|
||||
|
||||
parser_pin_policy = subparser.add_parser('pin_policy', help='Manage PIN policy.')
|
||||
parser_pin_policy.add_argument('length', type=int, help='Minimum PIN length (4-63).')
|
||||
parser_pin_policy.add_argument('--rpids', help='Comma separated list of Relying Party IDs that have authorization to receive minimum PIN length.')
|
||||
parser_pin_policy.add_argument('--url', help='URL where the user can consult PIN policy.')
|
||||
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
@@ -584,6 +617,14 @@ def memory(vdr: Vendor, args):
|
||||
print(f'\tFlash size: {mem["size"]/1024:.2f} kilobytes')
|
||||
print(f'\tFiles: {mem["files"]}')
|
||||
|
||||
|
||||
def pin_policy(vdr: Vendor, args):
|
||||
rpids = None
|
||||
if (args.rpids):
|
||||
rpids = args.rpids.split(',')
|
||||
vdr.set_min_pin_length(args.length, rpids, args.url)
|
||||
|
||||
|
||||
def main(args):
|
||||
print('Pico Fido Tool v1.10')
|
||||
print('Author: Pol Henarejos')
|
||||
@@ -607,6 +648,9 @@ def main(args):
|
||||
phy(vdr, args)
|
||||
elif (args.command == 'memory'):
|
||||
memory(vdr, args)
|
||||
elif (args.command == 'pin_policy'):
|
||||
pin_policy(vdr, args)
|
||||
|
||||
|
||||
def run():
|
||||
args = parse_args()
|
||||
|
||||
Reference in New Issue
Block a user