Skip to content

Commit 4b2bd1d

Browse files
committed
Remote unlock support
Unlocking an encrypted machine remotely over the network is one of the actively used use-cases. Add the remote unlocking using ECMR protocol, the same as used for Tang bindings. In fact, there is not much difference between these 2 ways of binding. The major difference is for "tang" protocol booster is the TCP client, for "remote" protocol booster is TCP server. To enable remote locking please follow these instructions: * install `clevis-extra-pins-git` `tang.go-git` packages from AUR * generate private keys with `tang-keys create . sig exc`. It creates 2 files: a signing and a keyDerive keys. Please keep these files private. * generate advertisement: `tang-keys adv --output advertisement.json sig.jwk exc.jwk`. An advertisement is the equivalent of a public signing certificate. This file is used later to encrypt partitions and the file can be shared with other parties. * encrypt the partition itself using advertisement generated above: `clevis luks bind -d /dev/fooo remote '{"adv":"advertisement.json", "port":34551}'`. This tells booster to stop at the boot and use port `34551` to listen to incoming TCP requests. now reboot your machine. It will stop and wait for unlock requests. To unlock it run `unlock-remote $YOURMACHINE:34551 exc.jwk sig.jwk`, where exc.jwk sig.jwk are files generated above. Closes #24
1 parent 8ef90ed commit 4b2bd1d

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

tests/assets.go

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var assetGenerators = map[string]assetGenerator{
2121
"assets/luks2.clevis.tpm2.img": {"generate_asset_luks.sh", []string{"LUKS_VERSION=2", "LUKS_PASSWORD=1234", "LUKS_UUID=3756ba2c-1505-4283-8f0b-b1d1bd7b844f", "FS_UUID=c3cc0321-fba8-42c3-ad73-d13f8826d8d7", "CLEVIS_PIN=tpm2", "CLEVIS_CONFIG={}"}},
2222
"assets/luks2.clevis.tang.img": {"generate_asset_luks.sh", []string{"LUKS_VERSION=2", "LUKS_PASSWORD=1234", "LUKS_UUID=f2473f71-9a68-4b16-ae54-8f942b2daf50", "FS_UUID=7acb3a9e-9b50-4aa2-9965-e41ae8467d8a", "CLEVIS_PIN=tang", `CLEVIS_CONFIG={"url":"http://10.0.2.100:5697", "adv":"assets/tang/adv.json"}`}},
2323
"assets/luks2.clevis.yubikey.img": {"generate_asset_luks.sh", []string{"LUKS_VERSION=2", "LUKS_PASSWORD=1234", "LUKS_UUID=f2473f71-9a61-4b16-ae54-8f942b2daf52", "FS_UUID=7acb3a9e-9b50-4aa2-9965-e41ae8467d8a", "CLEVIS_PIN=yubikey", `CLEVIS_CONFIG={"slot":2}`}},
24+
"assets/luks2.clevis.remote.img": {"generate_asset_luks.sh", []string{"LUKS_VERSION=2", "LUKS_PASSWORD=1234", "LUKS_UUID=f2473f71-9a61-4b16-ae54-8f942b2daf22", "FS_UUID=7acb3a9e-9b51-4aa2-9965-e41ae8467d8a", "CLEVIS_PIN=remote", `CLEVIS_CONFIG={"adv":"assets/remote/adv.json", "port":34551}`}},
2425
"assets/gpt.img": {"generate_asset_gpt.sh", []string{"FS_UUID=e5404205-ac6a-4e94-bb3b-14433d0af7d1", "FS_LABEL=newpart"}},
2526
"assets/gpt_4ksector.img": {"generate_asset_gpt_4ksector.sh", nil},
2627
"assets/lvm.img": {"generate_asset_lvm.sh", []string{"FS_UUID=74c9e30c-506f-4106-9f61-a608466ef29c", "FS_LABEL=lvmr00t"}},

tests/clevis_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package tests
22

33
import (
4+
"os"
5+
"os/exec"
46
"testing"
7+
"time"
58

69
"github.com/stretchr/testify/require"
710
)
@@ -134,3 +137,27 @@ func TestInactiveNetwork(t *testing.T) {
134137

135138
require.NoError(t, vm.ConsoleExpect("Timeout waiting for root filesystem"))
136139
}
140+
141+
func TestRemoteUnlock(t *testing.T) {
142+
vm, err := buildVmInstance(t, Opts{
143+
disk: "assets/luks2.clevis.remote.img",
144+
enableNetwork: true,
145+
params: []string{"-nic", "user,id=n1,hostfwd=tcp::34551-:34551"},
146+
kernelArgs: []string{"rd.luks.uuid=f2473f71-9a61-4b16-ae54-8f942b2daf22", "root=UUID=7acb3a9e-9b51-4aa2-9965-e41ae8467d8a"},
147+
})
148+
require.NoError(t, err)
149+
defer vm.Kill()
150+
151+
require.NoError(t, vm.ConsoleExpect("link becomes ready")) // wait for the network
152+
time.Sleep(time.Second)
153+
154+
// unlock remotely
155+
cmd := exec.Command("unlock-remote", "localhost:34551", "assets/remote/exc.jwk", "assets/remote/sig.jwk")
156+
if testing.Verbose() {
157+
cmd.Stdout = os.Stdout
158+
cmd.Stderr = os.Stderr
159+
}
160+
require.NoError(t, cmd.Run())
161+
162+
require.NoError(t, vm.ConsoleExpect("Hello, booster!"))
163+
}

tests/generate_asset_luks.sh

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ if [ "$CLEVIS_PIN" == "tpm2" ]; then
2222
swtpm socket --tpmstate dir=assets/tpm2.generate --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear &
2323
fi
2424

25+
if [ "$CLEVIS_PIN" == "remote" ]; then
26+
mkdir -p assets/remote
27+
tang-keys create assets/remote sig exc
28+
tang-keys adv --output assets/remote/adv.json assets/remote/*.jwk
29+
fi
30+
2531
truncate --size 40M $OUTPUT
2632
lodev=$(sudo losetup -f --show $OUTPUT)
2733
sudo cryptsetup luksFormat --uuid $LUKS_UUID --type $LUKS_TYPE $lodev <<<"$LUKS_PASSWORD"

0 commit comments

Comments
 (0)