indygreg / apple-platform-rs

Rust crates supporting Apple platform development
568 stars 40 forks source link

Concurrent Yubikey access leads to PCSC Error #49

Open wrl opened 1 year ago

wrl commented 1 year ago

I am using rcodesign in a on-premises CI server, with the smartcard functionality backed by a Yubikey 5 token.

When two (or more) jobs attempt to sign executables simultaneously, at least one (sometimes all) of them will begin exiting unsuccessfully with the pcsc-rust error Error::ResetCard, which has the description "The smart card has been reset, so any shared state information is invalid".

It's unclear to me where this error is being raised (i.e. when first connecting to the token, or when the signing operation is attempted), but it seems like pcsc-rust resets the Card when dropped (https://github.com/bluetech/pcsc-rust/blob/master/pcsc/src/lib.rs#L1670-L1684) and yubikey-rs doesn't change this or attempt to reconnect to the card on reset, though it does specify that the card should reset on reconnect (https://github.com/iqlusioninc/yubikey.rs/blob/main/src/yubikey.rs#L220-L224) and it seems like the card should perhaps reconnect if there's an error when starting a transaction (https://github.com/iqlusioninc/yubikey.rs/blob/main/src/yubikey.rs#L241-L245).

I am unfamiliar with PCSC and smartcards as a whole, so I'm not sure what the best practices for all of this are.

indygreg commented 1 year ago

No worries about the GitHub issues... it happens.

Thanks for the bug report. I can easily see how 2 concurrent operations would fail.

At the end of the day, each client needs to have some form of exclusive access to the hardware to perform signing, as a signing operation consists of multiple packets sent to the hardware and the protocol is stateful.

I'm far from an expert on the PCSC interface and how yubikey.rs interfaces with it. This may require some cooperation with the yubikey.rs maintainers on best ways to proceed.

I wouldn't be surprised if we to implement our own locking using a file-based lock or something. From my perspective, ideally any locking would be implemented in yubikey.rs. But I can relate with them if they want to defer that complexity to downstream customers!

wrl commented 1 year ago

As a perhaps-interesting point, I have a whole separate flow for code-signing my Windows binaries using osslsigncode, which sits on OpenSSL and uses its PKCS 11 interface for smartcard support. When I have two parallel Windows codesign jobs running, they proceed more slowly than if only one was running, but there's no concurrency or reset errors.

This leads me to believe that this should be possible without explicit locking in rcodesign, but I'm not 100% sure how just yet.