From e0adc3df651dca07ce8ce43602d87728e4d6eab0 Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Thu, 18 Apr 2024 10:59:29 +0100 Subject: [PATCH] Add the things needed for the host to the demo. --- demos/2024-04-23-cheritech/morello/README.txt | 139 ++++++++++++++++++ .../morello/home/demo/.minirc.dfl | 9 ++ .../morello/home/demo/audit.sh | 21 +++ .../morello/home/demo/script/cheri.js | 87 +++++++++++ .../morello/home/demo/script/compile.sh | 5 + .../morello/home/demo/script/demo.js | 109 ++++++++++++++ .../morello/opt/etc/mosquitto/certs/cert.pem | 11 ++ .../morello/opt/etc/mosquitto/certs/key.pem | 5 + .../morello/opt/etc/mosquitto/mosquitto.conf | 8 + .../morello/usr/local/etc/ntpd.conf | 13 ++ .../morello/usr/local64/etc/dhcpd.conf | 22 +++ .../usr/local64/etc/namedb/db.cheriot.demo | 10 ++ .../usr/local64/etc/namedb/db.pool.ntp.org | 11 ++ 13 files changed, 450 insertions(+) create mode 100644 demos/2024-04-23-cheritech/morello/README.txt create mode 100644 demos/2024-04-23-cheritech/morello/home/demo/.minirc.dfl create mode 100755 demos/2024-04-23-cheritech/morello/home/demo/audit.sh create mode 100644 demos/2024-04-23-cheritech/morello/home/demo/script/cheri.js create mode 100755 demos/2024-04-23-cheritech/morello/home/demo/script/compile.sh create mode 100644 demos/2024-04-23-cheritech/morello/home/demo/script/demo.js create mode 100644 demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/certs/cert.pem create mode 100644 demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/certs/key.pem create mode 100644 demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/mosquitto.conf create mode 100644 demos/2024-04-23-cheritech/morello/usr/local/etc/ntpd.conf create mode 100644 demos/2024-04-23-cheritech/morello/usr/local64/etc/dhcpd.conf create mode 100644 demos/2024-04-23-cheritech/morello/usr/local64/etc/namedb/db.cheriot.demo create mode 100644 demos/2024-04-23-cheritech/morello/usr/local64/etc/namedb/db.pool.ntp.org diff --git a/demos/2024-04-23-cheritech/morello/README.txt b/demos/2024-04-23-cheritech/morello/README.txt new file mode 100644 index 0000000..d1693d9 --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/README.txt @@ -0,0 +1,139 @@ +Morello machine setup +===================== + +This directory contains the files that are necessary to set up the Morello machine to act as the server in this demo. + +Note: This contains the *private* key used on the server for the demo. +This would allow anyone to impersonate the server. +This does not matter because it is used *only* for the demo, never use this key for anything important! +Including the key here remove the need to generate a new header file for the client portion of the demo. + +Pure-capability packages: + +minicom + +Hybrid packages: + +bind918 +isc-dhcp44-server +jq +npm +wireshark + +Built from source: + +cheriot-audit (no port yet) +mosquitto (xsltproc is broken and the port's no-docs mode doesn't work). + +Make sure to build Release builds (-O0 is *really* slow on Morello, with -O0 Mosquitto can't keep up with two clients on FPGA!). +Install in /opt. + +The following lines need to be added to /etc/rc.conf: + +``` +# Network interface for the demo +ifconfig_ue0="inet 10.0.0.10 netmask 255.0.0.0" + +# DHCP server +dhcpd_enable="YES" # dhcpd enabled? +dhcpd_ifaces="ue0" # ethernet interface(s) +dhcpd_withumask="022" # file creation mask + +# bind +named_enable="YES" + +# NTP +ntpd_enable="YES" + +# Mosquitto +mosquitto_enable="YES" + +devfs_enable="YES" +``` + +Setting up DHCP +--------------- + +The first thing that the demo will do is try to get a DHCP lease. +This requires dhcpd to listen in the demo ethernet adaptor (configured in `rc.conf`) and to provide the host IP (10.0.0.10) as the DNS server. +The `usr/local64/etc/dhcpd.conf` file contains the configuration for the DHCP server and should be copied into `/usr/local64/etc/dhcpd.conf`. + +Setting up DNS +-------------- + +After acquiring a DHCP lease, the demo will try to look up host names via DNS. +For disconnected operation, we will fake the two DNS names (pool.ntp.org and cheriot.demo) by configuring the DNS server to be authoritative for these zones. +Add the following lines to the end of `/usr/local64/etc/namedb/named.conf`: + +``` +zone "cheriot.demo" { + type master; + file "/usr/local64/etc/namedb/db.cheriot.demo"; +}; + +zone "pool.ntp.org" { + type master; + file "/usr/local64/etc/namedb/db.pool.ntp.org"; +}; +``` + +Then copy the `db.cheriot.demo` and `db.pool.ntp.org` files from `usr/local64/etc/namedb` to `/usr/local64/etc/namedb/`. + +Setting up NTP +-------------- + +For disconnected operation, the NTP server needs to be configured to lie and pretend that it is an authoritative server when it can't sync with a real NTP server. +The following lines in /etc/ntp.conf will do this: + +``` +server 127.127.1.0 prefer +fudge 127.127.1.0 #stratum 10 +``` + +Note: It would be better to use `tos orphan 4`, but this defaults to a 10-minute timeout before deciding to become authoritative and this needs to be dropped to a few seconds. + +Setting up Mosquitto +-------------------- + +The Mosquitto MQTT server configuration is in `opt/etc/mosquitto/`. +Copy these files into `/opt/etc/mosquitto/`. +You can also copy the [rc script](https://github.com/freebsd/freebsd-ports/blob/main/net/mosquitto/files/mosquitto.in) from the port into `/usr/local/etc/rc.d/mosquitto` (replace `%%PREFIX%%` with `/opt`). +Alternatively, you can just start mosquitto manually and run it in the foreground. + +Wireshark +--------- + +To inspect the packets, use Wireshark. +This requires that the demo user has access to the `bpf` device. +The easiest way of doing this is to add the user to a group called `bpf` and add the following to `/etc/devfs.conf`: + +``` +own bpf root:bpf +perm bpf 660 +``` + +Console UART +------------ + +The `home/demo/.minirc.dfl` file contains the configuration for minicom to connect to the FPGA. +Run minicom as `minicom -c on -D /dev/ttyU1` or `minicom -c on -D /dev/ttyU3` to connect to the FPGA. +The demo user will need to have access to the USB TTY devices. +The easiest way to do this is to add the user to the `dialer` group and add the following to `/etc/devfs.conf`: + +``` +own ttyU* root:dialer +perm ttyU* 660 +``` + +Note that each FPGA has two FDTI devices, you need to use the *odd* numbered ones. + +Driving the demo +---------------- + +The auditing portions of the demo are driven by the `audit.sh` script in `home/demo`. +Drop this in a directory along with the board description JSON and the firmware JSON from the final build. + +The script to push new JavaScript, and an example JavaScript file, for the demo are in: `home/demo/script` +The `cheri.js` file here is the host interfaces, people may wish to modify `demo.js` to show dynamic code updates. +Note: MQTT does not do caching, so you must push out the JavaScript each time a new client connects. + diff --git a/demos/2024-04-23-cheritech/morello/home/demo/.minirc.dfl b/demos/2024-04-23-cheritech/morello/home/demo/.minirc.dfl new file mode 100644 index 0000000..b309104 --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/home/demo/.minirc.dfl @@ -0,0 +1,9 @@ +# Machine-generated file - use setup menu in minicom to change parameters. +pu baudrate 115200 +pu bits 8 +pu parity N +pu stopbits 1 +pu rtscts No +pu addlinefeed No +pu linewrap Yes +pu addcarreturn Yes diff --git a/demos/2024-04-23-cheritech/morello/home/demo/audit.sh b/demos/2024-04-23-cheritech/morello/home/demo/audit.sh new file mode 100755 index 0000000..5898a0a --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/home/demo/audit.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +if [ $# -eq 0 ] ; then + echo Query required. Try one of the following: + echo Print all connection capabilities: + echo -e \\tdata.network_stack.all_connection_capabilities + echo Is the network stack configuration valid? + echo -e "\\t'data.network_stack.valid(kunyan_ethernet)'" + echo Print all allocator capabilities and their owners: + echo -e "\\t'[ { \"owner\": owner, \"capability\": data.rtos.decode_allocator_capability(c) } | c = input.compartments[owner].imports[_] ; data.rtos.is_allocator_capability(c) ]'" + echo Print all compartments that invoke functions in the JavaScript compartment: + echo -e "\\t'data.compartment.compartments_calling(\"javascript\")'" + echo Print all compartments that invoke functions in the allocator: + echo -e "\\t'data.compartment.compartments_calling(\"allocator\")'" + echo Print all compartments that have direct access to the LEDs / switches: + echo -e "\\t'data.compartment.compartments_with_mmio_import(data.board.devices.gpio_led0)'" +else + echo "cheriot-audit --board ibex-arty-a7-100.json --firmware-report cheritech-demo.json --module network_stack.rego --query \"$1\"" + cheriot-audit --board ibex-arty-a7-100.json --firmware-report cheritech-demo.json --module network_stack.rego --query "$1" | jq +fi + diff --git a/demos/2024-04-23-cheritech/morello/home/demo/script/cheri.js b/demos/2024-04-23-cheritech/morello/home/demo/script/cheri.js new file mode 100644 index 0000000..cb0ea1a --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/home/demo/script/cheri.js @@ -0,0 +1,87 @@ +// FFI Imports +// Each function imported from the host environment needs to be assigned to a +// global like this and identified by a constant that the resolver in the C/C++ +// code will understand. +// These constants are defined in the `Exports` enumeration. + + +var FFINumber = 1; + +/** + * Log function, writes all arguments to the UART. + */ +export const print = vmImport(FFINumber++); + +/** + * led_on(index). + * + * Turns on the LED at the specified index. + */ +export const led_on = vmImport(FFINumber++); + +/** + * led_off(index). + * + * Turns off the LED at the specified index. + */ +export const led_off = vmImport(FFINumber++); + +/** + * buttons_read(). + * + * Reads the value of all of the buttons, returning a 4-bit value indicating + * the states of all of them. + */ +export const buttons_read = vmImport(FFINumber++); + +/** + * switches_read(). + * + * Reads the value of all of the switches, returning a 4-bit value indicating + * the states of all of them. + */ +export const switches_read = vmImport(FFINumber++); + + +export const mqtt_publish = vmImport(FFINumber++); +export const mqtt_subscribe = vmImport(FFINumber++); + +/** + * led_set(index, state). + * + * Turns the LED at the specified index on or off depending on whether state is + * true or false. + */ +export function led_set(index, state) +{ + if (state) + { + led_on(index); + } + else + { + led_off(index); + } +} + +/** + * button_read(index). + * + * Reads the value of the button at the specified index. + */ +export function button_read(index) +{ + return (buttons_read() & (1 << index)) !== 0; +} + + +/** + * switch_read(index). + * + * Reads the value of the switch at the specified index. + */ +export function switch_read(index) +{ + return (switches_read() & (1 << index)) !== 0; +} + diff --git a/demos/2024-04-23-cheritech/morello/home/demo/script/compile.sh b/demos/2024-04-23-cheritech/morello/home/demo/script/compile.sh new file mode 100755 index 0000000..7a8718f --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/home/demo/script/compile.sh @@ -0,0 +1,5 @@ +#!/bin/sh +set -e +microvium demo.js +echo Publishing code to MQTT broker +mosquitto_pub -h cheriot.demo -p 8883 --cafile /opt/etc/mosquitto/certs/cert.pem -t cheri-code -f demo.mvm-bc diff --git a/demos/2024-04-23-cheritech/morello/home/demo/script/demo.js b/demos/2024-04-23-cheritech/morello/home/demo/script/demo.js new file mode 100644 index 0000000..57adddd --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/home/demo/script/demo.js @@ -0,0 +1,109 @@ +import * as host from "./cheri.js" + +var ticks = 0 +var switches = 0 + +/** + * Subscribe to a topic, print to the UART whether the subscription was + * successful. + */ +function subscribe(topic) +{ + var ret = host.mqtt_subscribe(topic) + host.print("Subscribe ", topic, " returned: ", ret) + if (ret) + { + host.print("Subscribed to", topic) + } + else + { + host.print("Failed to subscribe to ", topic) + } +} + +/** + * On first run, subscribe to the switch topics. + */ +function first_run() +{ + subscribe("cheri-switch-0") + subscribe("cheri-switch-1") +} + +/** + * Tick function, called every 100ms (roughly). + */ +function tick() +{ + if (ticks === 0) + { + first_run(); + } + ticks++ + // If we're not a lightswitch, don't do anything else. + if (host.switch_read(3)) + { + return; + } + // If we're not a lightbulb, make sure the lights are out + host.led_off(0) + host.led_off(1) + // Uncomment the next block to validate that the tick callback is being called. + /* + if (ticks % 5 === 0) + { + host.print("tick: ", ticks) + } + */ + var new_switches = host.switches_read() + if (new_switches !== switches) + { + for (var i = 0 ; i < 2 ; i++) + { + if ((new_switches & (1 << i)) !== (switches & (1 << i))) + { + host.print("Switch ", i, " changed to ", (new_switches & (1 << i)) ? "on" : "off") + host.mqtt_publish("cheri-switch-" + i, (new_switches & (1 << i)) ? "on" : "off") + } + } + switches = new_switches + } +} + +/** + * Publish notification callback, called whenever a new publish message is + * received from the MQTT broker. + */ +function message(topic, message) +{ + host.print("Received message on topic: ", topic, " message: ", message) + var switchNumber = -1 + // If we're not a lightbulb, don't do anything else. + if (!host.switch_read(3)) + { + return; + } + if (topic === "cheri-switch-0") + { + switchNumber = 0 + } + else if (topic === "cheri-switch-1") + { + switchNumber = 1 + } + else + { + return + } + if (message === "on") + { + host.led_on(switchNumber) + } + else + { + host.led_off(switchNumber) + } +} + +vmExport(1234, tick); +vmExport(1235, message); diff --git a/demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/certs/cert.pem b/demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/certs/cert.pem new file mode 100644 index 0000000..1ddab5d --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/certs/cert.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBgzCCASmgAwIBAgIUeyRaxt/cqeeZ1JByg4V4shx4lhowCgYIKoZIzj0EAwIw +FzEVMBMGA1UEAwwMY2hlcmlvdC5kZW1vMB4XDTI0MDQwODE0NTcwMVoXDTI1MDQw +ODE0NTcwMVowFzEVMBMGA1UEAwwMY2hlcmlvdC5kZW1vMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAE2zq+r59p+QKkoKdBguXxBl4KoX5DYb6gHyI9Wrn7o4bz8rNZ +4JPG4J+mIlEQKv9eIJYn1owIWQ5YbKaHpZqWAqNTMFEwHQYDVR0OBBYEFBdDvYEz +T9pLdHbNwBVFT9wwQGVdMB8GA1UdIwQYMBaAFBdDvYEzT9pLdHbNwBVFT9wwQGVd +MA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgb2epifZyBtLofZsk +gs5HqfpKuiMijfe3Q+H7ETP3aIwCIQDYBIR7uQ4s24mK3dcj+u5Qc6gSr/WuBZGO +xzxrtzDGTw== +-----END CERTIFICATE----- diff --git a/demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/certs/key.pem b/demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/certs/key.pem new file mode 100644 index 0000000..e912dcc --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/certs/key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgFF2t/aeGHzLHsP4k +63Q9yIFLeU8+mtOylWjhfwwQbNihRANCAATbOr6vn2n5AqSgp0GC5fEGXgqhfkNh +vqAfIj1aufujhvPys1ngk8bgn6YiURAq/14glifWjAhZDlhspoelmpYC +-----END PRIVATE KEY----- diff --git a/demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/mosquitto.conf b/demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/mosquitto.conf new file mode 100644 index 0000000..2d9f63b --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/opt/etc/mosquitto/mosquitto.conf @@ -0,0 +1,8 @@ +listener 8883 10.0.0.10 +tls_keyform pem +keyfile /opt/etc/mosquitto/certs/key.pem +certfile /opt/etc/mosquitto/certs/cert.pem +log_type all +allow_anonymous true +connection_messages true + diff --git a/demos/2024-04-23-cheritech/morello/usr/local/etc/ntpd.conf b/demos/2024-04-23-cheritech/morello/usr/local/etc/ntpd.conf new file mode 100644 index 0000000..84b4177 --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/usr/local/etc/ntpd.conf @@ -0,0 +1,13 @@ +# $OpenBSD: ntpd.conf,v 1.16 2019/11/06 19:04:12 deraadt Exp $ +# +# See ntpd.conf(5) and /etc/examples/ntpd.conf + +servers pool.ntp.org +server time.cloudflare.com +sensor * + +listen on 10.0.0.10 + +constraint from "9.9.9.9" # quad9 v4 without DNS +constraint from "2620:fe::fe" # quad9 v6 without DNS +constraints from "www.google.com" # intentionally not 8.8.8.8 diff --git a/demos/2024-04-23-cheritech/morello/usr/local64/etc/dhcpd.conf b/demos/2024-04-23-cheritech/morello/usr/local64/etc/dhcpd.conf new file mode 100644 index 0000000..39cffce --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/usr/local64/etc/dhcpd.conf @@ -0,0 +1,22 @@ +# dhcpd.conf +# +# Sample configuration file for ISC dhcpd +# + +default-lease-time 600; +max-lease-time 6000; + +# If this DHCP server is the official DHCP server for the local +# network, the authoritative directive should be uncommented. +authoritative; + +# Use this to send dhcp log messages to a different log file (you also +# have to hack syslog.conf to complete the redirection). +log-facility local7; + +subnet 10.0.0.0 netmask 255.0.0.0 { + range 10.0.0.1 10.0.0.8; + option domain-name-servers 10.0.0.10; + allow-unknown-clients; +} + diff --git a/demos/2024-04-23-cheritech/morello/usr/local64/etc/namedb/db.cheriot.demo b/demos/2024-04-23-cheritech/morello/usr/local64/etc/namedb/db.cheriot.demo new file mode 100644 index 0000000..3298085 --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/usr/local64/etc/namedb/db.cheriot.demo @@ -0,0 +1,10 @@ +@ IN SOA cheriot.demo. root.cheriot.demo. ( + 2 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 604800 ) ; Negative Cache TTL +; +@ IN NS ns.cheriot.demo. +@ IN A 10.0.0.10 +ns IN A 10.0.0.10 diff --git a/demos/2024-04-23-cheritech/morello/usr/local64/etc/namedb/db.pool.ntp.org b/demos/2024-04-23-cheritech/morello/usr/local64/etc/namedb/db.pool.ntp.org new file mode 100644 index 0000000..d197174 --- /dev/null +++ b/demos/2024-04-23-cheritech/morello/usr/local64/etc/namedb/db.pool.ntp.org @@ -0,0 +1,11 @@ +@ IN SOA pool.ntp.org. root.pool.ntp.org. ( + 2 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 604800 ) ; Negative Cache TTL +; +@ IN NS ns.pool.ntp.org. +@ IN A 10.0.0.10 +ns IN A 10.0.0.10 +