Add commands

This commit is contained in:
Andrew Pau 2021-04-07 14:22:09 -07:00
parent f66dd01301
commit 76fb3dd4fd
No known key found for this signature in database
GPG Key ID: 49D8DE552B3A2FBC
7 changed files with 205 additions and 143 deletions

View File

@ -9,14 +9,17 @@ Currently the following commands are implemented:
* Reset * Reset
* GenerateAsymmetricKey * GenerateAsymmetricKey
* SignDataEddsa * SignDataEddsa
* SignDataPkcs1
* PutAsymmetricKey * PutAsymmetricKey
* GetPubKey * GetPubKey
* DeriveEcdh * DeriveEcdh
* Echo * Echo
* ChangeAuthenticationKey * ChangeAuthenticationKey
* PutAuthenticationKey
* GetOpaque
* PutOpaque
* SignDataPkcs1
* SignAttestationCertificate
* Authentication & Session related commands * Authentication & Session related commands
* GetPseudoRandom
Implementing new commands is really easy. Please consult `commands/constructors.go` and `commands/response.go` for reference. Implementing new commands is really easy. Please consult `commands/constructors.go` and `commands/response.go` for reference.

View File

@ -94,20 +94,6 @@ func CreateSignDataEcdsaCommand(keyID uint16, data []byte) (*CommandMessage, err
return command, nil return command, nil
} }
func CreateSignDataPkcs1Command(keyID uint16, data []byte) (*CommandMessage, error) {
command := &CommandMessage{
CommandType: CommandTypeSignDataPkcs1,
}
payload := bytes.NewBuffer([]byte{})
binary.Write(payload, binary.BigEndian, keyID)
payload.Write(data)
command.Data = payload.Bytes()
return command, nil
}
func CreatePutAsymmetricKeyCommand(keyID uint16, label []byte, domains uint16, capabilities uint64, algorithm Algorithm, keyPart1 []byte, keyPart2 []byte) (*CommandMessage, error) { func CreatePutAsymmetricKeyCommand(keyID uint16, label []byte, domains uint16, capabilities uint64, algorithm Algorithm, keyPart1 []byte, keyPart2 []byte) (*CommandMessage, error) {
if len(label) > LabelLength { if len(label) > LabelLength {
return nil, errors.New("label is too long") return nil, errors.New("label is too long")
@ -151,6 +137,26 @@ func NewIDOption(id uint16) ListCommandOption {
} }
} }
func NewDomainOption(domain uint16) ListCommandOption {
return func(w io.Writer) {
binary.Write(w, binary.BigEndian, ListObjectParamDomains)
binary.Write(w, binary.BigEndian, domain)
}
}
func NewLabelOption(label []byte) (ListCommandOption, error) {
if len(label) > LabelLength {
return nil, errors.New("label is too long")
}
if len(label) < LabelLength {
label = append(label, bytes.Repeat([]byte{0x00}, LabelLength-len(label))...)
}
return func(w io.Writer) {
binary.Write(w, binary.BigEndian, ListObjectParamLabel)
binary.Write(w, binary.BigEndian, label)
}, nil
}
func CreateListObjectsCommand(options ...ListCommandOption) (*CommandMessage, error) { func CreateListObjectsCommand(options ...ListCommandOption) (*CommandMessage, error) {
command := &CommandMessage{ command := &CommandMessage{
CommandType: CommandTypeListObjects, CommandType: CommandTypeListObjects,
@ -235,6 +241,33 @@ func CreateDeriveEcdhCommand(objID uint16, pubkey []byte) (*CommandMessage, erro
return command, nil return command, nil
} }
func CreatePutAuthenticationKeyCommand(objID uint16, label []byte, domains uint16, capabilities uint64, delegated uint64, password string) (*CommandMessage, error) {
if len(label) > LabelLength {
return nil, errors.New("label is too long")
}
if len(label) < LabelLength {
label = append(label, bytes.Repeat([]byte{0x00}, LabelLength-len(label))...)
}
command := &CommandMessage{
CommandType: CommandTypePutAuthKey,
}
authKey := authkey.NewFromPassword(password)
payload := bytes.NewBuffer([]byte{})
binary.Write(payload, binary.BigEndian, objID)
payload.Write(label)
binary.Write(payload, binary.BigEndian, domains)
binary.Write(payload, binary.BigEndian, capabilities)
binary.Write(payload, binary.BigEndian, AlgorithmYubicoAESAuthentication)
binary.Write(payload, binary.BigEndian, delegated)
payload.Write(authKey.GetEncKey())
payload.Write(authKey.GetMacKey())
command.Data = payload.Bytes()
return command, nil
}
func CreateChangeAuthenticationKeyCommand(objID uint16, newPassword string) (*CommandMessage, error) { func CreateChangeAuthenticationKeyCommand(objID uint16, newPassword string) (*CommandMessage, error) {
command := &CommandMessage{ command := &CommandMessage{
CommandType: CommandTypeChangeAuthenticationKey, CommandType: CommandTypeChangeAuthenticationKey,
@ -251,90 +284,65 @@ func CreateChangeAuthenticationKeyCommand(objID uint16, newPassword string) (*Co
return command, nil return command, nil
} }
func CreateGetPseudoRandomCommand(numBytes uint16) *CommandMessage { func CreatePutOpaqueCommand(objID uint16, label []byte, domains uint16, capabilities uint64, algorithm Algorithm, data []byte) (*CommandMessage, error) {
command := &CommandMessage{
CommandType: CommandTypeGetPseudoRandom,
}
payload := bytes.NewBuffer([]byte{})
binary.Write(payload, binary.BigEndian, numBytes)
command.Data = payload.Bytes()
return command
}
func CreatePutWrapkeyCommand(objID uint16, label []byte, domains uint16, capabilities uint64, algorithm Algorithm, delegated uint64, wrapkey []byte) (*CommandMessage, error) {
if len(label) > LabelLength { if len(label) > LabelLength {
return nil, errors.New("label is too long") return nil, errors.New("label is too long")
} }
if len(label) < LabelLength { if len(label) < LabelLength {
label = append(label, bytes.Repeat([]byte{0x00}, LabelLength-len(label))...) label = append(label, bytes.Repeat([]byte{0x00}, LabelLength-len(label))...)
} }
switch algorithm {
case AlgorithmAES128CCMWrap:
if keyLen := len(wrapkey); keyLen != 16 {
return nil, errors.New("wrapkey is wrong length")
}
case AlgorithmAES192CCMWrap:
if keyLen := len(wrapkey); keyLen != 24 {
return nil, errors.New("wrapkey is wrong length")
}
case AlgorithmAES256CCMWrap:
if keyLen := len(wrapkey); keyLen != 32 {
return nil, errors.New("wrapkey is wrong length")
}
default:
return nil, errors.New("invalid algorithm")
}
command := &CommandMessage{ command := &CommandMessage{
CommandType: CommandTypePutWrapKey, CommandType: CommandTypePutOpaque,
} }
payload := bytes.NewBuffer([]byte{}) payload := bytes.NewBuffer(nil)
binary.Write(payload, binary.BigEndian, objID) binary.Write(payload, binary.BigEndian, objID)
payload.Write(label) payload.Write(label)
binary.Write(payload, binary.BigEndian, domains) binary.Write(payload, binary.BigEndian, domains)
binary.Write(payload, binary.BigEndian, capabilities) binary.Write(payload, binary.BigEndian, capabilities)
binary.Write(payload, binary.BigEndian, algorithm) binary.Write(payload, binary.BigEndian, algorithm)
binary.Write(payload, binary.BigEndian, delegated) payload.Write(data)
payload.Write(wrapkey)
command.Data = payload.Bytes() command.Data = payload.Bytes()
return command, nil return command, nil
} }
func CreatePutAuthkeyCommand(objID uint16, label []byte, domains uint16, capabilities, delegated uint64, encKey, macKey []byte) (*CommandMessage, error) { func CreateGetOpaqueCommand(objID uint16) (*CommandMessage, error) {
if len(label) > LabelLength { command := &CommandMessage{
return nil, errors.New("label is too long") CommandType: CommandTypeGetOpaque,
}
if len(label) < LabelLength {
label = append(label, bytes.Repeat([]byte{0x00}, LabelLength-len(label))...)
}
algorithm := AlgorithmYubicoAESAuthentication
// TODO: support P256 Authentication when it is released
// https://github.com/Yubico/yubihsm-shell/blob/1c8e254603e72f3f39cf1c3910996dbfcdba2b12/lib/yubihsm.c#L3110
if len(encKey) != 16 {
return nil, errors.New("invalid encryption key length")
}
if len(macKey) != 16 {
return nil, errors.New("invalid mac key length")
} }
payload := bytes.NewBuffer(nil)
binary.Write(payload, binary.BigEndian, objID)
command.Data = payload.Bytes()
return command, nil
}
func CreateSignDataPkcs1Command(objID uint16, data []byte) (*CommandMessage, error) {
command := &CommandMessage{ command := &CommandMessage{
CommandType: CommandTypePutAuthKey, CommandType: CommandTypeSignDataPkcs1,
} }
payload := bytes.NewBuffer([]byte{}) payload := bytes.NewBuffer([]byte{})
binary.Write(payload, binary.BigEndian, objID) binary.Write(payload, binary.BigEndian, objID)
payload.Write(label) payload.Write(data)
binary.Write(payload, binary.BigEndian, domains)
binary.Write(payload, binary.BigEndian, capabilities) command.Data = payload.Bytes()
binary.Write(payload, binary.BigEndian, algorithm)
binary.Write(payload, binary.BigEndian, delegated) return command, nil
payload.Write(encKey) }
payload.Write(macKey)
func CreateSignAttestationCertCommand(keyObjID, attestationObjID uint16) (*CommandMessage, error) {
command := &CommandMessage{
CommandType: CommandTypeAttestAsymmetric,
}
payload := bytes.NewBuffer([]byte{})
binary.Write(payload, binary.BigEndian, keyObjID)
binary.Write(payload, binary.BigEndian, attestationObjID)
command.Data = payload.Bytes() command.Data = payload.Bytes()

View File

@ -62,10 +62,6 @@ type (
Signature []byte Signature []byte
} }
SignDataPkcs1Response struct {
Signature []byte
}
SignDataEcdsaResponse struct { SignDataEcdsaResponse struct {
Signature []byte Signature []byte
} }
@ -84,16 +80,28 @@ type (
XCoordinate []byte XCoordinate []byte
} }
PutAuthenticationKeyResponse struct {
ObjectID uint16
}
ChangeAuthenticationKeyResponse struct { ChangeAuthenticationKeyResponse struct {
ObjectID uint16 ObjectID uint16
} }
PutWrapkeyResponse struct { PutOpaqueResponse struct {
ObjectID uint16 ObjectID uint16
} }
PutAuthkeyResponse struct { GetOpaqueResponse struct {
ObjectID uint16 Data []byte
}
SignDataPkcs1Response struct {
Signature []byte
}
SignAttestationCertResponse struct {
Cert []byte
} }
) )
@ -131,8 +139,6 @@ func ParseResponse(data []byte) (Response, error) {
return parseSignDataEddsaResponse(payload) return parseSignDataEddsaResponse(payload)
case CommandTypeSignDataEcdsa: case CommandTypeSignDataEcdsa:
return parseSignDataEcdsaResponse(payload) return parseSignDataEcdsaResponse(payload)
case CommandTypeSignDataPkcs1:
return parseSignDataPkcs1Response(payload)
case CommandTypePutAsymmetric: case CommandTypePutAsymmetric:
return parsePutAsymmetricKeyResponse(payload) return parsePutAsymmetricKeyResponse(payload)
case CommandTypeListObjects: case CommandTypeListObjects:
@ -149,14 +155,18 @@ func ParseResponse(data []byte) (Response, error) {
return parseEchoResponse(payload) return parseEchoResponse(payload)
case CommandTypeDeriveEcdh: case CommandTypeDeriveEcdh:
return parseDeriveEcdhResponse(payload) return parseDeriveEcdhResponse(payload)
case CommandTypePutAuthKey:
return parsePutAuthenticationKeyResponse(payload)
case CommandTypeChangeAuthenticationKey: case CommandTypeChangeAuthenticationKey:
return parseChangeAuthenticationKeyResponse(payload) return parseChangeAuthenticationKeyResponse(payload)
case CommandTypeGetPseudoRandom: case CommandTypePutOpaque:
return parseGetPseudoRandomResponse(payload), nil return parsePutOpaqueResponse(payload)
case CommandTypePutWrapKey: case CommandTypeGetOpaque:
return parsePutWrapkeyResponse(payload) return parseGetOpaqueResponse(payload)
case CommandTypePutAuthKey: case CommandTypeSignDataPkcs1:
return parsePutAuthkeyResponse(payload) return parseSignDataPkcs1Response(payload)
case CommandTypeAttestAsymmetric:
return parseAttestationCertResponse(payload)
case ErrorResponseCode: case ErrorResponseCode:
return nil, parseErrorResponse(payload) return nil, parseErrorResponse(payload)
default: default:
@ -216,12 +226,6 @@ func parseSignDataEddsaResponse(payload []byte) (Response, error) {
}, nil }, nil
} }
func parseSignDataPkcs1Response(payload []byte) (Response, error) {
return &SignDataPkcs1Response{
Signature: payload,
}, nil
}
func parseSignDataEcdsaResponse(payload []byte) (Response, error) { func parseSignDataEcdsaResponse(payload []byte) (Response, error) {
return &SignDataEcdsaResponse{ return &SignDataEcdsaResponse{
Signature: payload, Signature: payload,
@ -294,6 +298,20 @@ func parseDeriveEcdhResponse(payload []byte) (Response, error) {
}, nil }, nil
} }
func parsePutAuthenticationKeyResponse(payload []byte) (Response, error) {
if len(payload) != 2 {
return nil, errors.New("invalid response payload length")
}
var objectID uint16
err := binary.Read(bytes.NewReader(payload), binary.BigEndian, &objectID)
if err != nil {
return nil, err
}
return &PutAuthenticationKeyResponse{ObjectID: objectID}, nil
}
func parseChangeAuthenticationKeyResponse(payload []byte) (Response, error) { func parseChangeAuthenticationKeyResponse(payload []byte) (Response, error) {
if len(payload) != 2 { if len(payload) != 2 {
return nil, errors.New("invalid response payload length") return nil, errors.New("invalid response payload length")
@ -308,11 +326,7 @@ func parseChangeAuthenticationKeyResponse(payload []byte) (Response, error) {
return &ChangeAuthenticationKeyResponse{ObjectID: objectID}, nil return &ChangeAuthenticationKeyResponse{ObjectID: objectID}, nil
} }
func parseGetPseudoRandomResponse(payload []byte) Response { func parsePutOpaqueResponse(payload []byte) (Response, error) {
return payload
}
func parsePutWrapkeyResponse(payload []byte) (Response, error) {
if len(payload) != 2 { if len(payload) != 2 {
return nil, errors.New("invalid response payload length") return nil, errors.New("invalid response payload length")
} }
@ -322,20 +336,40 @@ func parsePutWrapkeyResponse(payload []byte) (Response, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &PutWrapkeyResponse{ObjectID: objectID}, nil
return &PutOpaqueResponse{
ObjectID: objectID,
}, nil
} }
func parsePutAuthkeyResponse(payload []byte) (Response, error) { func parseGetOpaqueResponse(payload []byte) (Response, error) {
if len(payload) != 2 { if len(payload) < 1 {
return nil, errors.New("invalid response payload length") return nil, errors.New("invalid response payload length")
} }
var objectID uint16 return &GetOpaqueResponse{
err := binary.Read(bytes.NewReader(payload), binary.BigEndian, &objectID) Data: payload,
if err != nil { }, nil
return nil, err }
func parseSignDataPkcs1Response(payload []byte) (Response, error) {
if len(payload) < 1 {
return nil, errors.New("invalid response payload length")
} }
return &PutAuthkeyResponse{ObjectID: objectID}, nil
return &SignDataPkcs1Response{
Signature: payload,
}, nil
}
func parseAttestationCertResponse(payload []byte) (Response, error) {
if len(payload) < 1 {
return nil, errors.New("invalid response payload length")
}
return &SignAttestationCertResponse{
Cert: payload,
}, nil
} }
// Error formats a card error message into a human readable format // Error formats a card error message into a human readable format
@ -366,12 +400,18 @@ func (e *Error) Error() string {
message = "Log full" message = "Log full"
case ErrorCodeObjectNotFound: case ErrorCodeObjectNotFound:
message = "Object not found" message = "Object not found"
case ErrorCodeIDIllegal: case ErrorCodeInvalidID:
message = "ID illegal" message = "Invalid ID"
case ErrorCodeCommandUnexecuted: case ErrorCodeSSHCAConstraintViolation:
message = "Command unexecuted" message = "SSH CA constraint violation"
case ErrorCodeInvalidOTP:
message = "Invalid OTP"
case ErrorCodeDemoMode:
message = "Demo mode"
case ErrorCodeObjectExists:
message = "Object exists"
default: default:
message = "unknown" message = "Unknown"
} }
return fmt.Sprintf("card responded with error: %s", message) return fmt.Sprintf("card responded with error: %s", message)

View File

@ -64,31 +64,35 @@ const (
CommandTypeChangeAuthenticationKey CommandType = 0x6c CommandTypeChangeAuthenticationKey CommandType = 0x6c
// Errors // Errors
ErrorCodeOK ErrorCode = 0x00 ErrorCodeOK ErrorCode = 0x00
ErrorCodeInvalidCommand ErrorCode = 0x01 ErrorCodeInvalidCommand ErrorCode = 0x01
ErrorCodeInvalidData ErrorCode = 0x02 ErrorCodeInvalidData ErrorCode = 0x02
ErrorCodeInvalidSession ErrorCode = 0x03 ErrorCodeInvalidSession ErrorCode = 0x03
ErrorCodeAuthFail ErrorCode = 0x04 ErrorCodeAuthFail ErrorCode = 0x04
ErrorCodeSessionFull ErrorCode = 0x05 ErrorCodeSessionFull ErrorCode = 0x05
ErrorCodeSessionFailed ErrorCode = 0x06 ErrorCodeSessionFailed ErrorCode = 0x06
ErrorCodeStorageFailed ErrorCode = 0x07 ErrorCodeStorageFailed ErrorCode = 0x07
ErrorCodeWrongLength ErrorCode = 0x08 ErrorCodeWrongLength ErrorCode = 0x08
ErrorCodeInvalidPermission ErrorCode = 0x09 ErrorCodeInvalidPermission ErrorCode = 0x09
ErrorCodeLogFull ErrorCode = 0x0a ErrorCodeLogFull ErrorCode = 0x0a
ErrorCodeObjectNotFound ErrorCode = 0x0b ErrorCodeObjectNotFound ErrorCode = 0x0b
ErrorCodeIDIllegal ErrorCode = 0x0c ErrorCodeInvalidID ErrorCode = 0x0c
ErrorCodeCommandUnexecuted ErrorCode = 0xff ErrorCodeSSHCAConstraintViolation ErrorCode = 0x0e
ErrorCodeInvalidOTP ErrorCode = 0x0f
ErrorCodeDemoMode ErrorCode = 0x10
ErrorCodeObjectExists ErrorCode = 0x11
// Algorithms // Algorithms
AlgorithmRSA2048 Algorithm = 9
AlgorithmP256 Algorithm = 12 AlgorithmP256 Algorithm = 12
AlgorithmSecp256k1 Algorithm = 15 AlgorithmSecp256k1 Algorithm = 15
AlgorithmOpaqueData Algorithm = 30
AlgorithmOpaqueX509Certificate Algorithm = 31
AlgorithmYubicoAESAuthentication Algorithm = 38 AlgorithmYubicoAESAuthentication Algorithm = 38
AlgorighmED25519 Algorithm = 46 AlgorithmED25519 Algorithm = 46
AlgorithmAES128CCMWrap Algorithm = 29
AlgorithmAES192CCMWrap Algorithm = 41
AlgorithmAES256CCMWrap Algorithm = 42
// Capabilities // Capabilities
CapabilityNone uint64 = 0x0000000000000000
CapabilityGetOpaque uint64 = 0x0000000000000001 CapabilityGetOpaque uint64 = 0x0000000000000001
CapabilityPutOpaque uint64 = 0x0000000000000002 CapabilityPutOpaque uint64 = 0x0000000000000002
CapabilityPutAuthKey uint64 = 0x0000000000000004 CapabilityPutAuthKey uint64 = 0x0000000000000004
@ -106,7 +110,7 @@ const (
CapabilityImportWrapped uint64 = 0x0000000000002000 CapabilityImportWrapped uint64 = 0x0000000000002000
CapabilityPutWrapKey uint64 = 0x0000000000004000 CapabilityPutWrapKey uint64 = 0x0000000000004000
CapabilityGenerateWrapKey uint64 = 0x0000000000008000 CapabilityGenerateWrapKey uint64 = 0x0000000000008000
CapabilityExportUnderWrap uint64 = 0x0000000000010000 CapabilityExportableUnderWrap uint64 = 0x0000000000010000
CapabilityPutOption uint64 = 0x0000000000020000 CapabilityPutOption uint64 = 0x0000000000020000
CapabilityGetOption uint64 = 0x0000000000040000 CapabilityGetOption uint64 = 0x0000000000040000
CapabilityGetRandomness uint64 = 0x0000000000080000 CapabilityGetRandomness uint64 = 0x0000000000080000
@ -136,6 +140,7 @@ const (
CapabilityDeleteHmacKey uint64 = 0x0000080000000000 CapabilityDeleteHmacKey uint64 = 0x0000080000000000
CapabilityDeleteTemplate uint64 = 0x0000100000000000 CapabilityDeleteTemplate uint64 = 0x0000100000000000
CapabilityDeleteOtpAeadKey uint64 = 0x0000200000000000 CapabilityDeleteOtpAeadKey uint64 = 0x0000200000000000
CapabilityChangeAuthKey uint64 = 0x0000400000000000
// Domains // Domains
Domain1 uint16 = 0x0001 Domain1 uint16 = 0x0001
@ -165,15 +170,10 @@ const (
ObjectTypeOtpAeadKey uint8 = 0x07 ObjectTypeOtpAeadKey uint8 = 0x07
// list objects params // list objects params
ListObjectParamID uint8 = 0x01 ListObjectParamID uint8 = 0x01
ListObjectParamType uint8 = 0x02 ListObjectParamType uint8 = 0x02
ListObjectParamDomains uint8 = 0x03
ListObjectParamCapabilities uint8 = 0x04
ListObjectParamAlgorithm uint8 = 0x05
ListObjectParamLabel uint8 = 0x06
) )
// CapabilityPrimitiveFromSlice OR's all the capabilitites together.
func CapabilityPrimitiveFromSlice(capabilitites []uint64) uint64 {
var primitive uint64
for _, c := range capabilitites {
primitive |= c
}
return primitive
}

4
go.mod
View File

@ -1,6 +1,8 @@
module github.com/certusone/yubihsm-go module github.com/certusone/yubihsm-go
go 1.14
require ( require (
github.com/enceve/crypto v0.0.0-20160707101852-34d48bb93815 github.com/enceve/crypto v0.0.0-20160707101852-34d48bb93815
golang.org/x/crypto v0.0.0-20180830192347-182538f80094 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
) )

7
go.sum
View File

@ -2,3 +2,10 @@ github.com/enceve/crypto v0.0.0-20160707101852-34d48bb93815 h1:D22EM5TeYZJp43hGD
github.com/enceve/crypto v0.0.0-20160707101852-34d48bb93815/go.mod h1:wYFFK4LYXbX7j+76mOq7aiC/EAw2S22CrzPHqgsisPw= github.com/enceve/crypto v0.0.0-20160707101852-34d48bb93815/go.mod h1:wYFFK4LYXbX7j+76mOq7aiC/EAw2S22CrzPHqgsisPw=
golang.org/x/crypto v0.0.0-20180830192347-182538f80094 h1:rVTAlhYa4+lCfNxmAIEOGQRoD23UqP72M3+rSWVGDTg= golang.org/x/crypto v0.0.0-20180830192347-182538f80094 h1:rVTAlhYa4+lCfNxmAIEOGQRoD23UqP72M3+rSWVGDTg=
golang.org/x/crypto v0.0.0-20180830192347-182538f80094/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180830192347-182538f80094/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@ -85,6 +85,8 @@ const (
MaxMessagesPerSession = 10000 MaxMessagesPerSession = 10000
) )
var ErrAuthCryptogram = errors.New("authentication failed: device sent wrong cryptogram")
// NewSecureChannel initiates a new secure channel to communicate with an HSM using the given authKey // NewSecureChannel initiates a new secure channel to communicate with an HSM using the given authKey
// Call Authenticate next to establish a session. // Call Authenticate next to establish a session.
func NewSecureChannel(connector connector.Connector, authKeySlot uint16, password string) (*SecureChannel, error) { func NewSecureChannel(connector connector.Connector, authKeySlot uint16, password string) (*SecureChannel, error) {
@ -143,7 +145,7 @@ func (s *SecureChannel) Authenticate() error {
} }
if !bytes.Equal(deviceCryptogram, createSessionResp.CardCryptogram) { if !bytes.Equal(deviceCryptogram, createSessionResp.CardCryptogram) {
return errors.New("authentication failed: device sent wrong cryptogram") return ErrAuthCryptogram
} }
// Create host cryptogram // Create host cryptogram