pair

package
v1.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 10, 2020 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package pair implements the pairing and verification protocol.

Index

Constants

View Source
const (
	NonAdminPerm = 0x00
	AdminPerm    = 0x01
)
View Source
const (
	// ErrCodeNo is code for no error
	ErrCodeNo errCode = 0x00

	// ErrCodeUnknown is code for unknown error
	ErrCodeUnknown errCode = 0x01

	// ErrCodeAuthenticationFailed is code for authentication error e.g. client proof is wrong
	ErrCodeAuthenticationFailed errCode = 0x02

	// ErrCodeTooManyAttempts is code for too many attempts error (not used)
	ErrCodeTooManyAttempts errCode = 0x03

	// ErrCodeUnknownPeer is code for unknown accessory or client error
	ErrCodeUnknownPeer errCode = 0x04

	// ErrCodeMaxPeer is code for reaching maximum number of peers error (not used)
	ErrCodeMaxPeer errCode = 0x05

	// ErrCodeMaxAuthenticationAttempts is code for reaching maximum number of authentication attemps error (not used)
	ErrCodeMaxAuthenticationAttempts errCode = 0x06
)
View Source
const (
	// TagPairingMethod is the paring method tag. The value is of type PairMethodType.
	TagPairingMethod = 0x00

	// TagUsername is the username tag. The value is of type string.
	TagUsername = 0x01

	// TagSalt is the salt tag. The value is of type 16 bytes.
	TagSalt = 0x02

	// TagPublicKey is the public key tag. The value is either SRP client public key (384 bytes) or ED25519 public key (32 bytes) - depending on the context.
	TagPublicKey = 0x03

	// TagProof is the SRP proof tag. The value is of type 64 bytes.
	TagProof = 0x04

	// TagEncryptedData is the encrypted data tag. The value includes the encrypted message and auth tag.
	TagEncryptedData = 0x05

	// TagSequence is the sequence tag. The value is of type PairStepType or VerifyStepType - depending on the context.
	TagSequence = 0x06

	// TagErrCode is the error tag. The value is of type ErrCode.
	TagErrCode = 0x07

	// TagMFiCertificate is the MFi certificate tag (currently not used).
	TagMFiCertificate = 0x09

	// TagSignature is the Ed25519 signature tag. The value is of type 64 bytes.
	TagSignature = 0x0A

	// TagPermission is the permission tag. A value of 0x00 means a regular user, 0x01 is an admin which can remove and add pairings.
	TagPermission = 0x0B
)

These constants are used to access values in a TLV8 container.

View Source
const (
	SRPGroup = "rfc5054.3072" // N (modulo) => 384 byte
)

Main SRP algorithm is described in http://srp.stanford.edu/design.html The HAP uses the SRP-6a Stanford implementation with the following characteristics

x = H(s | H(I | ":" | P)) -> called the key derivate function
M1 = H(H(N) xor H(g), H(I), s, A, B, K)

Variables

This section is empty.

Functions

func HandleReaderForHandler

func HandleReaderForHandler(r io.Reader, h hap.ContainerHandler) (rOut io.Reader, err error)

HandleReaderForHandler wraps h.Handle() call and logs sequence numbers and errors to the console.

func KeyDerivativeFuncRFC2945

func KeyDerivativeFuncRFC2945(h srp.HashFunc, username []byte) srp.KeyDerivationFunc

KeyDerivativeFuncRFC2945 returns the SRP-6a key derivative function which does

x = H(s | H(I | ":" | P))

Types

type PairMethodType

type PairMethodType byte
const (
	// PairingMethodDefault is the default pairing method.
	PairingMethodDefault PairMethodType = 0x00

	// PairingMethodMFi is used to pair with an MFi compliant accessory (not used).
	PairingMethodMFi PairMethodType = 0x01

	// PairingMethodAdd is used to pair a client by exchanging keys on a secured
	// connection and without going through the pairing process.
	PairingMethodAdd PairMethodType = 0x03

	// PairingMethodDelete is used to delete a pairing with a client.
	PairingMethodDelete PairMethodType = 0x04
)

func (PairMethodType) Byte

func (m PairMethodType) Byte() byte

func (PairMethodType) String

func (m PairMethodType) String() string

type PairStepType

type PairStepType byte

PairStepType defines the type of pairing steps.

const (
	// PairStepWaiting is the step when waiting server waits for pairing request from a client.
	PairStepWaiting PairStepType = 0x00

	// PairStepStartRequest sent from the client to the accessory to start pairing.
	PairStepStartRequest PairStepType = 0x01

	// PairStepStartResponse sent from the accessory to the client alongside the server's salt and public key
	PairStepStartResponse PairStepType = 0x02

	// PairStepVerifyRequest sent from the client to the accessory alongside the client public key and proof.
	PairStepVerifyRequest PairStepType = 0x03

	// PairStepVerifyResponse sent from the accessory to the client alongside the server's proof.
	PairStepVerifyResponse PairStepType = 0x04

	// PairStepKeyExchangeRequest sent from the client to the accessory alongside the client encrypted username and public key
	PairStepKeyExchangeRequest PairStepType = 0x05

	// PairStepKeyExchangeResponse sent from the accessory to the client alongside the accessory encrypted username and public key
	PairStepKeyExchangeResponse PairStepType = 0x06
)

func (PairStepType) Byte

func (t PairStepType) Byte() byte

Byte returns the raw byte value.

func (PairStepType) String

func (t PairStepType) String() string

type PairingController

type PairingController struct {
	// contains filtered or unexported fields
}

PairingController handles un-/pairing with a client by simply exchanging the keys going through the pairing process.

func NewPairingController

func NewPairingController(database db.Database) *PairingController

NewPairingController returns a pairing controller.

func (*PairingController) Handle

func (c *PairingController) Handle(cont util.Container) (util.Container, error)

Handle processes a container to pair with a new client without going through the pairing process.

type SetupClientController

type SetupClientController struct {
	// contains filtered or unexported fields
}

SetupClientController handles pairing with an accessory using SRP.

func NewSetupClientController

func NewSetupClientController(pin string, client hap.Device, database db.Database) *SetupClientController

NewSetupClientController returns a new setup client controller.

func (*SetupClientController) Handle

func (setup *SetupClientController) Handle(in util.Container) (util.Container, error)

Handle processes a container to pair (exchange keys) with an accessory.

func (*SetupClientController) InitialPairingRequest

func (setup *SetupClientController) InitialPairingRequest() io.Reader

InitialPairingRequest returns the first request the client sends to an accessory to start the paring process. The request contains the sequence set to PairStepStartRequest.

type SetupClientSession

type SetupClientSession struct {
	PublicKey     []byte   // A
	PrivateKey    []byte   // S
	Proof         []byte   // M1
	EncryptionKey [32]byte // K
	// contains filtered or unexported fields
}

SetupClientSession holds the keys to pair with an accessory.

func NewSetupClientSession

func NewSetupClientSession(username string, pin string) *SetupClientSession

NewSetupClientSession returns a new setup client session

func (*SetupClientSession) GenerateKeys

func (s *SetupClientSession) GenerateKeys(salt []byte, otherPublicKey []byte) error

GenerateKeys generates public and private keys based on server's salt and public key.

func (*SetupClientSession) IsServerProofValid

func (s *SetupClientSession) IsServerProofValid(proof []byte) bool

IsServerProofValid returns true when the server proof `M2` is valid.

func (*SetupClientSession) SetupEncryptionKey

func (s *SetupClientSession) SetupEncryptionKey(salt []byte, info []byte) error

SetupEncryptionKey calculates encryption key `K` based on salt and info.

type SetupServerController

type SetupServerController struct {
	// contains filtered or unexported fields
}

SetupServerController handles pairing with a cliet using SRP. The entity has to known the bridge pin to successfully pair. When pairing was successful, the entity's public key (refered as ltpk - long term public key) is stored in the database.

Pairing may fail because the pin is wrong or the key exchange failed (e.g. packet seals or SRP key authenticator is wrong, ...).

func NewSetupServerController

func NewSetupServerController(device hap.SecuredDevice, database db.Database) (*SetupServerController, error)

NewSetupServerController returns a new pair setup controller.

func (*SetupServerController) Handle

func (setup *SetupServerController) Handle(in util.Container) (out util.Container, err error)

Handle processes a container to pair (exchange keys) with a client.

type SetupServerSession

type SetupServerSession struct {
	Salt          []byte   // s
	PublicKey     []byte   // B
	PrivateKey    []byte   // S
	EncryptionKey [32]byte // K
	Username      []byte
	// contains filtered or unexported fields
}

SetupServerSession holds the keys to pair with a client.

func NewSetupServerSession

func NewSetupServerSession(username, pin string) (*SetupServerSession, error)

NewSetupServerSession return a new setup server session.

func (*SetupServerSession) ProofFromClientProof

func (p *SetupServerSession) ProofFromClientProof(clientProof []byte) ([]byte, error)

ProofFromClientProof validates client proof (`M1`) and returns authenticator or error if proof is not valid.

func (*SetupServerSession) SetupEncryptionKey

func (p *SetupServerSession) SetupEncryptionKey(salt []byte, info []byte) error

SetupEncryptionKey calculates and internally sets encryption key `K` based on salt and info

Only 32 bytes are used from HKDF-SHA512

func (*SetupServerSession) SetupPrivateKeyFromClientPublicKey

func (p *SetupServerSession) SetupPrivateKeyFromClientPublicKey(key []byte) error

SetupPrivateKeyFromClientPublicKey calculates and internally sets secret key `S` based on client public key `A`

type VerifyClientController

type VerifyClientController struct {
	// contains filtered or unexported fields
}

VerifyClientController verifies the stored accessory public key and negotiates a shared secret which is used encrypt the upcoming session.

Verification fails when the accessory is not known, the public key for the accessory was not found, or the packet's seal could not be verified.

func NewVerifyClientController

func NewVerifyClientController(client hap.Device, database db.Database) *VerifyClientController

NewVerifyClientController returns a new verify client controller.

func (*VerifyClientController) Handle

func (verify *VerifyClientController) Handle(in util.Container) (util.Container, error)

Handle processes a container to verify if an accessory is paired correctly.

func (*VerifyClientController) InitialKeyVerifyRequest

func (verify *VerifyClientController) InitialKeyVerifyRequest() io.Reader

InitialKeyVerifyRequest returns the first request the client sends to an accessory to start the paring verifcation process. The request contains the client public key and sequence set to VerifyStepStartRequest.

type VerifyServerController

type VerifyServerController struct {
	// contains filtered or unexported fields
}

VerifyServerController verifies the stored client public key and negotiates a shared secret which is used encrypt the upcoming session.

Verification fails when the client is not known, the public key for the client was not found, or the packet's seal could not be verified.

func NewVerifyServerController

func NewVerifyServerController(database db.Database, context hap.Context) *VerifyServerController

NewVerifyServerController returns a new verify server controller.

func (*VerifyServerController) Handle

func (verify *VerifyServerController) Handle(in util.Container) (util.Container, error)

Handle processes a container to verify if a client is paired correctly.

func (*VerifyServerController) SharedKey

func (verify *VerifyServerController) SharedKey() [32]byte

SharedKey returns the shared key which was negotiated with the client.

type VerifySession

type VerifySession struct {
	OtherPublicKey [32]byte
	PublicKey      [32]byte
	PrivateKey     [32]byte
	SharedKey      [32]byte
	EncryptionKey  [32]byte
}

VerifySession holds keys to encrypt a tcp connection.

func NewVerifySession

func NewVerifySession() *VerifySession

NewVerifySession creates a new session with random public and private key

func (*VerifySession) GenerateSharedKeyWithOtherPublicKey

func (s *VerifySession) GenerateSharedKeyWithOtherPublicKey(otherPublicKey [32]byte)

GenerateSharedKeyWithOtherPublicKey generates a Curve25519 shared key based on a public key. The other public key is also stored for further use in `otherPublicKey` property.

func (*VerifySession) SetupEncryptionKey

func (s *VerifySession) SetupEncryptionKey(salt []byte, info []byte) error

SetupEncryptionKey generates an encryption key based on the shared key, salt and info.

type VerifyStepType

type VerifyStepType byte

VerifyStepType defines the type of pairing verification steps.

const (
	// VerifyStepWaiting is the step when waiting server waits for pair verification request from the client.
	VerifyStepWaiting VerifyStepType = 0x00
	// VerifyStepStartRequest sent from the client to the accessory to start pairing verification alongside the client public key.
	VerifyStepStartRequest VerifyStepType = 0x01
	// VerifyStepStartResponse sent from the accessory to the client alongside the accessory public key and signature (derived from the on the accessory public key, username and client public and private key)
	VerifyStepStartResponse VerifyStepType = 0x02
	// VerifyStepFinishRequest sent from the client to the accessory alongside the client public key and signature (derived from the on the client public key, username and accessory public and private key)
	VerifyStepFinishRequest VerifyStepType = 0x03
	// VerifyStepFinishResponse sent from the accessory to the client alongside an error code when verification failed.
	VerifyStepFinishResponse VerifyStepType = 0x04
)

func (VerifyStepType) Byte

func (t VerifyStepType) Byte() byte

Byte returns the raw byte value.

func (VerifyStepType) String

func (t VerifyStepType) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL