mirror of
https://github.com/status-im/keycard-cli.git
synced 2025-02-28 20:00:38 +00:00
add cash applet features
This commit is contained in:
parent
cc4e5638f2
commit
90247e62fd
4
Gopkg.lock
generated
4
Gopkg.lock
generated
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "develop"
|
branch = "develop"
|
||||||
digest = "1:428d2c2f86c07c78f39d379b809c317b3792d0248e76d60bf78dcf101596c770"
|
digest = "1:9b4833a900fe5a52f64346bde7749ea58797e8d010ca05d5a78e2ba5ca1864cd"
|
||||||
name = "github.com/status-im/keycard-go"
|
name = "github.com/status-im/keycard-go"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@ -57,7 +57,7 @@
|
|||||||
"types",
|
"types",
|
||||||
]
|
]
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "9d48af884d5b92339229bf57df18d0f882ba70be"
|
revision = "6dd40a46baa0d4c8b6fcb69f7e2362e21d89df4d"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
@ -7,9 +7,12 @@ gp-select
|
|||||||
gp-open-secure-channel
|
gp-open-secure-channel
|
||||||
gp-delete D2760000850101
|
gp-delete D2760000850101
|
||||||
gp-delete A00000080400010101
|
gp-delete A00000080400010101
|
||||||
|
gp-delete A00000080400010301
|
||||||
gp-delete A0000008040001
|
gp-delete A0000008040001
|
||||||
gp-load _assets/keycard_v2.2.1.cap A0000008040001
|
gp-load _assets/keycard_v3.0.cap A0000008040001
|
||||||
# NDEF applet
|
# NDEF applet
|
||||||
gp-install-for-install A0000008040001 A000000804000102 D2760000850101 0024d40f12616e64726f69642e636f6d3a706b67696d2e7374617475732e657468657265756d
|
gp-install-for-install A0000008040001 A000000804000102 D2760000850101 0024d40f12616e64726f69642e636f6d3a706b67696d2e7374617475732e657468657265756d
|
||||||
# Keycard applet
|
# Keycard applet
|
||||||
gp-install-for-install A0000008040001 A000000804000101 A00000080400010101
|
gp-install-for-install A0000008040001 A000000804000101 A00000080400010101
|
||||||
|
# Cash applet
|
||||||
|
gp-install-for-install A0000008040001 A000000804000103 A00000080400010301
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
# select with raw apdu command
|
|
||||||
gp-send-apdu 00A4040000
|
|
||||||
|
|
||||||
# install
|
|
||||||
gp-open-secure-channel
|
|
||||||
gp-delete D2760000850101
|
|
||||||
gp-delete A00000080400010101
|
|
||||||
gp-delete A0000008040001
|
|
||||||
gp-load _assets/keycard_v2.2.1.cap A0000008040001
|
|
||||||
gp-install-for-install A0000008040001 A000000804000102 D2760000850101 0024d40f12616e64726f69642e636f6d3a706b67696d2e7374617475732e657468657265756d
|
|
||||||
gp-install-for-install A0000008040001 A000000804000101 A00000080400010101
|
|
||||||
|
|
||||||
# init
|
|
||||||
keycard-select
|
|
||||||
keycard-init
|
|
||||||
|
|
||||||
# pair
|
|
||||||
keycard-select
|
|
||||||
keycard-pair
|
|
||||||
keycard-open-secure-channel
|
|
||||||
|
|
||||||
# get status
|
|
||||||
keycard-get-status
|
|
||||||
|
|
||||||
# verify PIN
|
|
||||||
keycard-verify-pin {{ session_pin }}
|
|
||||||
|
|
||||||
# change secrets
|
|
||||||
keycard-change-pin 888888
|
|
||||||
keycard-change-puk 111222333444
|
|
||||||
keycard-change-pairing-secret foobarbaz
|
|
||||||
|
|
||||||
# sign
|
|
||||||
keycard-generate-key
|
|
||||||
keycard-derive-key m/44'/60'/0'/0/0
|
|
||||||
keycard-sign 0000000000000000000000000000000000000000000000000000000000000000
|
|
||||||
|
|
||||||
# remove master key
|
|
||||||
keycard-remove-key
|
|
||||||
|
|
||||||
# unpair and check card status
|
|
||||||
keycard-unpair {{ session_pairing_index }}
|
|
||||||
keycard-select
|
|
@ -17,6 +17,7 @@ var (
|
|||||||
|
|
||||||
ErrNotInitialized = errors.New("card not initialized")
|
ErrNotInitialized = errors.New("card not initialized")
|
||||||
ErrNotInstalled = errors.New("applet not initialized")
|
ErrNotInstalled = errors.New("applet not initialized")
|
||||||
|
ErrCashNotInstalled = errors.New("cash applet not initialized")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Initializer defines a struct with methods to install applets and initialize a card.
|
// Initializer defines a struct with methods to install applets and initialize a card.
|
||||||
|
@ -83,6 +83,12 @@ func (i *Installer) Install(capFile *os.File, overwriteApplet bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.Info("installing Cash applet")
|
||||||
|
if err = cmdSet.InstallCashApplet(); err != nil {
|
||||||
|
logger.Error("installing Cash applet failed", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
elapsed := time.Now().Sub(startTime)
|
elapsed := time.Now().Sub(startTime)
|
||||||
logger.Info(fmt.Sprintf("installation completed in %f seconds", elapsed.Seconds()))
|
logger.Info(fmt.Sprintf("installation completed in %f seconds", elapsed.Seconds()))
|
||||||
return err
|
return err
|
||||||
|
51
shell.go
51
shell.go
@ -94,6 +94,7 @@ type Shell struct {
|
|||||||
Secrets *keycard.Secrets
|
Secrets *keycard.Secrets
|
||||||
gpCmdSet *globalplatform.CommandSet
|
gpCmdSet *globalplatform.CommandSet
|
||||||
kCmdSet *keycard.CommandSet
|
kCmdSet *keycard.CommandSet
|
||||||
|
cashCmdSet *keycard.CashCommandSet
|
||||||
commands map[string]shellCommand
|
commands map[string]shellCommand
|
||||||
out *bytes.Buffer
|
out *bytes.Buffer
|
||||||
tplFuncMap template.FuncMap
|
tplFuncMap template.FuncMap
|
||||||
@ -106,6 +107,7 @@ func NewShell(t keycardio.Transmitter) *Shell {
|
|||||||
t: t,
|
t: t,
|
||||||
c: c,
|
c: c,
|
||||||
kCmdSet: keycard.NewCommandSet(c),
|
kCmdSet: keycard.NewCommandSet(c),
|
||||||
|
cashCmdSet: keycard.NewCashCommandSet(c),
|
||||||
gpCmdSet: globalplatform.NewCommandSet(c),
|
gpCmdSet: globalplatform.NewCommandSet(c),
|
||||||
out: new(bytes.Buffer),
|
out: new(bytes.Buffer),
|
||||||
}
|
}
|
||||||
@ -143,6 +145,8 @@ func NewShell(t keycardio.Transmitter) *Shell {
|
|||||||
"keycard-sign-pinless": s.commandKeycardSignPinless,
|
"keycard-sign-pinless": s.commandKeycardSignPinless,
|
||||||
"keycard-sign-message-pinless": s.commandKeycardSignMessagePinless,
|
"keycard-sign-message-pinless": s.commandKeycardSignMessagePinless,
|
||||||
"keycard-set-pinless-path": s.commandKeycardSetPinlessPath,
|
"keycard-set-pinless-path": s.commandKeycardSetPinlessPath,
|
||||||
|
"cash-select": s.commandCashSelect,
|
||||||
|
"cash-sign": s.commandCashSign,
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
@ -259,7 +263,7 @@ func (s *Shell) commandGPDelete(args ...string) error {
|
|||||||
|
|
||||||
logger.Info(fmt.Sprintf("delete %x", aid))
|
logger.Info(fmt.Sprintf("delete %x", aid))
|
||||||
|
|
||||||
return s.gpCmdSet.Delete(aid)
|
return s.gpCmdSet.DeleteObject(aid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shell) commandGPLoad(args ...string) error {
|
func (s *Shell) commandGPLoad(args ...string) error {
|
||||||
@ -781,6 +785,51 @@ func (s *Shell) commandKeycardSetPinlessPath(args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shell) commandCashSelect(args ...string) error {
|
||||||
|
if err := s.requireArgs(args, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("select cash")
|
||||||
|
err := s.cashCmdSet.Select()
|
||||||
|
info := s.cashCmdSet.CashApplicationInfo
|
||||||
|
|
||||||
|
s.write(fmt.Sprintf("Installed: %v\n", info.Installed))
|
||||||
|
s.write(fmt.Sprintf("PublicKey: %x\n", info.PublicKey))
|
||||||
|
s.write(fmt.Sprintf("PublicKeyData: %x\n", info.PublicKeyData))
|
||||||
|
s.write(fmt.Sprintf("Version: %x\n\n", info.Version))
|
||||||
|
|
||||||
|
if e, ok := err.(*apdu.ErrBadResponse); ok && e.Sw == globalplatform.SwFileNotFound {
|
||||||
|
logger.Error("select cash failed", "error", err)
|
||||||
|
return ErrCashNotInstalled
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Shell) commandCashSign(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.cashCmdSet.Sign(data)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("sign failed", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.writeSignatureInfo(sig)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Shell) requireArgs(args []string, possibleArgsN ...int) error {
|
func (s *Shell) requireArgs(args []string, possibleArgsN ...int) error {
|
||||||
for _, n := range possibleArgsN {
|
for _, n := range possibleArgsN {
|
||||||
if len(args) == n {
|
if len(args) == n {
|
||||||
|
70
vendor/github.com/status-im/keycard-go/cash_command_set.go
generated
vendored
Normal file
70
vendor/github.com/status-im/keycard-go/cash_command_set.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package keycard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/status-im/keycard-go/apdu"
|
||||||
|
"github.com/status-im/keycard-go/globalplatform"
|
||||||
|
"github.com/status-im/keycard-go/identifiers"
|
||||||
|
"github.com/status-im/keycard-go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CashCommandSet struct {
|
||||||
|
c types.Channel
|
||||||
|
CashApplicationInfo *types.CashApplicationInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCashCommandSet(c types.Channel) *CashCommandSet {
|
||||||
|
return &CashCommandSet{
|
||||||
|
c: c,
|
||||||
|
CashApplicationInfo: &types.CashApplicationInfo{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *CashCommandSet) Select() error {
|
||||||
|
cmd := globalplatform.NewCommandSelect(identifiers.CashInstanceAID)
|
||||||
|
cmd.SetLe(0)
|
||||||
|
resp, err := cs.c.Send(cmd)
|
||||||
|
if err = cs.checkOK(resp, err); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
appInfo, err := types.ParseCashApplicationInfo(resp.Data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cs.CashApplicationInfo = appInfo
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *CashCommandSet) Sign(data []byte) (*types.Signature, error) {
|
||||||
|
cmd, err := NewCommandSign(data, 0x00, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := cs.c.Send(cmd)
|
||||||
|
if err = cs.checkOK(resp, err); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.ParseSignature(data, resp.Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *CashCommandSet) checkOK(resp *apdu.Response, err error, allowedResponses ...uint16) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(allowedResponses) == 0 {
|
||||||
|
allowedResponses = []uint16{apdu.SwOK}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, code := range allowedResponses {
|
||||||
|
if code == resp.Sw {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return apdu.NewErrBadResponse(resp.Sw, "unexpected response")
|
||||||
|
}
|
2
vendor/github.com/status-im/keycard-go/command_set.go
generated
vendored
2
vendor/github.com/status-im/keycard-go/command_set.go
generated
vendored
@ -25,6 +25,7 @@ func NewCommandSet(c types.Channel) *CommandSet {
|
|||||||
return &CommandSet{
|
return &CommandSet{
|
||||||
c: c,
|
c: c,
|
||||||
sc: NewSecureChannel(c),
|
sc: NewSecureChannel(c),
|
||||||
|
ApplicationInfo: &types.ApplicationInfo{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +46,6 @@ func (cs *CommandSet) Select() error {
|
|||||||
cmd.SetLe(0)
|
cmd.SetLe(0)
|
||||||
resp, err := cs.c.Send(cmd)
|
resp, err := cs.c.Send(cmd)
|
||||||
if err = cs.checkOK(resp, err); err != nil {
|
if err = cs.checkOK(resp, err); err != nil {
|
||||||
cs.ApplicationInfo = &types.ApplicationInfo{}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
vendor/github.com/status-im/keycard-go/globalplatform/command_set.go
generated
vendored
32
vendor/github.com/status-im/keycard-go/globalplatform/command_set.go
generated
vendored
@ -57,29 +57,19 @@ func (cs *CommandSet) DeleteKeycardInstancesAndPackage() error {
|
|||||||
return ErrSecureChannelNotOpen
|
return ErrSecureChannelNotOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceAID, err := identifiers.KeycardInstanceAID(identifiers.KeycardDefaultInstanceIndex)
|
return cs.DeleteObjectAndRelatedObject(identifiers.PackageAID)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ids := [][]byte{
|
func (cs *CommandSet) DeleteObject(aid []byte) error {
|
||||||
identifiers.NdefInstanceAID,
|
return cs.Delete(aid, P2DeleteObject)
|
||||||
instanceAID,
|
|
||||||
identifiers.PackageAID,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, aid := range ids {
|
func (cs *CommandSet) DeleteObjectAndRelatedObject(aid []byte) error {
|
||||||
err := cs.Delete(aid)
|
return cs.Delete(aid, P2DeleteObjectAndRelatedObject)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
func (cs *CommandSet) Delete(aid []byte, p2 uint8) error {
|
||||||
}
|
cmd := NewCommandDelete(aid, p2)
|
||||||
|
|
||||||
func (cs *CommandSet) Delete(aid []byte) error {
|
|
||||||
cmd := NewCommandDelete(aid)
|
|
||||||
resp, err := cs.sc.Send(cmd)
|
resp, err := cs.sc.Send(cmd)
|
||||||
return cs.checkOK(resp, err, SwOK, SwReferencedDataNotFound)
|
return cs.checkOK(resp, err, SwOK, SwReferencedDataNotFound)
|
||||||
}
|
}
|
||||||
@ -137,6 +127,14 @@ func (cs *CommandSet) InstallKeycardApplet() error {
|
|||||||
[]byte{})
|
[]byte{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *CommandSet) InstallCashApplet() error {
|
||||||
|
return cs.InstallForInstall(
|
||||||
|
identifiers.PackageAID,
|
||||||
|
identifiers.CashAID,
|
||||||
|
identifiers.CashInstanceAID,
|
||||||
|
[]byte{})
|
||||||
|
}
|
||||||
|
|
||||||
func (cs *CommandSet) InstallForInstall(packageAID, appletAID, instanceAID, params []byte) error {
|
func (cs *CommandSet) InstallForInstall(packageAID, appletAID, instanceAID, params []byte) error {
|
||||||
cmd := NewCommandInstallForInstall(packageAID, appletAID, instanceAID, params)
|
cmd := NewCommandInstallForInstall(packageAID, appletAID, instanceAID, params)
|
||||||
resp, err := cs.sc.Send(cmd)
|
resp, err := cs.sc.Send(cmd)
|
||||||
|
6
vendor/github.com/status-im/keycard-go/globalplatform/commands.go
generated
vendored
6
vendor/github.com/status-im/keycard-go/globalplatform/commands.go
generated
vendored
@ -32,6 +32,8 @@ const (
|
|||||||
P1GetStatusExecLoadFilesAndModules = 0x10
|
P1GetStatusExecLoadFilesAndModules = 0x10
|
||||||
|
|
||||||
P2GetStatusTLVData = 0x02
|
P2GetStatusTLVData = 0x02
|
||||||
|
P2DeleteObject = 0x00
|
||||||
|
P2DeleteObjectAndRelatedObject = 0x80
|
||||||
|
|
||||||
Sw1ResponseDataIncomplete = 0x61
|
Sw1ResponseDataIncomplete = 0x61
|
||||||
|
|
||||||
@ -108,7 +110,7 @@ func NewCommandGetResponse(length uint8) *apdu.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewCommandDelete returns a Delete command as defined in the globalplatform specifications.
|
// NewCommandDelete returns a Delete command as defined in the globalplatform specifications.
|
||||||
func NewCommandDelete(aid []byte) *apdu.Command {
|
func NewCommandDelete(aid []byte, p2 uint8) *apdu.Command {
|
||||||
data := []byte{tagDeleteAID, byte(len(aid))}
|
data := []byte{tagDeleteAID, byte(len(aid))}
|
||||||
data = append(data, aid...)
|
data = append(data, aid...)
|
||||||
|
|
||||||
@ -116,7 +118,7 @@ func NewCommandDelete(aid []byte) *apdu.Command {
|
|||||||
ClaGp,
|
ClaGp,
|
||||||
InsDelete,
|
InsDelete,
|
||||||
0,
|
0,
|
||||||
0,
|
p2,
|
||||||
data,
|
data,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
5
vendor/github.com/status-im/keycard-go/identifiers/identifiers.go
generated
vendored
5
vendor/github.com/status-im/keycard-go/identifiers/identifiers.go
generated
vendored
@ -7,10 +7,15 @@ var (
|
|||||||
KeycardDevelopmentKey = []byte{0xc2, 0x12, 0xe0, 0x73, 0xff, 0x8b, 0x4b, 0xbf, 0xaf, 0xf4, 0xde, 0x8a, 0xb6, 0x55, 0x22, 0x1f}
|
KeycardDevelopmentKey = []byte{0xc2, 0x12, 0xe0, 0x73, 0xff, 0x8b, 0x4b, 0xbf, 0xaf, 0xf4, 0xde, 0x8a, 0xb6, 0x55, 0x22, 0x1f}
|
||||||
|
|
||||||
PackageAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01}
|
PackageAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01}
|
||||||
|
|
||||||
KeycardAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x01}
|
KeycardAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x01}
|
||||||
|
|
||||||
NdefAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x02}
|
NdefAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x02}
|
||||||
NdefInstanceAID = []byte{0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01}
|
NdefInstanceAID = []byte{0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01}
|
||||||
|
|
||||||
|
CashAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x03}
|
||||||
|
CashInstanceAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x03, 0x01}
|
||||||
|
|
||||||
KeycardDefaultInstanceIndex = 1
|
KeycardDefaultInstanceIndex = 1
|
||||||
|
|
||||||
ErrInvalidInstanceIndex = errors.New("instance index must be between 1 and 255")
|
ErrInvalidInstanceIndex = errors.New("instance index must be between 1 and 255")
|
||||||
|
41
vendor/github.com/status-im/keycard-go/types/cash_application_info.go
generated
vendored
Normal file
41
vendor/github.com/status-im/keycard-go/types/cash_application_info.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import "github.com/status-im/keycard-go/apdu"
|
||||||
|
|
||||||
|
type CashApplicationInfo struct {
|
||||||
|
Installed bool
|
||||||
|
PublicKey []byte
|
||||||
|
PublicKeyData []byte
|
||||||
|
Version []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseCashApplicationInfo(data []byte) (*CashApplicationInfo, error) {
|
||||||
|
info := &CashApplicationInfo{}
|
||||||
|
|
||||||
|
if data[0] != TagApplicationInfoTemplate {
|
||||||
|
return nil, ErrWrongApplicationInfoTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
info.Installed = true
|
||||||
|
|
||||||
|
pubKey, err := apdu.FindTag(data, apdu.Tag{TagApplicationInfoTemplate}, apdu.Tag{0x80})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pubKeyData, err := apdu.FindTag(data, apdu.Tag{TagApplicationInfoTemplate}, apdu.Tag{0x82})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
appVersion, err := apdu.FindTag(data, apdu.Tag{TagApplicationInfoTemplate}, apdu.Tag{0x02})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info.PublicKey = pubKey
|
||||||
|
info.PublicKeyData = pubKeyData
|
||||||
|
info.Version = appVersion
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user