github.com/zondax/ledger-go@v0.14.3/apduWrapper_test.go (about)

     1  /*******************************************************************************
     2  *   (c) 2018 - 2022 ZondaX AG
     3  *
     4  *  Licensed under the Apache License, Version 2.0 (the "License");
     5  *  you may not use this file except in compliance with the License.
     6  *  You may obtain a copy of the License at
     7  *
     8  *      http://www.apache.org/licenses/LICENSE-2.0
     9  *
    10  *  Unless required by applicable law or agreed to in writing, software
    11  *  distributed under the License is distributed on an "AS IS" BASIS,
    12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  *  See the License for the specific language governing permissions and
    14  *  limitations under the License.
    15  ********************************************************************************/
    16  
    17  package ledger_go
    18  
    19  import (
    20  	"bytes"
    21  	"math"
    22  	"testing"
    23  	"unsafe"
    24  
    25  	"github.com/stretchr/testify/assert"
    26  )
    27  
    28  func Test_SerializePacket_EmptyCommand(t *testing.T) {
    29  	var command = make([]byte, 1)
    30  
    31  	_, _, err := SerializePacket(0x0101, command, 64, 0)
    32  	assert.Nil(t, err, "Commands smaller than 3 bytes should return error")
    33  }
    34  
    35  func Test_SerializePacket_PacketSize(t *testing.T) {
    36  
    37  	var packetSize = 64
    38  	type header struct {
    39  		channel     uint16
    40  		tag         uint8
    41  		sequenceIdx uint16
    42  		commandLen  uint16
    43  	}
    44  
    45  	h := header{channel: 0x0101, tag: 0x05, sequenceIdx: 0, commandLen: 32}
    46  
    47  	var command = make([]byte, h.commandLen)
    48  
    49  	result, _, _ := SerializePacket(
    50  		h.channel,
    51  		command,
    52  		packetSize,
    53  		h.sequenceIdx)
    54  
    55  	assert.Equal(t, len(result), packetSize, "Packet size is wrong")
    56  }
    57  
    58  func Test_SerializePacket_Header(t *testing.T) {
    59  
    60  	var packetSize = 64
    61  	type header struct {
    62  		channel     uint16
    63  		tag         uint8
    64  		sequenceIdx uint16
    65  		commandLen  uint16
    66  	}
    67  
    68  	h := header{channel: 0x0101, tag: 0x05, sequenceIdx: 0, commandLen: 32}
    69  
    70  	var command = make([]byte, h.commandLen)
    71  
    72  	result, _, _ := SerializePacket(
    73  		h.channel,
    74  		command,
    75  		packetSize,
    76  		h.sequenceIdx)
    77  
    78  	assert.Equal(t, codec.Uint16(result), h.channel, "Channel not properly serialized")
    79  	assert.Equal(t, result[2], h.tag, "Tag not properly serialized")
    80  	assert.Equal(t, codec.Uint16(result[3:]), h.sequenceIdx, "SequenceIdx not properly serialized")
    81  	assert.Equal(t, codec.Uint16(result[5:]), h.commandLen, "Command len not properly serialized")
    82  }
    83  
    84  func Test_SerializePacket_Offset(t *testing.T) {
    85  
    86  	var packetSize = 64
    87  	type header struct {
    88  		channel     uint16
    89  		tag         uint8
    90  		sequenceIdx uint16
    91  		commandLen  uint16
    92  	}
    93  
    94  	h := header{channel: 0x0101, tag: 0x05, sequenceIdx: 0, commandLen: 100}
    95  
    96  	var command = make([]byte, h.commandLen)
    97  
    98  	_, offset, _ := SerializePacket(
    99  		h.channel,
   100  		command,
   101  		packetSize,
   102  		h.sequenceIdx)
   103  
   104  	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.")
   105  }
   106  
   107  func Test_WrapCommandAPDU_NumberOfPackets(t *testing.T) {
   108  
   109  	var packetSize = 64
   110  	type firstHeader struct {
   111  		channel     uint16
   112  		sequenceIdx uint16
   113  		commandLen  uint16
   114  		tag         uint8
   115  	}
   116  
   117  	h1 := firstHeader{channel: 0x0101, tag: 0x05, sequenceIdx: 0, commandLen: 100}
   118  
   119  	var command = make([]byte, h1.commandLen)
   120  
   121  	result, _ := WrapCommandAPDU(
   122  		h1.channel,
   123  		command,
   124  		packetSize)
   125  
   126  	assert.Equal(t, packetSize*2, len(result), "Result buffer size is not correct")
   127  }
   128  
   129  func Test_WrapCommandAPDU_CheckHeaders(t *testing.T) {
   130  
   131  	var packetSize = 64
   132  	type firstHeader struct {
   133  		channel     uint16
   134  		sequenceIdx uint16
   135  		commandLen  uint16
   136  		tag         uint8
   137  	}
   138  
   139  	h1 := firstHeader{channel: 0x0101, tag: 0x05, sequenceIdx: 0, commandLen: 100}
   140  
   141  	var command = make([]byte, h1.commandLen)
   142  
   143  	result, _ := WrapCommandAPDU(
   144  		h1.channel,
   145  		command,
   146  		packetSize)
   147  
   148  	assert.Equal(t, h1.channel, codec.Uint16(result), "Channel not properly serialized")
   149  	assert.Equal(t, h1.tag, result[2], "Tag not properly serialized")
   150  	assert.Equal(t, 0, int(codec.Uint16(result[3:])), "SequenceIdx not properly serialized")
   151  	assert.Equal(t, int(h1.commandLen), int(codec.Uint16(result[5:])), "Command len not properly serialized")
   152  
   153  	var offsetOfSecondPacket = packetSize
   154  	assert.Equal(t, h1.channel, codec.Uint16(result[offsetOfSecondPacket:]), "Channel not properly serialized")
   155  	assert.Equal(t, h1.tag, result[offsetOfSecondPacket+2], "Tag not properly serialized")
   156  	assert.Equal(t, 1, int(codec.Uint16(result[offsetOfSecondPacket+3:])), "SequenceIdx not properly serialized")
   157  }
   158  
   159  func Test_WrapCommandAPDU_CheckData(t *testing.T) {
   160  
   161  	var packetSize = 64
   162  	type firstHeader struct {
   163  		channel     uint16
   164  		sequenceIdx uint16
   165  		commandLen  uint16
   166  		tag         uint8
   167  	}
   168  
   169  	h1 := firstHeader{channel: 0x0101, tag: 0x05, sequenceIdx: 0, commandLen: 200}
   170  
   171  	var command = make([]byte, h1.commandLen)
   172  
   173  	for i := range command {
   174  		command[i] = byte(i % 256)
   175  	}
   176  
   177  	result, _ := WrapCommandAPDU(
   178  		h1.channel,
   179  		command,
   180  		packetSize)
   181  
   182  	// Check data in the first packet
   183  	assert.True(t, bytes.Equal(command[0:64-7], result[7:64]))
   184  
   185  	result = result[64:]
   186  	command = command[64-7:]
   187  	// Check data in the second packet
   188  	assert.True(t, bytes.Equal(command[0:64-5], result[5:64]))
   189  
   190  	result = result[64:]
   191  	command = command[64-5:]
   192  	// Check data in the third packet
   193  	assert.True(t, bytes.Equal(command[0:64-5], result[5:64]))
   194  
   195  	result = result[64:]
   196  	command = command[64-5:]
   197  
   198  	// Check data in the last packet
   199  	assert.True(t, bytes.Equal(command[0:], result[5:5+len(command)]))
   200  
   201  	// The remaining bytes in the result should be zeros
   202  	result = result[5+len(command):]
   203  	assert.True(t, bytes.Equal(result, make([]byte, len(result))))
   204  }
   205  
   206  func Test_DeserializePacket_FirstPacket(t *testing.T) {
   207  
   208  	var sampleCommand = []byte{'H', 'e', 'l', 'l', 'o', 0}
   209  
   210  	var packetSize = 64
   211  	var firstPacketHeaderSize = 7
   212  	packet, _, _ := SerializePacket(0x0101, sampleCommand, packetSize, 0)
   213  
   214  	output, totalSize, isSequenceZero, err := DeserializePacket(0x0101, packet, 0)
   215  
   216  	assert.Nil(t, err, "Simple deserialize should not have errors")
   217  	assert.Equal(t, len(sampleCommand), int(totalSize), "TotalSize is incorrect")
   218  	assert.Equal(t, packetSize-firstPacketHeaderSize, len(output), "Size of the deserialized packet is wrong")
   219  	assert.Equal(t, true, isSequenceZero, "Test Case Should Find Sequence == 0")
   220  	assert.True(t, bytes.Compare(output[:len(sampleCommand)], sampleCommand) == 0, "Deserialized message does not match the original")
   221  }
   222  
   223  func Test_DeserializePacket_SecondMessage(t *testing.T) {
   224  	var sampleCommand = []byte{'H', 'e', 'l', 'l', 'o', 0}
   225  
   226  	var packetSize = 64
   227  	var firstPacketHeaderSize = 5 // second packet does not have responseLength (uint16) in the header
   228  	packet, _, _ := SerializePacket(0x0101, sampleCommand, packetSize, 1)
   229  
   230  	output, totalSize, isSequenceZero, err := DeserializePacket(0x0101, packet, 1)
   231  
   232  	assert.Nil(t, err, "Simple deserialize should not have errors")
   233  	assert.Equal(t, 0, int(totalSize), "TotalSize should not be returned from deserialization of non-first packet")
   234  	assert.Equal(t, packetSize-firstPacketHeaderSize, len(output), "Size of the deserialized packet is wrong")
   235  	assert.Equal(t, false, isSequenceZero, "Test Case Should Find Sequence == 1")
   236  	assert.True(t, bytes.Equal(output[:len(sampleCommand)], sampleCommand), "Deserialized message does not match the original")
   237  }
   238  
   239  func Test_UnwrapApdu_SmokeTest(t *testing.T) {
   240  	const channel uint16 = 0x8002
   241  
   242  	inputSize := 200
   243  	var packetSize = 64
   244  
   245  	// Initialize some dummy input
   246  	var input = make([]byte, inputSize)
   247  	for i := range input {
   248  		input[i] = byte(i % 256)
   249  	}
   250  
   251  	serialized, _ := WrapCommandAPDU(channel, input, packetSize)
   252  
   253  	// Allocate enough buffers to keep all the packets
   254  	pipe := make(chan []byte, int(math.Ceil(float64(inputSize)/float64(packetSize))))
   255  	// Send all the packets to the pipe
   256  	for len(serialized) > 0 {
   257  		pipe <- serialized[:packetSize]
   258  		serialized = serialized[packetSize:]
   259  	}
   260  
   261  	output, _ := UnwrapResponseAPDU(channel, pipe, packetSize)
   262  
   263  	//fmt.Printf("INPUT     : %x\n", input)
   264  	//fmt.Printf("SERIALIZED: %x\n", serialized)
   265  	//fmt.Printf("OUTPUT    : %x\n", output)
   266  
   267  	assert.Equal(t, len(input), len(output), "Input and output messages have different size")
   268  	assert.True(t,
   269  		bytes.Equal(input, output),
   270  		"Input message does not match message which was serialized and then deserialized")
   271  }