Comments (8)
v1.4.1-0.20200426030018-8f5f73161d1d (from #44) fixes (1) 👍✨ Thank you!
Now trying to make a reproducer for (2), I'll open a new issue if it turns out to be an upstream issue.
from piv-go.
To get PIN caching to work, I had to have the YubiKey struct hold onto a PS/SC transaction #39, so theoretically no other process should be able to access the PIV applet until you call (*YubiKey).Close(). Will test some more later to see if there's a way around this.
from piv-go.
Uggg... yeah (1) sounds right. Let me think about that. For (2) your YubiKey would actually have to be rejecting the request and require authentication.
Thanks for the report!
from piv-go.
I double checked the code that refreshes the *YubiKey
is not firing, for (2), and it looks like it's not, so no idea what might be going on. Happy to provide traces or anything that helps.
This was the setup, and it's a YubiKey 4 with PIV version 4.3.6.
yubico-piv-tool -k -s 9a -a generate -o public.pem --pin-policy=once --touch-policy=always
yubico-piv-tool -a verify-pin -a selfsign-certificate -s 9a -S "/CN=SSH key/" -i public.pem -o cert.pem
yubico-piv-tool -a import-certificate -s 9a -i cert.pem -k
from piv-go.
Using management key 010203040506070801020304050607080102030405060708 and PIN 123456, the following program worked for me:
package main
import (
"crypto"
"crypto/rand"
"crypto/sha256"
"log"
"github.com/go-piv/piv-go/piv"
)
func main() {
cards, err := piv.Cards()
if err != nil {
log.Fatalf("cards: %v", err)
}
if len(cards) != 1 {
log.Fatalf("expected on card got %d", len(cards))
}
yk, err := piv.Open(cards[0])
if err != nil {
log.Fatalf("open card: %v", err)
}
a := piv.KeyAuth{
PINPrompt: func() (string, error) {
log.Println("pin prompt called")
return piv.DefaultPIN, nil
},
}
cert, err := yk.Attest(piv.SlotAuthentication)
if err != nil {
log.Fatalf("getting attestation cert for slot: %v", err)
}
priv, err := yk.PrivateKey(piv.SlotAuthentication, cert.PublicKey, a)
if err != nil {
log.Fatalf("private key: %v", err)
}
s, ok := priv.(crypto.Signer)
if !ok {
log.Fatalf("private key didn't implement crypto.Signer")
}
data := sha256.Sum256([]byte("hello"))
if _, err := s.Sign(rand.Reader, data[:], crypto.SHA256); err != nil {
log.Fatalf("signing: %v", err)
}
}
% yubico-piv-tool -k -s 9a -a generate -o public.pem --pin-policy=once --touch-policy=always
Enter management key:
Successfully generated a new private key.
% yubico-piv-tool -a verify-pin -a selfsign-certificate -s 9a -S "/CN=SSH key/" -i public.pem -o cert.pem
Enter PIN:
Successfully verified PIN.
Successfully generated a new self signed certificate.
% yubico-piv-tool -a import-certificate -s 9a -i cert.pem -k
Enter management key:
Successfully imported a new certificate.
% go run hi.go
2020/04/25 19:07:02 pin prompt called
I do have to touch the key twice, but the signing works fine.
With regards to the overall PIN prompt, I'm lookin at https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf to see if there's a way to determine when a PIN is needed or not.
Another idea is to let the caller keep the state. E.g. let you provide something like the following to KeyAuth:
type PINPrompter interface {
// PIN returns a PIN for a signing operation. This should be cached by the prompter
// for repeated calls.
PIN() (string, error)
// PINInvalid is called by the signer when the returned PIN is deemed invalid. This likely
// means the prompter should re-prompt for a PIN.
PINInvalid() error
}
Or you could write the PIN to disk with the threat model that malicious code still can't get a signing operation without tricking you into touching your security key.
from piv-go.
I do have to touch the key twice, but the signing works fine.
Indeed, even adding a second PrivateKey and Sign call only invokes PINPrompt once. I'll try to figure out what's going on on my side, ignore this part of the report for now.
Or you could write the PIN to disk with the threat model that malicious code still can't get a signing operation without tricking you into touching your security key.
I'd like to avoid that, part of why I am building yubikey-agent is that pivy-agent disregards the PIN policy and just keeps the PIN in memory.
I think you can tell the policy from the certificate. If that's the case, you can keep per-slot state about whether the PIN has been provided or not. The annoying part is that you now need a round of Attest, but the good news is that since you are holding a lock on the YubiKey, nothing external can change it from under your feet. Since most applications will call Attest before Sign, you can probably get away with caching Attest results, and calling it from Sign.
(Empirically, PKCS#11 somehow manages, I think, so we could also look into how that works.)
from piv-go.
Mind giving #44 a try?
from piv-go.
Figured it out: calling Serial on my older YubiKey was switching application, which presumably locks the session. I have it all working as intended now! Might be worth documenting it in the Serial docs.
I also tried Retries for a health check, but that fails when the session is unlocked. Ended up using AttestationCertificate, but maybe it's worth adding a Ping method? Could even return the PIN lock status.
Finally, I tested simultaneous use of other applets. FIDO2 works in parallel without even dropping the PIN! gpg-agent though can't see the key at all while a PIV session is running, maybe because they use the same macOS daemon =( I'll switch to age+PIV soon anyway, but that will be even worse, because it's even less likely the two PIV sessions can be made to work at the same time. Any ideas? I'd be ok with the PIN getting dropped when another application uses the PIV (or PGP) applets, so a way of detecting the other one would be enough. At the moment the second Open just hangs until the other program exits (or calls Close I presume).
BTW, it would be nice for Open and other operations that might block to be cancellable, somehow, or at least to have a timeout.
from piv-go.
Related Issues (20)
- Reordering the TouchPolicy in #74 makes the strictness order wrong HOT 2
- Build failure on arm FreeBSD HOT 2
- Possibility of cutting a new release to include OpenBSD support? HOT 3
- Support AES Management keys HOT 2
- NFC and ISO 7816 support HOT 3
- Expose keyRSA and keyEd25519 type HOT 2
- Incompatibility with Go 1.20rc1 HOT 3
- Support for linux armv7 HOT 3
- Pivot
- Error: Unable to open the Yubikey card: connecting to smart card: the smart card cannot be accessed because of other connections outstanding HOT 1
- rsassa-pss signatures not supported HOT 3
- Bump go.mod version HOT 1
- Unable to build on macOS HOT 6
- Cross compile linux amd64 -> darwin amd64 issues with CGO (`<angled> include; use "quotes" instead`) HOT 2
- PIV Emulation? HOT 2
- Private key decryption on Yubikey by ECDSA HOT 2
- Support GET METADATA command and use it to derive default PIN policy HOT 1
- Cross-compiling requirements HOT 2
- Windows: the Smart card resource manager is not running HOT 4
- Go PIV do not give Shared access to multiple processes HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from piv-go.