Merge conflicts
This commit is contained in:
parent
76fb3dd4fd
commit
86670f0fba
|
@ -9,6 +9,7 @@ Currently the following commands are implemented:
|
|||
* Reset
|
||||
* GenerateAsymmetricKey
|
||||
* SignDataEddsa
|
||||
* SignDataPkcs1
|
||||
* PutAsymmetricKey
|
||||
* GetPubKey
|
||||
* DeriveEcdh
|
||||
|
@ -17,9 +18,9 @@ Currently the following commands are implemented:
|
|||
* PutAuthenticationKey
|
||||
* GetOpaque
|
||||
* PutOpaque
|
||||
* SignDataPkcs1
|
||||
* SignAttestationCertificate
|
||||
* Authentication & Session related commands
|
||||
* GetPseudoRandom
|
||||
|
||||
Implementing new commands is really easy. Please consult `commands/constructors.go` and `commands/response.go` for reference.
|
||||
|
||||
|
|
|
@ -94,6 +94,20 @@ func CreateSignDataEcdsaCommand(keyID uint16, data []byte) (*CommandMessage, err
|
|||
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) {
|
||||
if len(label) > LabelLength {
|
||||
return nil, errors.New("label is too long")
|
||||
|
@ -241,33 +255,6 @@ func CreateDeriveEcdhCommand(objID uint16, pubkey []byte) (*CommandMessage, erro
|
|||
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) {
|
||||
command := &CommandMessage{
|
||||
CommandType: CommandTypeChangeAuthenticationKey,
|
||||
|
@ -321,20 +308,101 @@ func CreateGetOpaqueCommand(objID uint16) (*CommandMessage, error) {
|
|||
return command, nil
|
||||
}
|
||||
|
||||
func CreateSignDataPkcs1Command(objID uint16, data []byte) (*CommandMessage, error) {
|
||||
func CreateGetPseudoRandomCommand(numBytes uint16) *CommandMessage {
|
||||
command := &CommandMessage{
|
||||
CommandType: CommandTypeSignDataPkcs1,
|
||||
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 {
|
||||
return nil, errors.New("label is too long")
|
||||
}
|
||||
if len(label) < LabelLength {
|
||||
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{
|
||||
CommandType: CommandTypePutWrapKey,
|
||||
}
|
||||
|
||||
payload := bytes.NewBuffer([]byte{})
|
||||
binary.Write(payload, binary.BigEndian, objID)
|
||||
payload.Write(data)
|
||||
payload.Write(label)
|
||||
binary.Write(payload, binary.BigEndian, domains)
|
||||
binary.Write(payload, binary.BigEndian, capabilities)
|
||||
binary.Write(payload, binary.BigEndian, algorithm)
|
||||
binary.Write(payload, binary.BigEndian, delegated)
|
||||
payload.Write(wrapkey)
|
||||
|
||||
command.Data = payload.Bytes()
|
||||
|
||||
return command, nil
|
||||
}
|
||||
|
||||
func CreatePutAuthenticationKeyCommand(objID uint16, label []byte, domains uint16, capabilities, delegated uint64, encKey, macKey []byte) (*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))...)
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
||||
command := &CommandMessage{
|
||||
CommandType: CommandTypePutAuthenticationKey,
|
||||
}
|
||||
|
||||
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, algorithm)
|
||||
binary.Write(payload, binary.BigEndian, delegated)
|
||||
payload.Write(encKey)
|
||||
payload.Write(macKey)
|
||||
|
||||
command.Data = payload.Bytes()
|
||||
|
||||
return command, nil
|
||||
}
|
||||
|
||||
func CreatePutDerivedAuthenticationKeyCommand(objID uint16, label []byte, domains uint16, capabilities uint64, delegated uint64, password string) (*CommandMessage, error) {
|
||||
authKey := authkey.NewFromPassword(password)
|
||||
return CreatePutAuthenticationKeyCommand(objID, label, domains, capabilities, delegated, authKey.GetEncKey(), authKey.GetMacKey())
|
||||
}
|
||||
|
||||
func CreateSignAttestationCertCommand(keyObjID, attestationObjID uint16) (*CommandMessage, error) {
|
||||
command := &CommandMessage{
|
||||
CommandType: CommandTypeAttestAsymmetric,
|
||||
|
|
|
@ -62,6 +62,10 @@ type (
|
|||
Signature []byte
|
||||
}
|
||||
|
||||
SignDataPkcs1Response struct {
|
||||
Signature []byte
|
||||
}
|
||||
|
||||
SignDataEcdsaResponse struct {
|
||||
Signature []byte
|
||||
}
|
||||
|
@ -80,11 +84,15 @@ type (
|
|||
XCoordinate []byte
|
||||
}
|
||||
|
||||
PutAuthenticationKeyResponse struct {
|
||||
ChangeAuthenticationKeyResponse struct {
|
||||
ObjectID uint16
|
||||
}
|
||||
|
||||
ChangeAuthenticationKeyResponse struct {
|
||||
PutWrapkeyResponse struct {
|
||||
ObjectID uint16
|
||||
}
|
||||
|
||||
PutAuthenticationKeyResponse struct {
|
||||
ObjectID uint16
|
||||
}
|
||||
|
||||
|
@ -96,10 +104,6 @@ type (
|
|||
Data []byte
|
||||
}
|
||||
|
||||
SignDataPkcs1Response struct {
|
||||
Signature []byte
|
||||
}
|
||||
|
||||
SignAttestationCertResponse struct {
|
||||
Cert []byte
|
||||
}
|
||||
|
@ -139,6 +143,8 @@ func ParseResponse(data []byte) (Response, error) {
|
|||
return parseSignDataEddsaResponse(payload)
|
||||
case CommandTypeSignDataEcdsa:
|
||||
return parseSignDataEcdsaResponse(payload)
|
||||
case CommandTypeSignDataPkcs1:
|
||||
return parseSignDataPkcs1Response(payload)
|
||||
case CommandTypePutAsymmetric:
|
||||
return parsePutAsymmetricKeyResponse(payload)
|
||||
case CommandTypeListObjects:
|
||||
|
@ -155,16 +161,18 @@ func ParseResponse(data []byte) (Response, error) {
|
|||
return parseEchoResponse(payload)
|
||||
case CommandTypeDeriveEcdh:
|
||||
return parseDeriveEcdhResponse(payload)
|
||||
case CommandTypePutAuthKey:
|
||||
return parsePutAuthenticationKeyResponse(payload)
|
||||
case CommandTypeChangeAuthenticationKey:
|
||||
return parseChangeAuthenticationKeyResponse(payload)
|
||||
case CommandTypeGetPseudoRandom:
|
||||
return parseGetPseudoRandomResponse(payload), nil
|
||||
case CommandTypePutWrapKey:
|
||||
return parsePutWrapkeyResponse(payload)
|
||||
case CommandTypePutAuthenticationKey:
|
||||
return parsePutAuthenticationKeyResponse(payload)
|
||||
case CommandTypePutOpaque:
|
||||
return parsePutOpaqueResponse(payload)
|
||||
case CommandTypeGetOpaque:
|
||||
return parseGetOpaqueResponse(payload)
|
||||
case CommandTypeSignDataPkcs1:
|
||||
return parseSignDataPkcs1Response(payload)
|
||||
case CommandTypeAttestAsymmetric:
|
||||
return parseAttestationCertResponse(payload)
|
||||
case ErrorResponseCode:
|
||||
|
@ -226,6 +234,16 @@ func parseSignDataEddsaResponse(payload []byte) (Response, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func parseSignDataPkcs1Response(payload []byte) (Response, error) {
|
||||
if len(payload) < 1 {
|
||||
return nil, errors.New("invalid response payload length")
|
||||
}
|
||||
|
||||
return &SignDataPkcs1Response{
|
||||
Signature: payload,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseSignDataEcdsaResponse(payload []byte) (Response, error) {
|
||||
return &SignDataEcdsaResponse{
|
||||
Signature: payload,
|
||||
|
@ -298,20 +316,6 @@ func parseDeriveEcdhResponse(payload []byte) (Response, error) {
|
|||
}, 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) {
|
||||
if len(payload) != 2 {
|
||||
return nil, errors.New("invalid response payload length")
|
||||
|
@ -326,6 +330,37 @@ func parseChangeAuthenticationKeyResponse(payload []byte) (Response, error) {
|
|||
return &ChangeAuthenticationKeyResponse{ObjectID: objectID}, nil
|
||||
}
|
||||
|
||||
func parseGetPseudoRandomResponse(payload []byte) Response {
|
||||
return payload
|
||||
}
|
||||
|
||||
func parsePutWrapkeyResponse(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 &PutWrapkeyResponse{ObjectID: objectID}, 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 parsePutOpaqueResponse(payload []byte) (Response, error) {
|
||||
if len(payload) != 2 {
|
||||
return nil, errors.New("invalid response payload length")
|
||||
|
@ -352,16 +387,6 @@ func parseGetOpaqueResponse(payload []byte) (Response, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func parseSignDataPkcs1Response(payload []byte) (Response, error) {
|
||||
if len(payload) < 1 {
|
||||
return nil, errors.New("invalid response payload length")
|
||||
}
|
||||
|
||||
return &SignDataPkcs1Response{
|
||||
Signature: payload,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseAttestationCertResponse(payload []byte) (Response, error) {
|
||||
if len(payload) < 1 {
|
||||
return nil, errors.New("invalid response payload length")
|
||||
|
@ -402,6 +427,8 @@ func (e *Error) Error() string {
|
|||
message = "Object not found"
|
||||
case ErrorCodeInvalidID:
|
||||
message = "Invalid ID"
|
||||
case ErrorCodeCommandUnexecuted:
|
||||
message = "Command unexecuted"
|
||||
case ErrorCodeSSHCAConstraintViolation:
|
||||
message = "SSH CA constraint violation"
|
||||
case ErrorCodeInvalidOTP:
|
||||
|
|
|
@ -23,7 +23,7 @@ const (
|
|||
CommandTypeStorageStatus CommandType = 0x41
|
||||
CommandTypePutOpaque CommandType = 0x42
|
||||
CommandTypeGetOpaque CommandType = 0x43
|
||||
CommandTypePutAuthKey CommandType = 0x44
|
||||
CommandTypePutAuthenticationKey CommandType = 0x44
|
||||
CommandTypePutAsymmetric CommandType = 0x45
|
||||
CommandTypeGenerateAsymmetricKey CommandType = 0x46
|
||||
CommandTypeSignDataPkcs1 CommandType = 0x47
|
||||
|
@ -81,6 +81,7 @@ const (
|
|||
ErrorCodeInvalidOTP ErrorCode = 0x0f
|
||||
ErrorCodeDemoMode ErrorCode = 0x10
|
||||
ErrorCodeObjectExists ErrorCode = 0x11
|
||||
ErrorCodeCommandUnexecuted ErrorCode = 0xff
|
||||
|
||||
// Algorithms
|
||||
AlgorithmRSA2048 Algorithm = 9
|
||||
|
@ -89,13 +90,16 @@ const (
|
|||
AlgorithmOpaqueData Algorithm = 30
|
||||
AlgorithmOpaqueX509Certificate Algorithm = 31
|
||||
AlgorithmYubicoAESAuthentication Algorithm = 38
|
||||
AlgorithmAES128CCMWrap Algorithm = 29
|
||||
AlgorithmAES192CCMWrap Algorithm = 41
|
||||
AlgorithmAES256CCMWrap Algorithm = 42
|
||||
AlgorithmED25519 Algorithm = 46
|
||||
|
||||
// Capabilities
|
||||
CapabilityNone uint64 = 0x0000000000000000
|
||||
CapabilityGetOpaque uint64 = 0x0000000000000001
|
||||
CapabilityPutOpaque uint64 = 0x0000000000000002
|
||||
CapabilityPutAuthKey uint64 = 0x0000000000000004
|
||||
CapabilityPutAuthenticationKey uint64 = 0x0000000000000004
|
||||
CapabilityPutAsymmetric uint64 = 0x0000000000000008
|
||||
CapabilityAsymmetricGen uint64 = 0x0000000000000010
|
||||
CapabilityAsymmetricSignPkcs uint64 = 0x0000000000000020
|
||||
|
@ -140,7 +144,7 @@ const (
|
|||
CapabilityDeleteHmacKey uint64 = 0x0000080000000000
|
||||
CapabilityDeleteTemplate uint64 = 0x0000100000000000
|
||||
CapabilityDeleteOtpAeadKey uint64 = 0x0000200000000000
|
||||
CapabilityChangeAuthKey uint64 = 0x0000400000000000
|
||||
CapabilityChangeAuthenticationKey uint64 = 0x0000400000000000
|
||||
|
||||
// Domains
|
||||
Domain1 uint16 = 0x0001
|
||||
|
@ -177,3 +181,12 @@ const (
|
|||
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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue