setSecurity not working as expected

Posted on
  • I am trying to get some sort of proof that there is any security things happening at all. Most notably is that there is no prompt for a pin at any point.

    Here is all the code I am uploading to my puck.js although I don't think anything but the first line(obviously copy pasted from the docs) is relevant.

    NRF.setSecurity({passkey:"123456", mitm:1, display:1});
    NRF.setServices({
      0xabcd : {
        0xAB40 : {
          value : "Hello",
          maxLen : 50,
          notify: true
        },
        0xAB41 : {
          value : "Hello",
          maxLen : 50,
          notify: true,
          security: {
            read: {
              encrypted: true,
              mitm: true,
              lesc: true,
              signed: false
            }
          }
        }
      }
    }, {advertise: [ 0xabcd ]});
    var  on = false;
    setWatch(function(e) {
      on = !on;
      LED1.write(on);
      var pressTime = e.time - e.lastTime;
      NRF.updateServices({
        0xBC10 : {
          0xAB40 : {
            value : "time: " + e.time,
            notify: true
          },
          0xAB41 : {
            value : "lastTime: " + e.lastTime,
            maxLen : 50,
            notify: true
          },
        }
      });
    }, BTN, { repeat:true, edge:"falling", debounce: 50 });
    

    Puck js is updated to 2v04.

  • Hi, I've just looked into this, and I found that there was an issue inside the Bluetooth stack where sometimes the keys used for secure pairing weren't aligned on word boundaries.

    Unfortunately it looks like the Puck.js 2v04 build was one of those builds - passkey pairing would have failed and you should have been unable to access characteristic AB41. If you try a cutting edge build from http://www.espruino.com/binaries/travis/master/ then it should now be fine.

    However while at that point Android will request a passkey if you connect using the OS's menu, if you go through NRF Connect it won't. It will only require the passkey either when you explicitly try to bond, or when you try to access the 0xAB41 characteristic that you specified security for. I'll update the docs to reflect that.

  • The espruino_2v04_puckjs.zip file is not working for me. I even went and installed 2v03 to make sure it was not updating and that I was doing it properly. 2v03 worked just fine. That master branch version of 2v04 does not. The NRF Connect app says "Starting DFU" then immediately says "disconnecting..."

    I also wanted to say that I am using web-bluetooth to connect to the characteristic. Here is my code for that:

    connectClick(event) {
            console.log('clicked', event);
            navigator.bluetooth.requestDevice({
                filters: [{
                    services: [0xabcd],
                  }]
            })
            .then(device => {
                console.log("requested", device);
                return device.gatt.connect();
            })
            .then(server => {
                console.log('got server', server);
                return server.getPrimaryService(0xabcd);
            })
            .then(service => {
                console.log('got service', service);
    
                service.getCharacteristic(0xAB40).then(characteristic => {
                    this.startListeningForTime(characteristic);
                });
                service.getCharacteristic(0xAB41).then(characteristic => {
                    this.startListeningForTime(characteristic);
                }).catch(error => {
                    console.log('error', error);
                })
            })
        }
    
        handleCharacteristicValueChanged(event) {
            var enc = new TextDecoder("utf-8");
            var value = event.target.value;
            console.log('Received ' + enc.decode(value))
            // TODO: Parse Heart Rate Measurement value.
            // See https://github.com/WebBluetoothCG/demos/blob/gh-pages/heart-rate-sensor/heartRateSensor.js
        }
    
        startListeningForTime(characteristic) {
            characteristic.startNotifications()
            .then(char => {
                console.log('notification started', char)
                // Writing 1 is the signal to reset energy expended.
                char.addEventListener('characteristicvaluechanged', this.handleCharacteristicValueChanged.bind(this));
            })
        }
    

    Just wanted to make sure that I should not be able to access that without entering a passkey if it is working.

  • Sorry about that, there was a problem with the build - try now and it should update ok:

    http://www.espruino.com/binaries/travis/master/

    It's possible that you just won't get notifications on the characteristic? What happens if you try to read it?

    You could also try adding 'write':

    security: {
            read: {
              encrypted: true,
              mitm: true,
              lesc: true,
              signed: false
            },  write: {
              encrypted: true,
              mitm: true,
              lesc: true,
              signed: false
            }
          }
    

    It's possible that what's happening is the characteristic is still allowing writes which allow you to turn on notifications - that's something that should probably be fixed in firmware (to automatically stop writes if read is set to require encryption).

  • Now http://www.espruino.com/binaries/travis/­master/ does not even have a file for puck js.

  • Looks like there was a build glitch.
    Totally untested, but you can try the attached build :)


    1 Attachment

  • It's fixed now thanks to @AkosLukacs so the files will be back in http://www.espruino.com/binaries/travis/­master/

  • That did the trick. Much appreciated!

  • I would like to open this back up. I am not sure this is working properly. It is now prompting me for the passkey on mac os and android(using the nrf connect app). In Mac when I enter the key it gives me an "unkown error" and on the NRF connect app it acctually disconnects me from the puck when I enter the passkey.

    My current code is :

    NRF.setSecurity({passkey:"123456", mitm:1, display:1});
    NRF.setServices({
      0xabcd : {
        0xAB40 : {
          value : "Hello",
          maxLen : 50,
          notify: true,
          readable: true,
          writable: true,
        },
        0xAB41 : {
          value : "Hello",
          maxLen : 50,
          notify: true,
          readable: true,
          writable: true,
          security: {
            read: {
              encrypted: true,
              passkey:"123456",
              mitm: true,
              lesc: true,
              signed: false
            },  write: {
              encrypted: true,
              passkey:"123456",
              mitm: true,
              lesc: true,
              signed: false
            }
          }
        }
      }
    }, {advertise: [ 0xabcd ]});
    var  on = false;
    setWatch(function(e) {
      on = !on;
      LED1.write(on);
      var pressTime = e.time - e.lastTime;
      NRF.updateServices({
        0xabcd : {
          0xAB40 : {
            value : "time: " + e.time,
            notify: true
          },
          0xAB41 : {
            value : "lastTime: " + e.lastTime,
            maxLen : 50,
            notify: true
          },
        }
      });
    }, BTN, { repeat:true, edge:"falling", debounce: 50 });
    

    everything works fine on characteristic 0xAB40 but I cannot get the secure 0xAB41 characteristic to work. Please advice.

  • It is now prompting me for the passkey on mac os and android

    But it was working? Did you change anything?

    Can you try just fully restarting the Mac? I know it seems dumb but it has been an issue before that the Bluetooth stack gets confused.

  • I don't think it was ever working. When I said it was working it is because the passkey prompt popped up. I was never able to connect to it. I thought I was reproducing a reported Web Bluetooth bug in Chrome. However, when I dug further I found the issue was in the call to Core Bluetooth. I have now made a standalone Objective C OSX application that uses core bluetooth to connect and I am still getting the error. I then tried it on the NRF Connect app and it did not work there. I also tried through Chrome's web bluetooth on Windows and it did not work there either. This is leading me to believe the issue might be in the Puck.

    I did restart my Mac and try again and I am still not able to connect to the protected characteristic.

  • Ping

  • Just spend a few hours looking into this. If you'd put setSecurity after setServices it would have worked I believe, although there are some other issues.

    • passkey:"123456" isn't valid in setServices
    • If you specify lesc: true but then don't have it in setSecurity then it'll bond but you still won't be able to access
    • I don't believe the passkey is good enough for lesc - at least pairing with then enabled fails

    So if you do the following, you should be good:

    NRF.setServices({
      0xabcd : {
        0xAB40 : {
          value : "Hello",
          maxLen : 50,
          notify: true,
          readable: true,
          writable: true,
        },
        0xAB41 : {
          value : "Hello",
          maxLen : 50,
          notify: true,
          readable: true,
          writable: true,
          security: {
            read: {
              encrypted: true,
              mitm: true
            }, write: {
              encrypted: true,
              mitm: true
            }
          },
          onWrite : function(evt) { // optional
            console.log("Written ", evt.data); // an ArrayBuffer
          }
        }
      }
    }, {advertise: [ 0xabcd ]});
    NRF.setSecurity({passkey:"123456", mitm:1, display:1});
    NRF.on('disconnect',x=>print('disconnect',x));
    NRF.on('connect',x=>print('connect',x));
    
  • I'll get a new firmware out in the next few minutes that has the issue with ordering fixed though

  • Thanks for looking into this Gordon! How are you testing that this is working? I am using the NRFConnect app as a source of truth. I uploaded your code to my puck and tried to get the secure characteristic from that app and once I entered the passkey it just disconnects(same as before). I am also trying on an objective-c core bluetooth application I wrote to test connecting to the app and I get an "unknown error" after I type in the passkey(also, same as before). I am wondering what you are using to show that is does work as intended? I will try again with the new firmware.

  • Ok it is all working now with the newest firmware. Thanks a million Gordon I really appreciate it.

    ps. That watch is awesome!

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

setSecurity not working as expected

Posted by Avatar for jameshollyer @jameshollyer

Actions