mirror of
https://github.com/status-im/keycard-go.git
synced 2025-01-19 00:10:55 +00:00
add CommandSet and parse application info
This commit is contained in:
parent
077b96f9ee
commit
ce5141b390
@ -61,8 +61,11 @@ func (i *Initializer) Init() (*keycard.Secrets, error) {
|
||||
}
|
||||
|
||||
// Info returns a types.ApplicationInfo struct with info about the card.
|
||||
func (i *Initializer) Info() (*types.ApplicationInfo, error) {
|
||||
return keycard.Select(i.c, identifiers.KeycardAID)
|
||||
func (i *Initializer) Info() (types.ApplicationInfo, error) {
|
||||
cmdSet := keycard.NewCommandSet(i.c)
|
||||
err := cmdSet.Select()
|
||||
|
||||
return cmdSet.ApplicationInfo, err
|
||||
}
|
||||
|
||||
func (i *Initializer) initGPSecureChannel(sdaid []byte) error {
|
||||
|
65
command_set.go
Normal file
65
command_set.go
Normal file
@ -0,0 +1,65 @@
|
||||
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 CommandSet struct {
|
||||
c types.Channel
|
||||
ApplicationInfo types.ApplicationInfo
|
||||
}
|
||||
|
||||
func NewCommandSet(c types.Channel) *CommandSet {
|
||||
return &CommandSet{
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *CommandSet) Select() error {
|
||||
instanceAID, err := identifiers.KeycardInstanceAID(identifiers.KeycardDefaultInstanceIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := apdu.NewCommand(
|
||||
0x00,
|
||||
globalplatform.InsSelect,
|
||||
uint8(0x04),
|
||||
uint8(0x00),
|
||||
instanceAID,
|
||||
)
|
||||
|
||||
cmd.SetLe(0)
|
||||
resp, err := cs.c.Send(cmd)
|
||||
|
||||
err = cs.checkOK(resp, err)
|
||||
if err == nil {
|
||||
appInfo, err := types.ParseApplicationInfo(resp.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cs.ApplicationInfo = appInfo
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (cs *CommandSet) checkOK(resp *apdu.Response, err error, allowedResponses ...uint16) error {
|
||||
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")
|
||||
}
|
@ -12,6 +12,7 @@ const (
|
||||
InsPair = uint8(0x12)
|
||||
InsGetStatus = uint8(0xF2)
|
||||
|
||||
//TODO: remove
|
||||
TagSelectResponsePreInitialized = uint8(0x80)
|
||||
TagApplicationStatusTemplate = uint8(0xA3)
|
||||
TagApplicationInfoTemplate = uint8(0xA4)
|
||||
|
@ -11,6 +11,8 @@ var (
|
||||
NdefAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x02}
|
||||
NdefInstanceAID = []byte{0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01}
|
||||
|
||||
KeycardDefaultInstanceIndex = 1
|
||||
|
||||
ErrInvalidInstanceIndex = errors.New("instance index must be between 1 and 255")
|
||||
)
|
||||
|
||||
|
74
types/application_info.go
Normal file
74
types/application_info.go
Normal file
@ -0,0 +1,74 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/status-im/keycard-go/apdu"
|
||||
)
|
||||
|
||||
var ErrWrongApplicationInfoTemplate = errors.New("wrong application info template")
|
||||
|
||||
const (
|
||||
TagSelectResponsePreInitialized = uint8(0x80)
|
||||
TagApplicationStatusTemplate = uint8(0xA3)
|
||||
TagApplicationInfoTemplate = uint8(0xA4)
|
||||
)
|
||||
|
||||
type ApplicationInfo struct {
|
||||
Installed bool
|
||||
Initialized bool
|
||||
InstanceUID []byte
|
||||
PublicKey []byte
|
||||
Version []byte
|
||||
AvailableSlots []byte
|
||||
// KeyUID is the sha256 of of the master public key on the card.
|
||||
// It's empty if the card doesn't contain any key.
|
||||
KeyUID []byte
|
||||
}
|
||||
|
||||
func ParseApplicationInfo(data []byte) (info ApplicationInfo, err error) {
|
||||
info.Installed = true
|
||||
if data[0] == TagSelectResponsePreInitialized {
|
||||
info.PublicKey = data[2:]
|
||||
return info, nil
|
||||
}
|
||||
|
||||
info.Initialized = true
|
||||
|
||||
if data[0] != TagApplicationInfoTemplate {
|
||||
return info, ErrWrongApplicationInfoTemplate
|
||||
}
|
||||
|
||||
instanceUID, err := apdu.FindTag(data, TagApplicationInfoTemplate, uint8(0x8F))
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
pubKey, err := apdu.FindTag(data, TagApplicationInfoTemplate, uint8(0x80))
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
appVersion, err := apdu.FindTag(data, TagApplicationInfoTemplate, uint8(0x02))
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
availableSlots, err := apdu.FindTagN(data, 1, TagApplicationInfoTemplate, uint8(0x02))
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
keyUID, err := apdu.FindTagN(data, 0, TagApplicationInfoTemplate, uint8(0x8E))
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
info.InstanceUID = instanceUID
|
||||
info.PublicKey = pubKey
|
||||
info.Version = appVersion
|
||||
info.AvailableSlots = availableSlots
|
||||
info.KeyUID = keyUID
|
||||
|
||||
return info, nil
|
||||
}
|
@ -7,18 +7,6 @@ type Channel interface {
|
||||
Send(*apdu.Command) (*apdu.Response, error)
|
||||
}
|
||||
|
||||
type ApplicationInfo struct {
|
||||
Installed bool
|
||||
Initialized bool
|
||||
InstanceUID []byte
|
||||
PublicKey []byte
|
||||
Version []byte
|
||||
AvailableSlots []byte
|
||||
// KeyUID is the sha256 of of the master public key on the card.
|
||||
// It's empty if the card doesn't contain any key.
|
||||
KeyUID []byte
|
||||
}
|
||||
|
||||
type ApplicationStatus struct {
|
||||
PinRetryCount int
|
||||
PUKRetryCount int
|
||||
|
Loading…
x
Reference in New Issue
Block a user