Documentation ¶
Overview ¶
Package pair implements the pairing and verification protocol.
Index ¶
- Constants
- func HandleReaderForHandler(r io.Reader, h hap.ContainerHandler) (rOut io.Reader, err error)
- func KeyDerivativeFuncRFC2945(h srp.HashFunc, username []byte) srp.KeyDerivationFunc
- type PairMethodType
- type PairStepType
- type PairingController
- type SetupClientController
- type SetupClientSession
- type SetupServerController
- type SetupServerSession
- type VerifyClientController
- type VerifyServerController
- type VerifySession
- type VerifyStepType
Constants ¶
const ( NonAdminPerm = 0x00 AdminPerm = 0x01 )
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 )
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.
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 ¶
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) 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.
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 ¶
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.
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 ¶
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 ¶
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 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) String ¶
func (t VerifyStepType) String() string
Source Files ¶
- admin.go
- doc.go
- error_types.go
- errors.go
- handler.go
- method_types.go
- pairing_controller.go
- sequence_types.go
- setup_client_controller.go
- setup_client_session.go
- setup_server_controller.go
- setup_server_session.go
- srp.go
- tag_types.go
- verify_client_controller.go
- verify_server_controller.go
- verify_session.go