diff --git a/fido2/ctap.c b/fido2/ctap.c index 4e88dd6..f6be44e 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -777,7 +777,18 @@ int ctap_filter_invalid_credentials(CTAP_getAssertion * GA) if (! ctap_authenticate_credential(&GA->rp, &GA->creds[i])) { printf1(TAG_GA, "CRED #%d is invalid\n", GA->creds[i].credential.id.count); - GA->creds[i].credential.id.count = 0; // invalidate +#ifdef ENABLE_U2F_EXTENSIONS + if (is_extension_request((uint8_t*)&GA->creds[i].credential.id, sizeof(CredentialId))) + { + printf1(TAG_EXT, "CRED #%d is extension\n", GA->creds[i].credential.id.count); + count++; + } + else +#endif + { + GA->creds[i].credential.id.count = 0; // invalidate + } + } else { @@ -999,8 +1010,20 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) ret = cbor_encoder_create_map(encoder, &map, map_size); check_ret(ret); - ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0); - check_retr(ret); +#ifdef ENABLE_U2F_EXTENSIONS + if ( is_extension_request((uint8_t*)&GA.creds[validCredCount - 1].credential.id, sizeof(CredentialId)) ) + { + ret = cbor_encode_int(&map,RESP_authData); + check_ret(ret); + ret = cbor_encode_byte_string(&map, auth_data_buf, sizeof(CTAP_authDataHeader)); + check_ret(ret); + } + else +#endif + { + ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0); + check_retr(ret); + } /*for (int j = 0; j < GA.credLen; j++)*/ /*{*/ diff --git a/fido2/extensions/extensions.c b/fido2/extensions/extensions.c index 97bbe0a..d14cab8 100644 --- a/fido2/extensions/extensions.c +++ b/fido2/extensions/extensions.c @@ -82,7 +82,7 @@ int16_t extend_fido2(CredentialId * credid, uint8_t * output) { if (is_extension_request((uint8_t*)credid, sizeof(CredentialId))) { - bridge_u2f_to_solo(output, (uint8_t*)credid, sizeof(CredentialId)); + output[0] = bridge_u2f_to_solo(output+1, (uint8_t*)credid, sizeof(CredentialId)); return 1; } else diff --git a/fido2/extensions/solo.c b/fido2/extensions/solo.c index 4637b89..1a86422 100644 --- a/fido2/extensions/solo.c +++ b/fido2/extensions/solo.c @@ -31,7 +31,7 @@ #include "log.h" #include APP_CONFIG -// output must be at least 72 bytes +// output must be at least 71 bytes int16_t bridge_u2f_to_solo(uint8_t * output, uint8_t * keyh, int keylen) { int8_t ret = 0; diff --git a/tools/solotool.py b/tools/solotool.py index aafe5f5..1573979 100755 --- a/tools/solotool.py +++ b/tools/solotool.py @@ -201,6 +201,24 @@ class SoloClient: return res.signature[1:] + def exchange_fido2(self, cmd, addr=0, data=b"A" * 16): + chal = "B" * 32 + + req = SoloClient.format_request(cmd, addr, data) + + assertions, client_data = self.client.get_assertion( + self.host, chal, [{"id": req, "type": "public-key"}] + ) + if len(assertions) < 1: + raise RuntimeError("Device didn't respond to FIDO2 extended assertion") + + res = assertions[0] + ret = res.signature[0] + if ret != CtapError.ERR.SUCCESS: + raise RuntimeError("Device returned non-success code %02x" % (ret,)) + + return res.signature[1:] + def bootloader_version(self,): data = self.exchange(SoloBootloader.version) if len(data) > 2: @@ -208,7 +226,7 @@ class SoloClient: return data[0] def solo_version(self,): - data = self.exchange_u2f(SoloExtension.version) + data = self.exchange_fido2(SoloExtension.version) return (data[0], data[1], data[2]) def write_flash(self, addr, data): @@ -585,6 +603,7 @@ def solo_main(): action="store_true", help="Continuously dump random numbers generated from Solo.", ) + parser.add_argument("--wink", action="store_true", help="HID Wink command.") parser.add_argument( "--reset", @@ -596,6 +615,9 @@ def solo_main(): action="store_true", help="Verify that the Solo firmware is from SoloKeys. Check firmware version.", ) + parser.add_argument( + "--version", action="store_true", help="Check firmware version on Solo." + ) args = parser.parse_args() p = SoloClient() @@ -627,6 +649,9 @@ def solo_main(): else: print("Unknown fingerprint! ", cert.fingerprint(hashes.SHA256())) + args.version = True + + if args.version: try: v = p.solo_version() print("Version: ", v)