Skip to content

Commit

Permalink
Merge pull request #16 from Zondax/dev
Browse files Browse the repository at this point in the history
Adding zemu support
  • Loading branch information
jleni authored Jul 2, 2020
2 parents 5bb39de + 1dcb160 commit 9a633ce
Show file tree
Hide file tree
Showing 15 changed files with 976 additions and 318 deletions.
5 changes: 2 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ version: 2
jobs:
build:
docker:
- image: golang:1.13
- image: golang:1.14
environment:
GO111MODULE: "on"
working_directory: /ledger-go
steps:
- checkout
- run: go build -mod=readonly ledger.go apduWrapper.go
- run: go test
- run: go test -tags ledger_mock
workflows:
version: 2
build_all:
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
test:
go test ledger_test.go ledger.go apduWrapper.go
go test -tags ledger_mock
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

This project provides a library to connect to ledger devices.

It handles USB (HID) communication and APDU encapsulation.
It handles APDU encapsulation, Zemu and USB (HID) communication.

Linux, OSX and Windows are supported.

Expand Down
37 changes: 37 additions & 0 deletions apduWrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,48 @@ package ledger_go

import (
"encoding/binary"
"fmt"
"github.com/pkg/errors"
)

var codec = binary.BigEndian

func ErrorMessage(errorCode uint16) string {
switch errorCode {
// FIXME: Code and description don't match for 0x6982 and 0x6983 based on
// apdu spec: https://www.eftlab.co.uk/index.php/site-map/knowledge-base/118-apdu-response-list

case 0x6400:
return "[APDU_CODE_EXECUTION_ERROR] No information given (NV-Ram not changed)"
case 0x6700:
return "[APDU_CODE_WRONG_LENGTH] Wrong length"
case 0x6982:
return "[APDU_CODE_EMPTY_BUFFER] Security condition not satisfied"
case 0x6983:
return "[APDU_CODE_OUTPUT_BUFFER_TOO_SMALL] Authentication method blocked"
case 0x6984:
return "[APDU_CODE_DATA_INVALID] Referenced data reversibly blocked (invalidated)"
case 0x6985:
return "[APDU_CODE_CONDITIONS_NOT_SATISFIED] Conditions of use not satisfied"
case 0x6986:
return "[APDU_CODE_COMMAND_NOT_ALLOWED] Command not allowed (no current EF)"
case 0x6A80:
return "[APDU_CODE_BAD_KEY_HANDLE] The parameters in the data field are incorrect"
case 0x6B00:
return "[APDU_CODE_INVALID_P1P2] Wrong parameter(s) P1-P2"
case 0x6D00:
return "[APDU_CODE_INS_NOT_SUPPORTED] Instruction code not supported or invalid"
case 0x6E00:
return "[APDU_CODE_CLA_NOT_SUPPORTED] Class not supported"
case 0x6F00:
return "APDU_CODE_UNKNOWN"
case 0x6F01:
return "APDU_CODE_SIGN_VERIFY_ERROR"
default:
return fmt.Sprintf("Error code: %04x", errorCode)
}
}

func SerializePacket(
channel uint16,
command []byte,
Expand Down
46 changes: 15 additions & 31 deletions apduWrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package ledger_go

import (
"bytes"
"fmt"
"math"
"testing"
"unsafe"
Expand All @@ -35,7 +34,7 @@ func Test_SerializePacket_EmptyCommand(t *testing.T) {

func Test_SerializePacket_PacketSize(t *testing.T) {

var packetSize int = 64
var packetSize = 64
type header struct {
channel uint16
tag uint8
Expand All @@ -58,7 +57,7 @@ func Test_SerializePacket_PacketSize(t *testing.T) {

func Test_SerializePacket_Header(t *testing.T) {

var packetSize int = 64
var packetSize = 64
type header struct {
channel uint16
tag uint8
Expand All @@ -84,7 +83,7 @@ func Test_SerializePacket_Header(t *testing.T) {

func Test_SerializePacket_Offset(t *testing.T) {

var packetSize int = 64
var packetSize = 64
type header struct {
channel uint16
tag uint8
Expand All @@ -102,23 +101,18 @@ func Test_SerializePacket_Offset(t *testing.T) {
packetSize,
h.sequenceIdx)

assert.Equal(t, packetSize-int(unsafe.Sizeof(h))+1, offset, "Wrong offset returned. Offset must point to the next comamnd byte that needs to be packet-ized.")
assert.Equal(t, packetSize-int(unsafe.Sizeof(h))+1, offset, "Wrong offset returned. Offset must point to the next command byte that needs to be packetized.")
}

func Test_WrapCommandAPDU_NumberOfPackets(t *testing.T) {

var packetSize int = 64
var packetSize = 64
type firstHeader struct {
channel uint16
sequenceIdx uint16
commandLen uint16
tag uint8
}
type secondHeader struct {
channel uint16
sequenceIdx uint16
tag uint8
}

h1 := firstHeader{channel: 0x0101, tag: 0x05, sequenceIdx: 0, commandLen: 100}

Expand All @@ -134,18 +128,13 @@ func Test_WrapCommandAPDU_NumberOfPackets(t *testing.T) {

func Test_WrapCommandAPDU_CheckHeaders(t *testing.T) {

var packetSize int = 64
var packetSize = 64
type firstHeader struct {
channel uint16
sequenceIdx uint16
commandLen uint16
tag uint8
}
type secondHeader struct {
channel uint16
sequenceIdx uint16
tag uint8
}

h1 := firstHeader{channel: 0x0101, tag: 0x05, sequenceIdx: 0, commandLen: 100}

Expand All @@ -169,18 +158,13 @@ func Test_WrapCommandAPDU_CheckHeaders(t *testing.T) {

func Test_WrapCommandAPDU_CheckData(t *testing.T) {

var packetSize int = 64
var packetSize = 64
type firstHeader struct {
channel uint16
sequenceIdx uint16
commandLen uint16
tag uint8
}
type secondHeader struct {
channel uint16
sequenceIdx uint16
tag uint8
}

h1 := firstHeader{channel: 0x0101, tag: 0x05, sequenceIdx: 0, commandLen: 200}

Expand Down Expand Up @@ -223,8 +207,8 @@ func Test_DeserializePacket_FirstPacket(t *testing.T) {

var sampleCommand = []byte{'H', 'e', 'l', 'l', 'o', 0}

var packetSize int = 64
var firstPacketHeaderSize int = 7
var packetSize = 64
var firstPacketHeaderSize = 7
packet, _, _ := SerializePacket(0x0101, sampleCommand, packetSize, 0)

output, totalSize, err := DeserializePacket(0x0101, packet, 0)
Expand All @@ -238,8 +222,8 @@ func Test_DeserializePacket_FirstPacket(t *testing.T) {
func Test_DeserializePacket_SecondMessage(t *testing.T) {
var sampleCommand = []byte{'H', 'e', 'l', 'l', 'o', 0}

var packetSize int = 64
var firstPacketHeaderSize int = 5 // second packet does not have responseLegth (uint16) in the header
var packetSize = 64
var firstPacketHeaderSize = 5 // second packet does not have responseLength (uint16) in the header
packet, _, _ := SerializePacket(0x0101, sampleCommand, packetSize, 1)

output, totalSize, err := DeserializePacket(0x0101, packet, 1)
Expand All @@ -254,7 +238,7 @@ func Test_UnwrapApdu_SmokeTest(t *testing.T) {
const channel uint16 = 0x8002

inputSize := 200
var packetSize int = 64
var packetSize = 64

// Initialize some dummy input
var input = make([]byte, inputSize)
Expand All @@ -274,9 +258,9 @@ func Test_UnwrapApdu_SmokeTest(t *testing.T) {

output, _ := UnwrapResponseAPDU(channel, pipe, packetSize)

fmt.Printf("INPUT : %x\n", input)
fmt.Printf("SERIALIZED: %x\n", serialized)
fmt.Printf("OUTPUT : %x\n", output)
//fmt.Printf("INPUT : %x\n", input)
//fmt.Printf("SERIALIZED: %x\n", serialized)
//fmt.Printf("OUTPUT : %x\n", output)

assert.Equal(t, len(input), len(output), "Input and output messages have different size")
assert.True(t,
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ go 1.13

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v1.4.2
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.3.0
github.com/zondax/hid v0.9.0
google.golang.org/grpc v1.29.1
google.golang.org/protobuf v1.23.0
)
64 changes: 64 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,76 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Loading

0 comments on commit 9a633ce

Please sign in to comment.