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

Initial yubikey backend keytype support #418

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

tomis007
Copy link

@tomis007 tomis007 commented Feb 8, 2025

Same PR for initial yubikey piv support with the intermediate commits removed.

I also removed:

  • changes to the config parsing (will address in another pr)
  • prompting for yubikey pin (right now uses the default PIN)

Hopefully this helps for reviewing / testing. I think I also addressed all your comments from the previous review. Thank you for your help!

I do think the prompting for the PIN is important to avoid needing to store the pin anywhere, so once we get this PR done I can rework and submit that one separately

@tomis007 tomis007 mentioned this pull request Feb 8, 2025
@Foxboron
Copy link
Owner

Foxboron commented Feb 8, 2025

Please stop making new PRs :) Rebase and force-push the branch in-place is much easier instead of leaving 3 PRs around in the project.

@tomis007
Copy link
Author

tomis007 commented Feb 8, 2025

Sure, I'll do that going forward, I didn't know that worked in a github PR my bad!

@tomis007
Copy link
Author

tomis007 commented Feb 8, 2025

Would it be helpful if rebased and force pushed this commit PR over #413? I can then use this one for the prompt support PR

@Foxboron
Copy link
Owner

Would it be helpful if rebased and force pushed this commit PR over #413? I can then use this one for the prompt support PR

Nah, no we can work in this branch :)

Copy link
Owner

@Foxboron Foxboron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for splitting stuff up :) Makes easier to review this!

PublicKey string `json:"PublicKey"`
}

var YK *piv.YubiKey
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason we can't throw the piv connetion into the Yubikey struct?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to do that originally but I ended up needing to open up a piv connection and track piv state in YubikeyFromBytes during the signing workflow and it became more complicated. I ended up going with the most simple approach to start

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But can't we just have a pointer in the struct and use connectToYubikey() as a struct method when the actual card is needed?

Everything seems fairly self-contained at the moment?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That approach works for creating keys, but the tricky part is in the Signer interface. the piv-go library only lets you have one handle to the yubikey open at once (https://github.com/go-piv/piv-go/blob/0383b0aa884b2b642e9e3446ea01ba22ccadc83a/v2/piv/piv.go#L107). When you defer yk-piv.Close() after creating the handle in Signer() the signing operation happens after the function is returned and by then the handle is closed. If you leave the handle open you can't open a new handle to the yubikey for future operations.

I can make it work but I would likely need to change the Signer interface to return a function that gets called after signing operations to appropriately Close the handle. What do you think about that approach?

@tomis007
Copy link
Author

tomis007 commented Feb 17, 2025

Updated with the requested changes, I also verified that using sbctl to create a key with the yubikey type and signing files is working (for me at least) with the default pin

PublicKey string `json:"PublicKey"`
}

var YK *piv.YubiKey
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But can't we just have a pointer in the struct and use connectToYubikey() as a struct method when the actual card is needed?

Everything seems fairly self-contained at the moment?

Comment on lines +256 to +259
yubiData := YubikeyData{
Info: *f.pubKeyInfo,
Slot: "signature",
PublicKey: base64.StdEncoding.EncodeToString(x509.MarshalPKCS1PublicKey(f.pubKeyInfo.PublicKey.(*rsa.PublicKey))),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We same f.pubKeyInfo here, why do we have YubiConfig.PubKeyInfo as well stored as part of the state?

Is this to prevent us from reading the information from the yubikey multiple times?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also stored in the config to make sure when you want to overwrite or create a new one, it only creates a new one on signature slot in the yubikey once

@Foxboron
Copy link
Owner

Foxboron commented Mar 1, 2025

I saw down to try this change and I can't seem to get it to work. The yubikey blinks for a press, but nothing happens when I press. I suspect the issue is on my side, but I found this a bit weird. Have to spend a little bit of time to figure out why this happens and the potential failure case.

@tomis007
Copy link
Author

tomis007 commented Mar 1, 2025

Interesting, I have not encountered that behavior before with my yubikey.

Are you able to create any key on your yubikey in the piv slot with ykman?

ykman piv info
# you can set the touch/pin policy too
ykman piv keys generate --algorithm RSA2048 9a pubkey.test

What happens if you update yubikey.go and change the PIN/Touch policy to never?:

piv.Key{
    Algorithm:   piv.AlgorithmRSA2048,
    PINPolicy:   piv.PINPolicyNever,
    TouchPolicy: piv.TouchPolicyNever,
}

@tomis007
Copy link
Author

tomis007 commented Mar 1, 2025

I just tested after resetting my yubikey piv data and it worked as expected:

$ ykman info
Device type: YubiKey 5C
Serial number: 12341234
Firmware version: 5.7.1
Form factor: Keychain (USB-C)
Enabled USB interfaces: OTP, FIDO, CCID

Applications
Yubico OTP      Enabled
FIDO U2F        Enabled
FIDO2           Enabled
OATH            Enabled
PIV             Enabled
OpenPGP         Enabled
YubiHSM Auth    Enabled

$ ykman piv reset
WARNING! This will delete all stored PIV data and restore factory settings. Proceed? [y/N]: y
Resetting PIV data...
Reset complete. All PIV data has been cleared from the YubiKey.
Your YubiKey now has the default PIN, PUK and Management Key:
        PIN:    123456
        PUK:    12345678
        Management Key: 010203040506070801020304050607080102030405060708


$ ./sbctl create-keys --keytype yubikey
Created Owner UUID 865d27c1-27a4-4b1d-bc5b-36ebf1d39124
Creating RSA2048 key...
Please press Yubikey to confirm presense
Created RSA2048 key MD5: 9a50e63ad7c616fb6aa8f0f5b6ebb680
Creating PK key...
Please press Yubikey to confirm presence for key RSA2048 MD5: 9a50e63ad7c616fb6aa8f0f5b6ebb680
Creating KEK key...
Please press Yubikey to confirm presence for key RSA2048 MD5: 9a50e63ad7c616fb6aa8f0f5b6ebb680
Creating db key...
Please press Yubikey to confirm presence for key RSA2048 MD5: 9a50e63ad7c616fb6aa8f0f5b6ebb680
✓
Secure boot keys created!

How far did it get when you tested? I wonder if there is a missing dependency, do you have pcsclite installed?

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

Successfully merging this pull request may close these issues.

2 participants