Add ChangeAuthenticationKey command
Introduce the command which is used to change the password to authenticate to the HSM. A small refactoring of extracting authkey out was necessary to prevent an import cycle from securechannel importing commands which (without the refactor) imported secure channel again. Documentation for this command: https://developers.yubico.com/YubiHSM2/Commands/Change_Authentication_Key.html
This commit is contained in:
parent
d0ca2ed0df
commit
530348283f
|
@ -13,6 +13,7 @@ Currently the following commands are implemented:
|
||||||
* GetPubKey
|
* GetPubKey
|
||||||
* DeriveEcdh
|
* DeriveEcdh
|
||||||
* Echo
|
* Echo
|
||||||
|
* ChangeAuthenticationKey
|
||||||
* Authentication & Session related commands
|
* Authentication & Session related commands
|
||||||
|
|
||||||
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.
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package securechannel
|
package authkey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,17 +17,17 @@ const (
|
||||||
yubicoSeed = "Yubico"
|
yubicoSeed = "Yubico"
|
||||||
)
|
)
|
||||||
|
|
||||||
// deriveAuthKeyFromPwd derives an AuthKey using pkdf2 as specified in the HSM documentation
|
// NewFromPassword derives an AuthKey using pkdf2 as specified in the HSM documentation
|
||||||
func deriveAuthKeyFromPwd(password string) AuthKey {
|
func NewFromPassword(password string) AuthKey {
|
||||||
return pbkdf2.Key([]byte(password), []byte(yubicoSeed), authKeyIterations, authKeyLength, sha256.New)
|
return pbkdf2.Key([]byte(password), []byte(yubicoSeed), authKeyIterations, authKeyLength, sha256.New)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEncKey returns the EncryptionKey part of the AuthKey
|
// GetEncKey returns the EncryptionKey part of the AuthKey
|
||||||
func (k AuthKey) GetEncKey() []byte {
|
func (k AuthKey) GetEncKey() []byte {
|
||||||
return k[:KeyLength]
|
return k[:authKeyLength/2]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEncKey returns the MACKey part of the AuthKey
|
// GetMacKey returns the MACKey part of the AuthKey
|
||||||
func (k AuthKey) GetMacKey() []byte {
|
func (k AuthKey) GetMacKey() []byte {
|
||||||
return k[KeyLength:]
|
return k[authKeyLength/2:]
|
||||||
}
|
}
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/certusone/yubihsm-go/authkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateCreateSessionCommand(keySetID uint16, hostChallenge []byte) (*CommandMessage, error) {
|
func CreateCreateSessionCommand(keySetID uint16, hostChallenge []byte) (*CommandMessage, error) {
|
||||||
|
@ -218,3 +220,19 @@ func CreateDeriveEcdhCommand(objID uint16, pubkey []byte) (*CommandMessage, erro
|
||||||
|
|
||||||
return command, nil
|
return command, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateChangeAuthenticationKeyCommand(objID uint16, newPassword string) (*CommandMessage, error) {
|
||||||
|
command := &CommandMessage{
|
||||||
|
CommandType: CommandTypeChangeAuthenticationKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
authKey := authkey.NewFromPassword(newPassword)
|
||||||
|
payload := bytes.NewBuffer([]byte{})
|
||||||
|
binary.Write(payload, binary.BigEndian, objID)
|
||||||
|
binary.Write(payload, binary.BigEndian, AlgorithmYubicoAESAuthentication)
|
||||||
|
payload.Write(authKey.GetEncKey())
|
||||||
|
payload.Write(authKey.GetMacKey())
|
||||||
|
command.Data = payload.Bytes()
|
||||||
|
|
||||||
|
return command, nil
|
||||||
|
}
|
||||||
|
|
|
@ -79,6 +79,10 @@ type (
|
||||||
DeriveEcdhResponse struct {
|
DeriveEcdhResponse struct {
|
||||||
XCoordinate []byte
|
XCoordinate []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChangeAuthenticationKeyResponse struct {
|
||||||
|
ObjectID uint16
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseResponse parses the binary response from the card to the relevant Response type.
|
// ParseResponse parses the binary response from the card to the relevant Response type.
|
||||||
|
@ -131,6 +135,8 @@ func ParseResponse(data []byte) (Response, error) {
|
||||||
return parseEchoResponse(payload)
|
return parseEchoResponse(payload)
|
||||||
case CommandTypeDeriveEcdh:
|
case CommandTypeDeriveEcdh:
|
||||||
return parseDeriveEcdhResponse(payload)
|
return parseDeriveEcdhResponse(payload)
|
||||||
|
case CommandTypeChangeAuthenticationKey:
|
||||||
|
return parseChangeAuthenticationKeyResponse(payload)
|
||||||
case ErrorResponseCode:
|
case ErrorResponseCode:
|
||||||
return nil, parseErrorResponse(payload)
|
return nil, parseErrorResponse(payload)
|
||||||
default:
|
default:
|
||||||
|
@ -262,6 +268,20 @@ func parseDeriveEcdhResponse(payload []byte) (Response, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseChangeAuthenticationKeyResponse(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 &ChangeAuthenticationKeyResponse{ObjectID: objectID}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Error formats a card error message into a human readable format
|
// Error formats a card error message into a human readable format
|
||||||
func (e *Error) Error() string {
|
func (e *Error) Error() string {
|
||||||
message := ""
|
message := ""
|
||||||
|
|
|
@ -13,54 +13,55 @@ const (
|
||||||
// LabelLength is the max length of a label
|
// LabelLength is the max length of a label
|
||||||
LabelLength = 40
|
LabelLength = 40
|
||||||
|
|
||||||
CommandTypeEcho CommandType = 0x01
|
CommandTypeEcho CommandType = 0x01
|
||||||
CommandTypeCreateSession CommandType = 0x03
|
CommandTypeCreateSession CommandType = 0x03
|
||||||
CommandTypeAuthenticateSession CommandType = 0x04
|
CommandTypeAuthenticateSession CommandType = 0x04
|
||||||
CommandTypeSessionMessage CommandType = 0x05
|
CommandTypeSessionMessage CommandType = 0x05
|
||||||
CommandTypeDeviceInfo CommandType = 0x06
|
CommandTypeDeviceInfo CommandType = 0x06
|
||||||
CommandTypeReset CommandType = 0x08
|
CommandTypeReset CommandType = 0x08
|
||||||
CommandTypeCloseSession CommandType = 0x40
|
CommandTypeCloseSession CommandType = 0x40
|
||||||
CommandTypeStorageStatus CommandType = 0x41
|
CommandTypeStorageStatus CommandType = 0x41
|
||||||
CommandTypePutOpaque CommandType = 0x42
|
CommandTypePutOpaque CommandType = 0x42
|
||||||
CommandTypeGetOpaque CommandType = 0x43
|
CommandTypeGetOpaque CommandType = 0x43
|
||||||
CommandTypePutAuthKey CommandType = 0x44
|
CommandTypePutAuthKey CommandType = 0x44
|
||||||
CommandTypePutAsymmetric CommandType = 0x45
|
CommandTypePutAsymmetric CommandType = 0x45
|
||||||
CommandTypeGenerateAsymmetricKey CommandType = 0x46
|
CommandTypeGenerateAsymmetricKey CommandType = 0x46
|
||||||
CommandTypeSignDataPkcs1 CommandType = 0x47
|
CommandTypeSignDataPkcs1 CommandType = 0x47
|
||||||
CommandTypeListObjects CommandType = 0x48
|
CommandTypeListObjects CommandType = 0x48
|
||||||
CommandTypeDecryptPkcs1 CommandType = 0x49
|
CommandTypeDecryptPkcs1 CommandType = 0x49
|
||||||
CommandTypeExportWrapped CommandType = 0x4a
|
CommandTypeExportWrapped CommandType = 0x4a
|
||||||
CommandTypeImportWrapped CommandType = 0x4b
|
CommandTypeImportWrapped CommandType = 0x4b
|
||||||
CommandTypePutWrapKey CommandType = 0x4c
|
CommandTypePutWrapKey CommandType = 0x4c
|
||||||
CommandTypeGetLogs CommandType = 0x4d
|
CommandTypeGetLogs CommandType = 0x4d
|
||||||
CommandTypeGetObjectInfo CommandType = 0x4e
|
CommandTypeGetObjectInfo CommandType = 0x4e
|
||||||
CommandTypePutOption CommandType = 0x4f
|
CommandTypePutOption CommandType = 0x4f
|
||||||
CommandTypeGetOption CommandType = 0x50
|
CommandTypeGetOption CommandType = 0x50
|
||||||
CommandTypeGetPseudoRandom CommandType = 0x51
|
CommandTypeGetPseudoRandom CommandType = 0x51
|
||||||
CommandTypePutHMACKey CommandType = 0x52
|
CommandTypePutHMACKey CommandType = 0x52
|
||||||
CommandTypeHMACData CommandType = 0x53
|
CommandTypeHMACData CommandType = 0x53
|
||||||
CommandTypeGetPubKey CommandType = 0x54
|
CommandTypeGetPubKey CommandType = 0x54
|
||||||
CommandTypeSignDataPss CommandType = 0x55
|
CommandTypeSignDataPss CommandType = 0x55
|
||||||
CommandTypeSignDataEcdsa CommandType = 0x56
|
CommandTypeSignDataEcdsa CommandType = 0x56
|
||||||
CommandTypeDecryptEcdh CommandType = 0x57 // here for backwards compatibility
|
CommandTypeDecryptEcdh CommandType = 0x57 // here for backwards compatibility
|
||||||
CommandTypeDeriveEcdh CommandType = 0x57
|
CommandTypeDeriveEcdh CommandType = 0x57
|
||||||
CommandTypeDeleteObject CommandType = 0x58
|
CommandTypeDeleteObject CommandType = 0x58
|
||||||
CommandTypeDecryptOaep CommandType = 0x59
|
CommandTypeDecryptOaep CommandType = 0x59
|
||||||
CommandTypeGenerateHMACKey CommandType = 0x5a
|
CommandTypeGenerateHMACKey CommandType = 0x5a
|
||||||
CommandTypeGenerateWrapKey CommandType = 0x5b
|
CommandTypeGenerateWrapKey CommandType = 0x5b
|
||||||
CommandTypeVerifyHMAC CommandType = 0x5c
|
CommandTypeVerifyHMAC CommandType = 0x5c
|
||||||
CommandTypeOTPDecrypt CommandType = 0x60
|
CommandTypeOTPDecrypt CommandType = 0x60
|
||||||
CommandTypeOTPAeadCreate CommandType = 0x61
|
CommandTypeOTPAeadCreate CommandType = 0x61
|
||||||
CommandTypeOTPAeadRandom CommandType = 0x62
|
CommandTypeOTPAeadRandom CommandType = 0x62
|
||||||
CommandTypeOTPAeadRewrap CommandType = 0x63
|
CommandTypeOTPAeadRewrap CommandType = 0x63
|
||||||
CommandTypeAttestAsymmetric CommandType = 0x64
|
CommandTypeAttestAsymmetric CommandType = 0x64
|
||||||
CommandTypePutOTPAeadKey CommandType = 0x65
|
CommandTypePutOTPAeadKey CommandType = 0x65
|
||||||
CommandTypeGenerateOTPAeadKey CommandType = 0x66
|
CommandTypeGenerateOTPAeadKey CommandType = 0x66
|
||||||
CommandTypeSetLogIndex CommandType = 0x67
|
CommandTypeSetLogIndex CommandType = 0x67
|
||||||
CommandTypeWrapData CommandType = 0x68
|
CommandTypeWrapData CommandType = 0x68
|
||||||
CommandTypeUnwrapData CommandType = 0x69
|
CommandTypeUnwrapData CommandType = 0x69
|
||||||
CommandTypeSignDataEddsa CommandType = 0x6a
|
CommandTypeSignDataEddsa CommandType = 0x6a
|
||||||
CommandTypeSetBlink CommandType = 0x6b
|
CommandTypeSetBlink CommandType = 0x6b
|
||||||
|
CommandTypeChangeAuthenticationKey CommandType = 0x6c
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
ErrorCodeOK ErrorCode = 0x00
|
ErrorCodeOK ErrorCode = 0x00
|
||||||
|
@ -79,9 +80,10 @@ const (
|
||||||
ErrorCodeCommandUnexecuted ErrorCode = 0xff
|
ErrorCodeCommandUnexecuted ErrorCode = 0xff
|
||||||
|
|
||||||
// Algorithms
|
// Algorithms
|
||||||
AlgorithmP256 Algorithm = 12
|
AlgorithmP256 Algorithm = 12
|
||||||
AlgorithmSecp256k1 Algorithm = 15
|
AlgorithmSecp256k1 Algorithm = 15
|
||||||
AlgorighmED25519 Algorithm = 46
|
AlgorighmED25519 Algorithm = 46
|
||||||
|
AlgorithmYubicoAESAuthentication Algorithm = 38
|
||||||
|
|
||||||
// Capabilities
|
// Capabilities
|
||||||
CapabilityGetOpaque uint64 = 0x0000000000000001
|
CapabilityGetOpaque uint64 = 0x0000000000000001
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/enceve/crypto/cmac"
|
"github.com/enceve/crypto/cmac"
|
||||||
|
"github.com/certusone/yubihsm-go/authkey"
|
||||||
"github.com/certusone/yubihsm-go/commands"
|
"github.com/certusone/yubihsm-go/commands"
|
||||||
"github.com/certusone/yubihsm-go/connector"
|
"github.com/certusone/yubihsm-go/connector"
|
||||||
)
|
)
|
||||||
|
@ -39,7 +40,7 @@ type (
|
||||||
DeviceChallenge []byte
|
DeviceChallenge []byte
|
||||||
|
|
||||||
// AuthKey to authenticate against the HSM; must match authKeySlot
|
// AuthKey to authenticate against the HSM; must match authKeySlot
|
||||||
AuthKey AuthKey
|
AuthKey authkey.AuthKey
|
||||||
|
|
||||||
// MACChainValue is the last MAC to allow MAC chaining
|
// MACChainValue is the last MAC to allow MAC chaining
|
||||||
MACChainValue []byte
|
MACChainValue []byte
|
||||||
|
@ -89,7 +90,7 @@ const (
|
||||||
func NewSecureChannel(connector connector.Connector, authKeySlot uint16, password string) (*SecureChannel, error) {
|
func NewSecureChannel(connector connector.Connector, authKeySlot uint16, password string) (*SecureChannel, error) {
|
||||||
channel := &SecureChannel{
|
channel := &SecureChannel{
|
||||||
ID: 0,
|
ID: 0,
|
||||||
AuthKey: deriveAuthKeyFromPwd(password),
|
AuthKey: authkey.NewFromPassword(password),
|
||||||
MACChainValue: make([]byte, 16),
|
MACChainValue: make([]byte, 16),
|
||||||
SecurityLevel: SecurityLevelUnauthenticated,
|
SecurityLevel: SecurityLevelUnauthenticated,
|
||||||
authKeySlot: authKeySlot,
|
authKeySlot: authKeySlot,
|
||||||
|
|
Loading…
Reference in New Issue