Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

YubiKey index is not stable #161

Open
antelle opened this issue May 28, 2020 · 6 comments
Open

YubiKey index is not stable #161

antelle opened this issue May 28, 2020 · 6 comments

Comments

@antelle
Copy link

antelle commented May 28, 2020

Hi! I'm trying to use the library to enumerate connected YubiKeys to offer a way of selecting which YubiKey to use in the product, here's a piece of code I'm using to test it (on macOS):

    for (int i = 0; i < 100; i++) {
        YK_KEY *yk = nullptr;

        if (!(yk = yk_open_key(0))) {
            throwYubiKeyError(env, "yk_open_key");
            return result;
        }

        unsigned int serial;
        if (!yk_get_serial(yk, 1, 0, &serial)) {
            throwYubiKeyError(env, "yk_get_serial");
            return result;
        }
        std::cout << serial << "\n";

        yk_close_key(yk);
    }

When two YubiKeys are connected, the output contains two of YubiKeys in random order. Similarly, ykinfo -sn1 gives a random serial.

What would be the proper way to get the list of YubiKeys?

The issue seems to be here, where a set is converted to an array, which is supposed to give results in random order indeed.

I tried to figure out how you do it in ykman and came across this hack, which is actually how the proper yubikey is selected. Perhaps something like yk_open_all_keys would make more sense rather than doing it this way?

@Ken-CA
Copy link

Ken-CA commented Jun 26, 2020

Was there any resolution to this issue? I have a similar problem. I am creating an MacOS utility to program multiple keys via a USB hub. When more than one key is connected to the system, the index associated with each of the keys changes in an apparent random order. By that I mean if I have three keys inserted at once... and I enumerate the list of keys.. the key at any given index will change randomly when trying to open a key at a specific index.

I was hoping there was a way to save the USB device path.. and then access the key using that path reference, so as to open a specific key, but there appears to be no method in the personalization library to do that. Any advice would be most appreciated.

Another option would be to receive a list of key serial numbers and then open a specific key with the matching serial.

@antelle
Copy link
Author

antelle commented Jun 26, 2020

@Ken-CA I ended up in retrying a number of times until we get the right YubiKey.

Additionally if VID and PID are provided, it's possible to use yk_open_key_vid_pid method, which opens a random YubiKey but with specified parameters, this narrows down the list a bit. However it would be very nice to have a proper solution instead of this hack.

@Ken-CA
Copy link

Ken-CA commented Jun 26, 2020

@antelle, agreed. It would be nice to have a more deterministic way to open a key... either with a USB identifier or the serial number. I looked at the code and found the same thing you mention... with the conversion from a CFSetRef to an array. Since this is not ordered, the function support provided via an index is rather useless.

The open function appears to return a void pointer to a device. I wonder if it would be more helpful to return a set of pointers to all of the devices matching the vid/pid? Then, we could just hold on to that and then enumerate the set.

Doing so still creates the additional problem that if a key is removed or added.. the set of pointers needs to be expanded or reduced. This is become quite problematic...lol. There has to be a better way to reference keys by something unique in the USB subsystem?

Two questions come to mind... If I open each key and hold on to the device pointer...

  1. will that device pointer remain valid as long as the key is inserted and
  2. what happens to that device pointer if the user removes the key

@Ken-CA
Copy link

Ken-CA commented Jun 29, 2020

No word from YubiCo yet. This is a real problem as it makes all of the CLI tools the take an index parameter rather useless. If I can't depend that the index value points to a specific key, then CLI tools like ykpersonalize may end up programing the wrong key. A better implementation would be to allow a serial number to be passed in as a parameter. Another option is to offer a function that returns the set of keys...rather than an array.

@Ken-CA
Copy link

Ken-CA commented Jul 2, 2020

@antelle Not sure if this will help you in your situation, but the way I got around this was to use the HIDManager (MacOS) to list devices based on vid/pid, filter that list for devices with usagePage=1 and usage=6. This return one device handle per YubiKey. I then save a reference to that device handle. I also rewrote the YubiCo open key function to take a device handle rather than an index. I can then guarantee that I am opening the correct key.

@dragon788
Copy link

I came over here to report a similar issue trying to use the tool, querying ykpersonalize -N0 -d repeatedly results in the output device and firmware version changing every couple of calls when multiple Yubikeys are plugged in.

I'm guessing it also isn't safe to assume that the "show serial in USB descriptor" is consistently enabled on large batches of Yubikeys if they are a mix of the Neo/YK4/YK5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants