keycard-go/apdu/response.go

80 lines
1.7 KiB
Go
Raw Normal View History

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 (
// SwOK is returned from smartcards as a positive response code.
SwOK = 0x9000
2018-09-27 13:29:07 +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 {
2019-03-06 13:31:40 +00:00
Sw uint16
2018-09-27 13:29:07 +00:00
message string
}
// 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{
2019-03-06 13:31:40 +00:00
Sw: sw,
2018-09-27 13:29:07 +00:00
message: message,
}
}
// Error implements the error interface.
2018-09-27 13:29:07 +00:00
func (e *ErrBadResponse) Error() string {
2019-03-06 13:31:40 +00:00
return fmt.Sprintf("bad response %x: %s", e.Sw, e.message)
2018-09-27 13:29:07 +00:00
}
2018-09-25 15:48:21 +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
}
// 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")
// 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
// 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
}