func (handler *Characteristics) ServeHTTP(response http.ResponseWriter, request *http.Request) { var res io.Reader var err error handler.mutex.Lock() switch request.Method { case netio.MethodGET: log.Printf("[VERB] %v GET /characteristics", request.RemoteAddr) request.ParseForm() res, err = handler.controller.HandleGetCharacteristics(request.Form) case netio.MethodPUT: log.Printf("[VERB] %v PUT /characteristics", request.RemoteAddr) session := handler.context.GetSessionForRequest(request) conn := session.Connection() err = handler.controller.HandleUpdateCharacteristics(request.Body, conn) default: log.Println("[WARN] Cannot handle HTTP method", request.Method) } handler.mutex.Unlock() if err != nil { log.Println("[ERRO]", err) response.WriteHeader(http.StatusInternalServerError) } else { if res != nil { response.Header().Set("Content-Type", netio.HTTPContentTypeHAPJson) wr := netio.NewChunkedWriter(response, 2048) b, _ := ioutil.ReadAll(res) wr.Write(b) } else { response.WriteHeader(http.StatusNoContent) } } }
func (handler *PairSetup) ServeHTTP(response http.ResponseWriter, request *http.Request) { log.Printf("[VERB] %v POST /pair-setup", request.RemoteAddr) response.Header().Set("Content-Type", netio.HTTPContentTypePairingTLV8) key := handler.context.GetConnectionKey(request) session := handler.context.Get(key).(netio.Session) controller := session.PairSetupHandler() if controller == nil { log.Println("[VERB] Create new pair setup controller") var err error controller, err = pair.NewSetupServerController(handler.device, handler.database) if err != nil { log.Println(err) } session.SetPairSetupHandler(controller) } res, err := pair.HandleReaderForHandler(request.Body, controller) if err != nil { log.Println("[ERRO]", err) response.WriteHeader(http.StatusInternalServerError) } else { io.Copy(response, res) } }
func (handler *PairVerify) ServeHTTP(response http.ResponseWriter, request *http.Request) { log.Printf("[VERB] %v POST /pair-verify", request.RemoteAddr) response.Header().Set("Content-Type", netio.HTTPContentTypePairingTLV8) key := handler.context.GetConnectionKey(request) session := handler.context.Get(key).(netio.Session) controller := session.PairVerifyHandler() if controller == nil { log.Println("[VERB] Create new pair verify controller") controller = pair.NewVerifyServerController(handler.database, handler.context) session.SetPairVerifyHandler(controller) } res, err := pair.HandleReaderForHandler(request.Body, controller) if err != nil { log.Println(err) response.WriteHeader(http.StatusInternalServerError) } else { io.Copy(response, res) // Setup secure session if controller.KeyVerified() == true { // Verification is done // Switch to secure session secureSession, err := crypto.NewSecureSessionFromSharedKey(controller.SharedKey()) if err != nil { log.Println("[ERRO] Could not setup secure session.", err) } else { log.Println("[VERB] Setup secure session") } session.SetCryptographer(secureSession) } } }
// Handle processes a container to pair with a new client without going through the pairing process. func (c *PairingController) Handle(cont util.Container) (util.Container, error) { method := pairMethodType(cont.GetByte(TagPairingMethod)) username := cont.GetString(TagUsername) publicKey := cont.GetBytes(TagPublicKey) log.Println("[VERB] -> Method:", method) log.Println("[VERB] -> Username:"******"[VERB] -> LTPK:", publicKey) entity := db.NewEntity(username, publicKey, nil) switch method { case PairingMethodDelete: log.Printf("[INFO] Remove LTPK for client '%s'\n", username) c.database.DeleteEntity(entity) case PairingMethodAdd: err := c.database.SaveEntity(entity) if err != nil { log.Println("[ERRO]", err) return nil, err } default: return nil, fmt.Errorf("Invalid pairing method type %v", method) } out := util.NewTLV8Container() out.SetByte(TagSequence, 0x2) return out, nil }
func (t *Thermostat) RunLoop() { go t.boiler.RunLoop() for { select { case <-time.After(interval): temp = t.thermometer.Temperature() if temp >= t.targetTemp+maxOver { if t.boiler.GetCurrentCommand() == true { log.Println("[INFO] Over temperature, turning boiler off") t.boiler.SetCurrentCommand(false) t.isOn = false } } else if temp <= t.targetTemp-minUnder { if t.boiler.GetCurrentCommand() == false { log.Println("[INFO] Under temperature, turning boiler on") t.boiler.SetCurrentCommand(true) t.isOn = true } } case <-t.done: break } } t.boiler.Stop() }
func main() { log.Println("[ERRO] Just an error") log.Printf("[ERRO] Just an error %d", 1) log.Println("[WARN] Just a warning") log.Printf("[WARN] Just a warning %d", 1) log.Println("[INFO] Just an info") log.Printf("[INFO] Just an info %d", 1) log.Println("[VERB] Just an info") log.Printf("[VERB] Just an info %d", 1) log.Error = false log.Warn = false log.Info = false log.Verbose = false log.Println("MUST be displayed") log.Println("[ERRO] MUST NOT be displayed") log.Printf("[ERRO] MUST NOT be displayed %d", 1) log.Println("[WARN] MUST NOT be displayed") log.Printf("[WARN] MUST NOT be displayed %d", 1) log.Println("[INFO] MUST NOT be displayed") log.Printf("[INFO] MUST NOT be displayed %d", 1) log.Println("[VERB] MUST NOT be displayed") log.Printf("[VERB] MUST NOT be displayed %d", 1) }
func main() { flag.Float64Var(&temp, "temp", 20.0, "Target temperature") flag.StringVar(&tempPath, "tempPath", "", "Target temperature path") flag.StringVar(&device, "device", "", "Thermometer device") flag.BoolVar(&verbose, "verbose", false, "Verbose logging") flag.Parse() log.Verbose = verbose if device == "" { log.Fatal("No device specified") } if tempPath != "" { _, err := os.Stat(tempPath) if err != nil { log.Fatal(err) } log.Println("[INFO] Starting thermostat with temperature from path:", tempPath) } else { log.Println("[INFO] Starting thermostat with target temperature:", temp) } log.Println("[VERB] Using thermometer at", device) boiler := NewBoiler() thermometer := NewThermometer(device) go thermometer.RunLoop() thermostat := NewThermostat(boiler, thermometer, temp) go thermostat.RunLoop() if tempPath != "" { tempPoller := NewTempPoller(thermostat, tempPath) temp = tempPoller.PollTemp() go tempPoller.RunLoop() } api := NewAPI(thermostat) go api.RunLoop() homekitService := NewHomeKitService(thermostat) go homekitService.RunLoop() // Handle SIGINT and SIGTERM. ch := make(chan os.Signal) signal.Notify(ch, os.Interrupt, os.Kill, syscall.SIGINT, syscall.SIGTERM) signal := <-ch log.Println("[INFO] Received signal", signal, "terminating") homekitService.Stop() thermostat.Stop() }
// Client -> Server // - Auth start // // Server -> Client // - B: server public key // - s: salt func (setup *SetupServerController) handlePairStart(in util.Container) (util.Container, error) { out := util.NewTLV8Container() setup.step = PairStepStartResponse out.SetByte(TagSequence, setup.step.Byte()) out.SetBytes(TagPublicKey, setup.session.PublicKey) out.SetBytes(TagSalt, setup.session.Salt) log.Println("[VERB] <- B:", hex.EncodeToString(out.GetBytes(TagPublicKey))) log.Println("[VERB] <- s:", hex.EncodeToString(out.GetBytes(TagSalt))) return out, nil }
// Handle processes a container to pair (exchange keys) with an accessory. func (setup *SetupClientController) Handle(in util.Container) (util.Container, error) { method := pairMethodType(in.GetByte(TagPairingMethod)) // It is valid that method is not sent // If method is sent then it must be 0x00 if method != PairingMethodDefault { return nil, errInvalidPairMethod(method) } code := errCode(in.GetByte(TagErrCode)) if code != ErrCodeNo { log.Println("[ERRO]", code) return nil, code.Error() } seq := pairStepType(in.GetByte(TagSequence)) var out util.Container var err error switch seq { case PairStepStartResponse: out, err = setup.handlePairStepStartResponse(in) case PairStepVerifyResponse: out, err = setup.handlePairStepVerifyResponse(in) case PairStepKeyExchangeResponse: out, err = setup.handleKeyExchange(in) default: return nil, errInvalidPairStep(seq) } return out, err }
func (endpoint *Pairing) ServeHTTP(response http.ResponseWriter, request *http.Request) { log.Printf("[VERB] %v POST /pairings", request.RemoteAddr) response.Header().Set("Content-Type", netio.HTTPContentTypePairingTLV8) var err error var in util.Container var out util.Container if in, err = util.NewTLV8ContainerFromReader(request.Body); err == nil { out, err = endpoint.controller.Handle(in) } if err != nil { log.Println(err) response.WriteHeader(http.StatusInternalServerError) } else { io.Copy(response, out.BytesBuffer()) // Send events based on pairing method type b := in.GetByte(pair.TagPairingMethod) switch pair.PairMethodType(b) { case pair.PairingMethodDelete: // pairing removed endpoint.emitter.Emit(event.DeviceUnpaired{}) case pair.PairingMethodAdd: // pairing added endpoint.emitter.Emit(event.DevicePaired{}) } } }
func HandleInputValueWithName(v uvr.Value, name string) (s *hkuvr1611.Sensor) { var found bool if s, found = sensors[name]; found == false { s = hkuvr1611.NewSensorForInputValue(v, InfoForAccessoryName(name)) if s != nil { log.Println("[INFO]", reflect.TypeOf(s.Model), "with name", name) sensors[name] = s } } else { err := hkuvr1611.UpdateAccessoryWithInputValue(s.Model, v) if err != nil { log.Println("[ERRO]", err) } } return s }
// HandleUpdateCharacteristics handles an update characteristic request. The bytes must represent // a data.Characteristics json. func (ctr *CharacteristicController) HandleUpdateCharacteristics(r io.Reader, conn net.Conn) error { b, err := ioutil.ReadAll(r) if err != nil { return err } var chars data.Characteristics err = json.Unmarshal(b, &chars) if err != nil { return err } log.Println("[VERB]", string(b)) for _, c := range chars.Characteristics { characteristic := ctr.GetCharacteristic(c.AccessoryID, c.ID) if characteristic == nil { log.Printf("[ERRO] Could not find characteristic with aid %d and iid %d\n", c.AccessoryID, c.ID) continue } if c.Value != nil { characteristic.SetValueFromConnection(c.Value, conn) } if events, ok := c.Events.(bool); ok == true { characteristic.SetEventsEnabled(events) } } return err }
func NewDevice(device common.Device) { if light, ok := device.(common.Light); ok { hkLight := GetHKLight(light) hkLight.sub, _ = light.NewSubscription() for { event := <-hkLight.sub.Events() switch event.(type) { case common.EventUpdateLabel: log.Printf("[INFO] Updated Label for %s to %s", hkLight.accessory.Name(), event.(common.EventUpdateLabel).Label) // TODO Add support for label changes to HomeControl log.Printf("[INFO] Unsupported by HomeControl") case common.EventUpdatePower: log.Printf("[INFO] Updated Power for %s", hkLight.accessory.Name()) hkLight.light.SetOn(event.(common.EventUpdatePower).Power) case common.EventUpdateColor: log.Printf("[INFO] Updated Color for %s", hkLight.accessory.Name()) hue, saturation, brightness := ConvertLIFXColor(event.(common.EventUpdateColor).Color) hkLight.light.SetHue(hue) hkLight.light.SetSaturation(saturation) hkLight.light.SetBrightness(int(brightness)) default: log.Printf("[INFO] Unknown Device Event: %T", event) } } } else { log.Println("[INFO] Unsupported Device") } }
func (tp *TempPoller) updateTemp() { temp := tp.PollTemp() if temp != tp.lastTemp { log.Println("[INFO] Setting thermostat target temperature to", temp) tp.thermostat.targetTemp = temp tp.lastTemp = temp } }
func HandleOutletWithName(o uvr1611.Outlet, name string) (s *hkuvr1611.Sensor) { var found bool if s, found = sensors[name]; found == false { s = hkuvr1611.NewSensorForOutlet(o, InfoForAccessoryName(name)) if s != nil { log.Println("[INFO]", reflect.TypeOf(s.Model), "with name", name) sensors[name] = s } } else { err := hkuvr1611.UpdateAccessoryWithOutlet(s.Model, o) if err != nil { log.Println("[ERRO]", err) } } return s }
// Close closes the connection and deletes the related session from the context. func (con *HAPConnection) Close() error { log.Println("[INFO] Close connection and remove session") // Remove session from the context con.context.DeleteSessionForConnection(con.connection) return con.connection.Close() }
func (endpoint *PairVerify) ServeHTTP(response http.ResponseWriter, request *http.Request) { log.Printf("[VERB] %v POST /pair-verify", request.RemoteAddr) response.Header().Set("Content-Type", netio.HTTPContentTypePairingTLV8) key := endpoint.context.GetConnectionKey(request) session := endpoint.context.Get(key).(netio.Session) ctlr := session.PairVerifyHandler() if ctlr == nil { log.Println("[VERB] Create new pair verify controller") ctlr = pair.NewVerifyServerController(endpoint.database, endpoint.context) session.SetPairVerifyHandler(ctlr) } var err error var in util.Container var out util.Container var secSession crypto.Cryptographer if in, err = util.NewTLV8ContainerFromReader(request.Body); err == nil { out, err = ctlr.Handle(in) } if err != nil { log.Println(err) response.WriteHeader(http.StatusInternalServerError) } else { io.Copy(response, out.BytesBuffer()) // When key verification is done, switch to a secure session // based on the negotiated shared session key b := out.GetByte(pair.TagSequence) switch pair.VerifyStepType(b) { case pair.VerifyStepFinishResponse: if secSession, err = crypto.NewSecureSessionFromSharedKey(ctlr.SharedKey()); err == nil { log.Println("[VERB] Setup secure session") session.SetCryptographer(secSession) } else { log.Println("[ERRO] Could not setup secure session.", err) } } } }
func NewHomeKitService(thermostat *Thermostat) *HomeKitService { thermostatInfo := model.Info{ Name: "Thermostat", } hkThermostat := accessory.NewThermostat(thermostatInfo, temp, 17, 25, 0.5) hkThermostat.SetTargetMode(model.HeatCoolModeHeat) hkThermostat.OnTargetTempChange(func(temp float64) { log.Println("[INFO] HomeKit requested thermostat to change to", temp) thermostat.targetTemp = temp }) hkThermostat.OnTargetModeChange(func(mode model.HeatCoolModeType) { log.Println("[INFO] HomeKit requested thermostat to change to", mode) switch mode { case model.HeatCoolModeHeat: log.Println("[INFO] HomeKit setting thermostat to default on temp of", defaultOnTemp) thermostat.targetTemp = defaultOnTemp case model.HeatCoolModeOff: log.Println("[INFO] HomeKit setting thermostat to default off temp of", defaultOffTemp) thermostat.targetTemp = defaultOffTemp case model.HeatCoolModeAuto, model.HeatCoolModeCool: hkThermostat.SetTargetMode(model.HeatCoolModeHeat) } }) transport, err := hap.NewIPTransport("24282428", hkThermostat.Accessory) if err != nil { log.Fatal(err) } t := HomeKitService{ thermostat: thermostat, done: make(chan bool), hkThermostat: hkThermostat, transport: transport, } return &t }
func ExpireDevice(device common.Device) { if light, ok := device.(common.Light); ok { hkLight, _ := lights[light.ID()] light.CloseSubscription(hkLight.sub) hkLight.transport.Stop() delete(lights, light.ID()) } else { log.Println("[INFO] Unsupported Device") } }
// Server -> Client // - only sequence number // - error code (optional) func (verify *VerifyServerController) handlePairVerifyFinish(in util.Container) (util.Container, error) { verify.step = VerifyStepFinishResponse data := in.GetBytes(TagEncryptedData) message := data[:(len(data) - 16)] var mac [16]byte copy(mac[:], data[len(message):]) // 16 byte (MAC) log.Println("[VERB] -> Message:", hex.EncodeToString(message)) log.Println("[VERB] -> MAC:", hex.EncodeToString(mac[:])) decryptedBytes, err := chacha20poly1305.DecryptAndVerify(verify.session.EncryptionKey[:], []byte("PV-Msg03"), message, mac, nil) out := util.NewTLV8Container() out.SetByte(TagSequence, verify.step.Byte()) if err != nil { verify.reset() log.Println("[ERRO]", err) out.SetByte(TagErrCode, ErrCodeAuthenticationFailed.Byte()) // return error 2 } else { in, err := util.NewTLV8ContainerFromReader(bytes.NewBuffer(decryptedBytes)) if err != nil { return nil, err } username := in.GetString(TagUsername) signature := in.GetBytes(TagSignature) log.Println("[VERB] client:", username) log.Println("[VERB] signature:", hex.EncodeToString(signature)) entity := verify.database.EntityWithName(username) if entity == nil { return nil, fmt.Errorf("Client %s is unknown", username) } if len(entity.PublicKey()) == 0 { return nil, fmt.Errorf("No LTPK available for client %s", username) } var material []byte material = append(material, verify.session.OtherPublicKey[:]...) material = append(material, []byte(username)...) material = append(material, verify.session.PublicKey[:]...) if crypto.ValidateED25519Signature(entity.PublicKey(), material, signature) == false { log.Println("[WARN] signature is invalid") verify.reset() out.SetByte(TagErrCode, ErrCodeUnknownPeer.Byte()) // return error 4 } else { log.Println("[VERB] signature is valid") } } return out, nil }
func (endpoint *PairSetup) ServeHTTP(response http.ResponseWriter, request *http.Request) { log.Printf("[VERB] %v POST /pair-setup", request.RemoteAddr) response.Header().Set("Content-Type", netio.HTTPContentTypePairingTLV8) var err error var in util.Container var out util.Container key := endpoint.context.GetConnectionKey(request) session := endpoint.context.Get(key).(netio.Session) ctrl := session.PairSetupHandler() if ctrl == nil { log.Println("[VERB] Create new pair setup controller") if ctrl, err = pair.NewSetupServerController(endpoint.device, endpoint.database); err != nil { log.Println(err) } session.SetPairSetupHandler(ctrl) } if in, err = util.NewTLV8ContainerFromReader(request.Body); err == nil { out, err = ctrl.Handle(in) } if err != nil { log.Println("[ERRO]", err) response.WriteHeader(http.StatusInternalServerError) } else { io.Copy(response, out.BytesBuffer()) // Send event when key exchange is done b := out.GetByte(pair.TagSequence) switch pair.PairStepType(b) { case pair.PairStepKeyExchangeResponse: endpoint.emitter.Emit(event.DevicePaired{}) } } }
func (handler *Pairing) ServeHTTP(response http.ResponseWriter, request *http.Request) { log.Printf("[VERB] %v POST /pairings", request.RemoteAddr) response.Header().Set("Content-Type", netio.HTTPContentTypePairingTLV8) res, err := pair.HandleReaderForHandler(request.Body, handler.controller) if err != nil { log.Println(err) response.WriteHeader(http.StatusInternalServerError) } else { io.Copy(response, res) } }
// HandleReaderForHandler wraps h.Handle() call and logs sequence numbers and errors to the console. func HandleReaderForHandler(r io.Reader, h netio.ContainerHandler) (rOut io.Reader, err error) { in, err := util.NewTLV8ContainerFromReader(r) if err != nil { return nil, err } log.Println("[VERB] -> Seq:", in.GetByte(TagSequence)) out, err := h.Handle(in) if err != nil { log.Println("[ERRO]", err) } else { if out != nil { log.Println("[VERB] <- Seq:", out.GetByte(TagSequence)) rOut = out.BytesBuffer() } } log.Println("[VERB] --------------------------") return rOut, err }
func (handler *Accessories) ServeHTTP(response http.ResponseWriter, request *http.Request) { log.Printf("[VERB] %v GET /accessories", request.RemoteAddr) response.Header().Set("Content-Type", netio.HTTPContentTypeHAPJson) handler.mutex.Lock() res, err := handler.controller.HandleGetAccessories(request.Body) handler.mutex.Unlock() if err != nil { log.Println("[ERRO]", err) response.WriteHeader(http.StatusInternalServerError) } else { // Write the data in chunks of 2048 bytes // http.ResponseWriter should do this already, but crashes because of an unkown reason wr := netio.NewChunkedWriter(response, 2048) b, _ := ioutil.ReadAll(res) log.Println("[VERB]", string(b)) _, err := wr.Write(b) if err != nil { log.Println("[ERRO]", err) } } }
// EncryptedWrite encrypts and writes bytes to the connection. // The method returns the number of written bytes and an error when writing failed. func (con *HAPConnection) EncryptedWrite(b []byte) (int, error) { var buffer bytes.Buffer buffer.Write(b) encrypted, err := con.getEncrypter().Encrypt(&buffer) if err != nil { log.Println("[ERRO] Encryption failed:", err) err = con.connection.Close() return 0, err } encryptedBytes, err := ioutil.ReadAll(encrypted) n, err := con.connection.Write(encryptedBytes) return n, err }
// Publish announces the service for the machine's ip address on a random port using mDNS. func (s *MDNSService) Publish() error { ip, err := GetFirstLocalIPAddress() if err != nil { return err } log.Println("[INFO] Accessory IP is", ip) // Host should end with '.' hostname, _ := os.Hostname() host := fmt.Sprintf("%s.", strings.Trim(hostname, ".")) text := s.txtRecords() server, err := bonjour.RegisterProxy(s.name, "_hap._tcp.", "", s.port, host, ip.String(), text, nil) if err != nil { log.Fatal(err) } s.server = server return err }
// HandleGetCharacteristics handles a get characteristic request. func (ctr *CharacteristicController) HandleGetCharacteristics(form url.Values) (io.Reader, error) { var b bytes.Buffer aid, cid, err := ParseAccessoryAndCharacterID(form.Get("id")) containerChar := ctr.GetCharacteristic(aid, cid) if containerChar == nil { log.Printf("[WARN] No characteristic found with aid %d and iid %d\n", aid, cid) return &b, nil } chars := data.NewCharacteristics() char := data.Characteristic{AccessoryID: aid, ID: cid, Value: containerChar.GetValue(), Events: containerChar.EventsEnabled()} chars.AddCharacteristic(char) result, err := json.Marshal(chars) if err != nil { log.Println("[ERRO]", err) } b.Write(result) return &b, err }
// DecryptedRead reads and decrypts bytes from the connection. // The method returns the number of read bytes and an error when reading failed. func (con *HAPConnection) DecryptedRead(b []byte) (int, error) { if con.readBuffer == nil { buffered := bufio.NewReader(con.connection) decrypted, err := con.getDecrypter().Decrypt(buffered) if err != nil { log.Println("[ERRO] Decryption failed:", err) err = con.connection.Close() return 0, err } con.readBuffer = decrypted } n, err := con.readBuffer.Read(b) if n < len(b) || err == io.EOF { con.readBuffer = nil } return n, err }
// Server -> Client // - B: server public key // - signature: from server session public key, server name, client session public key func (verify *VerifyServerController) handlePairVerifyStart(in util.Container) (util.Container, error) { verify.step = VerifyStepStartResponse clientPublicKey := in.GetBytes(TagPublicKey) log.Println("[VERB] -> A:", hex.EncodeToString(clientPublicKey)) if len(clientPublicKey) != 32 { return nil, errInvalidClientKeyLength } var otherPublicKey [32]byte copy(otherPublicKey[:], clientPublicKey) verify.session.GenerateSharedKeyWithOtherPublicKey(otherPublicKey) verify.session.SetupEncryptionKey([]byte("Pair-Verify-Encrypt-Salt"), []byte("Pair-Verify-Encrypt-Info")) device := verify.context.GetSecuredDevice() var material []byte material = append(material, verify.session.PublicKey[:]...) material = append(material, device.Name()...) material = append(material, clientPublicKey...) signature, err := crypto.ED25519Signature(device.PrivateKey(), material) if err != nil { log.Fatal(err) return nil, err } // Encrypt encryptedOut := util.NewTLV8Container() encryptedOut.SetString(TagUsername, device.Name()) encryptedOut.SetBytes(TagSignature, signature) encryptedBytes, mac, _ := chacha20poly1305.EncryptAndSeal(verify.session.EncryptionKey[:], []byte("PV-Msg02"), encryptedOut.BytesBuffer().Bytes(), nil) out := util.NewTLV8Container() out.SetByte(TagSequence, verify.step.Byte()) out.SetBytes(TagPublicKey, verify.session.PublicKey[:]) out.SetBytes(TagEncryptedData, append(encryptedBytes, mac[:]...)) log.Println("[VERB] K:", hex.EncodeToString(verify.session.EncryptionKey[:])) log.Println("[VERB] B:", hex.EncodeToString(verify.session.PublicKey[:])) log.Println("[VERB] S:", hex.EncodeToString(verify.session.PrivateKey[:])) log.Println("[VERB] Shared:", hex.EncodeToString(verify.session.SharedKey[:])) log.Println("[VERB] <- B:", hex.EncodeToString(out.GetBytes(TagPublicKey))) return out, nil }
// Client -> Server // - A: entity public key // - M1: proof // // Server -> entity // - M2: proof // or // - auth error func (setup *SetupServerController) handlePairVerify(in util.Container) (util.Container, error) { setup.step = PairStepVerifyResponse out := util.NewTLV8Container() out.SetByte(TagSequence, setup.step.Byte()) clientPublicKey := in.GetBytes(TagPublicKey) log.Println("[VERB] -> A:", hex.EncodeToString(clientPublicKey)) err := setup.session.SetupPrivateKeyFromClientPublicKey(clientPublicKey) if err != nil { return nil, err } clientProof := in.GetBytes(TagProof) log.Println("[VERB] -> M1:", hex.EncodeToString(clientProof)) proof, err := setup.session.ProofFromClientProof(clientProof) if err != nil || len(proof) == 0 { // proof `M1` is wrong log.Println("[WARN] Proof M1 is wrong") setup.reset() out.SetByte(TagErrCode, ErrCodeAuthenticationFailed.Byte()) // return error 2 } else { log.Println("[INFO] Proof M1 is valid") err := setup.session.SetupEncryptionKey([]byte("Pair-Setup-Encrypt-Salt"), []byte("Pair-Setup-Encrypt-Info")) if err != nil { return nil, err } // Return proof `M2` out.SetBytes(TagProof, proof) } log.Println("[VERB] <- M2:", hex.EncodeToString(out.GetBytes(TagProof))) log.Println("[VERB] S:", hex.EncodeToString(setup.session.PrivateKey)) log.Println("[VERB] K:", hex.EncodeToString(setup.session.EncryptionKey[:])) return out, nil }