status-keycard-go/flow_commands.go

446 lines
8.2 KiB
Go
Raw Normal View History

2021-10-20 12:01:38 +03:00
package statuskeycardgo
func (f *KeycardFlow) factoryReset(kc *keycardContext) error {
2021-10-27 09:17:12 +03:00
err := kc.factoryReset()
if err == nil {
delete(f.params, FactoryReset)
return restartErr()
} else {
return err
}
2021-10-20 12:01:38 +03:00
}
func (f *KeycardFlow) selectKeycard(kc *keycardContext) error {
appInfo, err := kc.selectApplet()
2021-10-27 08:46:00 +03:00
f.cardInfo.instanceUID = btox(appInfo.InstanceUID)
f.cardInfo.keyUID = btox(appInfo.KeyUID)
2021-10-20 12:01:38 +03:00
f.cardInfo.freeSlots = bytesToInt(appInfo.AvailableSlots)
if err != nil {
return restartErr()
}
if !appInfo.Installed {
return f.pauseAndRestart(SwapCard, ErrorNotAKeycard)
}
if requiredInstanceUID, ok := f.params[InstanceUID]; ok {
if f.cardInfo.instanceUID != requiredInstanceUID {
return f.pauseAndRestart(SwapCard, InstanceUID)
}
}
if requiredKeyUID, ok := f.params[KeyUID]; ok {
if f.cardInfo.keyUID != requiredKeyUID {
return f.pauseAndRestart(SwapCard, KeyUID)
}
}
return nil
}
func (f *KeycardFlow) pair(kc *keycardContext) error {
if f.cardInfo.freeSlots == 0 {
return f.pauseAndRestart(SwapCard, FreeSlots)
}
2022-02-07 16:19:32 +01:00
pairingPass, ok := f.params[PairingPass]
2021-10-20 12:01:38 +03:00
2022-02-07 16:19:32 +01:00
if !ok {
pairingPass = DefPairing
}
pairing, err := kc.pair(pairingPass.(string))
2021-10-20 12:01:38 +03:00
2022-02-07 16:19:32 +01:00
if err == nil {
return f.pairings.store(f.cardInfo.instanceUID, toPairInfo(pairing))
} else if isSCardError(err) {
return restartErr()
2021-10-20 12:01:38 +03:00
}
2022-02-07 16:19:32 +01:00
delete(f.params, PairingPass)
err = f.pauseAndWait(EnterPairing, ErrorPairing)
2021-10-20 12:01:38 +03:00
if err != nil {
return err
}
return f.pair(kc)
}
func (f *KeycardFlow) initCard(kc *keycardContext) error {
2021-10-22 09:55:00 +03:00
newPIN, pinOK := f.params[NewPIN]
if !pinOK {
2021-10-22 11:49:55 +03:00
err := f.pauseAndWait(EnterNewPIN, ErrorRequireInit)
if err != nil {
return err
}
2021-10-22 09:55:00 +03:00
return f.initCard(kc)
}
newPUK, pukOK := f.params[NewPUK]
if !pukOK {
2021-10-22 11:49:55 +03:00
err := f.pauseAndWait(EnterNewPUK, ErrorRequireInit)
if err != nil {
return err
}
2021-10-22 09:55:00 +03:00
return f.initCard(kc)
}
newPairing, pairingOK := f.params[NewPairing]
if !pairingOK {
2022-02-07 16:19:32 +01:00
newPairing = DefPairing
2021-10-22 09:55:00 +03:00
}
err := kc.init(newPIN.(string), newPUK.(string), newPairing.(string))
2021-10-28 09:52:39 +03:00
if err != nil {
return err
2021-10-22 09:55:00 +03:00
}
2021-10-28 09:52:39 +03:00
f.params[PIN] = newPIN
f.params[PairingPass] = newPairing
delete(f.params, NewPIN)
delete(f.params, NewPUK)
delete(f.params, NewPairing)
return restartErr()
2021-10-20 12:01:38 +03:00
}
2021-10-22 09:32:07 +03:00
func (f *KeycardFlow) openSC(kc *keycardContext, giveup bool) error {
var pairing *PairingInfo
if !kc.cmdSet.ApplicationInfo.Initialized && !giveup {
2021-10-20 12:01:38 +03:00
return f.initCard(kc)
2021-10-22 09:32:07 +03:00
} else {
pairing = f.pairings.get(f.cardInfo.instanceUID)
2021-10-20 12:01:38 +03:00
}
if pairing != nil {
err := kc.openSecureChannel(pairing.Index, pairing.Key)
if err == nil {
appStatus, err := kc.getStatusApplication()
if err != nil {
// getStatus can only fail for connection errors
return restartErr()
}
f.cardInfo.pinRetries = appStatus.PinRetryCount
f.cardInfo.pukRetries = appStatus.PUKRetryCount
return nil
} else if isSCardError(err) {
return restartErr()
}
f.pairings.delete(f.cardInfo.instanceUID)
}
2021-10-22 09:32:07 +03:00
if giveup {
return giveupErr()
}
2021-10-20 12:01:38 +03:00
err := f.pair(kc)
if err != nil {
return err
}
2021-10-22 09:32:07 +03:00
return f.openSC(kc, giveup)
2021-10-20 12:01:38 +03:00
}
2021-10-21 14:17:55 +03:00
func (f *KeycardFlow) unblockPIN(kc *keycardContext) error {
2021-10-21 10:41:20 +03:00
pukError := ""
var err error
newPIN, pinOK := f.params[NewPIN]
puk, pukOK := f.params[PUK]
if pinOK && pukOK {
2021-10-21 14:17:55 +03:00
err = kc.unblockPIN(puk.(string), newPIN.(string))
2021-10-21 10:41:20 +03:00
if err == nil {
f.cardInfo.pinRetries = maxPINRetries
f.cardInfo.pukRetries = maxPUKRetries
f.params[PIN] = newPIN
delete(f.params, NewPIN)
delete(f.params, PUK)
return nil
} else if isSCardError(err) {
return restartErr()
2021-10-22 12:57:53 +03:00
} else if leftRetries, ok := getRetries(err); ok {
2021-10-21 10:41:20 +03:00
f.cardInfo.pukRetries = leftRetries
delete(f.params, PUK)
pukOK = false
}
pukError = PUK
}
if !pukOK {
err = f.pauseAndWait(EnterPUK, pukError)
} else if !pinOK {
2021-10-22 09:55:00 +03:00
err = f.pauseAndWait(EnterNewPIN, ErrorUnblocking)
2021-10-21 10:41:20 +03:00
}
if err != nil {
return err
}
2021-10-21 14:17:55 +03:00
return f.unblockPIN(kc)
2021-10-20 12:01:38 +03:00
}
func (f *KeycardFlow) authenticate(kc *keycardContext) error {
if f.cardInfo.pukRetries == 0 {
return f.pauseAndRestart(SwapCard, PUKRetries)
} else if f.cardInfo.pinRetries == 0 {
2021-10-22 12:57:53 +03:00
// succesful unblock leaves the card authenticated
2021-10-21 14:17:55 +03:00
return f.unblockPIN(kc)
2021-10-20 12:01:38 +03:00
}
pinError := ""
if pin, ok := f.params[PIN]; ok {
err := kc.verifyPin(pin.(string))
if err == nil {
f.cardInfo.pinRetries = maxPINRetries
return nil
} else if isSCardError(err) {
return restartErr()
2021-10-22 12:57:53 +03:00
} else if leftRetries, ok := getRetries(err); ok {
2021-10-20 12:01:38 +03:00
f.cardInfo.pinRetries = leftRetries
2021-10-21 10:41:20 +03:00
delete(f.params, PIN)
2021-10-20 12:01:38 +03:00
}
pinError = PIN
}
err := f.pauseAndWait(EnterPIN, pinError)
if err != nil {
return err
}
return f.authenticate(kc)
}
2021-10-22 09:32:07 +03:00
func (f *KeycardFlow) openSCAndAuthenticate(kc *keycardContext, giveup bool) error {
err := f.openSC(kc, giveup)
2021-10-20 12:01:38 +03:00
if err != nil {
return err
}
return f.authenticate(kc)
}
2021-10-21 08:48:51 +03:00
func (f *KeycardFlow) unpairCurrent(kc *keycardContext) error {
err := kc.unpairCurrent()
if isSCardError(err) {
return restartErr()
}
return err
}
2021-10-25 08:41:53 +03:00
func (f *KeycardFlow) unpair(kc *keycardContext, idx int) error {
err := kc.unpair(uint8(idx))
if isSCardError(err) {
return restartErr()
}
return err
}
func (f *KeycardFlow) removeKey(kc *keycardContext) error {
err := kc.removeKey()
if isSCardError(err) {
return restartErr()
}
return err
}
2021-10-21 08:48:51 +03:00
func (f *KeycardFlow) exportKey(kc *keycardContext, path string, onlyPublic bool) (*KeyPair, error) {
keyPair, err := kc.exportKey(true, false, onlyPublic, path)
if isSCardError(err) {
return nil, restartErr()
}
return keyPair, err
}
2021-10-25 09:10:43 +03:00
2021-10-27 08:46:00 +03:00
func (f *KeycardFlow) exportBIP44Key(kc *keycardContext) (*KeyPair, error) {
2021-10-28 09:52:39 +03:00
if path, ok := f.params[BIP44Path]; ok {
2021-10-27 08:46:00 +03:00
return f.exportKey(kc, path.(string), true)
}
err := f.pauseAndWait(EnterPath, ErrorExporting)
if err != nil {
return nil, err
}
return f.exportBIP44Key(kc)
}
2021-10-28 09:52:39 +03:00
func (f *KeycardFlow) loadKeys(kc *keycardContext) error {
if mnemonic, ok := f.params[Mnemonic]; ok {
keyUID, err := kc.loadMnemonic(mnemonic.(string), "")
if isSCardError(err) {
return restartErr()
} else if err != nil {
return err
}
f.cardInfo.keyUID = btox(keyUID)
return nil
}
2022-06-09 11:16:31 +02:00
mnemonicLength, ok := f.params[MnemonicLen]
if !ok {
mnemonicLength = defMnemoLen
}
indexes, err := kc.generateMnemonic(mnemonicLength.(int) / 3)
if isSCardError(err) {
return restartErr()
} else if err != nil {
return err
}
err = f.pauseAndWaitWithStatus(EnterMnemonic, ErrorLoading, FlowParams{MnemonicIdxs: indexes})
2021-10-28 09:52:39 +03:00
if err != nil {
return err
}
return f.loadKeys(kc)
}
2021-10-25 09:10:43 +03:00
func (f *KeycardFlow) changePIN(kc *keycardContext) error {
if newPIN, ok := f.params[NewPIN]; ok {
err := kc.changePin(newPIN.(string))
if isSCardError(err) {
return restartErr()
} else if err != nil {
return err
}
return nil
}
err := f.pauseAndWait(EnterNewPIN, ErrorChanging)
if err != nil {
return err
}
return f.changePIN(kc)
}
func (f *KeycardFlow) changePUK(kc *keycardContext) error {
if newPUK, ok := f.params[NewPUK]; ok {
err := kc.changePuk(newPUK.(string))
if isSCardError(err) {
return restartErr()
} else if err != nil {
return err
}
return nil
}
err := f.pauseAndWait(EnterNewPUK, ErrorChanging)
if err != nil {
return err
}
return f.changePUK(kc)
}
func (f *KeycardFlow) changePairing(kc *keycardContext) error {
if newPairing, ok := f.params[NewPairing]; ok {
err := kc.changePairingPassword(newPairing.(string))
if isSCardError(err) {
return restartErr()
} else if err != nil {
return err
}
return nil
}
err := f.pauseAndWait(EnterNewPair, ErrorChanging)
if err != nil {
return err
}
return f.changePairing(kc)
}
2021-10-27 08:46:00 +03:00
func (f *KeycardFlow) sign(kc *keycardContext) (*Signature, error) {
var err error
path, pathOK := f.params[BIP44Path]
if !pathOK {
err = f.pauseAndWait(EnterPath, ErrorSigning)
if err != nil {
return nil, err
}
return f.sign(kc)
}
hash, hashOK := f.params[TXHash]
var rawHash []byte
if hashOK {
rawHash, err = xtob(hash.(string))
if err != nil {
hashOK = false
}
}
if !hashOK {
err := f.pauseAndWait(EnterTXHash, ErrorSigning)
if err != nil {
return nil, err
}
return f.sign(kc)
}
signature, err := kc.signWithPath(rawHash, path.(string))
if isSCardError(err) {
return nil, restartErr()
} else if err != nil {
return nil, err
}
return toSignature(signature), nil
}