github.com/ava-labs/subnet-evm@v0.6.4/accounts/scwallet/apdu.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2018 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package scwallet
    28  
    29  import (
    30  	"bytes"
    31  	"encoding/binary"
    32  	"fmt"
    33  )
    34  
    35  // commandAPDU represents an application data unit sent to a smartcard.
    36  type commandAPDU struct {
    37  	Cla, Ins, P1, P2 uint8  // Class, Instruction, Parameter 1, Parameter 2
    38  	Data             []byte // Command data
    39  	Le               uint8  // Command data length
    40  }
    41  
    42  // serialize serializes a command APDU.
    43  func (ca commandAPDU) serialize() ([]byte, error) {
    44  	buf := new(bytes.Buffer)
    45  
    46  	if err := binary.Write(buf, binary.BigEndian, ca.Cla); err != nil {
    47  		return nil, err
    48  	}
    49  	if err := binary.Write(buf, binary.BigEndian, ca.Ins); err != nil {
    50  		return nil, err
    51  	}
    52  	if err := binary.Write(buf, binary.BigEndian, ca.P1); err != nil {
    53  		return nil, err
    54  	}
    55  	if err := binary.Write(buf, binary.BigEndian, ca.P2); err != nil {
    56  		return nil, err
    57  	}
    58  	if len(ca.Data) > 0 {
    59  		if err := binary.Write(buf, binary.BigEndian, uint8(len(ca.Data))); err != nil {
    60  			return nil, err
    61  		}
    62  		if err := binary.Write(buf, binary.BigEndian, ca.Data); err != nil {
    63  			return nil, err
    64  		}
    65  	}
    66  	if err := binary.Write(buf, binary.BigEndian, ca.Le); err != nil {
    67  		return nil, err
    68  	}
    69  	return buf.Bytes(), nil
    70  }
    71  
    72  // responseAPDU represents an application data unit received from a smart card.
    73  type responseAPDU struct {
    74  	Data     []byte // response data
    75  	Sw1, Sw2 uint8  // status words 1 and 2
    76  }
    77  
    78  // deserialize deserializes a response APDU.
    79  func (ra *responseAPDU) deserialize(data []byte) error {
    80  	if len(data) < 2 {
    81  		return fmt.Errorf("can not deserialize data: payload too short (%d < 2)", len(data))
    82  	}
    83  
    84  	ra.Data = make([]byte, len(data)-2)
    85  
    86  	buf := bytes.NewReader(data)
    87  	if err := binary.Read(buf, binary.BigEndian, &ra.Data); err != nil {
    88  		return err
    89  	}
    90  	if err := binary.Read(buf, binary.BigEndian, &ra.Sw1); err != nil {
    91  		return err
    92  	}
    93  	if err := binary.Read(buf, binary.BigEndian, &ra.Sw2); err != nil {
    94  		return err
    95  	}
    96  	return nil
    97  }