2018-09-14 11:30:16 +00:00
|
|
|
package apdu
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
|
|
|
"errors"
|
2018-09-27 13:29:07 +00:00
|
|
|
"fmt"
|
2018-09-14 11:30:16 +00:00
|
|
|
)
|
|
|
|
|
2018-09-27 13:29:07 +00:00
|
|
|
const (
|
2018-10-05 11:03:58 +00:00
|
|
|
// SwOK is returned from smartcards as a positive response code.
|
2018-10-02 14:52:50 +00:00
|
|
|
SwOK = 0x9000
|
2018-09-27 13:29:07 +00:00
|
|
|
)
|
|
|
|
|
2018-10-05 11:03:58 +00:00
|
|
|
// ErrBadResponse defines an error conaining the returned Sw code and a description message.
|
2018-09-27 13:29:07 +00:00
|
|
|
type ErrBadResponse struct {
|
|
|
|
sw uint16
|
|
|
|
message string
|
|
|
|
}
|
|
|
|
|
2018-10-05 11:03:58 +00:00
|
|
|
// NewErrBadResponse returns a ErrBadResponse with the specified sw and message values.
|
2018-09-27 13:29:07 +00:00
|
|
|
func NewErrBadResponse(sw uint16, message string) *ErrBadResponse {
|
|
|
|
return &ErrBadResponse{
|
|
|
|
sw: sw,
|
|
|
|
message: message,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-05 11:03:58 +00:00
|
|
|
// Error implements the error interface.
|
2018-09-27 13:29:07 +00:00
|
|
|
func (e *ErrBadResponse) Error() string {
|
|
|
|
return fmt.Sprintf("bad response %x: %s", e.sw, e.message)
|
|
|
|
}
|
2018-09-25 15:48:21 +00:00
|
|
|
|
2018-10-05 11:03:58 +00:00
|
|
|
// Response represents a struct containing the smartcard response fields.
|
2018-09-14 11:30:16 +00:00
|
|
|
type Response struct {
|
|
|
|
Data []byte
|
|
|
|
Sw1 uint8
|
|
|
|
Sw2 uint8
|
|
|
|
Sw uint16
|
|
|
|
}
|
|
|
|
|
2018-10-05 11:03:58 +00:00
|
|
|
// ErrBadRawResponse is an error returned by ParseResponse in case the response data is not long enough.
|
2018-09-14 11:30:16 +00:00
|
|
|
var ErrBadRawResponse = errors.New("response data must be at least 2 bytes")
|
|
|
|
|
2018-10-05 11:03:58 +00:00
|
|
|
// ParseResponse parses a raw response and return a Response.
|
2018-09-25 15:44:25 +00:00
|
|
|
func ParseResponse(data []byte) (*Response, error) {
|
|
|
|
r := &Response{}
|
|
|
|
return r, r.deserialize(data)
|
|
|
|
}
|
|
|
|
|
2018-09-14 11:30:16 +00:00
|
|
|
func (r *Response) deserialize(data []byte) error {
|
|
|
|
if len(data) < 2 {
|
|
|
|
return ErrBadRawResponse
|
|
|
|
}
|
|
|
|
|
|
|
|
r.Data = make([]byte, len(data)-2)
|
|
|
|
buf := bytes.NewReader(data)
|
|
|
|
|
|
|
|
if err := binary.Read(buf, binary.BigEndian, &r.Data); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := binary.Read(buf, binary.BigEndian, &r.Sw1); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := binary.Read(buf, binary.BigEndian, &r.Sw2); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
r.Sw = (uint16(r.Sw1) << 8) | uint16(r.Sw2)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2018-09-25 15:48:21 +00:00
|
|
|
|
2018-10-05 11:03:58 +00:00
|
|
|
// IsOK returns true if the response Sw code is 0x9000.
|
2018-09-25 15:48:21 +00:00
|
|
|
func (r *Response) IsOK() bool {
|
2018-09-27 13:29:07 +00:00
|
|
|
return r.Sw == SwOK
|
2018-09-25 15:48:21 +00:00
|
|
|
}
|