Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
on: push

jobs:
build:
name: Build
strategy:
matrix:
os:
- ubuntu-24.04
- ubuntu-22.04
Comment on lines +9 to +10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ (recommended)

Do we really need to test the prior Ubuntu version? What are we getting from testing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are dependency differences between the two and as a rule of thumb we should generally be supporting and testing on the last 2 versions for the major distros.

- macos-13
runs-on: ${{ matrix.os }}
steps:
- name: Set up Elixir
if: ${{ startsWith(matrix.os, 'ubuntu') }}
uses: erlef/setup-beam@v1
with:
otp-version: "27.1.3"
elixir-version: "1.17.3"
- name: Set up Elixir
if: ${{ startsWith(matrix.os, 'macos') }}
run: brew install elixir
- name: Checkout repository
uses: actions/checkout@v4
- name: Get dependencies
run: mix deps.get --only dev
- name: Restore PLTs
uses: actions/cache@v4
with:
path: _build/dev/plt
key: plt-${{ github.ref }}-${{ github.sha }}
restore-keys: |
plt-${{ github.ref }}-${{ github.sha }}
plt-${{ github.ref }}-
plt-refs/heads/master-
- name: Install system deps
if: ${{ startsWith(matrix.os, 'ubuntu') }}
run: |
sudo apt install \
build-essential \
devscripts \
equivs \
libtasn1-6-dev \
libjson-glib-dev \
libseccomp-dev \
libgmp-dev
- name: Install system deps
if: ${{ startsWith(matrix.os, 'macos') }}
run: brew install automake gawk socat json-glib
- name: Compile
run: mix compile
type_check:
name: Type Check
runs-on: ubuntu-24.04
steps:
- name: Set up Elixir
uses: erlef/setup-beam@v1
with:
otp-version: "27.1.3"
elixir-version: "1.17.3"
- name: Checkout repository
uses: actions/checkout@v4
- name: Get dependencies
run: mix deps.get --only dev
- name: Restore PLTs
uses: actions/cache@v4
with:
path: _build/dev/plt
key: plt-${{ github.ref }}-${{ github.sha }}
restore-keys: |
plt-${{ github.ref }}-${{ github.sha }}
plt-${{ github.ref }}-
plt-refs/heads/master-
- name: Install system deps
run: |
sudo apt install \
build-essential \
devscripts \
equivs \
libtasn1-6-dev \
libjson-glib-dev \
libseccomp-dev \
libgmp-dev
- name: Compile
run: mix compile
- name: Run dialyzer
run: mix dialyzer
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/_build/
/cover/
/data/
/deps/
/doc/
/.fetch
Expand Down
57 changes: 57 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,60 @@ if(NOT EXISTS ${CPM_PATH})
file(DOWNLOAD ${CPM_RELEASE_URL} ${CPM_PATH})
endif()
include(${CPM_PATH})

# dependencies
set(LIBTPMS_VER v0.10.0)
set(SWTPM_VER v0.10.0)

if(DEFINED ENV{LIBTPMS_VER})
set(LIBTPMS_VER $ENV{LIBTPMS_VER})
endif()

if(DEFINED ENV{SWTPM_VER})
set(SWTPM_VER $ENV{SWTPM_VER})
endif()

CPMFindPackage(
NAME libtpms
GITHUB_REPOSITORY stefanberger/libtpms
GIT_TAG ${LIBTPMS_VER})

CPMFindPackage(
NAME swtpm
GITHUB_REPOSITORY stefanberger/swtpm
GIT_TAG ${SWTPM_VER})

# build
project(swtpm_ex)

include(ExternalProject)
include(ProcessorCount)

find_program(MAKE make REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBTASN1 libtasn1 REQUIRED)
pkg_check_modules(LIBJASON_GLIB json-glib-1.0 REQUIRED)
pkg_check_modules(LIBGMP gmp REQUIRED)

if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
pkg_check_modules(LIBSECCOMP libseccomp REQUIRED)
endif()

ProcessorCount(NPROC)

ExternalProject_Add(libtpms
SOURCE_DIR ${libtpms_SOURCE_DIR}
CONFIGURE_COMMAND ${libtpms_SOURCE_DIR}/autogen.sh
--with-tpm2
--with-openssl
--prefix=$ENV{MIX_APP_PATH}/priv
BUILD_COMMAND ${MAKE} -j ${NPROC})

ExternalProject_Add(swtpm
SOURCE_DIR ${swtpm_SOURCE_DIR}
CONFIGURE_COMMAND PKG_CONFIG_PATH=$ENV{MIX_APP_PATH}/priv/lib/pkgconfig
${swtpm_SOURCE_DIR}/autogen.sh
--disable-tests
--with-openssl
--prefix=$ENV{MIX_APP_PATH}/priv
BUILD_COMMAND ${MAKE} -j ${NPROC})
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# swtpm

An easy way to bring a Software TPM emulator into your elixir application by
wrapping [swtpm](https://github.com/stefanberger/swtpm).

## Prerequisites

Ensure the following are installed on your host system:
* [libtasn1](https://www.gnu.org/software/libtasn1/)
* [json-glib-1.0](https://wiki.gnome.org/Projects/JsonGlib)
* [libseccomp](https://github.com/seccomp/libseccomp)
* [gmp](https://gmplib.org/)

## Installation

The package can be installed by adding `swtpm` to your list of dependencies
Expand All @@ -12,3 +23,16 @@ def deps do
]
end
```

## Supervision

Add the `SWTPM` module spec to your `application.ex`. For more details see docs
for `&SWTPM.child_spec/1`.

```elixir
defp children(:host) do
[
{SWTPM, [state_dir: "data/tpm"]}
]
end
```
55 changes: 55 additions & 0 deletions lib/swtpm.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,59 @@ defmodule SWTPM do
@moduledoc """
Software TPM emulator.
"""

@doc """
Integrates the `SWTPM` module with a supervision tree, providing a
standardized way to configure and start the Software TPM emulator as a
supervised process.

## Options
- `:state_dir` - Specifies the directory where the TPM state will be stored.

- `:server_port` - Specifies the TCP port used for the TPM server. Defaults
to `2321`.

- `:ctrl_port` - Specifies the TCP port used for TPM control commands.
Defaults to `2322`.

- `:flags` - Refer to https://man.archlinux.org/man/swtpm.8.en for full list
of flags. Defaults to `[:not_need_init, :startup_clear]`.

## Example
```elixir
children = [
{SWTPM, [state_dir: "/data/tpm"]}
]

Supervisor.start_link(children, [strategy: :one_for_one, name: MySupervisor])
```
"""
@spec child_spec(keyword) :: Supervisor.child_spec()
def child_spec(opts) do
state_dir = opts[:state_dir]
server_port = opts[:server_port] || 2321
ctrl_port = opts[:ctrl_port] || 2322

flags =
Keyword.get(opts, :flags, [:not_need_init, :startup_clear])
|> Enum.map(& to_string(&1) |> String.replace("_", "-"))
|> Enum.join(",")

command = Path.join([:code.priv_dir(:swtpm), "bin", "swtpm"])
args = [
"socket",
"--tpm2",
"--tpmstate", "dir=#{state_dir}",
"--server", "type=tcp,port=#{server_port}",
"--ctrl", "type=tcp,port=#{ctrl_port}",
"--flags", flags,
]

%{
id: __MODULE__,
start: {MuonTrap.Daemon, :start_link, [command, args, []]},
type: :worker,
restart: :permanent,
}
end
end
6 changes: 3 additions & 3 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ defmodule SWTPM.MixProject do

def application do
[
extra_applications: [:logger]
extra_applications: [:logger],
]
end

Expand All @@ -38,7 +38,7 @@ defmodule SWTPM.MixProject do
cookie: "#{@app}_cookie",
include_erts: &Nerves.Release.erts/0,
steps: [&Nerves.Release.init/1, :assemble],
strip_beams: Mix.env() == :prod or [keep: ["Docs"]]
strip_beams: Mix.env() == :prod or [keep: ["Docs"]],
]
end

Expand Down Expand Up @@ -68,7 +68,7 @@ defmodule SWTPM.MixProject do
defp docs do
[
main: "readme",
extras: ["README.md"]
extras: ["README.md"],
]
end

Expand Down