keycard-go/globalplatform/commands.go

201 lines
5.3 KiB
Go
Raw Normal View History

2018-09-19 13:31:06 +00:00
package globalplatform
2018-10-01 11:25:24 +00:00
import (
"github.com/status-im/status-go/smartcard/apdu"
"github.com/status-im/status-go/smartcard/globalplatform/crypto"
)
2018-09-19 13:31:06 +00:00
2018-10-05 11:46:34 +00:00
// Constants used in apdu commands and responses as defined by iso7816 and globalplatform.
2018-09-25 15:43:26 +00:00
const (
2018-10-02 11:24:13 +00:00
ClaISO7816 = uint8(0x00)
ClaGp = uint8(0x80)
ClaMac = uint8(0x84)
2018-09-19 13:31:06 +00:00
2018-10-01 11:25:24 +00:00
InsSelect = uint8(0xA4)
InsInitializeUpdate = uint8(0x50)
InsExternalAuthenticate = uint8(0x82)
2018-10-02 11:24:13 +00:00
InsGetResponse = uint8(0xC0)
2018-10-02 11:44:14 +00:00
InsDelete = uint8(0xE4)
2018-10-03 14:26:26 +00:00
InsLoad = uint8(0xE8)
2018-10-02 15:15:17 +00:00
InsInstall = uint8(0xE6)
2018-10-04 14:06:55 +00:00
InsGetStatus = uint8(0xF2)
2018-10-02 15:15:17 +00:00
2018-10-04 14:06:55 +00:00
P1ExternalAuthenticateCMAC = uint8(0x01)
P1InstallForLoad = uint8(0x02)
P1InstallForInstall = uint8(0x04)
P1InstallForMakeSelectable = uint8(0x08)
P1LoadMoreBlocks = uint8(0x00)
P1LoadLastBlock = uint8(0x80)
P1GetStatusIssuerSecurityDomain = uint8(0x80)
P1GetStatusApplications = uint8(0x40)
P1GetStatusExecLoadFiles = uint8(0x20)
P1GetStatusExecLoadFilesAndModules = uint8(0x10)
P2GetStatusTLVData = uint8(0x02)
2018-10-02 11:24:13 +00:00
Sw1ResponseDataIncomplete = uint8(0x61)
2018-10-02 12:24:30 +00:00
SwOK = uint16(0x9000)
SwReferencedDataNotFound = uint16(0x6A88)
SwSecurityConditionNotSatisfied = uint16(0x6982)
SwAuthenticationMethodBlocked = uint16(0x6983)
2018-10-03 14:26:26 +00:00
tagDeleteAID = byte(0x4F)
tagLoadFileDataBlock = byte(0xC4)
2018-10-04 14:06:55 +00:00
tagGetStatusAID = byte(0x4F)
2018-09-25 15:43:26 +00:00
)
2018-09-19 13:31:06 +00:00
2018-10-05 11:46:34 +00:00
// NewCommandSelect returns a Select command as defined in the globalplatform specifications.
2018-09-19 13:31:06 +00:00
func NewCommandSelect(aid []byte) *apdu.Command {
2018-10-02 11:24:13 +00:00
c := apdu.NewCommand(
ClaISO7816,
2018-09-19 13:31:06 +00:00
InsSelect,
uint8(0x04),
uint8(0x00),
aid,
)
2018-10-02 11:24:13 +00:00
// with T=0 we can both set or not the Le value
// with T=1 it works only without Le
// c.SetLe(0x00)
2018-10-02 11:24:13 +00:00
return c
2018-09-19 13:31:06 +00:00
}
2018-09-25 15:43:26 +00:00
2018-10-05 11:46:34 +00:00
// NewCommandSelect returns an Initialize Update command as defined in the globalplatform specifications.
2018-09-25 15:43:26 +00:00
func NewCommandInitializeUpdate(challenge []byte) *apdu.Command {
c := apdu.NewCommand(
2018-09-25 15:43:26 +00:00
ClaGp,
InsInitializeUpdate,
uint8(0x00),
uint8(0x00),
challenge,
)
// with T=0 we can both set or not the Le value
// with T=1 it works only if Le is set
c.SetLe(0x00)
return c
2018-09-25 15:43:26 +00:00
}
2018-10-01 11:25:24 +00:00
2018-10-05 11:46:34 +00:00
// NewCommandSelect returns an External Authenticate command as defined in the globalplatform specifications.
2018-10-01 11:25:24 +00:00
func NewCommandExternalAuthenticate(encKey, cardChallenge, hostChallenge []byte) (*apdu.Command, error) {
hostCryptogram, err := calculateHostCryptogram(encKey, cardChallenge, hostChallenge)
if err != nil {
return nil, err
}
return apdu.NewCommand(
ClaMac,
InsExternalAuthenticate,
2018-10-03 14:26:26 +00:00
P1ExternalAuthenticateCMAC,
2018-10-01 11:25:24 +00:00
uint8(0x00),
hostCryptogram,
), nil
}
2018-10-05 11:46:34 +00:00
// NewCommandSelect returns a Get Response command as defined in the globalplatform specifications.
2018-10-02 11:24:13 +00:00
func NewCommandGetResponse(length uint8) *apdu.Command {
c := apdu.NewCommand(
ClaISO7816,
InsGetResponse,
uint8(0),
uint8(0),
nil,
)
c.SetLe(length)
return c
}
2018-10-05 11:46:34 +00:00
// NewCommandSelect returns a Delete command as defined in the globalplatform specifications.
2018-10-02 11:44:14 +00:00
func NewCommandDelete(aid []byte) *apdu.Command {
2018-10-02 12:24:30 +00:00
data := []byte{tagDeleteAID, byte(len(aid))}
data = append(data, aid...)
2018-10-02 11:44:14 +00:00
return apdu.NewCommand(
ClaGp,
InsDelete,
uint8(0x00),
uint8(0x00),
2018-10-02 12:24:30 +00:00
data,
2018-10-02 11:44:14 +00:00
)
}
2018-10-05 11:46:34 +00:00
// NewCommandSelect returns an Install command with the install-for-load parameter as defined in the globalplatform specifications.
2018-10-02 15:15:17 +00:00
func NewCommandInstallForLoad(aid, sdaid []byte) *apdu.Command {
data := []byte{byte(len(aid))}
data = append(data, aid...)
data = append(data, byte(len(sdaid)))
data = append(data, sdaid...)
// empty hash length and hash
data = append(data, []byte{0x00, 0x00, 0x00}...)
return apdu.NewCommand(
ClaGp,
InsInstall,
P1InstallForLoad,
uint8(0x00),
data,
)
}
2018-10-05 11:46:34 +00:00
// NewCommandSelect returns an Install command with the install-for-instalp parameter as defined in the globalplatform specifications.
2018-10-02 15:37:28 +00:00
func NewCommandInstallForInstall(pkgAID, appletAID, instanceAID, params []byte) *apdu.Command {
data := []byte{byte(len(pkgAID))}
data = append(data, pkgAID...)
data = append(data, byte(len(appletAID)))
data = append(data, appletAID...)
data = append(data, byte(len(instanceAID)))
data = append(data, instanceAID...)
// privileges
priv := []byte{0x00}
data = append(data, byte(len(priv)))
data = append(data, priv...)
// params
fullParams := []byte{byte(0xC9), byte(len(params))}
fullParams = append(fullParams, params...)
data = append(data, byte(len(fullParams)))
data = append(data, fullParams...)
// empty perform token
data = append(data, byte(0x00))
return apdu.NewCommand(
ClaGp,
InsInstall,
P1InstallForInstall|P1InstallForMakeSelectable,
uint8(0x00),
data,
)
}
2018-10-05 11:46:34 +00:00
// NewCommandSelect returns a Get Status command as defined in the globalplatform specifications.
2018-10-04 14:06:55 +00:00
func NewCommandGetStatus(aid []byte, p1 uint8) *apdu.Command {
data := []byte{tagGetStatusAID}
data = append(data, byte(len(aid)))
data = append(data, aid...)
return apdu.NewCommand(
ClaGp,
InsGetStatus,
p1,
P2GetStatusTLVData,
data,
)
}
2018-10-01 11:25:24 +00:00
func calculateHostCryptogram(encKey, cardChallenge, hostChallenge []byte) ([]byte, error) {
var data []byte
data = append(data, cardChallenge...)
data = append(data, hostChallenge...)
data = crypto.AppendDESPadding(data)
return crypto.Mac3DES(encKey, data, crypto.NullBytes8)
}