Skip to content
Flomio edited this page Jul 18, 2020 · 79 revisions

Steps to setup RPi0 with Zymkey SE

Setting up the RaspberryPi Zero is not as straight forward as you would think. Mainly because we opt for using the Raspbian Buster Lite and it's terminal only interface can make it difficult to know all the commands needed. So this will serve as a quick reference.

Use Cloned SDcard Image to Skip Below

  • Use BalenaEtcher to flash passninja-image-with-zymkey.gz or use te command line:
    • diskutil list to see the disk names
    • append r to the disk name found. points to the card’s raw storage space to speed up process
    • gzip -dc /Users/rgrundy/Documents/personal/workspace/rpi0/passninja-image-with-zymkey-eth-gadget.gz | sudo dd of=/dev/rdisk1 bs1m
  • takes about 25mins
  • Place SDCard and Zymkey 4i (no battery) onto RPi0 without perimeter circuit
  • Zymkey Phase 2: Encrypt the boot file system with USB stick and enable LUKS here
    • make sure no data lines are soldered to RPi USB OTG port (causes usb 1-1: device descriptor read/64, error -71)
    • make sure on USB slave device settings in /boot/cmdline.txt and /boot/config.txt
    • setup wifi and ssh into RPi as root
    • alias: enc -- reboots automatically --
    • alias: st -- pgrep chained into strace for status monitoring
    • df -h to check cfg_SD_crfs.sh progress as well
    • nano /etc/hostname : scanterminal
    • nano /etc/hosts : 127.0.1.1 scanterminal <--- This should be permanently put in SDcard image
    • usermod -l NEW_USERNAME customer
    • groupmod customer -n NEW_USERNAME
    • systemctl enable tampercheck.service
    • systemctl enable passninja.service
    • systemctl start passninja.service
    • journalctl -f -u passninja.service - verify scans
alias enc='curl -G https://s3.amazonaws.com/zk-sw-repo/mk_encr_sd_rfs.sh | sudo bash'
alias st='pgrep -f cfg_SD_crfs.sh | xargs strace -s9999 -e write -p'
alias ld='systemctl list-unit-files |grep -e "passninja\|tampercheck"'
alias epn='systemctl enable passninja.service'
alias bpn='systemctl start passninja.service'
alias btc='systemctl start tampercheck.service'
alias cpn='journalctl -f -u passninja.service'
alias ctc='journalctl -f -u tampercheck.service'
alias fpn='systemctl stop passninja.service'
alias ftc='systemctl stop tampercheck.service'
alias stc='systemctl status tampercheck.service'
alias spn='systemctl status passninja.service'
alias log='more /var/log/syslog'
alias lsd='fdisk -l'
  • optional: mv /home/customer /home/NEW_USERNAME
  • optional: nano /etc/passwd
    • edit NEW_USERNAME account to point to /home/NEW_USERNAME
  • add Wifi of new user here
    • sudo nmap -sS -p 22 172.168.10.0/24
  • configure USB slave device here
  • if USB terminal access malfunctioning because Bonjour missing on PC, you can add fixed IP address by editing sudo nano /etc/network/interfaces to add following:
allow-hotplug usb0
iface usb0 inet static
        address 192.168.7.2
        netmask 255.255.255.0
        network 192.168.7.0
        broadcast 192.168.7.255
        gateway 192.168.7.1
  • Power down, place Zymkey 4i with perimeter circuit and boot up

Download latest image from web

Use Etcher to flash into SDcard

  • Download Balena Etcher from here.
  • Install Etcher and launch.
  • Select the downloaded image zip file.
  • Select a Drive (Use an SDcard with micro SDcard, insert on right side of Macbook) and select.
  • Click on "Flash!".

Boot RPi as slave device

  • mount boot partition MacOSX
  • edit config.txt put at end of file: dtoverlay=dwc2
  • edit cmdline.txt put after =1000: modules-load=dwc2,g_ether
  • create empty ssh file
  • plug in RPi0 as a slave device to MacOSX laptop
  • ssh passninja@scanterminal.local

Boot RPi as master device

  • Slide micro SDcard into RPi with the metal contacts facing the PCB (Printed Circuit Board).
  • Connect RPi to a monitor via HDMI cable
  • Connect USB keyboard to RPi
  • Apply USB power to the RPi
  • Wait for boot to complete and login with user: pi; pwd: raspberry

Change password

$ passwd
Changing password for pi.
(current) UNIX password: raspberry
Enter UNIX password: pi2$PI
Retype UNIX password: pi2$PI
passwd: password updated successfully

Setup keyboard for US

  • Change keyboard layout
$ sudo vi /etc/default/keyboard

set -> XKBLAYOUT="us"
  • Reboot RPi
$ sudo reboot

Setup WiFi and USB tethering

Details about a Wifi driver issue and fix with Raspbian: https://github.com/flomio/passninja-cli/issues/59

$ sudo nano /etc/dhcpcd.conf
interface wlan0
env ifwireless=1
env wpa_supplicant_driver=wext,nl80211

$ sudo iwlist wlan0 scan | more // may not be needed if you already know the SSID
$ sudo vi /etc/wpa_supplicant/wpa_supplicant.conf

network={
    ssid="RichardsiPhone"
    psk="123456789+"
}
network={
    ssid="Casa Bahia Condo"
    proto=RSN
    key_mgmt=WPA-EAP
    pairwise=CCMP
    auth_alg=OPEN
    eap=MSCHAPV2
    identity="Unit-6"
    password="1zy#+AeO2K"
}

$ sudo wpa_cli -i wlan0 reconfigure
Selected interface 'wlan0'
OK
$ systemctl stop wpa_supplicant && killall wpa_supplicant // for debugging connectivity issues with wpa_supplicant
$ wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant.conf -Dwext,nl80211 -iwlan0 // verify CTRL-EVENT-CONNECTED
$ apt-get update
$ apt-get install gvfs ipheth-utils libimobiledevice-utils gvfs-backends gvfs-bin gvfs-fuse ifuse usbmuxd
$ vi /etc/network/interfaces

#iface eth0 inet manual
allow-hotplug eth0
iface eth0 inet dhcp

$ sudo reboot
$ ping google.com

Setup SSH for remote login and I2C for Zymkey SE

$ sudo raspi-config
Interfacing Options
SSH
Yes
Ok
I2C
Yes
Ok
Finish

Install Zymbit hardware

Follow these steps to place Zymkey on proper pins. Once in place continue:

$ sudo reboot
$ ifconfig
wlan0 inet addr:"IPAddress"

From remote computer
$ ssh pi@"IPAddress"

Install Zymbit services

$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install python-pip

if keys not found, do this:

$ sudo gpg --keyserver keys.gnupg.net --recv-key _missing_key_
$ sudo gpg -a --export _missing_key_ | sudo apt-key add -

Now you can continue installing Zymkey and LUKS/dm-crypt with apt-get (20mins)

curl -G https://s3.amazonaws.com/zk-sw-repo/install_zk_sw.sh | sudo bash
# this will reboot but need check progress after reboot before next step
# should see Zymkey binding (led 0.33Hz) and `sudo journalctl -u zkbootrtc.service` no errors
# insert blank USB flash drive of 16GB+ for next step

curl -G https://s3.amazonaws.com/zk-sw-repo/mk_encr_sd_rfs.sh | sudo bash
# this will reboot (phase 1 complete, running from USB)

# check progress using `df -h` iteratively, watch cryptfs fill to 1.8GB
# this will reboot (phase 2 complete, running from encrypted SDcard, Zymkey LED should blink 1 every 3secs)

You can now cut the Zymkey fuse tab and insert the coincell battery

Install NodeJs and other useful packages

$ wget https://nodejs.org/dist/v8.16.0/node-v8.16.0-linux-armv6l.tar.xz
## Follow https://github.com/nodejs/help/wiki/Installation with VERSION=v8.16.0 and DISTRO=linux-armv6l

$ sudo apt-get install -y build-essential netatalk git libusb-dev libusb-1.0-0-dev libudev-dev
$ sudo apt-get install -y bluetooth bluez libbluetooth-dev libudev-dev mercurial cmake

Setup ACS Drivers and PCSCLite

$ git clone https://github.com/acshk/acsccid.git
$ cd acsccid
$ sudo apt-get install -y perl flex pkg-config libusb-1.0-0-dev automake gettext libtool pcscd libpcsclite1 libpcsclite-dev
$ ./bootstrap
$ ./configure
$ make
$ sudo make install
$ sudo vi /usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/Info.plist
change to have:
        <key>ifdDriverOptions</key>
        <string>0x0001</string>

Install PassNinja

First we need to prepare the passninja-rpi-toolchain on our development laptop. For this we will need to install Docker. Next we need to clone and build the toolchain:

$ git clone https://github.com/flomio/passninja-rpi-toolchain.git
$ cd passninja-rpi-toolchain && mkdir rootfs && ./build_docker.sh && ./run_docker.sh

Now from within the Docker instance:

$ rsync -vR --progress -rl --delete-after --safe-links passninja@192.168.1.64:/{lib,usr,etc/ld.so.conf.d,opt/vc/lib} /home/develop/rootfs/
$
$ git config --global user.email "richard@flomio.com"
$ git config --global user.name "Richard Grundy"
$ git config --global credential.helper 'cache'  # this will cache creds for 15mins
$ git clone https://github.com/flomio/passninja-cli.git
$ cd passninja-cli && git checkout remove-xpc && npm i && npm run build

Now from the RPi:

$ sudo su 
$ cp -R out /root/passninja && cd /root/passninja
$ vi passninja.service

[Unit]
Description=Passninja Scan Terminal service
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
RestartSec=1
User=root
ExecStart=/usr/local/bin/node /root/passninja/pn.js scan --http --config /home/customer/config.json
Restart=always

[Install]
WantedBy=multi-user.target

$ sudo cp -f /root/passninja/passninja.service /lib/systemd/system/
$ sudo chmod 644 /lib/systemd/system/passninja.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable passninja.service
Created symlink from /etc/systemd/system/multi-user.target.wants/passninja.service to /lib/systemd/system/passninja.service.
$ sudo systemctl start passninja.service  ## start daemon
$ sudo systemctl status passninja.service ## check status
$ sudo systemctl stop passninja.service  ## stop daemon
$ sudo journalctl -f -u passninja.service ## check logs

You can now plug in FloBLE Mini module and scan PassNinja demo passes

Create Customer Account

While logged in as root, create user accounts with passninja config.json file:

$ adduser username
set default password to be `new.user`
$ login username
$ vi config.json
{
  "httpUrl": "http://localhost:3000/fancy/path",
  "passTypeId": "pass.com.passninja.demo.boardingPass",
  "collectorId": 77501435
}

Add basic tools for verifying passninja POST functionality:

$ vi .profile

# Nodejs
VERSION=v8.16.0
DISTRO=linux-armv6l
export PATH=/usr/local/lib/nodejs/node-$VERSION-$DISTRO/bin:$PATH

$ source .profile
$ wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip
$ unzip ngrok-stable-linux-arm.zip && rm ngrok-stable-linux-arm.zip
$ mkdir simple-express-server && cd simple-express-server && npm init 

package name: (simple-express-server)
version: (1.0.0)
description: listens for a POST request
entry point: (index.js)
test command:
git repository:
keywords:
author: Richard Grundy
license: (ISC)

$ npm install express body-parser nodemon --save
$ vi index.js

const express = require('express')
const bodyParser = require('body-parser');

const app = express()
const port = 3000

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get('/', (req, res) => res.send('Express is alive'))
app.post('/fancy/path',function(request,response){
  var body=request.body;
  console.log("Body: %j",body);
  response.end("received");
});

app.listen(port, () => console.log(`Express app listening on port ${port}!`))

To test you can run:

  • details in simple-express-server ./node_modules/nodemon/bin/nodemon.js index.js
  • simpler in home dir node simple-express-server

Create a concealed Passninja account and Cleanup

In order to remotely manage the reader terminals to support customer needs we install a service account. We will do so without a home directory to conceal it's identity.

$ sudo su
$ useradd -d /home passninja
$ usermod -aG sudo passninja
$ passwd passninja

Now that we have everything in place, you should be able to plug in a FloBLE Plus reader, scan demo passes, and see POST requests received on the username account. Now that this is done, you can delete the original pi account. SSH in with the newly created passninja account:

$ ssh passninja@192.168.1.64
$ sudo su
$ userdel -r pi

Retest to make sure nothing broke as a result.

Add GPIO Control

$ apt-get install wiringpi // this is for gpio terminal command (debugging)
$ cd simple-express-server && vi index.js

const gpio = require('rpi-gpio');
const express = require('express');
 : 
  response.end("received");
  if (body.message == "286205e7-d281-4a48-84ff-64c50789e0f3") {
    setTimeout(function() {
      gpio.write(18, true, function(err) {
        if (err) throw err;
        console.log('GPIO is being set HIGH for 2 seconds');
      });
    }, 2000);
  }
 :
// +-----+-----+---------+------+---+-Pi ZeroW-+---+------+---------+-----+-----+
// | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
// +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
// |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
// |   2 |   8 |   SDA.1 |  OUT | 1 |  3 || 4  |   |      | 5v      |     |     |
// |   3 |   9 |   SCL.1 |  OUT | 1 |  5 || 6  |   |      | 0v      |     |     |
// |   4 |   7 | GPIO. 7 |  OUT | 0 |  7 || 8  | 0 | IN   | TxD     | 15  | 14  |
// |     |     |      0v |      |   |  9 || 10 | 1 | IN   | RxD     | 16  | 15  |
// |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 1 | IN   | GPIO. 1 | 1   | 18  |
// |  27 |   2 | GPIO. 2 |   IN | 1 | 13 || 14 |   |      | 0v      |     |     |

gpio.setMode(gpio.MODE_BCM); //set GPIO numbering to match Broadcom chip labels
gpio.on('change', toggle);   //register callback on GPIO change event
gpio.setup(18, gpio.DIR_IN, gpio.EDGE_RISING, confirm); // GPIO that you will toggle

function confirm(err) {
  if (err) throw err;
  // write your setup logic here
}

function toggle(channel, value) {
  // write your toggle LOW logic here
  gpio.write(18, false, function(err) {
    if (err) throw err;
    console.log('GPIO is being set LOW');
  });
}

$ cd .. && sudo adduser customer gpio

Install CAM Lock Control

$ git clone https://github.com/flomio/lock-control-node.git
$ git checkout car-door
$ npm install
$ sudo cp -f /home/pi/lock-control-node/lock-control-node.service /lib/systemd/system/
$ sudo chmod 644 /lib/systemd/system/lock-control-node.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable lock-control-node.service
$ sudo systemctl start lock-control-node.service  ## start daemon
$ sudo journalctl -f -u lock-control-node.service ## check logs