mirror of
https://github.com/status-im/keycard-cli.git
synced 2025-03-01 04:10:33 +00:00
add more commands and shell vars
This commit is contained in:
parent
7a8338f547
commit
e249a4e724
238
shell.go
238
shell.go
@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -15,13 +16,14 @@ import (
|
|||||||
keycard "github.com/status-im/keycard-go"
|
keycard "github.com/status-im/keycard-go"
|
||||||
"github.com/status-im/keycard-go/apdu"
|
"github.com/status-im/keycard-go/apdu"
|
||||||
"github.com/status-im/keycard-go/globalplatform"
|
"github.com/status-im/keycard-go/globalplatform"
|
||||||
|
keycardio "github.com/status-im/keycard-go/io"
|
||||||
"github.com/status-im/keycard-go/types"
|
"github.com/status-im/keycard-go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type shellCommand = func(args ...string) error
|
type shellCommand = func(args ...string) error
|
||||||
|
|
||||||
type Shell struct {
|
type Shell struct {
|
||||||
t globalplatform.Transmitter
|
t keycardio.Transmitter
|
||||||
c types.Channel
|
c types.Channel
|
||||||
secrets *keycard.Secrets
|
secrets *keycard.Secrets
|
||||||
gpCmdSet *globalplatform.CommandSet
|
gpCmdSet *globalplatform.CommandSet
|
||||||
@ -30,8 +32,8 @@ type Shell struct {
|
|||||||
out *bytes.Buffer
|
out *bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewShell(t globalplatform.Transmitter) *Shell {
|
func NewShell(t keycardio.Transmitter) *Shell {
|
||||||
c := globalplatform.NewNormalChannel(t)
|
c := keycardio.NewNormalChannel(t)
|
||||||
|
|
||||||
s := &Shell{
|
s := &Shell{
|
||||||
t: t,
|
t: t,
|
||||||
@ -42,24 +44,31 @@ func NewShell(t globalplatform.Transmitter) *Shell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.commands = map[string]shellCommand{
|
s.commands = map[string]shellCommand{
|
||||||
"gp-send-apdu": s.commandGPSendAPDU,
|
"echo": s.commandEcho,
|
||||||
"gp-select": s.commandGPSelect,
|
"gp-send-apdu": s.commandGPSendAPDU,
|
||||||
"gp-open-secure-channel": s.commandGPOpenSecureChannel,
|
"gp-select": s.commandGPSelect,
|
||||||
"gp-delete": s.commandGPDelete,
|
"gp-open-secure-channel": s.commandGPOpenSecureChannel,
|
||||||
"gp-load": s.commandGPLoad,
|
"gp-delete": s.commandGPDelete,
|
||||||
"gp-install-for-install": s.commandGPInstallForInstall,
|
"gp-load": s.commandGPLoad,
|
||||||
"keycard-init": s.commandKeycardInit,
|
"gp-install-for-install": s.commandGPInstallForInstall,
|
||||||
"keycard-select": s.commandKeycardSelect,
|
"keycard-init": s.commandKeycardInit,
|
||||||
"keycard-pair": s.commandKeycardPair,
|
"keycard-select": s.commandKeycardSelect,
|
||||||
"keycard-open-secure-channel": s.commandKeycardOpenSecureChannel,
|
"keycard-pair": s.commandKeycardPair,
|
||||||
"keycard-get-status": s.commandKeycardGetStatus,
|
"keycard-unpair": s.commandKeycardUnpair,
|
||||||
"keycard-set-secrets": s.commandKeycardSetSecrets,
|
"keycard-open-secure-channel": s.commandKeycardOpenSecureChannel,
|
||||||
"keycard-set-pairing": s.commandKeycardSetPairing,
|
"keycard-get-status": s.commandKeycardGetStatus,
|
||||||
"keycard-verify-pin": s.commandKeycardVerifyPIN,
|
"keycard-set-secrets": s.commandKeycardSetSecrets,
|
||||||
"keycard-generate-key": s.commandKeycardGenerateKey,
|
"keycard-set-pairing": s.commandKeycardSetPairing,
|
||||||
"keycard-derive-key": s.commandKeycardDeriveKey,
|
"keycard-verify-pin": s.commandKeycardVerifyPIN,
|
||||||
"keycard-sign": s.commandKeycardSign,
|
"keycard-change-pin": s.commandKeycardChangePIN,
|
||||||
"keycard-set-pinless-path": s.commandKeycardSetPinlessPath,
|
"keycard-change-puk": s.commandKeycardChangePUK,
|
||||||
|
"keycard-change-pairing-secret": s.commandKeycardChangePairingSecret,
|
||||||
|
"keycard-generate-key": s.commandKeycardGenerateKey,
|
||||||
|
"keycard-remove-key": s.commandKeycardRemoveKey,
|
||||||
|
"keycard-derive-key": s.commandKeycardDeriveKey,
|
||||||
|
"keycard-sign": s.commandKeycardSign,
|
||||||
|
"keycard-sign-message": s.commandKeycardSignMessage,
|
||||||
|
"keycard-set-pinless-path": s.commandKeycardSetPinlessPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
@ -92,6 +101,11 @@ func (s *Shell) Run() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shell) commandEcho(args ...string) error {
|
||||||
|
fmt.Printf("> %s\n", strings.Join(args, " "))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Shell) commandGPSendAPDU(args ...string) error {
|
func (s *Shell) commandGPSendAPDU(args ...string) error {
|
||||||
if err := s.requireArgs(args, 1); err != nil {
|
if err := s.requireArgs(args, 1); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -213,7 +227,7 @@ func (s *Shell) commandGPInstallForInstall(args ...string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("install for install", "pkg", pkgAID, "applet", appletAID, "instance", instanceAID, "params", params)
|
logger.Info("install for install", "pkg", fmt.Sprintf("%x", pkgAID), "applet", fmt.Sprintf("%x", appletAID), "instance", fmt.Sprintf("%x", instanceAID), "params", fmt.Sprintf("%x", params))
|
||||||
|
|
||||||
return s.gpCmdSet.InstallForInstall(pkgAID, appletAID, instanceAID, params)
|
return s.gpCmdSet.InstallForInstall(pkgAID, appletAID, instanceAID, params)
|
||||||
}
|
}
|
||||||
@ -308,8 +322,10 @@ func (s *Shell) commandKeycardPair(args ...string) error {
|
|||||||
return errors.New("cannot pair without setting secrets")
|
return errors.New("cannot pair without setting secrets")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.Info("pair")
|
||||||
err := s.kCmdSet.Pair(s.secrets.PairingPass())
|
err := s.kCmdSet.Pair(s.secrets.PairingPass())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logger.Error("pair failed", "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,6 +335,34 @@ func (s *Shell) commandKeycardPair(args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shell) commandKeycardUnpair(args ...string) error {
|
||||||
|
if err := s.requireArgs(args, 1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
indexInt, err := strconv.ParseInt(args[0], 10, 8)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
index := uint8(indexInt)
|
||||||
|
|
||||||
|
if s.secrets == nil {
|
||||||
|
return errors.New("cannot unpair without setting secrets")
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info(fmt.Sprintf("unpair index %d", index))
|
||||||
|
err = s.kCmdSet.Unpair(index)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("unpair failed", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.write("UNPAIRED\n")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Shell) commandKeycardSetPairing(args ...string) error {
|
func (s *Shell) commandKeycardSetPairing(args ...string) error {
|
||||||
if err := s.requireArgs(args, 2); err != nil {
|
if err := s.requireArgs(args, 2); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -398,6 +442,48 @@ func (s *Shell) commandKeycardVerifyPIN(args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shell) commandKeycardChangePIN(args ...string) error {
|
||||||
|
if err := s.requireArgs(args, 1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("change PIN")
|
||||||
|
if err := s.kCmdSet.ChangePIN(args[0]); err != nil {
|
||||||
|
logger.Error("change PIN failed", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Shell) commandKeycardChangePUK(args ...string) error {
|
||||||
|
if err := s.requireArgs(args, 1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("change PUK")
|
||||||
|
if err := s.kCmdSet.ChangePUK(args[0]); err != nil {
|
||||||
|
logger.Error("change PUK failed", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Shell) commandKeycardChangePairingSecret(args ...string) error {
|
||||||
|
if err := s.requireArgs(args, 1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("change pairing secret")
|
||||||
|
if err := s.kCmdSet.ChangePairingSecret(args[0]); err != nil {
|
||||||
|
logger.Error("change pairing secret failed", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Shell) commandKeycardGenerateKey(args ...string) error {
|
func (s *Shell) commandKeycardGenerateKey(args ...string) error {
|
||||||
if err := s.requireArgs(args, 0); err != nil {
|
if err := s.requireArgs(args, 0); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -414,6 +500,22 @@ func (s *Shell) commandKeycardGenerateKey(args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shell) commandKeycardRemoveKey(args ...string) error {
|
||||||
|
if err := s.requireArgs(args, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("remove key")
|
||||||
|
err := s.kCmdSet.RemoveKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.write(fmt.Sprintf("KEY REMOVED \n"))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Shell) commandKeycardDeriveKey(args ...string) error {
|
func (s *Shell) commandKeycardDeriveKey(args ...string) error {
|
||||||
if err := s.requireArgs(args, 1); err != nil {
|
if err := s.requireArgs(args, 1); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -454,6 +556,32 @@ func (s *Shell) commandKeycardSign(args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shell) commandKeycardSignMessage(args ...string) error {
|
||||||
|
if err := s.requireArgs(args, 1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := s.parseHex(args[0])
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("failed parsing hex data", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("sign")
|
||||||
|
sig, err := s.kCmdSet.Sign(data)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("sign failed", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.write(fmt.Sprintf("SIGNATURE R: %x\n", sig.R()))
|
||||||
|
s.write(fmt.Sprintf("SIGNATURE S: %x\n", sig.S()))
|
||||||
|
s.write(fmt.Sprintf("SIGNATURE V: %x\n", sig.V()))
|
||||||
|
s.write(fmt.Sprintf("PUBLIC KEY: %x\n", sig.PubKey()))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Shell) commandKeycardSetPinlessPath(args ...string) error {
|
func (s *Shell) commandKeycardSetPinlessPath(args ...string) error {
|
||||||
if err := s.requireArgs(args, 1); err != nil {
|
if err := s.requireArgs(args, 1); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -490,6 +618,11 @@ func (s *Shell) evalLine(rawLine string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
line, err := s.evalTemplate(line)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
reg := regexp.MustCompile("\\s+")
|
reg := regexp.MustCompile("\\s+")
|
||||||
parts := reg.Split(line, -1)
|
parts := reg.Split(line, -1)
|
||||||
if cmd, ok := s.commands[parts[0]]; ok {
|
if cmd, ok := s.commands[parts[0]]; ok {
|
||||||
@ -506,3 +639,64 @@ func (s *Shell) parseHex(str string) ([]byte, error) {
|
|||||||
|
|
||||||
return hex.DecodeString(str)
|
return hex.DecodeString(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shell) evalTemplate(text string) (string, error) {
|
||||||
|
funcMap := template.FuncMap{
|
||||||
|
"env": func(name string) (string, error) {
|
||||||
|
value := os.Getenv(name)
|
||||||
|
if value == "" {
|
||||||
|
return "", fmt.Errorf("env variable is empty: %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, nil
|
||||||
|
},
|
||||||
|
"session_pairing_key": func() (string, error) {
|
||||||
|
if s.kCmdSet.PairingInfo == nil {
|
||||||
|
return "", errors.New("pairing key not known")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%x", s.kCmdSet.PairingInfo.Key), nil
|
||||||
|
},
|
||||||
|
"session_pairing_index": func() (string, error) {
|
||||||
|
if s.kCmdSet.PairingInfo == nil {
|
||||||
|
return "", errors.New("pairing index not known")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%d", s.kCmdSet.PairingInfo.Index), nil
|
||||||
|
},
|
||||||
|
"session_pin": func() (string, error) {
|
||||||
|
if s.secrets == nil {
|
||||||
|
return "", errors.New("pin is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.secrets.Pin(), nil
|
||||||
|
},
|
||||||
|
"session_puk": func() (string, error) {
|
||||||
|
if s.secrets == nil {
|
||||||
|
return "", errors.New("puk is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.secrets.Puk(), nil
|
||||||
|
},
|
||||||
|
"session_pairing_password": func() (string, error) {
|
||||||
|
if s.secrets == nil {
|
||||||
|
return "", errors.New("pairing password is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.secrets.PairingPass(), nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tpl, err := template.New("").Funcs(funcMap).Parse(text)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.NewBufferString("")
|
||||||
|
err = tpl.Execute(buf, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user