예제 #1
0
// Tests the pairing key verification
func TestInvalidPublicKey(t *testing.T) {
	storage, err := util.NewTempFileStorage()

	if err != nil {
		t.Fatal(err)
	}

	database := db.NewDatabaseWithStorage(storage)
	bridge, err := hap.NewSecuredDevice("Macbook Bridge", "001-02-003", database)

	if err != nil {
		t.Fatal(err)
	}

	context := hap.NewContextForSecuredDevice(bridge)

	controller := NewVerifyServerController(database, context)

	client, _ := hap.NewDevice("HomeKit Client", database)
	clientController := NewVerifyClientController(client, database)

	req := clientController.InitialKeyVerifyRequest()
	reqContainer, err := util.NewTLV8ContainerFromReader(req)

	if err != nil {
		t.Fatal(err)
	}

	reqContainer.SetByte(TagPublicKey, byte(0x01))
	// 1) C -> S
	if _, err = HandleReaderForHandler(reqContainer.BytesBuffer(), controller); err != errInvalidClientKeyLength {
		t.Fatal("expected invalid client key length error")
	}
}
예제 #2
0
// NewIPTransport creates a transport to provide accessories over IP.
//
// The IP transports stores the crypto keys inside a database, which
// is by default inside a folder at the current working directory.
// The folder is named exactly as the accessory name.
//
// The transports can contain more than one accessory. If this is the
// case, the first accessory acts as the HomeKit bridge.
//
// *Important:* Changing the name of the accessory, or letting multiple
// transports store the data inside the same database lead to
// unexpected behavior – don't do that.
//
// The transport is secured with an 8-digit pin, which must be entered
// by an iOS client to successfully pair with the accessory. If the
// provided transport config does not specify any pin, 00102003 is used.
func NewIPTransport(config Config, a *accessory.Accessory, as ...*accessory.Accessory) (Transport, error) {
	// Find transport name which is visible in mDNS
	name := a.Info.Name.GetValue()
	if len(name) == 0 {
		log.Info.Panic("Invalid empty name for first accessory")
	}

	cfg := defaultConfig(name)
	cfg.merge(config)

	storage, err := util.NewFileStorage(cfg.StoragePath)
	if err != nil {
		return nil, err
	}

	database := db.NewDatabaseWithStorage(storage)

	hap_pin, err := NewPin(cfg.Pin)
	if err != nil {
		return nil, err
	}

	cfg.load(storage)

	device, err := hap.NewSecuredDevice(cfg.id, hap_pin, database)

	t := &ipTransport{
		storage:   storage,
		database:  database,
		device:    device,
		config:    cfg,
		container: accessory.NewContainer(),
		mutex:     &sync.Mutex{},
		context:   hap.NewContextForSecuredDevice(device),
		emitter:   event.NewEmitter(),
	}

	t.addAccessory(a)
	for _, a := range as {
		t.addAccessory(a)
	}

	// Users can only pair discoverable accessories
	if t.isPaired() {
		cfg.discoverable = false
	}

	cfg.categoryId = int(t.container.AccessoryType())
	cfg.updateConfigHash(t.container.ContentHash())
	cfg.save(storage)

	// Listen for events to update mDNS txt records
	t.emitter.AddListener(t)

	return t, err
}
예제 #3
0
// Tests the pairing key verification
func TestPairVerifyIntegration(t *testing.T) {
	storage, err := util.NewTempFileStorage()

	if err != nil {
		t.Fatal(err)
	}

	database := db.NewDatabaseWithStorage(storage)
	bridge, err := hap.NewSecuredDevice("Macbook Bridge", "001-02-003", database)

	if err != nil {
		t.Fatal(err)
	}

	context := hap.NewContextForSecuredDevice(bridge)
	controller := NewVerifyServerController(database, context)

	clientDatabase, _ := db.NewTempDatabase()
	bridgeEntity := db.NewEntity(bridge.Name(), bridge.PublicKey(), nil)
	err = clientDatabase.SaveEntity(bridgeEntity)

	if err != nil {
		t.Fatal(err)
	}

	client, _ := hap.NewDevice("HomeKit Client", clientDatabase)
	clientEntity := db.NewEntity(client.Name(), client.PublicKey(), nil)
	err = database.SaveEntity(clientEntity)

	if err != nil {
		t.Fatal(err)
	}

	clientController := NewVerifyClientController(client, clientDatabase)

	tlvVerifyStepStartRequest := clientController.InitialKeyVerifyRequest()
	// 1) C -> S
	tlvVerifyStepStartResponse, err := HandleReaderForHandler(tlvVerifyStepStartRequest, controller)

	if err != nil {
		t.Fatal(err)
	}

	// 2) S -> C
	tlvFinishRequest, err := HandleReaderForHandler(tlvVerifyStepStartResponse, clientController)

	if err != nil {
		t.Fatal(err)
	}

	// 3) C -> S
	tlvFinishRespond, err := HandleReaderForHandler(tlvFinishRequest, controller)

	if err != nil {
		t.Fatal(err)
	}

	// 4) S -> C
	response, err := HandleReaderForHandler(tlvFinishRespond, clientController)

	if err != nil {
		t.Fatal(err)
	}
	if response != nil {
		t.Fatal(response)
	}
}
예제 #4
0
// Tests the pairing setup
func TestPairingIntegration(t *testing.T) {
	storage, err := util.NewTempFileStorage()

	if err != nil {
		t.Fatal(err)
	}

	database := db.NewDatabaseWithStorage(storage)
	bridge, err := hap.NewSecuredDevice("Macbook Bridge", "001-02-003", database)

	if err != nil {
		t.Fatal(err)
	}

	controller, err := NewSetupServerController(bridge, database)

	if err != nil {
		t.Fatal(err)
	}

	clientDatabase, _ := db.NewTempDatabase()
	client, _ := hap.NewDevice("Client", clientDatabase)
	clientController := NewSetupClientController("001-02-003", client, clientDatabase)
	pairStartRequest := clientController.InitialPairingRequest()

	// 1) C -> S
	pairStartResponse, err := HandleReaderForHandler(pairStartRequest, controller)

	if err != nil {
		t.Fatal(err)
	}

	// 2) S -> C
	pairVerifyRequest, err := HandleReaderForHandler(pairStartResponse, clientController)

	if err != nil {
		t.Fatal(err)
	}

	// 3) C -> S
	pairVerifyResponse, err := HandleReaderForHandler(pairVerifyRequest, controller)

	if err != nil {
		t.Fatal(err)
	}

	// 4) S -> C
	pairKeyRequest, err := HandleReaderForHandler(pairVerifyResponse, clientController)

	if err != nil {
		t.Fatal(err)
	}

	// 5) C -> S
	pairKeyRespond, err := HandleReaderForHandler(pairKeyRequest, controller)

	if err != nil {
		t.Fatal(err)
	}

	// 6) S -> C
	request, err := HandleReaderForHandler(pairKeyRespond, clientController)
	if err != nil {
		t.Fatal(err)
	}

	if request != nil {
		t.Fatal(request)
	}
}