Documentation
¶
Overview ¶
Package apdu implements parsing and conversion of Application Protocol Data Units (APDU) which is the communication format between a card and off-card applications. The format of the APDU is defined in ISO specification 7816-4. The package has support for extended length APDUs as well.
Index ¶
Examples ¶
Constants ¶
const ( // OffsetCla defines the offset to the Cla byte of a Capdu. OffsetCla int = 0 // OffsetIns defines the offset to the Ins byte of a Capdu. OffsetIns int = 1 // OffsetP1 defines the offset to the P1 byte of a Capdu. OffsetP1 int = 2 // OffsetP2 defines the offset to the P2 byte of a Capdu. OffsetP2 int = 3 // OffsetLcStandard defines the offset to the LC byte of a standard length Capdu. OffsetLcStandard int = 4 // OffsetLcExtended defines the offset to the LC byte of an extended length Capdu. OffsetLcExtended int = 5 // OffsetCdataStandard defines the offset to the beginning of the data field of a standard length Capdu. OffsetCdataStandard int = 5 // OffsetCdataExtended defines the offset to the beginning of the data field of an extended length Capdu. OffsetCdataExtended int = 7 // MaxLenCommandDataStandard defines the maximum command data length of a standard length Capdu. MaxLenCommandDataStandard int = 255 // MaxLenResponseDataStandard defines the maximum response data length of a standard length RAPDU. MaxLenResponseDataStandard int = 256 // MaxLenCommandDataExtended defines the maximum command data length of an extended length Capdu. MaxLenCommandDataExtended int = 65535 // MaxLenResponseDataExtended defines the maximum response data length of an extended length RAPDU. MaxLenResponseDataExtended int = 65536 // LenHeader defines the length of the header of an APDU. LenHeader int = 4 // LenLCStandard defines the length of the LC of a standard length APDU. LenLCStandard int = 1 // LenLCExtended defines the length of the LC of an extended length APDU. LenLCExtended int = 3 // LenResponseTrailer defines the length of the trailer of a Response APDU. LenResponseTrailer int = 2 )
Variables ¶
var ( // ErrInvalidLength indicates that the input has an invalid length. ErrInvalidLength = errors.New("invalid length") // ErrInvalidLC indicates that the LC value does not match the data length. ErrInvalidLC = errors.New("invalid LC value") // ErrInvalidHex indicates that the hex string input is malformed. ErrInvalidHex = errors.New("invalid hex string") // ErrDataTooLong indicates that the data field exceeds the maximum allowed length. ErrDataTooLong = errors.New("data too long") // ErrNeTooLarge indicates that Ne exceeds the maximum allowed value. ErrNeTooLarge = errors.New("ne too large") )
Functions ¶
This section is empty.
Types ¶
type Capdu ¶
type Capdu struct {
Cla byte // Cla is the class byte.
Ins byte // Ins is the instruction byte.
P1 byte // P1 is the p1 byte.
P2 byte // P2 is the p2 byte.
Data []byte // Data is the data field.
Ne int // Ne is the total number of expected response data byte (not LE encoded).
}
Capdu is a Command APDU.
func ParseCapdu ¶
ParseCapdu parses a Command APDU and returns a Capdu.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
c, err := apdu.ParseCapdu([]byte{0x80, 0xF2, 0xE0, 0x02, 0x02, 0x4F, 0x00, 0x00})
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("CLA: %02X, INS: %02X, P1: %02X, P2: %02X, Data: %X, Ne: %d\n",
c.Cla, c.Ins, c.P1, c.P2, c.Data, c.Ne)
}
Output: CLA: 80, INS: F2, P1: E0, P2: 02, Data: 4F00, Ne: 256
Example (ErrorHandling) ¶
package main
import (
"errors"
"fmt"
"github.com/skythen/apdu"
)
func main() {
_, err := apdu.ParseCapdu([]byte{0x00, 0xA4})
if errors.Is(err, apdu.ErrInvalidLength) {
fmt.Println("invalid length")
}
}
Output: invalid length
func ParseCapduHexString ¶
ParseCapduHexString decodes the hex-string representation of a Command APDU, calls ParseCapdu and returns a Capdu.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
c, err := apdu.ParseCapduHexString("80F2E002024F0000")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("CLA: %02X, INS: %02X, P1: %02X, P2: %02X, Data: %X, Ne: %d\n",
c.Cla, c.Ins, c.P1, c.P2, c.Data, c.Ne)
}
Output: CLA: 80, INS: F2, P1: E0, P2: 02, Data: 4F00, Ne: 256
func (*Capdu) Bytes ¶
Bytes returns the byte representation of the Capdu.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
c := apdu.Capdu{Cla: 0x00, Ins: 0xA4, P1: 0x04, P2: 0x00, Data: []byte{0xA0, 0x00, 0x00, 0x00, 0x03}, Ne: 256}
b, err := c.Bytes()
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%X\n", b)
}
Output: 00A4040005A00000000300
func (*Capdu) IsExtendedLength ¶
IsExtendedLength returns true if the Capdu has extended length (len of Data > 65535 or Ne > 65536), else false.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
standard := apdu.Capdu{Cla: 0x00, Ins: 0xA4, P1: 0x04, P2: 0x00, Ne: 256}
extended := apdu.Capdu{Cla: 0x00, Ins: 0xA4, P1: 0x04, P2: 0x00, Ne: 65536}
fmt.Println(standard.IsExtendedLength())
fmt.Println(extended.IsExtendedLength())
}
Output: false true
func (*Capdu) String ¶
String calls Bytes and returns the hex encoded string representation of the Capdu.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
c := apdu.Capdu{Cla: 0x00, Ins: 0xA4, P1: 0x04, P2: 0x00, Data: []byte{0xA0, 0x00, 0x00, 0x00, 0x03}}
s, err := c.String()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(s)
}
Output: 00A4040005A000000003
type Rapdu ¶
type Rapdu struct {
Data []byte // Data is the data field.
SW1 byte // SW1 is the first byte of a status word.
SW2 byte // SW2 is the second byte of a status word.
}
Rapdu is a Response APDU.
func ParseRapdu ¶
ParseRapdu parses a Response APDU and returns a Rapdu.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
r, err := apdu.ParseRapdu([]byte{0x01, 0x02, 0x03, 0x90, 0x00})
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Data: %X, SW1: %02X, SW2: %02X\n", r.Data, r.SW1, r.SW2)
}
Output: Data: 010203, SW1: 90, SW2: 00
func ParseRapduHexString ¶
ParseRapduHexString decodes the hex-string representation of a Response APDU, calls ParseRapdu and returns a Rapdu.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
r, err := apdu.ParseRapduHexString("0102039000")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Data: %X, SW1: %02X, SW2: %02X\n", r.Data, r.SW1, r.SW2)
}
Output: Data: 010203, SW1: 90, SW2: 00
func (*Rapdu) Bytes ¶
Bytes returns the byte representation of the RAPDU.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
r := apdu.Rapdu{Data: []byte{0x01, 0x02, 0x03}, SW1: 0x90, SW2: 0x00}
b, err := r.Bytes()
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%X\n", b)
}
Output: 0102039000
func (*Rapdu) IsError ¶
IsError returns true if the RAPDU indicates an error during the execution of a command ('0x64xx', '0x65xx' or from '0x67xx' to 0x6Fxx'), otherwise false.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
r := apdu.Rapdu{SW1: 0x6A, SW2: 0x82}
fmt.Println(r.IsError())
}
Output: true
func (*Rapdu) IsSuccess ¶
IsSuccess returns true if the RAPDU indicates the successful execution of a command ('0x61xx' or '0x9000'), otherwise false.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
r := apdu.Rapdu{SW1: 0x90, SW2: 0x00}
fmt.Println(r.IsSuccess())
}
Output: true
func (*Rapdu) IsWarning ¶
IsWarning returns true if the RAPDU indicates the execution of a command with a warning ('0x62xx' or '0x63xx'), otherwise false.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
r := apdu.Rapdu{SW1: 0x62, SW2: 0x84}
fmt.Println(r.IsWarning())
}
Output: true
func (*Rapdu) String ¶
String calls Bytes and returns the hex encoded string representation of the RAPDU.
Example ¶
package main
import (
"fmt"
"github.com/skythen/apdu"
)
func main() {
r := apdu.Rapdu{Data: []byte{0x01, 0x02, 0x03}, SW1: 0x90, SW2: 0x00}
s, err := r.String()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(s)
}
Output: 0102039000