in yubikey/pkg/value/encryption/envelope/piv/manager.go [50:99]
func (o *pivOpener) Open(serial uint32, slot uint8) (Card, error) {
// Get a retired slot.
pivSlot, ok := gopiv.RetiredKeyManagementSlot(uint32(slot))
if !ok {
return nil, fmt.Errorf("unrecognized slot: %02x", slot)
}
// Retrieve all cards
cards, err := gopiv.Cards()
if err != nil {
return nil, fmt.Errorf("cannot list PIV cards: %w", err)
}
for _, name := range cards {
// Try to open card by name
card, err := o.tryOpen(name, serial)
if err != nil {
log.Bg().Debug("ignoring card", zap.Error(err), zap.String("name", name), zap.Uint32("serial", serial))
continue
}
// Retrieve certificate
cert, err := card.Certificate(pivSlot)
if err != nil {
if errors.Is(err, gopiv.ErrNotFound) {
log.Bg().Debug("ignoring card without certificate", zap.Error(err), zap.String("name", name), zap.Uint32("serial", serial), zap.String("slot", fmt.Sprintf("%02x", slot)))
} else {
log.Bg().Debug("communication error", zap.Error(err), zap.String("name", name), zap.Uint32("serial", serial), zap.String("slot", fmt.Sprintf("%02x", slot)))
}
continue
}
// Filter on required organization
orgs := cert.Subject.Organization
if len(orgs) != 1 || orgs[0] != pivOrganization {
log.Bg().Debug("ignoring card with wrong organization", zap.Error(err), zap.String("name", name), zap.Uint32("serial", serial), zap.String("slot", fmt.Sprintf("%02x", slot)))
continue
}
// Wrap card and return
return &pivCard{
card: card,
serial: serial,
slot: pivSlot,
pub: cert.PublicKey.(*ecdsa.PublicKey),
}, nil
}
return nil, errors.New("card not found")
}