From 55a60f8875586e5f99fbee3a339d45a43a6d46c2 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 22 Jan 2026 00:26:13 +0100 Subject: [PATCH 01/12] Fix power_cycle behavior Signed-off-by: Pol Henarejos --- src/fido/cbor_client_pin.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/fido/cbor_client_pin.c b/src/fido/cbor_client_pin.c index 7a4097c..2a681af 100644 --- a/src/fido/cbor_client_pin.c +++ b/src/fido/cbor_client_pin.c @@ -334,6 +334,10 @@ int cbor_client_pin(const uint8_t *data, size_t len) { } CBOR_PARSE_MAP_END(map, 1); + if (needs_power_cycle) { + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_BLOCKED); + } + cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0); if (subcommand == 0x0) { CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER); From 60165c21cade5fadae061f30c07fa539da9c7890 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 22 Jan 2026 00:26:27 +0100 Subject: [PATCH 02/12] Fix vendor keydev loading Signed-off-by: Pol Henarejos --- src/fido/cbor_vendor.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/fido/cbor_vendor.c b/src/fido/cbor_vendor.c index e102aab..b59abb3 100644 --- a/src/fido/cbor_vendor.c +++ b/src/fido/cbor_vendor.c @@ -206,7 +206,12 @@ int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) { uint8_t buffer[1024]; mbedtls_ecdsa_context ekey; mbedtls_ecdsa_init(&ekey); - int ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, &ekey, file_get_data(ef_keydev), file_get_size(ef_keydev)); + uint8_t keydev[32] = {0}; + if (load_keydev(keydev) != 0) { + CBOR_ERROR(CTAP1_ERR_OTHER); + } + int ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, &ekey, keydev, 32); + mbedtls_platform_zeroize(keydev, sizeof(keydev)); if (ret != 0) { mbedtls_ecdsa_free(&ekey); CBOR_ERROR(CTAP2_ERR_PROCESSING); From c8d62de621c0e2d3605dcf0e2dc4ee8679b9bb14 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 22 Jan 2026 00:26:51 +0100 Subject: [PATCH 03/12] Add vendor commands via CCID Signed-off-by: Pol Henarejos --- src/fido/fido.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/fido/fido.c b/src/fido/fido.c index d6cb9d9..c03124f 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -53,6 +53,11 @@ const uint8_t fido_aid[] = { 0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01 }; +const uint8_t fido_aid_backup[] = { + 8, + 0xB0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01 +}; + const uint8_t atr_fido[] = { 23, 0x3b, 0xfd, 0x13, 0x00, 0x00, 0x81, 0x31, 0xfe, 0x15, 0x80, 0x73, 0xc0, 0x21, 0xc0, 0x57, 0x59, @@ -86,6 +91,7 @@ INITIALIZER ( fido_ctor ) { get_version_major = fido_get_version_major; get_version_minor = fido_get_version_minor; register_app(fido_select, fido_aid); + register_app(fido_select, fido_aid_backup); } int fido_unload() { @@ -530,18 +536,32 @@ extern int cmd_register(); extern int cmd_authenticate(); extern int cmd_version(); extern int cbor_parse(int, uint8_t *, size_t); +extern int cbor_vendor(const uint8_t *data, size_t len); extern void driver_init_hid(); #define CTAP_CBOR 0x10 +int cmd_vendor() { + uint8_t *old_buf = res_APDU; + driver_init_hid(); + int ret = cbor_vendor(apdu.data, apdu.nc); + res_APDU = old_buf; + if (ret != 0) { + return SW_EXEC_ERROR(); + } + res_APDU_size += 1; + memcpy(res_APDU, ctap_resp->init.data, res_APDU_size); + return SW_OK(); +} + int cmd_cbor() { uint8_t *old_buf = res_APDU; driver_init_hid(); int ret = cbor_parse(0x90, apdu.data, apdu.nc); + res_APDU = old_buf; if (ret != 0) { return SW_EXEC_ERROR(); } - res_APDU = old_buf; res_APDU_size += 1; memcpy(res_APDU, ctap_resp->init.data, res_APDU_size); return SW_OK(); @@ -552,6 +572,7 @@ static const cmd_t cmds[] = { { CTAP_AUTHENTICATE, cmd_authenticate }, { CTAP_VERSION, cmd_version }, { CTAP_CBOR, cmd_cbor }, + { 0x41, cmd_vendor }, { 0x00, 0x0 } }; From 18d68d7e055b2c1106e577859343f74bf3ca7bec Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 22 Jan 2026 00:57:31 +0100 Subject: [PATCH 04/12] Fix needs power cycle logic. Signed-off-by: Pol Henarejos --- src/fido/cbor_client_pin.c | 15 +++++++++++---- src/fido/fido.c | 2 ++ tests/pico-fido/test_010_pin.py | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/fido/cbor_client_pin.c b/src/fido/cbor_client_pin.c index 2a681af..b2c6732 100644 --- a/src/fido/cbor_client_pin.c +++ b/src/fido/cbor_client_pin.c @@ -334,10 +334,6 @@ int cbor_client_pin(const uint8_t *data, size_t len) { } CBOR_PARSE_MAP_END(map, 1); - if (needs_power_cycle) { - CBOR_ERROR(CTAP2_ERR_PIN_AUTH_BLOCKED); - } - cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0); if (subcommand == 0x0) { CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER); @@ -423,6 +419,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) { hsh[1] = pin_len; hsh[2] = 1; // New format indicator mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin, pin_len, dhash); + mbedtls_platform_zeroize(paddedNewPin, sizeof(paddedNewPin)); pin_derive_verifier(dhash, 16, hsh + 3); file_put_data(ef_pin, hsh, sizeof(hsh)); low_flash_available(); @@ -434,6 +431,8 @@ int cbor_client_pin(const uint8_t *data, size_t len) { } mbedtls_platform_zeroize(hsh, sizeof(hsh)); mbedtls_platform_zeroize(dhash, sizeof(dhash)); + needs_power_cycle = false; + goto err; //No return } else if (subcommand == 0x4) { //changePIN @@ -462,6 +461,9 @@ int cbor_client_pin(const uint8_t *data, size_t len) { if (mbedtls_mpi_read_binary(&hkey.ctx.mbed_ecdh.Qp.Y, kay.data, kay.len) != 0) { CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER); } + if (needs_power_cycle) { + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_BLOCKED); + } uint8_t sharedSecret[64]; int ret = ecdh((uint8_t)pinUvAuthProtocol, &hkey.ctx.mbed_ecdh.Qp, sharedSecret); if (ret != 0) { @@ -591,6 +593,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) { low_flash_available(); resetPinUvAuthToken(); resetPersistentPinUvAuthToken(); + needs_power_cycle = false; goto err; // No return } else if (subcommand == 0x9 || subcommand == 0x5) { //getPinUvAuthTokenUsingPinWithPermissions @@ -627,6 +630,9 @@ int cbor_client_pin(const uint8_t *data, size_t len) { if (mbedtls_mpi_read_binary(&hkey.ctx.mbed_ecdh.Qp.Y, kay.data, kay.len) != 0) { CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER); } + if (needs_power_cycle) { + CBOR_ERROR(CTAP2_ERR_PIN_AUTH_BLOCKED); + } uint8_t sharedSecret[64]; int ret = ecdh((uint8_t)pinUvAuthProtocol, &hkey.ctx.mbed_ecdh.Qp, sharedSecret); if (ret != 0) { @@ -724,6 +730,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) { CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, 1)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x02)); CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, pinUvAuthToken_enc, 32 + poff)); + needs_power_cycle = false; } else { CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION); diff --git a/src/fido/fido.c b/src/fido/fido.c index c03124f..af4f790 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -483,11 +483,13 @@ void scan_all() { } extern void init_otp(); +extern bool needs_power_cycle; void init_fido() { scan_all(); #ifdef ENABLE_OTP_APP init_otp(); #endif + needs_power_cycle = false; } bool wait_button_pressed() { diff --git a/tests/pico-fido/test_010_pin.py b/tests/pico-fido/test_010_pin.py index 0e947f4..06443ae 100644 --- a/tests/pico-fido/test_010_pin.py +++ b/tests/pico-fido/test_010_pin.py @@ -51,7 +51,7 @@ def test_lockout(device, resetdevice, client_pin): res = client_pin.get_pin_retries() assert res[0] == attempts - if err == CtapError.ERR.PIN_AUTH_BLOCKED: + if e.value.code == CtapError.ERR.PIN_AUTH_BLOCKED: device.reboot() client_pin = ClientPin(resetdevice.client()._backend.ctap2) From 3f890757ac40b430e0c5df8ade8603968b76a9db Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 22 Jan 2026 01:00:18 +0100 Subject: [PATCH 05/12] Not present Signed-off-by: Pol Henarejos --- tools/words.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 tools/words.py diff --git a/tools/words.py b/tools/words.py deleted file mode 100644 index 4e17003..0000000 --- a/tools/words.py +++ /dev/null @@ -1 +0,0 @@ -words = ['shape', 'reject', 'trains', 'skirt', 'magnificent', 'sloppy', 'harsh', 'valuable', 'yak', 'knit', 'ghost', 'offer', 'necessary', 'hilarious', 'wealth', 'far-flung', 'scary', 'yoke', 'cruel', 'unbecoming', 'sin', 'draconian', 'undress', 'various', 'annoying', 'great', 'flashy', 'materialistic', 'spiritual', 'writer', 'prickly', 'therapeutic', 'curvy', 'terrific', 'paste', 'reminiscent', 'range', 'female', 'trees', 'cat', 'cow', 'furtive', 'run', 'swing', 'early', 'marked', 'terrify', 'wind', 'stretch', 'bells', 'eminent', 'deserted', 'nondescript', 'basketball', 'wine', 'boast', 'food', 'fowl', 'cheerful', 'kettle', 'jazzy', 'greasy', 'sick', 'sort', 'excuse', 'impolite', 'attraction', 'ultra', 'axiomatic', 'promise', 'blood', 'camp', 'macho', 'material', 'earthquake', 'window', 'taste', 'buzz', 'identify', 'education', 'hapless', 'perfect', 'stare', 'bell', 'snail', 'powerful', 'unarmed', 'company', 'mist', 'seat', 'empty', 'plantation', 'sheet', 'pinch', 'mate', 'null', 'obtain', 'jumbled', 'awful', 'loving', 'moaning', 'chief', 'lethal', 'crabby', 'preserve', 'scratch', 'tax', 'ink', 'quack', 'produce', 'madly', 'open', 'cagey', 'mountain', 'irritating', 'attack', 'oven', 'faithful', 'sharp', 'uncle', 'wicked', 'rigid', 'theory', 'try', 'wobble', 'cloth', 'wood', 'strip', 'surround', 'uneven', 'reach', 'bright', 'agonizing', 'crate', 'rock', 'moor', 'bike', 'tired', 'tenuous', 'beg', 'boiling', 'creator', 'chance', 'scared', 'flowers', 'eye', 'limping', 'yielding', 'understood', 'longing', 'love', 'quirky', 'homely', 'crown', 'waste', 'rustic', 'thoughtless', 'flimsy', 'glossy', 'part', 'good', 'receive', 'division', 'snails', 'attractive', 'cuddly', 'release', 'gamy', 'name', 'decorate', 'move', 'plot', 'star', 'writing', 'house', 'thaw', 'robust', 'testy', 'elated', 'calm', 'sneaky', 'tomatoes', 'disgusting', 'fence', 'capable', 'rural', 'melodic', 'hysterical', 'entertaining', 'man', 'ill-informed', 'misty', 'scatter', 'jump', 'rightful', 'educated', 'adjoining', 'abashed', 'disturbed', 'fade', 'stamp', 'stream', 'boorish', 'two', 'worry', 'thank', 'trot', 'delicate', 'argument', 'creepy', 'dependent', 'rough', 'symptomatic', 'authority', 'actually', 'join', 'ignorant', 'radiate', 'aboard', 'bead', 'energetic', 'abandoned', 'shy', 'raise', 'blind', 'talented', 'stroke', 'devilish', 'death', 'type', 'taboo', 'depressed', 'level', 'equable', 'activity', 'accidental', 'ski', 'purring', 'juicy', 'maid', 'decide', 'overconfident', 'pipe', 'afternoon', 'file', 'peaceful', 'delicious', 'continue', 'imperfect', 'glow', 'haircut', 'frequent', 'arrogant', 'toothbrush', 'refuse', 'meek', 'spectacular', 'homeless', 'half', 'grateful', 'old', 'psychedelic', 'obnoxious', 'bridge', 'pies', 'invention', 'hose', 'flood', 'badge', 'unhealthy', 'deadpan', 'owe', 'undesirable', 'dock', 'insect', 'rose', 'boil', 'warlike', 'abortive', 'wriggle', 'excellent', 'fear', 'nation', 'unknown', 'press', 'wasteful', 'boundary', 'abrasive', 'glamorous', 'bag', 'army', 'punishment', 'lettuce', 'system', 'queen', 'branch', 'fretful', 'flawless', 'flap', 'observation', 'juice', 'punch', 'pretend', 'pocket', 'simplistic', 'serve', 'oval', 'weary', 'mourn', 'river', 'selective', 'heat', 'include', 'filthy', 'amuck', 'tender', 'mix', 'towering', 'shut', 'sponge', 'transport', 'communicate', 'squalid', 'unit', 'smoke', 'carriage', 'clumsy', 'abiding', 'fish', 'grease', 'frogs', 'classy', 'slim', 'needless', 'nasty', 'equal', 'relax', 'noise', 'wiry', 'cheer', 'gold', 'insidious', 'bounce', 'past', 'same', 'design', 'power', 'probable', 'sheep', 'trucks', 'agree', 'exclusive', 'smoggy', 'fumbling', 'exercise', 'astonishing', 'stupendous', 'bad', 'charming', 'birthday', 'spiteful', 'toys', 'plant', 'abnormal', 'racial', 'squeamish', 'decorous', 'woman', 'protest', 'literate', 'inquisitive', 'skillful', 'sidewalk', 'internal', 'judicious', 'hall', 'paltry', 'safe', 'deeply', 'melt', 'direction', 'relieved', 'red', 'future', 'wander', 'loaf', 'fit', 'telling', 'aquatic', 'notice', 'apathetic', 'flame', 'look', 'show', 'sable', 'hallowed', 'miss', 'premium', 'pin', 'handsome', 'volleyball', 'adhesive', 'mind', 'helpless', 'lighten', 'industry', 'mother', 'feigned', 'permit', 'plain', 'flight', 'burn', 'unruly', 'damp', 'digestion', 'air', 'x-ray', 'hook', 'squealing', 'ablaze', 'cowardly', 'dinner', 'closed', 'things', 'toothpaste', 'gaudy', 'pretty', 'finicky', 'retire', 'amount', 'sticky', 'bless', 'visitor', 'screw', 'subsequent', 'absorbing', 'left', 'parched', 'guarded', 'ants', 'squeak', 'glue', 'umbrella', 'government', 'peep', 'unkempt', 'hard', 'foolish', 'daffy', 'letters', 'ask', 'language', 'harm', 'greedy', 'wanting', 'size', 'way', 'cute', 'satisfying', 'oranges', 'second', 'pigs', 'intend', 'cast', 'somber', 'assorted', 'decision', 'ugliest', 'chop', 'excite', 'lunch', 'possessive', 'volatile', 'pricey', 'cooing', 'tearful', 'tan', 'whirl', 'worm', 'curve', 'squash', 'ceaseless', 'suck', 'obsolete', 'rabbit', 'door', 'flag', 'program', 'gullible', 'disastrous', 'lopsided', 'substance', 'kind', 'feeling', 'shiny', 'hole', 'club', 'troubled', 'heady', 'rambunctious', 'questionable', 'massive', 'balance', 'envious', 'throne', 'condemned', 'zippy', 'interesting', 'zephyr', 'thundering', 'paddle', 'nimble', 'stranger', 'fertile', 'prevent', 'hydrant', 'messy', 'floor', 'boy', 'unused', 'meal', 'occur', 'rabbits', 'spicy', 'highfalutin', 'parcel', 'action', 'dispensable', 'tree', 'better', 'bushes', 'wheel', 'fact', 'guitar', 'courageous', 'threatening', 'typical', 'paper', 'flaky', 'spoon', 'sparkle', 'sturdy', 'march', 'detail', 'coal', 'ritzy', 'team', 'duck', 'drag', 'defective', 'chivalrous', 'zesty', 'disapprove', 'cure', 'succeed', 'glib', 'grubby', 'young', 'dashing', 'clover', 'signal', 'thunder', 'illegal', 'tumble', 'wrestle', 'soft', 'waggish', 'merciful', 'stain', 'receptive', 'choke', 'jail', 'nifty', 'coast', 'berserk', 'nod', 'chilly', 'magic', 'cool', 'employ', 'alert', 'low', 'handy', 'card', 'fail', 'plate', 'lake', 'vase', 'venomous', 'violet', 'form', 'daughter', 'guttural', 'appliance', 'wren', 'doll', 'brainy', 'extend', 'trick', 'flow', 'miscreant', 'yawn', 'son', 'street', 'land', 'wing', 'grandmother', 'certain', 'rhythm', 'pray', 'cover', 'swanky', 'wrathful', 'saw', 'strong', 'amazing', 'blue', 'slave', 'hurt', 'string', 'person', 'slow', 'warm', 'babies', 'tent', 'truthful', 'white', 'bustling', 'mouth', 'property', 'art', 'oceanic', 'zip', 'parallel', 'nappy', 'dime', 'porter', 'puzzling', 'appear', 'workable', 'hesitant', 'stuff', 'defeated', 'chunky', 'bath', 'mere', 'argue', 'mature', 'waiting', 'harmonious', 'command', 'weak', 'precede', 'disagree', 'colorful', 'unequaled', 'untidy', 'tug', 'embarrassed', 'work', 'broken', 'free', 'suspect', 'event', 'limit', 'cook', 'used', 'curved', 'current', 'jolly', 'ring', 'grip', 'bizarre', 'powder', 'stew', 'careful', 'cellar', 'rely', 'ill-fated', 'sand', 'respect', 'hard-to-find', 'mixed', 'scent', 'bite', 'confuse', 'burst', 'reflect', 'breakable', 'useless', 'combative', 'trust', 'godly', 'expect', 'spiky', 'statement', 'alarm', 'ahead', 'black-and-white', 'cumbersome', 'bore', 'interfere', 'winter', 'picture', 'meaty', 'ragged', 'grouchy', 'impress', 'potato', 'edge', 'cent', 'prefer', 'roasted', 'dance', 'spot', 'itchy', 'brash', 'motion', 'bawdy', 'tour', 'old-fashioned', 'muddled', 'downtown', 'doubt', 'fortunate', 'futuristic', 'exchange', 'clean', 'flower', 'whole', 'whine', 'versed', 'groovy', 'muddle', 'divide', 'huge', 'toad', 'fast', 'lonely', 'historical', 'annoy', 'mitten', 'cattle', 'unusual', 'houses', 'magical', 'outrageous', 'pass', 'belligerent', 'knot', 'believe', 'mess up', 'dam', 'market', 'protect', 'lame', 'tame', 'sedate', 'fanatical', 'uttermost', 'list', 'dysfunctional', 'drawer', 'dirty', 'structure', 'malicious', 'hat', 'melted', 'race', 'tidy', 'pickle', 'flagrant', 'tendency', 'torpid', 'stimulating', 'cup', 'doctor', 'color', 'skip', 'bikes', 'temper', 'offbeat', 'value', 'absent', 'adorable', 'arrange', 'fine', 'space', 'changeable', 'eggs', 'remind', 'general', 'clam', 'dream', 'loss', 'repair', 'alcoholic', 'macabre', 'imminent', 'canvas', 'subdued', 'rake', 'roof', 'solid', 'military', 'physical', 'useful', 'concern', 'dislike', 'lush', 'righteous', 'wandering', 'shelf', 'rare', 'zealous', 'linen', 'grain', 'tasteful', 'camera', 'can', 'pail', 'add', 'sophisticated', 'upset', 'tremble', 'flippant', 'nail', 'snakes', 'film', 'risk', 'synonymous', 'cloistered', 'visit', 'call', 'cross', 'agreement', 'husky', 'wash', 'windy', 'hum', 'acrid', 'odd', 'depend', 'elastic', 'groan', 'ban', 'sudden', 'follow', 'rail', 'soothe', 'remove', 'intelligent', 'domineering', 'grieving', 'gaze', 'knowledge', 'birds', 'boring', 'lumpy', 'embarrass', 'many', 'drum', 'voyage', 'icicle', 'labored', 'burly', 'superficial', 'truculent', 'ice', 'obese', 'royal', 'ugly', 'van', 'high-pitched', 'tie', 'sigh', 'vacation', 'dusty', 'unfasten', 'woozy', 'treat', 'dreary', 'mellow', 'bump', 'tail', 'freezing', 'rat', 'story', 'tickle', 'onerous', 'ball', 'hungry', 'brick', 'political', 'train', 'library', 'bubble', 'imported', 'helpful', 'dull', 'unlock', 'popcorn', 'stiff', 'moan', 'crow', 'cultured', 'scale', 'force', 'zany', 'greet', 'books', 'brave', 'sweet', 'bewildered', 'thoughtful', 'dirt', 'nippy', 'pear', 'easy', 'side', 'multiply', 'gather', 'fill', 'enthusiastic', 'plan', 'living', 'blot', 'number', 'degree', 'idiotic', 'profit', 'impossible', 'nervous', 'support', 'vigorous', 'shocking', 'bottle', 'boat', 'memorize', 'trousers', 'elegant', 'unsightly', 'important', 'fabulous', 'weigh', 'erratic', 'sassy', 'absurd', 'special', 'dog', 'jittery', 'kick', 'chess', 'travel', 'song', 'sad', 'vest', 'productive', 'scene', 'stupid', 'delight', 'statuesque', 'breathe', 'awesome', 'injure', 'beam', 'class', 'screeching', 'hour', 'blow', 'bolt', 'profuse', 'bored', 'overt', 'famous', 'scissors', 'unnatural', 'kitty', 'trip', 'ruin', 'incandescent', 'jaded', 'fax', 'top', 'adjustment', 'leg', 'bait', 'cheap', 'zebra', 'develop', 'coordinated', 'educate', 'engine', 'cream', 'nine', 'admire', 'remember', 'grey', 'act', 'earthy', 'quiet', 'wound', 'awake', 'ticket', 'mundane', 'drunk', 'squeal', 'chemical', 'colour', 'connection', 'encouraging', 'roomy', 'protective', 'vessel', 'steady', 'well-groomed', 'moldy', 'cart', 'coil', 'tall', 'subtract', 'rule', 'tricky', 'alike', 'ajar', 'crash', 'mushy', 'spotless', 'volcano', 'calculate', 'uptight', 'tawdry', 'iron', 'aftermath', 'chalk', 'difficult', 'three', 'flash', 'sun', 'numerous', 'talk', 'available', 'scattered', 'striped', 'smiling', 'seashore', 'face', 'sugar', 'tick', 'overrated', 'poke', 'suit', 'elite', 'liquid', 'reply', 'habitual', 'magenta', 'clear', 'tongue', 'field', 'raspy', 'temporary', 'provide', 'sleet', 'quickest', 'scream', 'spark', 'approve', 'detect', 'exist', 'entertain', 'plastic', 'wilderness', 'crowd', 'square', 'upbeat', 'ship', 'regular', 'analyze', 'hurried', 'bathe', 'sea', 'want', 'copy', 'debt', 'pest', 'practice', 'glistening', 'tight', 'periodic', 'ubiquitous', 'aloof', 'robin', 'smile', 'confused', 'admit', 'skinny', 'whistle', 'secretary', 'satisfy', 'bulb', 'beautiful', 'unique', 'boot', 'lovely', 'inconclusive', 'childlike', 'pleasure', 'slap', 'ashamed', 'humdrum', 'interrupt', 'ignore', 'page', 'eatable', 'married', 'delay', 'object', 'foot', 'passenger', 'extra-small', 'instrument', 'industrious', 'resolute', 'dangerous', 'rate', 'big', 'deer', 'line', 'high', 'abject', 'hunt', 'lively', 'book', 'heal', 'suspend', 'smooth', 'hobbies', 'achiever', 'spring', 'possible', 'mice', 'elfin', 'snotty', 'shop', 'inexpensive', 'throat', 'suppose', 'straw', 'chicken', 'omniscient', 'steep', 'mean', 'shoe', 'moon', 'avoid', 'vanish', 'mysterious', 'fresh', 'meat', 'simple', 'wild', 'cheat', 'erect', 'kaput', 'illustrious', 'didactic', 'plough', 'fork', 'icy', 'joke', 'exotic', 'notebook', 'calendar', 'encourage', 'root', 'sulky', 'loud', 'reflective', 'school', 'expand', 'jelly', 'irritate', 'anger', 'addition', 'addicted', 'boundless', 'representative', 'lacking', 'airport', 'handle', 'hammer', 'aspiring', 'fasten', 'painful', 'cannon', 'noisy', 'offend', 'hateful', 'bedroom', 'steer', 'apparatus', 'realize', 'pastoral', 'science', 'one', 'oatmeal', 'zoo', 'dead', 'quaint', 'amused', 'exciting', 'pale', 'stem', 'end', 'discussion', 'arrive', 'bang', 'selection', 'tough', 'cushion', 'afterthought', 'dramatic', 'governor', 'sack', 'yell', 'learn', 'direful', 'locket', 'skin', 'describe', 'clever', 'obedient', 'real', 'attempt', 'surprise', 'chin', 'trace', 'pizzas', 'cough', 'weight', 'repulsive', 'hop', 'piquant', 'expert', 'box', 'dress', 'penitent', 'plants', 'substantial', 'live', 'laughable', 'abhorrent', 'friend', 'growth', 'delightful', 'sweltering', 'finger', 'monkey', 'second-hand', 'compete', 'north', 'tasteless', 'truck', 'complete', 'outgoing', 'parsimonious', 'unite', 'faulty', 'separate', 'crime', 'stitch', 'wonder', 'wary', 'squeeze', 'measure', 'treatment', 'ambiguous', 'pollution', 'cold', 'laborer', 'night', 'ambitious', 'pencil', 'bird', 'nosy', 'effect', 'soap', 'acceptable', 'pathetic', 'dust', 'spoil', 'amusing', 'lip', 'elderly', 'optimal', 'toe', 'wire', 'angry', 'example', 'heap', 'eyes', 'sneeze', 'six', 'best', 'beds', 'disgusted', 'summer', 'hate', 'petite', 'kindhearted', 'damaging', 'explode', 'steel', 'nonchalant', 'thick', 'fire', 'tip', 'unequal', 'smell', 'peel', 'lazy', 'wealthy', 'enchanting', 'chase', 'sound', 'miniature', 'efficacious', 'bouncy', 'verdant', 'abaft', 'decay', 'silent', 'late', 'grotesque', 'secretive', 'holistic', 'wiggly', 'nose', 'tranquil', 'sleep', 'pat', 'count', 'shave', 'wipe', 'seemly', 'flock', 'dare', 'wonderful', 'road', 'machine', 'children', 'stir', 'clap', 'apparel', 'strengthen', 'knock', 'pets', 'muscle', 'allow', 'insurance', 'thin', 'destruction', 'superb', 'car', 'nauseating', 'few', 'deceive', 'creature', 'momentous', 'tacit', 'curtain', 'pause', 'cooperative', 'humorous', 'hope', 'unbiased', 'clammy', 'consider', 'careless', 'sign', 'aware', 'absorbed', 'silver', 'back', 'adventurous', 'stay', 'brief', 'business', 'attract', 'pack', 'dear', 'sense', 'fireman', 'mark', 'scribble', 'girls', 'word', 'change', 'shelter', 'natural', 'funny', 'kiss', 'breath', 'holiday', 'celery', 'borrow', 'mountainous', 'coach', 'nebulous', 'harbor', 'pumped', 'round', 'voracious', 'planes', 'brush', 'common', 'trite', 'dizzy', 'grate', 'five', 'copper', 'wretched', 'fat', 'position', 'blink', 'enjoy', 'cluttered', 'legal', 'perform', 'measly', 'collect', 'tow', 'report', 'friction', 'splendid', 'silky', 'soak', 'horses', 'vegetable', 'frighten', 'regret', 'scintillating', 'welcome', 'scandalous', 'spill', 'wool', 'shiver', 'silly', 'title', 'handsomely', 'trouble', 'juggle', 'whispering', 'day', 'claim', 'women', 'repeat', 'hellish', 'rainy', 'first', 'expensive', 'fearless', 'yummy', 'wreck', 'reason', 'cable', 'prepare', 'step', 'plucky', 'bear', 'victorious', 'milky', 'sore', 'knee', 'lunchroom', 'unable', 'touch', 'trade', 'town', 'neighborly', 'approval', 'income', 'steadfast', 'scrub', 'trap', 'accessible', 'apologise', 'scare', 'bow', 'noxious', 'snatch', 'mine', 'rhetorical', 'jar', 'skate', 'staking', 'stop', 'earn', 'lamentable', 'noiseless', 'narrow', 'ruthless', 'harmony', 'abstracted', 'button', 'dynamic', 'bite-sized', 'quilt', 'leather', 'busy', 'marry', 'festive', 'thirsty', 'voice', 'majestic', 'jumpy', 'immense', 'obscene', 'pine', 'determined', 'lavish', 'agreeable', 'savory', 'unsuitable', 'grandfather', 'fragile', 'settle', 'self', 'pig', 'utter', 'stove', 'cherries', 'different', 'efficient', 'secret', 'organic', 'sister', 'cake', 'fall', 'exuberant', 'opposite', 'well-to-do', 'caption', 'vacuous', 'alive', 'smash', 'zonked', 'black', 'religion', 'maddening', 'wet', 'collar', 'sleepy', 'horn', 'seed', 'punish', 'last', 'advice', 'well-made', 'hot', 'wish', 'horse', 'credit', 'blush', 'orange', 'use', 'quixotic', 'murky', 'reproduce', 'wave', 'hurry', 'bit', 'infamous', 'soup', 'flowery', 'pen', 'brake', 'pump', 'unaccountable', 'actor', 'building', 'yarn', 'gruesome', 'angle', 'place', 'cut', 'obsequious', 'texture', 'short', 'crowded', 'spotted', 'rabid', 'concentrate', 'please', 'thinkable', 'gusty', 'disillusioned', 'laugh', 'mindless', 'bloody', 'shame', 'zipper', 'knotty', 'frog', 'tempt', 'learned', 'spy', 'hill', 'utopian', 'modern', 'craven', 'idea', 'wrap', 'load', 'new', 'quarrelsome', 'cry', 'dazzling', 'vivacious', 'cloudy', 'ripe', 'mailbox', 'overwrought', 'bitter', 'spurious', 'crib', 'vein', 'play', 'comparison', 'distance', 'blushing', 'scorch', 'ludicrous', 'thing', 'spell', 'bomb', 'start', 'squirrel', 'overflow', 'near', 'pointless', 'order', 'listen', 'belief', 'needle', 'fog', 'heartbreaking', 'hideous', 'wide', 'ill', 'group', 'beginner', 'tangible', 'escape', 'abusive', 'scarce', 'basket', 'spade', 'tremendous', 'dinosaurs', 'whisper', 'view', 'aberrant', 'sky', 'switch', 'elbow', 'aunt', 'scarf', 'songs', 'uppity', 'existence', 'discreet', 'heavenly', 'pour', 'tire', 'matter', 'instinctive', 'time', 'demonic', 'scrape', 'placid', 'puffy', 'violent', 'wail', 'debonair', 'wrong', 'irate', 'private', 'giants', 'carry', 'right', 'daily', 'able', 'foamy', 'full', 'farm', 'dapper', 'rot', 'ethereal', 'icky', 'cause', 'girl', 'advertisement', 'mighty', 'marvelous', 'male', 'earsplitting', 'adaptable', 'familiar', 'sip', 'obeisant', 'prose', 'slimy', 'hug', 'youthful', 'suggestion', 'interest', 'cabbage', 'standing', 'territory', 'shrill', 'chubby', 'outstanding', 'bare', 'drop', 'grumpy', 'precious', 'sweater', 'nerve', 'unpack', 'drab', 'battle', 'goofy', 'naive', 'little', 'tin', 'hair', 'room', 'recondite', 'friends', 'tap', 'teaching', 'cars', 'furry', 'minister', 'sparkling', 'fair', 'clip', 'butter', 'expansion', 'eggnog', 'drain', 'front', 'reduce', 'pull', 'wistful', 'price', 'point', 'carpenter', 'snore', 'vast', 'complain', 'afraid', 'invincible', 'jam', 'kindly', 'help', 'curl', 'deserve', 'makeshift', 'office', 'mom', 'mint', 'rude', 'guess', 'decisive', 'nostalgic', 'sisters', 'rub', 'walk', 'hover', 'tasty', 'tested', 'vulgar', 'snobbish', 'haunt', 'true', 'reign', 'capricious', 'fancy', 'deafening', 'reading', 'church', 'basin', 'observe', 'stage', 'fallacious', 'introduce', 'bury', 'rebel', 'telephone', 'thought', 'yellow', 'wink', 'error', 'turkey', 'shrug', 'history', 'loose', 'shoes', 'appreciate', 'attend', 'foregoing', 'frame', 'pop', 'soggy', 'aboriginal', 'pedal', 'tiresome', 'distinct', 'baby', 'border', 'wide-eyed', 'teeny-tiny', 'quartz', 'carve', 'trashy', 'ladybug', 'baseball', 'berry', 'roll', 'slope', 'pushy', 'sniff', 'post', 'ready', 'park', 'pink', 'witty', 'acoustics', 'stale', 'guiltless', 'crook', 'keen', 'donkey', 'grab', 'swim', 'afford', 'compare', 'cycle', 'flavor', 'frail', 'memory', 'tease', 'float', 'frantic', 'ratty', 'paint', 'crack', 'store', 'whimsical', 'increase', 'rest', 'grape', 'yard', 'tiny', 'applaud', 'shade', 'jagged', 'thankful', 'acidic', 'wrist', 'silk', 'glorious', 'pancake', 'impartial', 'tedious', 'belong', 'invent', 'rush', 'like', 'push', 'brawny', 'reward', 'fantastic', 'grandiose', 'lowly', 'eight', 'fairies', 'shake', 'thrill', 'accurate', 'poor', 'lackadaisical', 'four', 'obey', 'preach', 'incredible', 'quill', 'womanly', 'soda', 'base', 'hissing', 'lucky', 'puny', 'stereotyped', 'murder', 'watery', 'heavy', 'painstaking', 'marble', 'knife', 'third', 'home', 'stick', 'curly', 'manage', 'fang', 'crazy', 'drown', 'green', 'salty', 'health', 'fetch', 'hulking', 'desire', 'blue-eyed', 'attach', 'knowledgeable', 'well-off', 'examine', 'year', 'flesh', 'judge', 'tub', 'bone', 'birth', 'broad', 'neat', 'board', 'plane', 'shaggy', 'coherent', 'letter', 'deep', 'detailed', 'enchanted', 'fold', 'improve', 'incompetent', 'spiders', 'gorgeous', 'suffer', 'remain', 'rich', 'salt', 'lamp', 'coat', 'swift', 'partner', 'honey', 'pan', 'animated', 'corn', 'normal', 'oafish', 'lewd', 'bake', 'medical', 'peck', 'hands', 'thumb', 'mask', 'hollow', 'alluring', 'curious', 'abounding', 'invite', 'puncture', 'straight', 'station', 'bed', 'save', 'behavior', 'guarantee', 'sour', 'stingy', 'delirious', 'forgetful', 'panoramic', 'crush', 'hypnotic', 'bashful', 'minute', 'dogs', 'concerned', 'unwieldy', 'tramp', 'driving', 'close', 'country', 'quicksand', 'perpetual', 'sincere', 'sofa', 'pie', 'fly', 'war', 'lumber', 'innate', 'spray', 'cemetery', 'prick', 'average', 'rifle', 'grass', 'happy', 'toy', 'supreme', 'search', 'aback', 'suggest', 'relation', 'tacky', 'animal', 'sail', 'enter', 'scold', 'scrawny', 'morning', 'smart', 'bruise', 'vagabond', 'ocean', 'horrible', 'sprout', 'juvenile', 'selfish', 'grade', 'request', 'brother', 'bleach', 'unadvised', 'eager', 'consist', 'jeans', 'charge'] From bc6ebdd069e2e4fc6efa7a2afaf4a1bc1bb55a82 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 22 Jan 2026 12:09:42 +0100 Subject: [PATCH 06/12] Upgrade to new layout Signed-off-by: Pol Henarejos --- CMakeLists.txt | 4 ++-- pico-keys-sdk | 2 +- src/fido/CMakeLists.txt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cc83a2..3d70791 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ cmake_minimum_required(VERSION 3.13) if(ESP_PLATFORM) set(DENABLE_POWER_ON_RESET 0) -set(EXTRA_COMPONENT_DIRS src pico-keys-sdk/src) +set(EXTRA_COMPONENT_DIRS pico-keys-sdk/config/esp32/components src/fido) include($ENV{IDF_PATH}/tools/cmake/project.cmake) else() @@ -161,7 +161,7 @@ if(ENABLE_EMULATION) -Wl,--gc-sections ) endif (APPLE) - target_link_libraries(pico_fido PRIVATE pthread m) + target_link_libraries(pico_fido PRIVATE pico_keys_sdk mbedtls pthread m) else() target_link_libraries(pico_fido PRIVATE pico_keys_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id pico_aon_timer tinyusb_device tinyusb_board) pico_add_extra_outputs(${CMAKE_PROJECT_NAME}) diff --git a/pico-keys-sdk b/pico-keys-sdk index 8a0ef0b..b5c2e55 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 8a0ef0b30cf4fa586b415a37578695efe35a04be +Subproject commit b5c2e55c7196a2e12429b30b971e152001588eae diff --git a/src/fido/CMakeLists.txt b/src/fido/CMakeLists.txt index e6dfbac..e9c6774 100644 --- a/src/fido/CMakeLists.txt +++ b/src/fido/CMakeLists.txt @@ -1,6 +1,6 @@ idf_component_register( SRCS ${SOURCES} - INCLUDE_DIRS . ../../pico-keys-sdk/src ../../pico-keys-sdk/src/fs ../../pico-keys-sdk/src/rng ../../pico-keys-sdk/src/usb ../../pico-keys-sdk/tinycbor/src - REQUIRES esp_tinyusb mbedtls efuse + INCLUDE_DIRS . + REQUIRES esp_tinyusb mbedtls efuse pico-keys-sdk ) idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON) From f2eef5b839a9da1bf5937bb218450ac5e44ac601 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 22 Jan 2026 12:33:08 +0100 Subject: [PATCH 07/12] Use new VID:PID allocated to Pico Fido. Signed-off-by: Pol Henarejos --- CMakeLists.txt | 3 +++ README.md | 4 ++-- pico-keys-sdk | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d70791..bd9fd12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,9 @@ cmake_minimum_required(VERSION 3.13) +set(USB_VID 0x2E8A) +set(USB_PID 0x10FE) + if(ESP_PLATFORM) set(DENABLE_POWER_ON_RESET 0) set(EXTRA_COMPONENT_DIRS pico-keys-sdk/config/esp32/components src/fido) diff --git a/README.md b/README.md index e12f571..fd92c56 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,9 @@ Microcontrollers RP2350 and ESP32-S3 are designed to support secure environments If you own a Raspberry Pico (RP2040 or RP2350), go to [Download page](https://www.picokeys.com/getting-started/), select your vendor and model and download the proper firmware; or go to [Release page](https://www.github.com/polhenarejos/pico-fido/releases/) and download the UF2 file for your board. -Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you plan to use it with OpenSC or similar tools, you should modify Info.plist of CCID driver to add these VID/PID or use the [PicoKey App](https://www.picokeys.com/picokeyapp/ "PicoKey App"). +UF2 files are shiped with a VID/PID granted by RaspberryPi (2E8A:10FE). If you plan to use it with OpenSC or similar tools, you should modify Info.plist of CCID driver to add these VID/PID or use the [PicoKey App](https://www.picokeys.com/picokeyapp/ "PicoKey App"). -You can use whatever VID/PID (i.e., 234b:0000 from FISJ), but remember that you are not authorized to distribute the binary with a VID/PID that you do not own. +You can use whatever VID/PID for internal purposes, but remember that you are not authorized to distribute the binary with a VID/PID that you do not own. Note that the [PicoKey App](https://www.picokeys.com/picokeyapp/ "PicoKey App") is the most recommended. diff --git a/pico-keys-sdk b/pico-keys-sdk index b5c2e55..42267cb 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit b5c2e55c7196a2e12429b30b971e152001588eae +Subproject commit 42267cb237cb0a610ad7d3aa3feab9baa31a0fa1 From 3c208008392672eab1020df6f80dbbd9d414ded5 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 24 Jan 2026 01:14:46 +0100 Subject: [PATCH 08/12] Add rtc to credential. Signed-off-by: Pol Henarejos --- src/fido/cbor_get_assertion.c | 2 +- src/fido/credential.c | 10 +++++++++- src/fido/credential.h | 3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/fido/cbor_get_assertion.c b/src/fido/cbor_get_assertion.c index fac8e01..3ba9fb5 100644 --- a/src/fido/cbor_get_assertion.c +++ b/src/fido/cbor_get_assertion.c @@ -428,7 +428,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) { if (!silent) { for (int i = 0; i < numberOfCredentials; i++) { for (int j = i + 1; j < numberOfCredentials; j++) { - if (creds[j].creation > creds[i].creation) { + if (creds[j].board_creation > creds[i].board_creation) { Credential tmp = creds[j]; creds[j] = creds[i]; creds[i] = tmp; diff --git a/src/fido/credential.c b/src/fido/credential.c index 645417d..46b079a 100644 --- a/src/fido/credential.c +++ b/src/fido/credential.c @@ -29,6 +29,7 @@ #include "files.h" #include "otp.h" +extern bool has_set_rtc(); int credential_derive_chacha_key(uint8_t *outk, const uint8_t *); static int credential_silent_tag(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash, uint8_t *outk) { @@ -148,6 +149,10 @@ int credential_create(CborCharString *rpId, } CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &mapEncoder2)); } + if (has_set_rtc()) { + CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0C)); + CBOR_CHECK(cbor_encode_uint(&mapEncoder, (uint64_t) get_rtc_time())); + } CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder)); size_t rs = cbor_encoder_get_buffer_size(&encoder, cred_id); *cred_id_len = CRED_PROTO_LEN + CRED_IV_LEN + (uint16_t)rs + CRED_TAG_LEN + CRED_SILENT_TAG_LEN; @@ -220,7 +225,7 @@ int credential_load(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *r CBOR_FIELD_GET_TEXT(cred->userDisplayName, 1); } else if (val_u == 0x06) { - CBOR_FIELD_GET_UINT(cred->creation, 1); + CBOR_FIELD_GET_UINT(cred->board_creation, 1); } else if (val_u == 0x07) { cred->extensions.present = true; @@ -255,6 +260,9 @@ int credential_load(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *r } CBOR_PARSE_MAP_END(_f1, 2); } + else if (val_u == 0x0C) { + CBOR_FIELD_GET_UINT(cred->rtc_creation, 1); + } else { CBOR_ADVANCE(1); } diff --git a/src/fido/credential.h b/src/fido/credential.h index a77b72f..76f4e67 100644 --- a/src/fido/credential.h +++ b/src/fido/credential.h @@ -43,7 +43,7 @@ typedef struct Credential { CborByteString userId; CborCharString userName; CborCharString userDisplayName; - uint64_t creation; + uint64_t board_creation; CredExtensions extensions; const bool *use_sign_count; int64_t alg; @@ -51,6 +51,7 @@ typedef struct Credential { CborByteString id; CredOptions opts; bool present; + uint64_t rtc_creation; } Credential; #define CRED_PROT_UV_OPTIONAL 0x01 From 8e6f571b48620dd9b54cc621313d3a8f4a67e793 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 24 Jan 2026 01:15:23 +0100 Subject: [PATCH 09/12] Move rtc Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 42267cb..860f77a 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 42267cb237cb0a610ad7d3aa3feab9baa31a0fa1 +Subproject commit 860f77a45bc6d4e4ba37c7b04422f6e8f22f28ab From 8ea118fe91a69fd90511bf1bf51b6f28477ccbe8 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 26 Jan 2026 01:18:51 +0100 Subject: [PATCH 10/12] Fix OATH in iOS Authenticator. Fixes #248. For strange reason, iOS app doesn't follow strictly YKOATH spec. When there are remaining bytes after serial, it assumes there's challenge (and thus, access code), but algorithm 7B is there. Apparently algorithm 7B is only returned when challenge is present but I could not see where it is used. Signed-off-by: Pol Henarejos --- src/fido/oath.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/fido/oath.c b/src/fido/oath.c index 0c293c7..f8de9a7 100644 --- a/src/fido/oath.c +++ b/src/fido/oath.c @@ -94,22 +94,22 @@ int oath_select(app_t *a, uint8_t force) { res_APDU[res_APDU_size++] = sizeof(challenge); memcpy(res_APDU + res_APDU_size, challenge, sizeof(challenge)); res_APDU_size += sizeof(challenge); - } - file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF); - if (file_has_data(ef_otp_pin)) { - const uint8_t *pin_data = file_get_data(ef_otp_pin); - res_APDU[res_APDU_size++] = TAG_PIN_COUNTER; + res_APDU[res_APDU_size++] = TAG_ALGO; res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = *pin_data; + res_APDU[res_APDU_size++] = ALG_HMAC_SHA1; } - res_APDU[res_APDU_size++] = TAG_ALGO; - res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = ALG_HMAC_SHA1; if (is_nk) { res_APDU[res_APDU_size++] = TAG_SERIAL_NUMBER; res_APDU[res_APDU_size++] = 8; memcpy(res_APDU + res_APDU_size, pico_serial_str, 8); res_APDU_size += 8; + file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF); + if (file_has_data(ef_otp_pin)) { + const uint8_t *pin_data = file_get_data(ef_otp_pin); + res_APDU[res_APDU_size++] = TAG_PIN_COUNTER; + res_APDU[res_APDU_size++] = 1; + res_APDU[res_APDU_size++] = *pin_data; + } } apdu.ne = res_APDU_size; return PICOKEY_OK; From cfd22c2d2c91c053642840b873c82d8de12a1ca5 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 26 Jan 2026 01:20:22 +0100 Subject: [PATCH 11/12] Fix ccid max packet length & interface naming. Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 860f77a..20f2b3b 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 860f77a45bc6d4e4ba37c7b04422f6e8f22f28ab +Subproject commit 20f2b3b74b4b86eaf32b12aee8cf093a0c9263fc From bea7706d63f4b4ed5859e81635cf3c14c10fa859 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 26 Jan 2026 01:27:12 +0100 Subject: [PATCH 12/12] Fix emulation build Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 20f2b3b..668b1ac 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 20f2b3b74b4b86eaf32b12aee8cf093a0c9263fc +Subproject commit 668b1ac1dd2fdd0934ae1f92bea8e266e8319f4f