aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2018-04-18 18:59:32 +0800
committerGuillaume Ballet <gballet@gmail.com>2019-04-08 19:19:37 +0800
commit114de0fe2a7ff43ec9811cc11a5f555795a716a0 (patch)
tree521d71c988429f1d9da46360d21486c42be75901
parent475e8719baa05b135bd281b6a402d0cbf7f6c729 (diff)
downloadgo-tangerine-114de0fe2a7ff43ec9811cc11a5f555795a716a0.tar
go-tangerine-114de0fe2a7ff43ec9811cc11a5f555795a716a0.tar.gz
go-tangerine-114de0fe2a7ff43ec9811cc11a5f555795a716a0.tar.bz2
go-tangerine-114de0fe2a7ff43ec9811cc11a5f555795a716a0.tar.lz
go-tangerine-114de0fe2a7ff43ec9811cc11a5f555795a716a0.tar.xz
go-tangerine-114de0fe2a7ff43ec9811cc11a5f555795a716a0.tar.zst
go-tangerine-114de0fe2a7ff43ec9811cc11a5f555795a716a0.zip
accounts/scwallet, console: user friendly card opening
-rw-r--r--accounts/scwallet/wallet.go72
-rw-r--r--console/bridge.go56
2 files changed, 90 insertions, 38 deletions
diff --git a/accounts/scwallet/wallet.go b/accounts/scwallet/wallet.go
index c2cf93965..2f40afbaa 100644
--- a/accounts/scwallet/wallet.go
+++ b/accounts/scwallet/wallet.go
@@ -41,13 +41,26 @@ import (
"github.com/ethereum/go-ethereum/log"
)
+// ErrPUKNeeded is returned if opening the smart card requires pairing with a PUK
+// code. In this case, the calling application should request user input to enter
+// the PUK and send it back.
+var ErrPUKNeeded = errors.New("smartcard: puk needed")
+
+// ErrPINNeeded is returned if opening the smart card requires a PIN code. In
+// this case, the calling application should request user input to enter the PIN
+// and send it back.
+var ErrPINNeeded = errors.New("smartcard: pin needed")
+
+// ErrAlreadyOpen is returned if the smart card is attempted to be opened, but
+// there is already a paired and unlocked session.
+var ErrAlreadyOpen = errors.New("smartcard: already open")
+
+// ErrPubkeyMismatch is returned if the public key recovered from a signature
+// does not match the one expected by the user.
+var ErrPubkeyMismatch = errors.New("smartcard: recovered public key mismatch")
+
var (
appletAID = []byte{0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x41, 0x70, 0x70}
- AlreadyOpenError = errors.New("Wallet already open")
- PairingRequiredError = errors.New("Pairing required with personal.openWallet(puk)")
- PinRequiredError = errors.New("Must unlock with personal.openWallet(pin)")
- PubkeyMismatchError = errors.New("Could not recover matching public key from signature")
- WalletChangedError = errors.New("Smartcard has been changed")
DerivationSignatureHash = sha256.Sum256([]byte("STATUS KEY DERIVATION"))
)
@@ -240,21 +253,17 @@ func (w *Wallet) Unpair(pin []byte) error {
defer w.lock.Unlock()
if !w.session.paired() {
- return fmt.Errorf("Wallet %x not paired", w.PublicKey)
+ return fmt.Errorf("wallet %x not paired", w.PublicKey)
}
-
if err := w.session.verifyPin(pin); err != nil {
- return fmt.Errorf("Error verifying pin: %s", err)
+ return fmt.Errorf("failed to verify pin: %s", err)
}
-
if err := w.session.unpair(); err != nil {
- return fmt.Errorf("Error unpairing: %s", err)
+ return fmt.Errorf("failed to unpair: %s", err)
}
-
if err := w.Hub.setPairing(w, nil); err != nil {
return err
}
-
return nil
}
@@ -306,34 +315,39 @@ func (w *Wallet) Open(passphrase string) error {
w.lock.Lock()
defer w.lock.Unlock()
+ // If the session is already open, bail out
if w.session.verified {
- // Already open
- return AlreadyOpenError
+ return ErrAlreadyOpen
}
-
+ // If the smart card is not yet paired, attempt to do so either from a previous
+ // pairing key or form the supplied PUK code.
if !w.session.paired() {
- // Unpaired.
+ // If a previous pairing exists, only ever try to use that
if pairing := w.Hub.getPairing(w); pairing != nil {
- // Authenticate with the existing pairing.
if err := w.session.authenticate(*pairing); err != nil {
- return fmt.Errorf("Could not authenticate with paired card %x: %s", w.PublicKey[:4], err)
+ return fmt.Errorf("failed to authenticate card %x: %s", w.PublicKey[:4], err)
}
- } else if passphrase != "" {
- // Establish a new pairing
- return w.pair([]byte(passphrase))
- } else {
- return PairingRequiredError
+ return nil
+ }
+ // If no passphrase was supplied, request the PUK from the user
+ if passphrase == "" {
+ return ErrPUKNeeded
}
+ // Attempt to pair the smart card with the user supplied PUK
+ if err := w.pair([]byte(passphrase)); err != nil {
+ return err
+ }
+ return ErrPINNeeded // We always need the PIN after the PUK
}
-
+ // The smart card was successfully paired, request a PIN code or use the one
+ // supplied by the user
if passphrase == "" {
- return PinRequiredError
+ return ErrPINNeeded
}
- // Verify pin
if err := w.session.verifyPin([]byte(passphrase)); err != nil {
return err
}
-
+ // Smart card paired and unlocked, initialize and register
w.deriveReq = make(chan chan struct{})
w.deriveQuit = make(chan chan error)
@@ -990,7 +1004,7 @@ func determinePublicKey(sig, pubkeyX []byte) ([]byte, error) {
return nil, err
}
}
- return nil, PubkeyMismatchError
+ return nil, ErrPubkeyMismatch
}
// makeRecoverableSignature uses a signature and an expected public key to
@@ -1007,5 +1021,5 @@ func makeRecoverableSignature(hash, sig, expectedPubkey []byte) ([]byte, error)
return nil, err
}
}
- return nil, PubkeyMismatchError
+ return nil, ErrPubkeyMismatch
}
diff --git a/console/bridge.go b/console/bridge.go
index 33277cf6e..03d97e0ef 100644
--- a/console/bridge.go
+++ b/console/bridge.go
@@ -23,6 +23,7 @@ import (
"strings"
"time"
+ "github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/accounts/usbwallet"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
@@ -104,22 +105,59 @@ func (b *bridge) OpenWallet(call otto.FunctionCall) (response otto.Value) {
if err == nil {
return val
}
- // Wallet open failed, report error unless it's a PIN entry
- if strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()) {
+
+ // Wallet open failed, report error unless it's a PIN or PUK entry
+ switch {
+ case strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()):
val, err = b.readPinAndReopenWallet(call)
if err == nil {
return val
}
- }
- // Check if the user needs to input a passphrase
- if !strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPassphraseNeeded.Error()) {
- throwJSException(err.Error())
- }
- val, err = b.readPassphraseAndReopenWallet(call)
- if err != nil {
+ val, err = b.readPassphraseAndReopenWallet(call)
+ if err != nil {
+ throwJSException(err.Error())
+ }
+
+ case strings.HasSuffix(err.Error(), scwallet.ErrPUKNeeded.Error()):
+ // PUK input requested, fetch from the user and call open again
+ if input, err := b.prompter.PromptPassword("Please enter current PUK: "); err != nil {
+ throwJSException(err.Error())
+ } else {
+ passwd, _ = otto.ToValue(input)
+ }
+ if val, err = call.Otto.Call("jeth.openWallet", nil, wallet, passwd); err != nil {
+ if !strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()) {
+ throwJSException(err.Error())
+ } else {
+ // PIN input requested, fetch from the user and call open again
+ if input, err := b.prompter.PromptPassword("Please enter current PIN: "); err != nil {
+ throwJSException(err.Error())
+ } else {
+ passwd, _ = otto.ToValue(input)
+ }
+ if val, err = call.Otto.Call("jeth.openWallet", nil, wallet, passwd); err != nil {
+ throwJSException(err.Error())
+ }
+ }
+ }
+
+ case strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()):
+ // PIN input requested, fetch from the user and call open again
+ if input, err := b.prompter.PromptPassword("Please enter current PIN: "); err != nil {
+ throwJSException(err.Error())
+ } else {
+ passwd, _ = otto.ToValue(input)
+ }
+ if val, err = call.Otto.Call("jeth.openWallet", nil, wallet, passwd); err != nil {
+ throwJSException(err.Error())
+ }
+
+ default:
+ // Unknown error occurred, drop to the user
throwJSException(err.Error())
}
return val
+>>>>>>> accounts/scwallet, console: user friendly card opening
}
func (b *bridge) readPassphraseAndReopenWallet(call otto.FunctionCall) (otto.Value, error) {