Saturday, October 27, 2018

Attaching a Bluetooth keyboard to a NetBSD machine

I am FINALLY able to use my Apple Bluetooth keyboard with NetBSD! I am writing this blog post right now using it. The NetBSD Guide helped me a LOT with this, but I believe it requires a little bit of updating… so in the meantime, let me show you how I did it.

Overall strategy

  • Enable the Bluetooth system service.
  • Figure out what your machine’s Bluetooth device node is called.
  • Put your keyboard into discover mode.
  • Figure out what your keyboard’s Bluetooth address is.
  • Register a temporary PIN to be used when pairing the keyboard.
  • Type the PIN in with the keyboard.
  • Attach the device.

In detail:

Enable the Bluetooth system service.

This is simply adding “bluetooth=YES” in your rc.conf and then turning it on with sudo service bluetooth start.

Figure out what your machine’s Bluetooth device node is called.

That’s just a matter of dmesg. We are interested in finding out where a Bluetooth remote device hub (bthub(4)) has set itself up:

$ dmesg | grep bthub
[    15.588860] bthub0 at ubt0 local-bdaddr 48:45:20:52:f6:60

ubt0 is where our Bluetooth remote device hub is located. That’s the part we’re interested in. We’ll make a note of it.

Put your keyboard into discover mode.

In the case of my keyboard from Apple, that means pressing and holding the power button until the status light blinks. When that happens, the keyboard will be discoverable when my laptop’s Bluetooth device tries to discover it (and anything else in the vicinity).

Figure out what your keyboard’s Bluetooth address is.

Apparently, the technical term for “discover all the discoverables” is actually an “inquiry.”

$ btconfig ubt0 inquiry
Device Discovery from device: ubt0 ... 3 responses
  1: bdaddr e4:8b:7f:2e:bb:60
   : name "Apple Keyboard"
   : class [0x002540] Peripheral Keyboard <Limited Discoverable>
   : page scan rep mode 0x01
   : clock offset 31094
   : rssi 0

  2: bdaddr b0:67:2f:00:54:ff
   : name "Audio Device"
   : class [0x080428] HiFi Audio <Capturing>
   : page scan rep mode 0x01
   : clock offset 23232
   : rssi 0

  3: bdaddr 60:6b:bd:c2:89:de
   : name "DTVBluetooth"
   : class [0x08043c] Video Display and Loudspeaker <Capturing>
   : page scan rep mode 0x01
   : clock offset 24943
   : rssi 0

I’m interested in the first device, the keyboard with the BDADDR “e4:8b:7f:2e:bb:60”. At this stage, we can register an alias or “nickname” for this device, so that we don’t have remember the address:

 $ sudo echo e4:8b:7f:2e:bb:60 CharlotteAppleKeyboard >> /etc/bluetooth/hosts

Register a temporary PIN to be used when pairing the keyboard.

The btpin command sets up a number to be typed in. I typed the number on my Bluetooth keyboard and pressed ENTER.

$ btpin -d ubt0 -a CharlotteAppleKeyboard -r -P
PIN: (numbers)
Pairing.. done

Pairing is done. Nice!

Attach the device.

The btdevctl -A command will do that for us.

$ sudo btdevctl -d ubt0 -a CharlotteAppleKeyboard -s HID -A

You can confirm that the device has attached as a keyboard (rather than something else) by inspecting /var/log/messages or dmesg. This is the third keyboard attached to my laptop (my laptop’s own keyboard and a USB keyboard were already attached). So the fact that it’s wskbd2 makes sense:

Oct 27 10:26:53 sakuracity /netbsd: [ 510454.1260370] btkbd0 at bthidev0 reportid 1
Oct 27 10:26:53 sakuracity /netbsd: [ 510454.1260370] wskbd2 at btkbd0 mux 1
Oct 27 10:26:53 sakuracity /netbsd: [ 510454.1260370] wskbd2: connecting to wsdisplay0

At this point you can try typing! That’s what I’m doing right now!

Unfortunately, there are a few shortcomings with this keyboard. For example, The media keys don’t work. Volume up, volume down, you name it. Page up and page down, even. All of these nonworking keys are “function” keys (not F1-F12, but, like, “extended” functionality) and none of them work because every time you press the Fn key, this happens:

[ 512317.5222648] bthidev0: autoconfiguration error: report id 17, len = 1 ignored

Not sure what that’s all about, but I’m willing to dig deeper into it.


So, the instructions here are NOT exactly what is detailed in the NetBSD Guide. I (or someone) should fix that.

Also, I’ve been inspired to write a tool or two which makes this process A LOT simpler. I feel like this should be a task that requires 1 command rather than 3 or 4. I also believe it would be useful to automate maintaining /etc/bluetooth/hosts somehow.

Thursday, October 11, 2018

Porting Keybase to NetBSD

Keybase significantly simplifies the whole keypair/PGP thing and makes what is usually a confusing, difficult experience actually rather pleasant. At its heart is an open-source command line utility that does all of the heavy cryptographic lifting. But it's also hooked up to the network of all other Keybase users, so you don't have to work very hard to maintain big keychains. Pretty cool!

So, this evening, I tried to get it to all work on NetBSD.

The Keybase client code base is, in my opinion, not very well architected... there exist many different Keybase clients (command line apps, desktop apps, mobile apps) and for some reason the code for all of them are seemingly in this single repository, without even using Git submodules. Not sure what that's about.

Anyway, "go build"-ing the command line program (it's written in Go) failed immediately because there's some platform-specific code that just does not seem to recognize that NetBSD exists (but they do for FreeBSD and OpenBSD). Looks like the Keybase developers maintain a Golang wrapper around struct proc, which of course is different from OS to OS. So I literally just copypasted the OpenBSD wrapper, renamed it to "NetBSD", and the build basically succeeded from there! This is of course super janky and untrustworthy, but it seems to Mostly Just Work...

I forked the GitHub repo, you can see the diff on top of keybase 2.7.3 here: bccaaf3096a

Eventually I ended up with a ~/go/bin/keybase which launches just fine. Meaning, I can main() okay. But the moment you try to do anything interesting, it looks super scary:

charlotte@sakuracity:~/go/bin ./keybase login
▶ WARNING Running in devel mode
▶ INFO Forking background server with pid=12932
▶ ERROR unexpected error in Login: API network error: doRetry failed,
attempts: 1, timeout 5s, last err: Get
dial tcp [::1]:3000: connect: connection refused

There's a few things about this error message that stuck out to me:

  • Forking a background server? What?
  • It's trying to connect to localhost? That must be the server that doesn't work ...

Unfortunately, this nonfunctional "background server" sticks around even when a command as simple as 'login' command just failed:

charlotte@sakuracity:~/go/bin ps 12932
  12932 ?   Ssl  0:00.21 ./keybase --debug --log-file
  /home/charlotte/.cache/keybase.devel/keybase.service.log service --chdir
  /home/charlotte/.config/keybase.devel --auto-forked 

I'm not exactly sure what the intended purpose of the "background server" even is, but fortunately we can kill it and even tell the keybase command to not even spawn one:

charlotte@sakuracity:~/go/bin ./keybase help advanced | grep -- --standalone
   --standalone                         Use the client without any daemon support.

And then we can fix wanting to connect to localhost by specifying an expected Keybase API server -- how about the one hosted at

charlotte@sakuracity:~/go/bin ./keybase help advanced | grep -- --server
   --server, -s                         Specify server API.

Basically, what I'm trying to say is that if you specify both of these options, the keybase command does what I expect on NetBSD:

charlotte@sakuracity:~/go/bin ./keybase --standalone -s login
▶ WARNING Running in devel mode
Please enter the Keybase passphrase for dressupgeekout (6+ characters): 

charlotte@sakuracity:~/go/bin ./keybase --standalone -s id dressupgeekout
▶ WARNING Running in devel mode
▶ INFO Identifying dressupgeekout
✔ public key fingerprint: 7873 DA50 A786 9A3F 1662 3A17 20BD 8739 E82C 7F2F
✔ "dressupgeekout" on github: [cached 2018-10-11
20:55:21 PDT]
✔ "dressupgeekout" on reddit:
[cached 2018-10-11 20:55:21 PDT]

Hey, that's pretty cool!

I verified that signing data works:

charlotte@sakuracity:~/go/bin echo "SOYLENT GREEN IS PEOPLE" > /tmp/secret.txt

charlotte@sakuracity:~/go/bin ./keybase --standalone -s sign -i /tmp/secret.txt -o /tmp/secret.signed.txt 
▶ WARNING Running in devel mode
charlotte@sakuracity:~/go/bin cat /tmp/secret.signed.txt 

And verifying that signature works:

charlotte@sakuracity:~/go/bin ./keybase --standalone -s verify -i /tmp/secret.signed.txt 
▶ WARNING Running in devel mode
Signed by dressupgeekout (you).

But unfortunately, encrypting data (and I guess decrypting it, too) is not functional at this time:

charlotte@sakuracity:~/go/bin ./keybase --standalone -s encrypt -i ~/pictures/random/unicorn.jpg -o /tmp/unicorn.jpg.encrypted dressupgeekout
▶ WARNING Running in devel mode
▶ ERROR Can't run command in standalone mode

But you can't turn off standalone mode because then we're back to where we started:

charlotte@sakuracity:~/go/bin ./keybase -s encrypt -i ~/pictures/random/unicorn.jpg -o /tmp/unicorn.jpg.encrypted dressupgeekout
▶ WARNING Running in devel mode
▶ INFO Forking background server with pid=4222
▶ ERROR Keybase services aren't running - KBFS client not found.

It is kinda cool that some of the interesting functionality of Keybase does work on NetBSD though!

New blog for technical writings

Hey gang, this is Charlotte. And I decided that Tumblr wasn't exactly the best place to do technical writing after all. Like, talking about open source and BSD and multimedia science and all of that. So, enjoy! And I do promise to update this from time to time!