2019-03-28 10:33:48 +00:00
|
|
|
package io
|
2018-10-02 11:25:04 +00:00
|
|
|
|
|
|
|
import (
|
2021-10-21 12:27:09 +00:00
|
|
|
"github.com/status-im/go-ethereum/log"
|
2019-03-01 17:44:07 +00:00
|
|
|
"github.com/status-im/keycard-go/apdu"
|
2019-03-28 10:33:48 +00:00
|
|
|
"github.com/status-im/keycard-go/globalplatform"
|
2019-03-01 17:44:07 +00:00
|
|
|
"github.com/status-im/keycard-go/hexutils"
|
2018-10-02 11:25:04 +00:00
|
|
|
)
|
|
|
|
|
2019-03-28 10:33:48 +00:00
|
|
|
var logger = log.New("package", "io")
|
|
|
|
|
2018-10-05 14:40:32 +00:00
|
|
|
// Transmitter defines an interface with one method to transmit raw commands and receive raw responses.
|
2018-10-02 11:25:04 +00:00
|
|
|
type Transmitter interface {
|
|
|
|
Transmit([]byte) ([]byte, error)
|
|
|
|
}
|
|
|
|
|
2018-10-05 14:40:32 +00:00
|
|
|
// NormalChannel implements a normal channel to send apdu commands and receive apdu responses.
|
2018-10-02 11:25:04 +00:00
|
|
|
type NormalChannel struct {
|
|
|
|
t Transmitter
|
|
|
|
}
|
|
|
|
|
2018-10-05 14:40:32 +00:00
|
|
|
// NewNormalChannel returns a new NormalChannel that sends commands to Transmitter t.
|
2018-10-02 11:25:04 +00:00
|
|
|
func NewNormalChannel(t Transmitter) *NormalChannel {
|
|
|
|
return &NormalChannel{t}
|
|
|
|
}
|
|
|
|
|
2018-10-05 14:40:32 +00:00
|
|
|
// Send sends apdu commands to the current Transmitter.
|
|
|
|
// Based on the smartcard transport protocol (T=0, T=1), it checks responses and sends a Get Response
|
|
|
|
// command in case of T=0.
|
2018-10-02 11:25:04 +00:00
|
|
|
func (c *NormalChannel) Send(cmd *apdu.Command) (*apdu.Response, error) {
|
|
|
|
rawCmd, err := cmd.Serialize()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-10-05 09:35:56 +00:00
|
|
|
logger.Debug("apdu command", "hex", hexutils.BytesToHexWithSpaces(rawCmd))
|
2018-10-02 11:25:04 +00:00
|
|
|
rawResp, err := c.t.Transmit(rawCmd)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-10-05 09:35:56 +00:00
|
|
|
logger.Debug("apdu response", "hex", hexutils.BytesToHexWithSpaces(rawResp))
|
2018-10-02 11:25:04 +00:00
|
|
|
|
|
|
|
resp, err := apdu.ParseResponse(rawResp)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-03-28 10:33:48 +00:00
|
|
|
if resp.Sw1 == globalplatform.Sw1ResponseDataIncomplete && (cmd.Cla != globalplatform.ClaISO7816 || cmd.Ins != globalplatform.InsGetResponse) {
|
|
|
|
getResponse := globalplatform.NewCommandGetResponse(resp.Sw2)
|
2018-10-02 11:25:04 +00:00
|
|
|
return c.Send(getResponse)
|
|
|
|
}
|
|
|
|
|
|
|
|
return apdu.ParseResponse(rawResp)
|
|
|
|
}
|