add FindTag utils function to parse TLV data

This commit is contained in:
Andrea Franz 2018-09-25 15:26:06 +02:00
parent 739696e6f9
commit 0c3a4d0c01
No known key found for this signature in database
GPG Key ID: 4F0D2F2D9DE7F29D
3 changed files with 105 additions and 0 deletions

View File

@ -4,12 +4,14 @@ import (
"encoding/hex"
"fmt"
"log"
"regexp"
"testing"
"github.com/stretchr/testify/assert"
)
func hexToBytes(s string) []byte {
s = regexp.MustCompile(" ").ReplaceAllString(s, "")
b := make([]byte, hex.DecodedLen(len(s)))
_, err := hex.Decode(b, []byte(s))
if err != nil {

61
apdu/utils.go Normal file
View File

@ -0,0 +1,61 @@
package apdu
import (
"bytes"
"fmt"
"io"
)
type ErrTagNotFound struct {
tag uint8
}
func (e *ErrTagNotFound) Error() string {
return fmt.Sprintf("tag %x not found", e.tag)
}
func FindTag(raw []byte, tags ...uint8) ([]byte, error) {
if len(tags) == 0 {
return raw, nil
}
target := tags[0]
buf := bytes.NewBuffer(raw)
var (
tag uint8
length uint8
err error
)
for {
tag, err = buf.ReadByte()
switch {
case err == io.EOF:
return []byte{}, &ErrTagNotFound{target}
case err != nil:
return nil, err
}
length, err = buf.ReadByte()
if err != nil {
return nil, err
}
data := make([]byte, length)
if length != 0 {
_, err = buf.Read(data)
if err != nil {
return nil, err
}
}
if tag == target {
if len(tags) == 1 {
return data, nil
}
return FindTag(data, tags[1:]...)
}
}
}

42
apdu/utils_test.go Normal file
View File

@ -0,0 +1,42 @@
package apdu
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFindTag(t *testing.T) {
var (
tagData []byte
err error
)
data := hexToBytes("C1 02 BB CC C2 04 C3 02 11 22 C3 02 88 99")
tagData, err = FindTag(data, uint8(0xC1))
assert.NoError(t, err)
assert.Equal(t, "BB CC", bytesToHexWithSpaces(tagData))
tagData, err = FindTag(data, uint8(0xC2))
assert.NoError(t, err)
assert.Equal(t, "C3 02 11 22", bytesToHexWithSpaces(tagData))
tagData, err = FindTag(data, uint8(0xC3))
assert.NoError(t, err)
assert.Equal(t, "88 99", bytesToHexWithSpaces(tagData))
tagData, err = FindTag(data, uint8(0xC2), uint8(0xC3))
assert.NoError(t, err)
assert.Equal(t, "11 22", bytesToHexWithSpaces(tagData))
// tag not found
badData := hexToBytes("C1 00")
_, err = FindTag(badData, uint8(0xC2))
assert.Equal(t, &ErrTagNotFound{uint8(0xC2)}, err)
// sub-tag not found
badData = hexToBytes("C1 02 C2 00")
_, err = FindTag(badData, uint8(0xC1), uint8(0xC3))
assert.Equal(t, &ErrTagNotFound{uint8(0xC3)}, err)
}