keycard-go/lightwallet/actions/actions.go

98 lines
2.3 KiB
Go
Raw Normal View History

2018-10-24 11:42:00 +00:00
package actions
import (
"errors"
"github.com/status-im/smartcard-go/apdu"
"github.com/status-im/smartcard-go/globalplatform"
"github.com/status-im/smartcard-go/lightwallet"
)
var (
ErrAlreadyInitialized = errors.New("card already initialized")
ErrNotInitialized = errors.New("card not initialized")
ErrUnknownApplicationInfoTemplate = errors.New("unknown application info template")
)
type ApplicationInfo struct {
InstanceUID []byte
PublicKey []byte
Version []byte
AvailableSlots []byte
}
func Select(c globalplatform.Channel, aid []byte) (*ApplicationInfo, error) {
sel := globalplatform.NewCommandSelect(aid)
resp, err := c.Send(sel)
if err != nil {
return nil, err
}
if resp.Data[0] == lightwallet.TagSelectResponsePreInitialized {
return nil, ErrNotInitialized
}
return parseApplicationInfo(resp)
}
func Init(c globalplatform.Channel, secrets *lightwallet.Secrets, aid []byte) error {
sel := globalplatform.NewCommandSelect(aid)
resp, err := c.Send(sel)
if err != nil {
return err
}
if resp.Data[0] != lightwallet.TagSelectResponsePreInitialized {
return ErrAlreadyInitialized
}
cardKeyData := resp.Data[2:]
secureChannel, err := lightwallet.NewSecureChannel(c, cardKeyData)
if err != nil {
return err
}
data, err := secureChannel.OneShotEncrypt(secrets)
if err != nil {
return err
}
init := lightwallet.NewCommandInit(data)
_, err = c.Send(init)
return err
}
func parseApplicationInfo(resp *apdu.Response) (*ApplicationInfo, error) {
if resp.Data[0] != lightwallet.TagApplicationInfoTemplate {
return nil, ErrUnknownApplicationInfoTemplate
}
instanceUID, err := apdu.FindTag(resp.Data, lightwallet.TagApplicationInfoTemplate, uint8(0x8F))
if err != nil {
return nil, err
}
pubKey, err := apdu.FindTag(resp.Data, lightwallet.TagApplicationInfoTemplate, uint8(0x80))
if err != nil {
return nil, err
}
appVersion, err := apdu.FindTag(resp.Data, lightwallet.TagApplicationInfoTemplate, uint8(0x02))
if err != nil {
return nil, err
}
availableSlots, err := apdu.FindTagN(resp.Data, 1, lightwallet.TagApplicationInfoTemplate, uint8(0x02))
if err != nil {
return nil, err
}
return &ApplicationInfo{
InstanceUID: instanceUID,
PublicKey: pubKey,
Version: appVersion,
AvailableSlots: availableSlots,
}, nil
}