164 lines
No EOL
6.9 KiB
Markdown
164 lines
No EOL
6.9 KiB
Markdown
<!--
|
|
SPDX-FileCopyrightText: 2021-2023 Heiko Schaefer <heiko@schaefer.name>
|
|
SPDX-License-Identifier: MIT OR Apache-2.0
|
|
-->
|
|
|
|
This project implements client software for the
|
|
[OpenPGP card](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.1.pdf)
|
|
standard, in Rust.
|
|
|
|
## Architecture
|
|
|
|
This project consists of the following library crates:
|
|
|
|
- [openpgp-card](https://crates.io/crates/openpgp-card), which offers a
|
|
relatively low-level OpenPGP card client API.
|
|
It is PGP implementation agnostic.
|
|
- [card-backend](https://crates.io/crates/card-backend),
|
|
a shared trait for Smart Card backends
|
|
- [card-backend-pcsc](https://crates.io/crates/card-backend-pcsc),
|
|
a backend implementation to communicate with smartcards via
|
|
[pcsc](https://pcsclite.apdu.fr/).
|
|
- [card-backend-scdc](https://crates.io/crates/card-backend-scdc),
|
|
a backend implementation to communicate with smartcards via an
|
|
[scdaemon](https://www.gnupg.org/documentation/manuals/gnupg/Invoking-SCDAEMON.html#Invoking-SCDAEMON)
|
|
instance.
|
|
- [openpgp-card-sequoia](https://crates.io/crates/openpgp-card-sequoia),
|
|
a higher level API for conveniently using openpgp-card with
|
|
[Sequoia PGP](https://sequoia-pgp.org/).
|
|
|
|
This is how the libraries relate to each other (and to applications):
|
|
|
|
```mermaid
|
|
graph BT
|
|
CB["card-backend <br/> (shared trait)"] --> OP
|
|
CB --> OS
|
|
OP["card-backend-pcsc <br/> (pcsclite backend)"] --> OC
|
|
OS["card-backend-scdc <br/> (scdaemon backend)"] --> OC["openpgp-card <br/> (low level API)"]
|
|
OC --> OCS["openpgp-card-sequoia <br/> (high level Sequoia PGP-based API)"]
|
|
OC -.-> U1[Applications based on low level API]
|
|
OCS -.-> U2[Sequoia PGP-based applications]
|
|
|
|
classDef userApp fill:#f8f8f8,stroke-dasharray: 5 5;
|
|
class U1,U2 userApp;
|
|
```
|
|
|
|
Additionally, there are the following non-library crates that are built on
|
|
top of the libraries described above:
|
|
|
|
- [openpgp-card-tools](https://crates.io/crates/openpgp-card-sequoia),
|
|
the `opgpcard` CLI tool to inspect, manage and use OpenPGP cards, aimed at end users.
|
|
- [openpgp-card-tests](https://gitlab.com/openpgp-card/openpgp-card/-/tree/main/card-functionality),
|
|
a test-suite that runs OpenPGP card operations on Smart Cards.
|
|
- [openpgp-card-examples](https://gitlab.com/openpgp-card/openpgp-card/-/tree/main/card-examples),
|
|
small example applications that demonstrate how you can use these
|
|
libraries in your own projects to access OpenPGP card functionality.
|
|
|
|
### The openpgp-card crate
|
|
|
|
Implements the functionality described in the OpenPGP card specification,
|
|
offering an API at roughly the level of abstraction of that specification,
|
|
using Rust data structures.
|
|
(However, this crate may work around some minor quirks of specific card
|
|
models, in order to offer clients a somewhat uniform view)
|
|
|
|
This crate and its API do not depend or rely on any particular OpenPGP
|
|
implementation.
|
|
|
|
### Backends
|
|
|
|
Typically, `openpgp-card` will be used with the `card-backend-pcsc` backend,
|
|
which uses the standard pcsc-lite library to communicate with cards.
|
|
|
|
However, alternative backends can be used and may be useful.
|
|
The experimental, alternative `card-backend-scdc` backend uses scdaemon from
|
|
the GnuPG project as a low-level transport layer to interact with OpenPGP
|
|
cards.
|
|
|
|
Backends implement:
|
|
|
|
1) functionality to find and connect to a card (these operations may vary
|
|
significantly between different backends),
|
|
|
|
2) transaction management (where applicable), by implementing the `CardBackend` trait, and
|
|
|
|
3) simple communication primitives, by implementing the `CardTransaction`
|
|
trait, to send individual APDU commands and receive responses.
|
|
|
|
All higher level and/or OpenPGP card-specific logic (including command
|
|
chaining) is handled in the `openpgp-card` layer.
|
|
|
|
### The openpgp-card-sequoia crate
|
|
|
|
Offers a higher level interface, based around Sequoia PGP datastructures.
|
|
|
|
Most client projects will probably want to use only this crate, and
|
|
ignore the lower level crates as implementation details.
|
|
|
|
## Testing
|
|
|
|
The subcrate `openpgp-card-tests` (in the directory `card-functionality`)
|
|
contains the beginnings of a framework that tests the `openpgp-card`
|
|
library against OpenPGP cards.
|
|
|
|
However, OpenPGP cards are, usually, physical devices that you plug into your
|
|
computer, e.g. as USB sticks, or Smart cards (this is, of course, the usual
|
|
point of these cards: they are independent devices, which are only loosely
|
|
coupled with your regular computing environment).
|
|
For automated testing, such as CI, this is a complication.
|
|
|
|
There are at least two approaches for running tests against software-based
|
|
OpenPGP cards:
|
|
|
|
### Virtual JavaCards
|
|
|
|
It's possible to run simulated JavaCard applets on a host computer, and
|
|
make those available via the [PCSC lite](https://pcsclite.apdu.fr/) framework.
|
|
|
|
To simplify testing against such simulated cards, the
|
|
https://gitlab.com/openpgp-card/virtual-cards repository provides Container
|
|
images for the "SmartPGP" and "YubiKey NEO" OpenPGP card implementations.
|
|
|
|
These images are used to run card-functionality tests on gitlab's CI.
|
|
See the GitLab CI config
|
|
[openpgp-card/openpgp-card:.gitlab-ci.yml](https://gitlab.com/openpgp-card/openpgp-card/-/blob/main/.gitlab-ci.yml)
|
|
and the Dockerfiles and run script:
|
|
[openpgp-card/openpgp-card:card-functionality/docker/](https://gitlab.com/openpgp-card/openpgp-card/-/tree/main/card-functionality/docker/).
|
|
|
|
|
|
### Emulated Gnuk
|
|
|
|
Gnuk is a free implementation of the OpenPGP card spec by
|
|
[Gniibe](https://www.gniibe.org/), see: http://www.fsij.org/doc-gnuk/.
|
|
|
|
Gnuk normally runs on STM32-based hardware tokens. However, it's also
|
|
possible to compile the Gnuk code to run on your host machine. This is
|
|
useful for testing purposes.
|
|
|
|
Emulated Gnuk is connected to the system via http://usbip.sourceforge.net/.
|
|
This means that to use an emulated Gnuk, you need to have both root
|
|
privileges and be able to load a kernel module (so running an emulated
|
|
Gnuk is not currently possible in GitLab CI).
|
|
|
|
See the [README](https://gitlab.com/openpgp-card/openpgp-card/-/tree/main/card-functionality#running-tests-against-emulated-gnuk-via-pcsc)
|
|
of the `card-functionality` project for more information on this.
|
|
|
|
|
|
## Acknowledgements
|
|
|
|
This project is based on the
|
|
[OpenPGP card spec](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.1.pdf),
|
|
version 3.4.1.
|
|
|
|
Other helpful resources included:
|
|
- The free [Gnuk](https://git.gniibe.org/cgit/gnuk/gnuk.git/)
|
|
OpenPGP card implementation by [gniibe](https://www.gniibe.org/).
|
|
- The Rust/Sequoia-based OpenPGP card client code in
|
|
[kushaldas](https://kushaldas.in/)' project
|
|
[johnnycanencrypt](https://github.com/kushaldas/johnnycanencrypt/).
|
|
- The [scdaemon](https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=tree;f=scd;hb=refs/heads/master)
|
|
client implementation by the [GnuPG](https://gnupg.org/) project.
|
|
- The [open-keychain](https://github.com/open-keychain/open-keychain) project,
|
|
which implements an OpenPGP card client for Java/Android.
|
|
- The Rust/Sequoia-based OpenPGP card client code by
|
|
[Robin Krahl](https://git.sr.ht/~ireas/sqsc). |