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