add status command and action

This commit is contained in:
Andrea Franz 2018-11-07 14:39:58 +01:00
parent 6e7e217179
commit a6d70a9e67
No known key found for this signature in database
GPG Key ID: 4F0D2F2D9DE7F29D
5 changed files with 93 additions and 15 deletions

View File

@ -258,5 +258,15 @@ func commandStatus(i *actionsets.Installer) error {
index := askUint8("Pairing index")
key := askHex("Pairing key")
return i.Status(index, key)
appStatus, err := i.Status(index, key)
if err != nil {
return err
}
fmt.Printf("Pin retry count: %d\n", appStatus.PinRetryCount)
fmt.Printf("PUK retry count: %d\n", appStatus.PUKRetryCount)
fmt.Printf("Key initialized: %v\n", appStatus.KeyInitialized)
fmt.Printf("Public key derivation: %v\n", appStatus.PubKeyDerivation)
return nil
}

View File

@ -1,6 +1,7 @@
package actions
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"errors"
@ -13,9 +14,10 @@ import (
)
var (
ErrAlreadyInitialized = errors.New("card already initialized")
ErrNotInitialized = errors.New("card not initialized")
ErrUnknownApplicationInfoTemplate = errors.New("unknown application info template")
ErrAlreadyInitialized = errors.New("card already initialized")
ErrNotInitialized = errors.New("card not initialized")
ErrWrongApplicationInfoTemplate = errors.New("wrong application info template")
ErrApplicationStatusTemplateNotFound = errors.New("application status template not found")
)
func Select(c globalplatform.Channel, aid []byte) (*lightwallet.ApplicationInfo, error) {
@ -164,13 +166,19 @@ func mutualAuthenticate(sc *lightwallet.SecureChannel) error {
return checkOKResponse(err, resp)
}
func Status(index uint8, key []byte) error {
return nil
func GetStatusApplication(c globalplatform.Channel) (*lightwallet.ApplicationStatus, error) {
cmd := lightwallet.NewCommandGetStatusApplication()
resp, err := c.Send(cmd)
if err = checkOKResponse(err, resp); err != nil {
return nil, err
}
return parseApplicationStatus(resp.Data)
}
func parseApplicationInfo(data []byte, info *lightwallet.ApplicationInfo) (*lightwallet.ApplicationInfo, error) {
if data[0] != lightwallet.TagApplicationInfoTemplate {
return nil, ErrUnknownApplicationInfoTemplate
return nil, ErrWrongApplicationInfoTemplate
}
instanceUID, err := apdu.FindTag(data, lightwallet.TagApplicationInfoTemplate, uint8(0x8F))
@ -207,6 +215,37 @@ func parseApplicationInfo(data []byte, info *lightwallet.ApplicationInfo) (*ligh
return info, nil
}
func parseApplicationStatus(data []byte) (*lightwallet.ApplicationStatus, error) {
appStatus := &lightwallet.ApplicationStatus{}
tpl, err := apdu.FindTag(data, lightwallet.TagApplicationStatusTemplate)
if err != nil {
return nil, ErrApplicationStatusTemplateNotFound
}
if pinRetryCount, err := apdu.FindTag(tpl, uint8(0x02)); err == nil && len(pinRetryCount) == 1 {
appStatus.PinRetryCount = int(pinRetryCount[0])
}
if pukRetryCount, err := apdu.FindTagN(tpl, 1, uint8(0x02)); err == nil && len(pukRetryCount) == 1 {
appStatus.PUKRetryCount = int(pukRetryCount[0])
}
if keyInitialized, err := apdu.FindTag(tpl, uint8(0x01)); err == nil {
if bytes.Equal(keyInitialized, []byte{0xFF}) {
appStatus.KeyInitialized = true
}
}
if keyDerivationSupported, err := apdu.FindTagN(tpl, 1, uint8(0x01)); err == nil {
if bytes.Equal(keyDerivationSupported, []byte{0xFF}) {
appStatus.PubKeyDerivation = true
}
}
return appStatus, nil
}
func checkOKResponse(err error, resp *apdu.Response) error {
if err != nil {
return err

View File

@ -110,26 +110,26 @@ func (i *Installer) Info() (*lightwallet.ApplicationInfo, error) {
}
// Status returns
func (i *Installer) Status(index uint8, key []byte) error {
func (i *Installer) Status(index uint8, key []byte) (*lightwallet.ApplicationStatus, error) {
info, err := actions.Select(i.c, walletAID)
if err != nil {
return err
return nil, err
}
if !info.Installed {
return errAppletNotInstalled
return nil, errAppletNotInstalled
}
if !info.Initialized {
return errCardNotInitialized
return nil, errCardNotInitialized
}
sc, err := actions.OpenSecureChannel(i.c, info, index, key)
if err != nil {
return err
return nil, err
}
return nil
return actions.GetStatusApplication(sc)
}
// Delete deletes the applet and related package from the card.

View File

@ -10,12 +10,16 @@ const (
InsOpenSecureChannel = uint8(0x10)
InsMutuallyAuthenticate = uint8(0x11)
InsPair = uint8(0x12)
InsGetStatus = uint8(0xF2)
TagSelectResponsePreInitialized = uint8(0x80)
TagApplicationStatusTemplate = uint8(0xA3)
TagApplicationInfoTemplate = uint8(0xA4)
P1PairingFirstStep = uint8(0x00)
P1PairingFinalStep = uint8(0x01)
P1PairingFirstStep = uint8(0x00)
P1PairingFinalStep = uint8(0x01)
P1GetStatusApplication = uint8(0x00)
P1GetStatusKeyPath = uint8(0x01)
)
func NewCommandInit(data []byte) *apdu.Command {
@ -67,3 +71,21 @@ func NewCommandMutuallyAuthenticate(data []byte) *apdu.Command {
data,
)
}
func NewCommandGetStatus(p1 uint8) *apdu.Command {
return apdu.NewCommand(
globalplatform.ClaGp,
InsGetStatus,
p1,
uint8(0x00),
[]byte{},
)
}
func NewCommandGetStatusApplication() *apdu.Command {
return NewCommandGetStatus(P1GetStatusApplication)
}
func NewCommandGetStatusKeyPath() *apdu.Command {
return NewCommandGetStatus(P1GetStatusKeyPath)
}

View File

@ -12,6 +12,13 @@ type ApplicationInfo struct {
KeyUID []byte
}
type ApplicationStatus struct {
PinRetryCount int
PUKRetryCount int
KeyInitialized bool
PubKeyDerivation bool
}
type PairingInfo struct {
Key []byte
Index int