add load command
This commit is contained in:
parent
d5b7793219
commit
415fe350bf
|
@ -15,12 +15,15 @@ const (
|
|||
InsExternalAuthenticate = uint8(0x82)
|
||||
InsGetResponse = uint8(0xC0)
|
||||
InsDelete = uint8(0xE4)
|
||||
InsLoad = uint8(0xE8)
|
||||
InsInstall = uint8(0xE6)
|
||||
|
||||
P1ExternalAuthenticateCMAC = uint8(0x01)
|
||||
P1InstallForLoad = uint8(0x02)
|
||||
P1InstallForInstall = uint8(0x04)
|
||||
P1InstallForMakeSelectable = uint8(0x08)
|
||||
P1LoadMoreBlocks = uint8(0x00)
|
||||
P1LoadLastBlock = uint8(0x80)
|
||||
|
||||
Sw1ResponseDataIncomplete = uint8(0x61)
|
||||
|
||||
|
@ -29,7 +32,8 @@ const (
|
|||
SwSecurityConditionNotSatisfied = uint16(0x6982)
|
||||
SwAuthenticationMethodBlocked = uint16(0x6983)
|
||||
|
||||
tagDeleteAID = byte(0x4F)
|
||||
tagDeleteAID = byte(0x4F)
|
||||
tagLoadFileDataBlock = byte(0xC4)
|
||||
)
|
||||
|
||||
func NewCommandSelect(aid []byte) *apdu.Command {
|
||||
|
@ -65,7 +69,7 @@ func NewCommandExternalAuthenticate(encKey, cardChallenge, hostChallenge []byte)
|
|||
return apdu.NewCommand(
|
||||
ClaMac,
|
||||
InsExternalAuthenticate,
|
||||
P1ExternalAuthenticateCMAC, // C-MAC
|
||||
P1ExternalAuthenticateCMAC,
|
||||
uint8(0x00),
|
||||
hostCryptogram,
|
||||
), nil
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
package globalplatform
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/status-im/status-go/smartcard/apdu"
|
||||
)
|
||||
|
||||
var internalFiles = []string{
|
||||
"Header", "Directory", "Import", "Applet", "Class",
|
||||
"Method", "StaticField", "Export", "ConstantPool", "RefLocation",
|
||||
}
|
||||
|
||||
type LoadCommandStream struct {
|
||||
data *bytes.Reader
|
||||
currentIndex uint8
|
||||
currentData []byte
|
||||
p1 uint8
|
||||
}
|
||||
|
||||
func NewLoadCommandStream(file *os.File) (*LoadCommandStream, error) {
|
||||
files, err := loadFiles(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := encodeFilesData(files)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &LoadCommandStream{
|
||||
data: bytes.NewReader(data),
|
||||
p1: P1LoadMoreBlocks,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO:@pilu update blockSize when using encrypted data
|
||||
func (lcs *LoadCommandStream) Next() bool {
|
||||
if lcs.data.Len() == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
blockSize := 247 // 255 - 8 bytes for MAC
|
||||
buf := make([]byte, blockSize)
|
||||
n, err := lcs.data.Read(buf)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
lcs.currentData = buf[:n]
|
||||
lcs.currentIndex++
|
||||
|
||||
if lcs.data.Len() == 0 {
|
||||
lcs.p1 = P1LoadLastBlock
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (lcs *LoadCommandStream) Index() uint8 {
|
||||
return lcs.currentIndex - 1
|
||||
}
|
||||
|
||||
func (lcs *LoadCommandStream) GetCommand() *apdu.Command {
|
||||
return apdu.NewCommand(ClaGp, InsLoad, lcs.p1, lcs.Index(), lcs.currentData)
|
||||
}
|
||||
|
||||
func loadFiles(f *os.File) (map[string][]byte, error) {
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
z, err := zip.NewReader(f, fi.Size())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
files := make(map[string][]byte)
|
||||
|
||||
for _, item := range z.File {
|
||||
name := strings.Split(item.FileInfo().Name(), ".")[0]
|
||||
f, err := item.Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
files[name] = data
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func encodeFilesData(files map[string][]byte) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
for _, name := range internalFiles {
|
||||
if data, ok := files[name]; ok {
|
||||
buf.Write(data)
|
||||
}
|
||||
}
|
||||
|
||||
filesData := buf.Bytes()
|
||||
length := encodeLength(len(filesData))
|
||||
|
||||
data := make([]byte, 0)
|
||||
data = append(data, tagLoadFileDataBlock)
|
||||
data = append(data, length...)
|
||||
data = append(data, filesData...)
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func encodeLength(length int) []byte {
|
||||
if length < 0x80 {
|
||||
return []byte{byte(length)}
|
||||
}
|
||||
|
||||
if length < 0xFF {
|
||||
return []byte{
|
||||
byte(0x81),
|
||||
byte(length),
|
||||
}
|
||||
}
|
||||
|
||||
if length < 0xFFFF {
|
||||
return []byte{
|
||||
byte(0x82),
|
||||
byte((length & 0xFF00) >> 8),
|
||||
byte(length & 0xFF),
|
||||
}
|
||||
}
|
||||
|
||||
return []byte{
|
||||
byte(0x83),
|
||||
byte((length & 0xFF0000) >> 16),
|
||||
byte((length & 0xFF00) >> 8),
|
||||
byte(length & 0xFF),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue